Я не могу сохранить предметы в плагине Minecraft 1.21.4JAVA

Программисты JAVA общаются здесь
Ответить Пред. темаСлед. тема
Anonymous
 Я не могу сохранить предметы в плагине Minecraft 1.21.4

Сообщение Anonymous »

Я пишу бумажный плагин для Minecraft 1.21.4 (Paper API 1.21.4-r0.1-snapshot). < /p>
Когда игрок сначала входит на сервер, плагин блокирует 27 слотов в инвентаризации с барьерами. После покупки слота он разблокирован, и барьер исчезает. Я считаю, что это происходит потому, что я пытаюсь проверить количество разблокированных слотов в моей базе данных. < /P>
Как я могу убедиться, что элементы сохраняются?

Код: Выделить всё

package ru.mopsland.pugSkills;

import net.kyori.adventure.text.Component;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;

public final class PugSkills extends JavaPlugin implements Listener, CommandExecutor {

private HeartUpgradeManager heartUpgradeManager;
private WaterResistanceManager waterResistanceManager;
private ToolUsageManager toolUsageManager;
private BarrierManager barrierManager;

@Override
public void onEnable() {
Bukkit.getPluginManager().registerEvents(this, this);
if (getCommand("skills") != null) {
getCommand("skills").setExecutor(this);
} else {
getLogger().warning("Command 'skills' is not registered in plugin.yml!");
}

heartUpgradeManager = new HeartUpgradeManager(this);
waterResistanceManager = new WaterResistanceManager(this);
toolUsageManager = new ToolUsageManager(this);
barrierManager = new BarrierManager(this);
}

@Override
public void onDisable() {
heartUpgradeManager.saveHeartUpgrades();
waterResistanceManager.saveWaterResistance();
toolUsageManager.saveToolUsage();
barrierManager.saveUnlockedSlots();
}

@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
if (sender instanceof Player player) {
openSkillsMenu(player);
return true;
}
return false;
}

private void openSkillsMenu(@NotNull Player player) {
// Создаем инвентарь для меню навыков
Inventory skillsMenu = Bukkit.createInventory(null, 18, "Меню навыков");

// Сердца - предмет для улучшения сердец
int heartLevel = heartUpgradeManager.getHeartUpgrades(player.getUniqueId());
String heartCostMessage = (heartLevel < HeartUpgradeManager.getMaxHeartUpgrades()) ? // Use getter
"§7Стоимость: §c" + ((heartLevel + 1) * 5) + " уровней опыта" : "§7Навык прокачен на максимум";
ItemStack regenPotion = createItem(Material.POTION, "§aДобавить сердце",
"§7Текущий уровень: §e" + heartLevel,
heartCostMessage);

// Устойчивость к воде - предмет для улучшения устойчивости
int waterLevel = waterResistanceManager.getWaterResistance(player.getUniqueId()); // Get water level
String waterCostMessage = (waterLevel < WaterResistanceManager.getMaxWaterResistance()) ? // Use getter
"§7Стоимость: §c" + ((waterLevel + 1) * 5) + " уровней опыта" : "§7Навык прокачен на максимум";
ItemStack waterResistanceItem = createItem(Material.WATER_BUCKET, "§aУстойчивость к воде",
"§7Текущий уровень: §e" + waterLevel,
waterCostMessage);

// Расчет стоимости улучшения для барьера (разблокировка слота инвентаря)
int unlockedSlots = barrierManager.getUnlockedSlots(player);
int unlockCost = (unlockedSlots + 1) * 5; // Цена увеличивается с каждым новым слотом

// Проверка на максимальное количество слотов
String unlockCostMessage = (unlockedSlots < 27) ?
"§7Стоимость: §c" + unlockCost + " уровней опыта"  :
"§7Максимальный уровень: §e27";

// Добавляем новый предмет - барьер для разблокировки слота
ItemStack barrierItem = createItem(Material.BARRIER, "§aРазблокировать слот инвентаря",
unlockCostMessage, "§7Максимальный уровень: §e27");

// Добавляем инструменты, начиная с палок
addToolUpgradeItem(skillsMenu, player, Material.STICK, "Меч", 3); // Начинаем с палки для Меча
addToolUpgradeItem(skillsMenu, player, Material.STICK, "Кирка", 4); // Начинаем с палки для Кирки
addToolUpgradeItem(skillsMenu, player, Material.STICK, "Топор", 5); // Начинаем с палки для Топора
addToolUpgradeItem(skillsMenu, player, Material.STICK, "Лопата", 6); // Начинаем с палки для Лопаты
addToolUpgradeItem(skillsMenu, player, Material.STICK, "Мотыга", 7); // Начинаем с палки для Мотыги

// Добавляем предметы в меню
skillsMenu.setItem(0, regenPotion);  // Добавляем предмет для улучшения сердец
skillsMenu.setItem(1, waterResistanceItem);
skillsMenu.setItem(2, barrierItem);// Добавляем предмет для устойчивости к воде
player.openInventory(skillsMenu); // Открываем инвентарь для игрока
}

