working marketplace

This commit is contained in:
2025-07-19 04:46:59 +05:00
parent f69b2c9c37
commit 0507d36933
4 changed files with 331 additions and 0 deletions

View File

@ -38,6 +38,7 @@ public final class popa extends JavaPlugin implements Listener {
private String serverIp;
private String commandsUrl;
private String inventoryRequestsUrl;
private String marketplaceUrl;
private final Map<UUID, Long> playerLoginTimes = new HashMap<>();
private final Map<UUID, String> playerNames = new HashMap<>();
private ScheduledExecutorService scheduler;
@ -77,6 +78,9 @@ public final class popa extends JavaPlugin implements Listener {
// Отправка текущих онлайн-игроков при старте плагина
scheduler.scheduleAtFixedRate(this::sendOnlinePlayersUpdate, 60, 60, TimeUnit.SECONDS);
marketplaceUrl = getConfig().getString("api-base", "http://localhost:8000") + "/api/marketplace";
scheduler.scheduleAtFixedRate(this::checkMarketplaceOperations, 3, 3, TimeUnit.SECONDS);
getLogger().info("PopaPlugin has been enabled!");
getLogger().info("API URL: " + apiUrl);
getLogger().info("Commands URL: " + commandsUrl);
@ -464,6 +468,333 @@ public final class popa extends JavaPlugin implements Listener {
}
}
/**
* Проверяет запросы на операции с торговой площадкой
*/
private void checkMarketplaceOperations() {
if (!getServer().isPrimaryThread()) {
Bukkit.getScheduler().runTask(this, this::checkMarketplaceOperations);
return;
}
try {
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(marketplaceUrl + "/operations?server_ip=" + serverIp))
.version(HttpClient.Version.HTTP_1_1)
.GET()
.build();
HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() == 200) {
JsonObject json = JsonParser.parseString(response.body()).getAsJsonObject();
if (json.has("operations") && json.get("operations").isJsonArray()) {
JsonArray operations = json.getAsJsonArray("operations");
for (JsonElement op : operations) {
JsonObject operation = op.getAsJsonObject();
String type = operation.get("type").getAsString();
String opId = operation.get("id").getAsString();
if ("sell".equals(type)) {
handleSellOperation(operation);
} else if ("buy".equals(type)) {
handleBuyOperation(operation);
}
// Подтверждаем выполнение операции
confirmOperation(opId);
}
}
}
} catch (Exception e) {
getLogger().warning("Ошибка при проверке операций торговой площадки: " + e.getMessage());
e.printStackTrace();
}
}
/**
* Обрабатывает операцию продажи предмета
*/
private void handleSellOperation(JsonObject operation) {
String playerName = operation.get("player_name").getAsString();
int slotIndex = operation.get("slot_index").getAsInt();
Player player = Bukkit.getPlayer(playerName);
if (player == null || !player.isOnline()) {
sendOperationError(operation.get("id").getAsString(), "Игрок не в сети");
return;
}
PlayerInventory inv = player.getInventory();
ItemStack item = null;
// Получаем предмет из нужного слота
if (slotIndex >= 0 && slotIndex <= 35) {
item = inv.getItem(slotIndex);
} else if (slotIndex == 36) {
item = inv.getBoots();
} else if (slotIndex == 37) {
item = inv.getLeggings();
} else if (slotIndex == 38) {
item = inv.getChestplate();
} else if (slotIndex == 39) {
item = inv.getHelmet();
} else if (slotIndex == 40) {
item = inv.getItemInOffHand();
}
if (item == null || item.getType() == Material.AIR) {
sendOperationError(operation.get("id").getAsString(), "Предмет не найден в указанном слоте");
return;
}
// Создаем полную копию предмета с метаданными для отправки на сервер
JsonObject itemData = itemStackToDetailedJson(item, slotIndex);
// Очищаем слот
if (slotIndex >= 0 && slotIndex <= 35) {
inv.setItem(slotIndex, null);
} else if (slotIndex == 36) {
inv.setBoots(null);
} else if (slotIndex == 37) {
inv.setLeggings(null);
} else if (slotIndex == 38) {
inv.setChestplate(null);
} else if (slotIndex == 39) {
inv.setHelmet(null);
} else if (slotIndex == 40) {
inv.setItemInOffHand(null);
}
// Отправляем сообщение игроку
int price = operation.get("price").getAsInt();
player.sendMessage("§aВы выставили предмет на продажу за " + price + " монет");
// Отправляем данные о предмете на сервер
sendItemDetails(operation.get("id").getAsString(), itemData);
}
/**
* Обрабатывает операцию покупки предмета
*/
private void handleBuyOperation(JsonObject operation) {
String playerName = operation.get("player_name").getAsString();
JsonObject itemData = operation.getAsJsonObject("item_data");
Player player = Bukkit.getPlayer(playerName);
if (player == null || !player.isOnline()) {
sendOperationError(operation.get("id").getAsString(), "Игрок не в сети");
return;
}
// Создаем предмет из данных
ItemStack item = jsonToItemStack(itemData);
if (item == null) {
sendOperationError(operation.get("id").getAsString(), "Не удалось создать предмет");
return;
}
// Добавляем предмет в инвентарь
HashMap<Integer, ItemStack> leftItems = player.getInventory().addItem(item);
// Если предмет не поместился полностью, бросаем остаток на землю
if (!leftItems.isEmpty()) {
for (ItemStack leftItem : leftItems.values()) {
player.getWorld().dropItem(player.getLocation(), leftItem);
}
}
// Отправляем сообщение игроку
int price = operation.get("price").getAsInt();
player.sendMessage("§aВы купили предмет за " + price + " монет");
}
/**
* Создает ItemStack из JSON данных
*/
private ItemStack jsonToItemStack(JsonObject itemData) {
try {
String materialName = itemData.get("material").getAsString();
Material material = Material.valueOf(materialName);
int amount = itemData.get("amount").getAsInt();
ItemStack item = new ItemStack(material, amount);
// Если есть мета-данные
if (itemData.has("meta") && !itemData.get("meta").isJsonNull()) {
JsonObject meta = itemData.getAsJsonObject("meta");
org.bukkit.inventory.meta.ItemMeta itemMeta = item.getItemMeta();
// Устанавливаем отображаемое имя
if (meta.has("display_name")) {
itemMeta.setDisplayName(meta.get("display_name").getAsString());
}
// Устанавливаем lore
if (meta.has("lore") && meta.get("lore").isJsonArray()) {
JsonArray loreArray = meta.getAsJsonArray("lore");
java.util.List<String> lore = new java.util.ArrayList<>();
for (JsonElement line : loreArray) {
lore.add(line.getAsString());
}
itemMeta.setLore(lore);
}
// Устанавливаем зачарования
if (meta.has("enchants") && meta.get("enchants").isJsonObject()) {
JsonObject enchants = meta.getAsJsonObject("enchants");
for (Map.Entry<String, JsonElement> entry : enchants.entrySet()) {
org.bukkit.enchantments.Enchantment enchantment =
org.bukkit.enchantments.Enchantment.getByKey(org.bukkit.NamespacedKey.minecraft(entry.getKey()));
if (enchantment != null) {
itemMeta.addEnchant(enchantment, entry.getValue().getAsInt(), true);
}
}
}
// Устанавливаем прочность
if (meta.has("durability") && itemMeta instanceof org.bukkit.inventory.meta.Damageable) {
org.bukkit.inventory.meta.Damageable damageable = (org.bukkit.inventory.meta.Damageable) itemMeta;
damageable.setDamage(meta.get("durability").getAsInt());
}
item.setItemMeta(itemMeta);
}
return item;
} catch (Exception e) {
getLogger().warning("Ошибка при создании предмета из JSON: " + e.getMessage());
e.printStackTrace();
return null;
}
}
/**
* Преобразует ItemStack в детальный JsonObject со всеми мета-данными
*/
private JsonObject itemStackToDetailedJson(ItemStack item, int slot) {
JsonObject itemJson = new JsonObject();
itemJson.addProperty("slot", slot);
if (item == null || item.getType() == Material.AIR) {
itemJson.addProperty("material", "AIR");
itemJson.addProperty("amount", 0);
return itemJson;
}
itemJson.addProperty("material", item.getType().toString());
itemJson.addProperty("amount", item.getAmount());
// Добавляем мета-данные
if (item.hasItemMeta()) {
JsonObject metaJson = new JsonObject();
if (item.getItemMeta().hasDisplayName()) {
metaJson.addProperty("display_name", item.getItemMeta().getDisplayName());
}
if (item.getItemMeta().hasLore()) {
JsonArray loreArray = new JsonArray();
for (String line : item.getItemMeta().getLore()) {
loreArray.add(line);
}
metaJson.add("lore", loreArray);
}
if (item.getItemMeta().hasEnchants()) {
JsonObject enchants = new JsonObject();
item.getItemMeta().getEnchants().forEach((enchantment, level) -> {
enchants.addProperty(enchantment.getKey().getKey(), level);
});
metaJson.add("enchants", enchants);
}
// Сохраняем данные о прочности
if (item.getItemMeta() instanceof org.bukkit.inventory.meta.Damageable) {
org.bukkit.inventory.meta.Damageable damageable =
(org.bukkit.inventory.meta.Damageable) item.getItemMeta();
metaJson.addProperty("durability", damageable.getDamage());
}
itemJson.add("meta", metaJson);
}
return itemJson;
}
/**
* Отправляет детальную информацию о предмете на сервер
*/
private void sendItemDetails(String operationId, JsonObject itemData) {
JsonObject payload = new JsonObject();
payload.addProperty("operation_id", operationId);
payload.add("item_data", itemData);
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(marketplaceUrl + "/items/details"))
.version(HttpClient.Version.HTTP_1_1)
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload.toString()))
.build();
try {
httpClient.send(request, HttpResponse.BodyHandlers.ofString());
} catch (Exception e) {
getLogger().warning("Ошибка при отправке данных предмета: " + e.getMessage());
}
}
/**
* Отправляет ошибку операции
*/
private void sendOperationError(String operationId, String error) {
JsonObject payload = new JsonObject();
payload.addProperty("operation_id", operationId);
payload.addProperty("status", "error");
payload.addProperty("error", error);
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(marketplaceUrl + "/operations/confirm"))
.version(HttpClient.Version.HTTP_1_1)
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload.toString()))
.build();
try {
httpClient.send(request, HttpResponse.BodyHandlers.ofString());
} catch (Exception e) {
getLogger().warning("Ошибка при отправке ошибки операции: " + e.getMessage());
}
}
/**
* Подтверждает выполнение операции
*/
private void confirmOperation(String operationId) {
JsonObject payload = new JsonObject();
payload.addProperty("operation_id", operationId);
payload.addProperty("status", "success");
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(marketplaceUrl + "/operations/confirm"))
.version(HttpClient.Version.HTTP_1_1)
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload.toString()))
.build();
try {
httpClient.send(request, HttpResponse.BodyHandlers.ofString());
} catch (Exception e) {
getLogger().warning("Ошибка при подтверждении операции: " + e.getMessage());
}
}
/**
* Пытается извлечь имя целевого игрока из команды
*/