working marketplace
This commit is contained in:
@ -38,6 +38,7 @@ public final class popa extends JavaPlugin implements Listener {
|
|||||||
private String serverIp;
|
private String serverIp;
|
||||||
private String commandsUrl;
|
private String commandsUrl;
|
||||||
private String inventoryRequestsUrl;
|
private String inventoryRequestsUrl;
|
||||||
|
private String marketplaceUrl;
|
||||||
private final Map<UUID, Long> playerLoginTimes = new HashMap<>();
|
private final Map<UUID, Long> playerLoginTimes = new HashMap<>();
|
||||||
private final Map<UUID, String> playerNames = new HashMap<>();
|
private final Map<UUID, String> playerNames = new HashMap<>();
|
||||||
private ScheduledExecutorService scheduler;
|
private ScheduledExecutorService scheduler;
|
||||||
@ -77,6 +78,9 @@ public final class popa extends JavaPlugin implements Listener {
|
|||||||
// Отправка текущих онлайн-игроков при старте плагина
|
// Отправка текущих онлайн-игроков при старте плагина
|
||||||
scheduler.scheduleAtFixedRate(this::sendOnlinePlayersUpdate, 60, 60, TimeUnit.SECONDS);
|
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("PopaPlugin has been enabled!");
|
||||||
getLogger().info("API URL: " + apiUrl);
|
getLogger().info("API URL: " + apiUrl);
|
||||||
getLogger().info("Commands URL: " + commandsUrl);
|
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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Пытается извлечь имя целевого игрока из команды
|
* Пытается извлечь имя целевого игрока из команды
|
||||||
*/
|
*/
|
||||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user