// Метод для добавления предметов в меню для улучшения инструментов
private void addToolUpgradeItem(Inventory menu, Player player, Material material, String name, int slot) {
String toolName = name; // Название инструмента (например, Меч, Кирка, Топор и т.д.)
int toolLevel = toolUsageManager.getToolLevel(player.getUniqueId(), toolName); // Получаем уровень текущего инструмента игрока
String toolCostMessage = (toolLevel < 6) ? "§7Стоимость: §c" + ((toolLevel + 1) * 5) + " уровней опыта" : "§7Навык прокачен на максимум";

// Определяем материал инструмента в зависимости от его уровня
Material displayMaterial = material; // Изначально используется палка

// Переход от палки к инструментам в зависимости от уровня
if (toolLevel >= 1) displayMaterial = Material.WOODEN_SWORD; // Палки заменяются на деревянные инструменты после уровня 1
if (toolLevel >= 2) displayMaterial = Material.STONE_SWORD;  // Каменные инструменты после уровня 2
if (toolLevel >= 3) displayMaterial = Material.IRON_SWORD;
if (toolLevel >= 4) displayMaterial = Material.GOLDEN_SWORD;// Железные инструменты после уровня 3
if (toolLevel >= 5) displayMaterial = Material.DIAMOND_SWORD; // Алмазные инструменты после уровня 4
if (toolLevel >= 6) displayMaterial = Material.NETHERITE_SWORD;  // Незеритовые инструменты после уровня 5

// Для других инструментов
if (name.equals("Кирка")) {
if (toolLevel >= 1) displayMaterial = Material.WOODEN_PICKAXE;
if (toolLevel >= 2) displayMaterial = Material.STONE_PICKAXE;
if (toolLevel >= 3) displayMaterial = Material.IRON_PICKAXE;
if (toolLevel >= 4) displayMaterial = Material.GOLDEN_PICKAXE;
if (toolLevel >= 5) displayMaterial = Material.DIAMOND_PICKAXE;
if (toolLevel >= 6) displayMaterial = Material.NETHERITE_PICKAXE;
}

if (name.equals("Топор")) {
if (toolLevel >= 1) displayMaterial = Material.WOODEN_AXE;
if (toolLevel >= 2) displayMaterial = Material.STONE_AXE;
if (toolLevel >= 3) displayMaterial = Material.IRON_AXE;
if (toolLevel >= 4) displayMaterial = Material.GOLDEN_AXE;
if (toolLevel >= 5) displayMaterial = Material.DIAMOND_AXE;
if (toolLevel >= 6) displayMaterial = Material.NETHERITE_AXE;
}

if (name.equals("Лопата")) {
if (toolLevel >= 1) displayMaterial = Material.WOODEN_SHOVEL;
if (toolLevel >= 2) displayMaterial = Material.STONE_SHOVEL;
if (toolLevel >= 3) displayMaterial = Material.IRON_SHOVEL;
if (toolLevel >= 4) displayMaterial = Material.GOLDEN_SHOVEL;
if (toolLevel >= 5) displayMaterial = Material.DIAMOND_SHOVEL;
if (toolLevel >= 6) displayMaterial = Material.NETHERITE_SHOVEL;
}

if (name.equals("Мотыга")) {
if (toolLevel >= 1) displayMaterial = Material.WOODEN_HOE;
if (toolLevel >= 2) displayMaterial = Material.STONE_HOE;
if (toolLevel >= 3) displayMaterial = Material.IRON_HOE;
if (toolLevel >= 4) displayMaterial = Material.GOLDEN_HOE;
if (toolLevel >= 5) displayMaterial = Material.DIAMOND_HOE;
if (toolLevel >= 6) displayMaterial = Material.NETHERITE_HOE;
}

// Создаем предмет с информацией о текущем уровне и стоимости улучшения
ItemStack toolItem = createItem(displayMaterial, "§aУлучшить " + name,
"§7Текущий уровень: §e" + toolLevel,
toolCostMessage,
"§7Максимальный уровень: §e6");  // Максимальный уровень всегда 6

// Устанавливаем предмет в соответствующий слот
menu.setItem(slot, toolItem);
}

// Создание предмета
private ItemStack createItem(Material material, String name, String...  lore) {
ItemStack item = new ItemStack(material);
var meta = item.getItemMeta();
if (meta != null) {
meta.setDisplayName(name);
meta.setLore(java.util.Arrays.asList(lore));
item.setItemMeta(meta);
}
return item;
}

@EventHandler
public void onPlayerJoin(PlayerJoinEvent event) {
Player player = event.getPlayer();
// Загружаем данные о разблокированных слотах для игрока
barrierManager.loadUnlockedSlots(player);  // Убедитесь, что предметы восстановлены
barrierManager.lockInventory(player);
}

@EventHandler
public void onPlayerQuit(PlayerQuitEvent event) {
Player player = event.getPlayer();
// Save inventory for the player when they disconnect
barrierManager.saveUnlockedSlots();  // Save unlocked slots and items
}

@EventHandler
public void onInventoryClick(InventoryClickEvent event) {
if (event.getView().getTitle().equals("Меню навыков")) {
event.setCancelled(true); // Останавливаем стандартное поведение

if (event.getWhoClicked() instanceof Player player) {
ItemStack clickedItem = event.getCurrentItem();
if (clickedItem != null && clickedItem.hasItemMeta() && clickedItem.getItemMeta().hasDisplayName()) {
String itemName = clickedItem.getItemMeta().getDisplayName();
boolean upgraded = false;

// Обработка улучшения сердец
if (itemName.contains("Добавить сердце")) {
upgraded = heartUpgradeManager.upgradeHeart(player);
}
// Обработка улучшения устойчивости к воде
else if (itemName.contains("Устойчивость к воде")) {
upgraded = waterResistanceManager.upgradeWaterResistance(player);
}
// Обработка улучшения разблокировки слотов
else if (itemName.contains("Разблокировать слот инвентаря")) {
// Разблокировка слота
int unlockedSlots = barrierManager.getUnlockedSlots(player);
int unlockCost = (unlockedSlots + 1) * 5; // Стоимость увеличивается с каждым новым слотом

if (player.getLevel() < unlockCost) {
player.sendMessage("§cУ вас недостаточно опыта для разблокировки слота! Необходимо " + unlockCost + " уровней опыта.");
} else {
player.setLevel(player.getLevel() - unlockCost); // Снимаем опыт
barrierManager.unlockSlot(player);  // Разблокируем слот
upgraded = true;
}
}
// Обработка улучшения инструментов
else {
String[] toolNames = {"Меч", "Кирка", "Топор", "Лопата", "Мотыга"};
Material[] toolMaterials = {Material.STICK, Material.STICK, Material.STICK, Material.STICK, Material.STICK};

for (int i = 0; i < toolNames.length; i++) {
if (itemName.contains(toolNames[i])) {
upgraded = toolUsageManager.upgradeToolUsage(player, toolNames[i]);
break;
}
}
}

// Отправляем сообщение только если улучшение прошло успешно
if (upgraded) {
player.sendMessage("§aНавык улучшен!");
updateSkillsMenu(player, event.getInventory()); // Обновление меню
}
}
}
}
}

// Метод для обновления содержимого инвентаря без его закрытия
// Метод для обновления содержимого инвентаря без его закрытия
private void updateSkillsMenu(Player player, Inventory skillsMenu) {
skillsMenu.clear();

// Перерисовываем предметы
ItemStack regenPotion = createItem(Material.POTION, "§aДобавить сердце",
"§7Текущий уровень: §e" + heartUpgradeManager.getHeartUpgrades(player.getUniqueId()),
"§7Стоимость: §c"  + ((heartUpgradeManager.getHeartUpgrades(player.getUniqueId()) + 1) * 5) + " уровней опыта");

ItemStack waterResistanceItem = createItem(Material.WATER_BUCKET, "§aУстойчивость к воде",
"§7Текущий уровень: §e" + waterResistanceManager.getWaterResistance(player.getUniqueId()),
"§7Стоимость: §c" + ((waterResistanceManager.getWaterResistance(player.getUniqueId()) + 1) * 5) + " уровней опыта");

// Добавляем барьер для разблокировки слота инвентаря
// Обновленный предмет для разблокировки слота инвентаря с изменяющейся стоимостью
ItemStack barrierItem = createItem(Material.BARRIER, "§aРазблокировать слот инвентаря",
"§7Стоимость: §c" + ((barrierManager.getUnlockedSlots(player) + 1) * 5) + " уровней опыта", "§7Максимальный уровень: §e27");

// Добавляем инструменты
addToolUpgradeItem(skillsMenu, player, Material.STICK, "Меч", 3);
addToolUpgradeItem(skillsMenu, player, Material.STICK, "Кирка", 4);
addToolUpgradeItem(skillsMenu, player, Material.STICK, "Топор", 5);
addToolUpgradeItem(skillsMenu, player, Material.STICK, "Лопата", 6);
addToolUpgradeItem(skillsMenu, player, Material.STICK, "Мотыга", 7);

// Добавляем предметы в меню
skillsMenu.setItem(0, regenPotion);  // Добавляем предмет для улучшения сердец
skillsMenu.setItem(1, waterResistanceItem); // Добавляем предмет для устойчивости к воде
skillsMenu.setItem(2, barrierItem);  // Добавляем барьер для разблокировки слота инвентаря

player.updateInventory(); // Принудительное обновление инвентаря
}

@EventHandler
public void onPlayerMove(PlayerMoveEvent event) {
Player player = event.getPlayer();
if (player.isInWater()) {
int waterResistanceLevel = waterResistanceManager.getWaterResistance(player.getUniqueId());
double damage = Math.max(0, 1 - waterResistanceLevel * 0.1);
if (damage > 0) {
player.damage(damage);
}
}
}
}
< /code>
barriermanager.java
package ru.mopsland.pugSkills;

import org.bukkit.entity.Player;
import org.bukkit.Material;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerRespawnEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerDropItemEvent;

import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

public class BarrierManager implements Listener {

private final JavaPlugin plugin;
private final Map playerUnlockedSlots = new HashMap(); // Track unlocked slots for each player
private final Map playerSavedItems = new HashMap(); // Сохраняем предметы в разблокированных слотах для каждого игрока

public BarrierManager(JavaPlugin plugin) {
this.plugin = plugin;
plugin.getServer().getPluginManager().registerEvents(this, plugin);
}

// Метод для блокировки инвентаря и сохранения предметов
public void lockInventory(Player player) {
Inventory inventory = player.getInventory();

if (!playerSavedItems.containsKey(player.getUniqueId())) {
playerSavedItems.put(player.getUniqueId(), new HashMap());
}

// Блокируем все слоты от 9 до 35 с барьером
for (int i = 9; i < 36; i++) {
ItemStack barrierItem = new ItemStack(Material.BARRIER);
ItemMeta meta = barrierItem.getItemMeta();
if (meta != null) {
meta.setDisplayName("§cСлот заблокирован");
barrierItem.setItemMeta(meta);
}
inventory.setItem(i, barrierItem);
}

// Разблокируем слоты на основе данных
int unlockedSlots = playerUnlockedSlots.getOrDefault(player.getUniqueId(), 0);
for (int i = 0; i <  unlockedSlots; i++) {
Map savedItems = playerSavedItems.get(player.getUniqueId());
if (savedItems != null && savedItems.containsKey(9 + i)) {
ItemStack itemInSlot = savedItems.get(9 + i);
inventory.setItem(9 + i, itemInSlot); // Восстанавливаем предмет
plugin.getLogger().info("Предмет в разблокированном слоте: " + itemInSlot.getType() + " в слот " + (9 + i));
} else {
inventory.setItem(9 + i, new ItemStack(Material.AIR)); // Если нет предмета, ставим пустое место
}
}

player.updateInventory();
}

// Метод для разблокировки одного слота инвентаря
public void unlockSlot(Player player) {
int unlockedSlots = playerUnlockedSlots.getOrDefault(player.getUniqueId(), 0);

if (unlockedSlots >= 27) {
player.sendMessage("§cВы достигли максимального количества разблокированных слотов!");
return;
}

int unlockCost = (unlockedSlots + 1) * 5;

if (player.getLevel() < unlockCost) {
player.sendMessage("§cУ вас недостаточно опыта для разблокировки слота! Необходимо " + unlockCost + " уровней опыта.");
return;
}

playerUnlockedSlots.put(player.getUniqueId(), unlockedSlots + 1);
Inventory inventory = player.getInventory();

// Восстанавливаем предметы из сохраненной карты
Map savedItems = playerSavedItems.get(player.getUniqueId());
if (savedItems != null && savedItems.containsKey(9 + unlockedSlots)) {
ItemStack restoredItem = savedItems.get(9 + unlockedSlots);
inventory.setItem(9 + unlockedSlots, restoredItem); // Восстанавливаем предмет
plugin.getLogger().info("Восстановлен предмет в слот: " + (9 + unlockedSlots) + " - " + restoredItem.getType());
} else {
inventory.setItem(9 + unlockedSlots, new ItemStack(Material.AIR)); // Если нет предмета, ставим пустое место
}

// Сохраняем предмет в карту, если он в инвентаре
ItemStack itemInSlot = inventory.getItem(9 + unlockedSlots);
if (itemInSlot != null && itemInSlot.getType() != Material.AIR) {
if (savedItems == null) {
savedItems = new HashMap();
playerSavedItems.put(player.getUniqueId(), savedItems);
}
savedItems.put(9 + unlockedSlots, itemInSlot);
plugin.getLogger().info("Предмет в разблокированном слоте: " + itemInSlot.getType());
}

player.setLevel(player.getLevel() - unlockCost);
player.updateInventory();
saveUnlockedSlots(); // Сохраняем изменения
player.sendMessage("§aСлот инвентаря успешно разблокирован!");
}

// Метод для получения количества разблокированных слотов
public int getUnlockedSlots(Player player) {
return playerUnlockedSlots.getOrDefault(player.getUniqueId(), 0);
}

// Метод для сохранения разблокированных слотов и предметов
public void saveUnlockedSlots() {
FileConfiguration dataConfig = getDataConfig();
for (Map.Entry entry : playerUnlockedSlots.entrySet()) {
UUID uuid = entry.getKey();
int unlockedSlots = entry.getValue();
dataConfig.set("players." + uuid.toString() + ".unlockedSlots", unlockedSlots);

// Сохраняем предметы для каждого разблокированного слота
Map savedItems = playerSavedItems.get(uuid);
for (int i = 9; i < 9 + unlockedSlots; i++) {
if (savedItems != null && savedItems.containsKey(i)) {
ItemStack item = savedItems.get(i);
if (item != null && item.getType() != Material.AIR) {
dataConfig.set("players." + uuid.toString() + ".unlockedSlotsItems."  + i, item.serialize());
}
}
}
}
saveDataConfig(dataConfig);
}

public void loadUnlockedSlots(Player player) {
FileConfiguration dataConfig = getDataConfig();
if (!dataConfig.contains("players")) {
dataConfig.createSection("players");
}

for (String key : dataConfig.getConfigurationSection("players").getKeys(false)) {
UUID uuid = UUID.fromString(key);
int unlockedSlots = dataConfig.getInt("players." + key + ".unlockedSlots", 0);
playerUnlockedSlots.put(uuid, unlockedSlots);

Map savedItems = new HashMap();
for (int i = 9; i < 9 + unlockedSlots; i++) {
if (dataConfig.contains("players." + key + ".unlockedSlotsItems." + i)) {
Map itemData = dataConfig.getConfigurationSection("players." + key + ".unlockedSlotsItems." + i).getValues(false);
ItemStack item = ItemStack.deserialize(itemData);
if (item != null && item.getType() != Material.AIR) {
savedItems.put(i, item);
}
}
}
playerSavedItems.put(uuid, savedItems);
}

// Восстановление предметов в инвентаре
Inventory inventory = player.getInventory();
Map savedItems = playerSavedItems.get(player.getUniqueId());
if (savedItems != null) {
for (Map.Entry entry : savedItems.entrySet()) {
inventory.setItem(entry.getKey(), entry.getValue());
}
}
player.updateInventory();
}

// Получение конфигурации данных
private FileConfiguration getDataConfig() {
return YamlConfiguration.loadConfiguration(getDataFile());
}

// Получение файла данных
private File getDataFile() {
return new File(plugin.getDataFolder(), "datab.yml");
}

// Сохранение конфигурации данных
private void saveDataConfig(FileConfiguration config) {
try {
config.save(getDataFile());
} catch (Exception e) {
plugin.getLogger().warning("Failed to save datab.yml: " + e.getMessage());
}
}

// Обработка кликов по инвентарю
@EventHandler
public void onInventoryClick(InventoryClickEvent event) {
ItemStack clickedItem = event.getCurrentItem();

if (clickedItem != null && clickedItem.getType() == Material.BARRIER) {
if (event.getSlot() >= 9 && event.getSlot() < 36) { // Проверяем, что слот находится между 9 и 35
if (event.getCurrentItem().getItemMeta() != null &&
event.getCurrentItem().getItemMeta().getDisplayName().equals("§cСлот заблокирован")) {
event.setCancelled(true); // Запрещаем перемещение барьера
}
} else {
event.setCancelled(true); // Запрещаем перемещение барьера в слотах для рук
}
}
}

@EventHandler
public void onPlayerJoin(PlayerJoinEvent event) {
Player player = event.getPlayer();
// Загружаем данные о разблокированных слотах для игрока
loadUnlockedSlots(player);
this.lockInventory(player); // Вызываем lockInventory для блокировки инвентаря
}

@EventHandler
public void onPlayerRespawn(PlayerRespawnEvent event) {
Player player = event.getPlayer();
// Восстанавливаем барьеры после респауна
lockInventory(player);
}

// Запрещаем сбрасывать барьерные предметы
@EventHandler
public void onPlayerDrop(PlayerDropItemEvent event) {
if (event.getItemDrop().getItemStack().getType() == Material.BARRIER) {
if (event.getItemDrop().getItemStack().getItemMeta() != null &&
event.getItemDrop().getItemStack().getItemMeta().getDisplayName().equals("§cСлот заблокирован")) {
event.setCancelled(true); // Prevent dropping barrier items
}
}
}
}
или проблема в том, что в коде есть ошибки, которые предотвращают это?


Подробнее здесь: https://stackoverflow.com/questions/794 ... 1-4-plugin
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «JAVA»