diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 9fcc74c2..01227363 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -27,9 +27,8 @@ jobs: # Build remapped Spigot versions - uses: SpraxDev/Action-SpigotMC@v4 with: - versions: 1.18.2, 1.19, 1.19.2 + versions: 1.18, 1.18.2, 1.19, 1.19.2, 1.19.3 remapped: true - forceRun: true # Build project - name: Build with Maven diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml index e5e004ee..e8c2d392 100644 --- a/.github/workflows/sonarcloud.yml +++ b/.github/workflows/sonarcloud.yml @@ -38,7 +38,7 @@ jobs: # Build remapped Spigot versions - uses: SpraxDev/Action-SpigotMC@v4 with: - versions: 1.18.2, 1.19 + versions: 1.18, 1.18.2, 1.19, 1.19.2, 1.19.3 remapped: true - name: Analyze project diff --git a/Compatibility/pom.xml b/Compatibility/pom.xml index 10dff5ca..9dbba0e2 100644 --- a/Compatibility/pom.xml +++ b/Compatibility/pom.xml @@ -7,7 +7,7 @@ com.songoda SongodaCore-Modules - 2.6.16 + 2.6.18 ../pom.xml diff --git a/Compatibility/src/main/java/com/songoda/core/compatibility/ClassMapping.java b/Compatibility/src/main/java/com/songoda/core/compatibility/ClassMapping.java index 117dcc7b..4fe950f7 100644 --- a/Compatibility/src/main/java/com/songoda/core/compatibility/ClassMapping.java +++ b/Compatibility/src/main/java/com/songoda/core/compatibility/ClassMapping.java @@ -47,6 +47,7 @@ public enum ClassMapping { CRAFT_PLAYER("entity", "CraftPlayer"), CRAFT_WORLD("CraftWorld"), + SINGLE_THREADED_RANDOM_SOURCE("world.level.levelgen", "SingleThreadedRandomSource"), RANDOM_SOURCE("util", "RandomSource"), MOJANGSON_PARSER("nbt", "MojangsonParser"); diff --git a/Core/pom.xml b/Core/pom.xml index 81754cd5..857c5316 100644 --- a/Core/pom.xml +++ b/Core/pom.xml @@ -7,7 +7,7 @@ com.songoda SongodaCore-Modules - 2.6.16 + 2.6.18 ../pom.xml @@ -98,6 +98,18 @@ + + + + com.intellectualsites.bom + bom-1.18.x + 1.18 + import + pom + + + + org.spigotmc @@ -116,7 +128,7 @@ de.tr7zw item-nbt-api - 2.10.0 + 2.11.1 compile @@ -249,6 +261,12 @@ ${project.version} compile + + ${project.groupId} + SongodaCore-NMS-v1_19_R2 + ${project.version} + compile + @@ -311,7 +329,7 @@ com.songoda UltimateStacker - 2.1.1 + 2.3.2 provided @@ -371,6 +389,24 @@ provided + + com.plotsquared + PlotSquared-Core + provided + + + + com.plotsquared + PlotSquared-Bukkit + provided + + + PlotSquared-Core + * + + + + com.songoda UltimateClaims @@ -437,6 +473,12 @@ 3.2.0 + + org.mariadb.jdbc + mariadb-java-client + 3.0.8 + + org.xerial sqlite-jdbc diff --git a/Core/src/main/java/com/songoda/core/SongodaCore.java b/Core/src/main/java/com/songoda/core/SongodaCore.java index edd3421f..5d76a5f9 100644 --- a/Core/src/main/java/com/songoda/core/SongodaCore.java +++ b/Core/src/main/java/com/songoda/core/SongodaCore.java @@ -8,6 +8,8 @@ import com.songoda.core.core.PluginInfo; import com.songoda.core.core.PluginInfoModule; import com.songoda.core.core.SongodaCoreCommand; import com.songoda.core.core.SongodaCoreDiagCommand; +import com.songoda.core.core.SongodaCoreIPCommand; +import com.songoda.core.core.SongodaCoreUUIDCommand; import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; @@ -53,7 +55,7 @@ public class SongodaCore { /** * @since coreRevision 6 */ - private final static String coreVersion = "2.6.16"; + private final static String coreVersion = "2.6.18"; /** * This is specific to the website api @@ -172,7 +174,7 @@ public class SongodaCore { private void init() { shadingListener = new ShadedEventListener(); commandManager.registerCommandDynamically(new SongodaCoreCommand()) - .addSubCommand(new SongodaCoreDiagCommand()); + .addSubCommands(new SongodaCoreDiagCommand(), new SongodaCoreIPCommand(), new SongodaCoreUUIDCommand()); Bukkit.getPluginManager().registerEvents(loginListener, piggybackedPlugin); Bukkit.getPluginManager().registerEvents(shadingListener, piggybackedPlugin); diff --git a/Core/src/main/java/com/songoda/core/SongodaPlugin.java b/Core/src/main/java/com/songoda/core/SongodaPlugin.java index 8b700be9..2dbf598f 100644 --- a/Core/src/main/java/com/songoda/core/SongodaPlugin.java +++ b/Core/src/main/java/com/songoda/core/SongodaPlugin.java @@ -4,6 +4,7 @@ import com.songoda.core.configuration.Config; import com.songoda.core.database.DataManagerAbstract; import com.songoda.core.locale.Locale; import com.songoda.core.utils.Metrics; +import com.songoda.core.utils.SongodaAuth; import de.tr7zw.changeme.nbtapi.utils.MinecraftVersion; import org.bukkit.Bukkit; import org.bukkit.ChatColor; @@ -90,6 +91,25 @@ public abstract class SongodaPlugin extends JavaPlugin { return; } + //Check plugin access, don't load plugin if user don't have access + if (!SongodaAuth.isAuthorized(true)) { + Thread thread = new Thread(() -> { + console.sendMessage(ChatColor.RED + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); + console.sendMessage(ChatColor.RED + "You do not have access to this plugin."); + console.sendMessage(ChatColor.YELLOW + "Please purchase a license at https://sngda.to/marketplace"); + console.sendMessage(ChatColor.YELLOW + "or set up your license at https://sngda.to/licenses"); + console.sendMessage(ChatColor.YELLOW + "License setup steps:"); + console.sendMessage(ChatColor.YELLOW + "Visit the link mentioned above and click the 'Create License button'"); + console.sendMessage(ChatColor.YELLOW + "Copy the following ip and uuid and click create."); + console.sendMessage(ChatColor.YELLOW + "IP: " + SongodaAuth.getIP()); + console.sendMessage(ChatColor.YELLOW + "UUID: " + SongodaAuth.getUUID()); + console.sendMessage(ChatColor.RED + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); + }); + thread.start(); + emergencyStop(); + return; + } + console.sendMessage(" "); // blank line to separate chatter console.sendMessage(ChatColor.GREEN + "============================="); console.sendMessage(String.format("%s%s %s by %sSongoda <3!", ChatColor.GRAY, diff --git a/Core/src/main/java/com/songoda/core/core/SongodaCoreDiagCommand.java b/Core/src/main/java/com/songoda/core/core/SongodaCoreDiagCommand.java index 28ed2644..04c2a94b 100644 --- a/Core/src/main/java/com/songoda/core/core/SongodaCoreDiagCommand.java +++ b/Core/src/main/java/com/songoda/core/core/SongodaCoreDiagCommand.java @@ -20,7 +20,7 @@ public class SongodaCoreDiagCommand extends AbstractCommand { private Field tpsField; public SongodaCoreDiagCommand() { - super(false, "diag"); + super(CommandType.CONSOLE_OK, "diag"); try { serverInstance = ClassMapping.MINECRAFT_SERVER.getClazz().getMethod("getServer").invoke(null); diff --git a/Core/src/main/java/com/songoda/core/core/SongodaCoreIPCommand.java b/Core/src/main/java/com/songoda/core/core/SongodaCoreIPCommand.java new file mode 100644 index 00000000..6f0e8a8c --- /dev/null +++ b/Core/src/main/java/com/songoda/core/core/SongodaCoreIPCommand.java @@ -0,0 +1,73 @@ +package com.songoda.core.core; + +import com.songoda.core.commands.AbstractCommand; +import com.songoda.core.utils.SongodaAuth; +import net.md_5.bungee.api.chat.BaseComponent; +import net.md_5.bungee.api.chat.ClickEvent; +import net.md_5.bungee.api.chat.HoverEvent; +import net.md_5.bungee.api.chat.TextComponent; +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.impl.client.HttpClients; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; + +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.util.List; + +public class SongodaCoreIPCommand extends AbstractCommand { + + public SongodaCoreIPCommand() { + super(CommandType.CONSOLE_OK, "myip"); + } + + @Override + protected ReturnType runCommand(CommandSender sender, String... args) { + Thread thread = new Thread(() -> { + String ip = SongodaAuth.getIP(); + sender.sendMessage(""); + sender.sendMessage("IP Information"); + sender.sendMessage(""); + if (sender instanceof Player) { + TextComponent component = new TextComponent("Your public IP is: " + ip); + component.setClickEvent(new ClickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, ip)); + component.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new BaseComponent[]{new TextComponent("Click to copy")})); + sender.spigot().sendMessage(component); + } else { + sender.sendMessage("Your public IP is: " + ip); + } + sender.sendMessage(""); + }); + thread.start(); + + return ReturnType.SUCCESS; + } + + @Override + protected List onTab(CommandSender sender, String... args) { + return null; + } + + @Override + public String getPermissionNode() { + return "songoda.admin"; + } + + @Override + public String getSyntax() { + return "/songoda myip"; + } + + @Override + public String getDescription() { + return "Displays your public IP address."; + } +} diff --git a/Core/src/main/java/com/songoda/core/core/SongodaCoreUUIDCommand.java b/Core/src/main/java/com/songoda/core/core/SongodaCoreUUIDCommand.java new file mode 100644 index 00000000..0bcb10c6 --- /dev/null +++ b/Core/src/main/java/com/songoda/core/core/SongodaCoreUUIDCommand.java @@ -0,0 +1,55 @@ +package com.songoda.core.core; + +import com.songoda.core.commands.AbstractCommand; +import com.songoda.core.utils.SongodaAuth; +import net.md_5.bungee.api.chat.BaseComponent; +import net.md_5.bungee.api.chat.ClickEvent; +import net.md_5.bungee.api.chat.HoverEvent; +import net.md_5.bungee.api.chat.TextComponent; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.util.List; +import java.util.UUID; + +public class SongodaCoreUUIDCommand extends AbstractCommand { + + public SongodaCoreUUIDCommand() { + super(CommandType.CONSOLE_OK, "uuid"); + } + + @Override + protected ReturnType runCommand(CommandSender sender, String... args) { + sender.sendMessage(""); + if (sender instanceof Player) { + TextComponent component = new TextComponent("Your server UUID is: " + SongodaAuth.getUUID()); + component.setClickEvent(new ClickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, SongodaAuth.getUUID().toString())); + component.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new BaseComponent[]{new TextComponent("Click to copy")})); + sender.spigot().sendMessage(component); + } else { + sender.sendMessage("Your server UUID is: " + SongodaAuth.getUUID()); + } + sender.sendMessage(""); + return ReturnType.SUCCESS; + } + + @Override + protected List onTab(CommandSender sender, String... args) { + return null; + } + + @Override + public String getPermissionNode() { + return "songodacore.admin"; + } + + @Override + public String getSyntax() { + return "/songodacore uuid"; + } + + @Override + public String getDescription() { + return "Returns your server's uuid"; + } +} diff --git a/Core/src/main/java/com/songoda/core/database/DataManagerAbstract.java b/Core/src/main/java/com/songoda/core/database/DataManagerAbstract.java index c6fcf188..78435c7d 100644 --- a/Core/src/main/java/com/songoda/core/database/DataManagerAbstract.java +++ b/Core/src/main/java/com/songoda/core/database/DataManagerAbstract.java @@ -21,6 +21,7 @@ import java.util.function.Consumer; public class DataManagerAbstract { protected final DatabaseConnector databaseConnector; protected final Plugin plugin; + protected final DatabaseType type; protected final ExecutorService asyncPool = Executors.newSingleThreadExecutor(); @@ -30,6 +31,7 @@ public class DataManagerAbstract { public DataManagerAbstract(DatabaseConnector databaseConnector, Plugin plugin) { this.databaseConnector = databaseConnector; this.plugin = plugin; + this.type = databaseConnector.getType(); } /** @@ -196,4 +198,11 @@ public class DataManagerAbstract { }); }); } + + public String getSyntax(String string, DatabaseType type) { + if (this.type == type) { + return string; + } + return ""; + } } diff --git a/Core/src/main/java/com/songoda/core/database/DatabaseConnector.java b/Core/src/main/java/com/songoda/core/database/DatabaseConnector.java index 7d0c0ff2..2be85c25 100644 --- a/Core/src/main/java/com/songoda/core/database/DatabaseConnector.java +++ b/Core/src/main/java/com/songoda/core/database/DatabaseConnector.java @@ -31,4 +31,6 @@ public interface DatabaseConnector { } Connection getConnection(); + + DatabaseType getType(); } diff --git a/Core/src/main/java/com/songoda/core/database/DatabaseType.java b/Core/src/main/java/com/songoda/core/database/DatabaseType.java new file mode 100644 index 00000000..e7ac08d6 --- /dev/null +++ b/Core/src/main/java/com/songoda/core/database/DatabaseType.java @@ -0,0 +1,8 @@ +package com.songoda.core.database; + +public enum DatabaseType { + + MARIADB, + MYSQL, + SQLITE +} diff --git a/Core/src/main/java/com/songoda/core/database/MariaDBConnector.java b/Core/src/main/java/com/songoda/core/database/MariaDBConnector.java new file mode 100644 index 00000000..7a507a5c --- /dev/null +++ b/Core/src/main/java/com/songoda/core/database/MariaDBConnector.java @@ -0,0 +1,70 @@ +package com.songoda.core.database; + +import com.zaxxer.hikari.HikariConfig; +import com.zaxxer.hikari.HikariDataSource; +import org.bukkit.plugin.Plugin; + +import java.sql.Connection; +import java.sql.SQLException; + +public class MariaDBConnector implements DatabaseConnector { + + private final Plugin plugin; + private HikariDataSource hikari; + private boolean initializedSuccessfully; + + public MariaDBConnector(Plugin plugin, String hostname, int port, String database, String username, String password, boolean useSSL, int poolSize) { + this.plugin = plugin; + + plugin.getLogger().info("connecting to " + hostname + " : " + port); + + HikariConfig config = new HikariConfig(); + config.setJdbcUrl("jdbc:mariadb://" + hostname + ":" + port + "/" + database + "?useSSL=" + useSSL); + config.setUsername(username); + config.setPassword(password); + config.setMaximumPoolSize(poolSize); + + try { + this.hikari = new HikariDataSource(config); + this.initializedSuccessfully = true; + } catch (Exception ex) { + this.initializedSuccessfully = false; + } + } + + @Override + public boolean isInitialized() { + return this.initializedSuccessfully; + } + + @Override + public void closeConnection() { + this.hikari.close(); + } + + @Deprecated + @Override + public void connect(DatabaseConnector.ConnectionCallback callback) { + try (Connection connection = this.hikari.getConnection()) { + callback.accept(connection); + } catch (SQLException ex) { + this.plugin.getLogger().severe("An error occurred executing a MySQL query: " + ex.getMessage()); + ex.printStackTrace(); + } + } + + @Override + public Connection getConnection() { + try { + return this.hikari.getConnection(); + } catch (Exception ex) { + ex.printStackTrace(); + } + return null; + } + + @Override + public DatabaseType getType() { + return DatabaseType.MARIADB; + } +} diff --git a/Core/src/main/java/com/songoda/core/database/MySQLConnector.java b/Core/src/main/java/com/songoda/core/database/MySQLConnector.java index 1b2fe4c1..910c8836 100644 --- a/Core/src/main/java/com/songoda/core/database/MySQLConnector.java +++ b/Core/src/main/java/com/songoda/core/database/MySQLConnector.java @@ -61,4 +61,9 @@ public class MySQLConnector implements DatabaseConnector { } return null; } + + @Override + public DatabaseType getType() { + return DatabaseType.MYSQL; + } } diff --git a/Core/src/main/java/com/songoda/core/database/SQLiteConnector.java b/Core/src/main/java/com/songoda/core/database/SQLiteConnector.java index 2a777a49..6882e2c5 100644 --- a/Core/src/main/java/com/songoda/core/database/SQLiteConnector.java +++ b/Core/src/main/java/com/songoda/core/database/SQLiteConnector.java @@ -42,16 +42,8 @@ public class SQLiteConnector implements DatabaseConnector { @Deprecated @Override public void connect(ConnectionCallback callback) { - if (this.connection == null) { - try { - this.connection = DriverManager.getConnection(this.connectionString); - } catch (SQLException ex) { - this.plugin.getLogger().severe("An error occurred retrieving the SQLite database connection: " + ex.getMessage()); - } - } - try { - callback.accept(this.connection); + callback.accept(getConnection()); } catch (Exception ex) { this.plugin.getLogger().severe("An error occurred executing an SQLite query: " + ex.getMessage()); ex.printStackTrace(); @@ -73,4 +65,9 @@ public class SQLiteConnector implements DatabaseConnector { } return this.connection; } + + @Override + public DatabaseType getType() { + return DatabaseType.SQLITE; + } } diff --git a/Core/src/main/java/com/songoda/core/hooks/protection/PlotSquaredProtection.java b/Core/src/main/java/com/songoda/core/hooks/protection/PlotSquaredProtection.java new file mode 100644 index 00000000..e5c23d54 --- /dev/null +++ b/Core/src/main/java/com/songoda/core/hooks/protection/PlotSquaredProtection.java @@ -0,0 +1,43 @@ +package com.songoda.core.hooks.protection; + +import com.plotsquared.core.PlotAPI; +import com.plotsquared.core.PlotSquared; +import com.plotsquared.core.plot.PlotArea; +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.plugin.Plugin; + +public class PlotSquaredProtection extends Protection { + + PlotSquared plotSquared; + + public PlotSquaredProtection(Plugin plugin) { + super(plugin); + plotSquared = PlotSquared.get(); + } + + @Override + public String getName() { + return "PlotSquared"; + } + + @Override + public boolean isEnabled() { + return plotSquared != null; + } + + @Override + public boolean canPlace(Player player, Location location) { + return plotSquared.getPlotAreaManager().getApplicablePlotArea(com.plotsquared.core.location.Location.at(location.getWorld().getName(), (int) location.getX(), (int) location.getY(), (int) location.getZ())).getPlots().stream().anyMatch(p -> p.isAdded(player.getUniqueId())); + } + + @Override + public boolean canBreak(Player player, Location location) { + return plotSquared.getPlotAreaManager().getApplicablePlotArea(com.plotsquared.core.location.Location.at(location.getWorld().getName(), (int) location.getX(), (int) location.getY(), (int) location.getZ())).getPlots().stream().anyMatch(p -> p.isAdded(player.getUniqueId())); + } + + @Override + public boolean canInteract(Player player, Location location) { + return plotSquared.getPlotAreaManager().getApplicablePlotArea(com.plotsquared.core.location.Location.at(location.getWorld().getName(), (int) location.getX(), (int) location.getY(), (int) location.getZ())).getPlots().stream().anyMatch(p -> p.isAdded(player.getUniqueId())); + } +} diff --git a/Core/src/main/java/com/songoda/core/lootables/loot/DropUtils.java b/Core/src/main/java/com/songoda/core/lootables/loot/DropUtils.java index ebc5d03d..40f00351 100644 --- a/Core/src/main/java/com/songoda/core/lootables/loot/DropUtils.java +++ b/Core/src/main/java/com/songoda/core/lootables/loot/DropUtils.java @@ -1,9 +1,17 @@ package com.songoda.core.lootables.loot; +import com.bgsoftware.wildstacker.api.objects.StackedItem; +import com.songoda.core.SongodaCore; +import com.songoda.ultimatestacker.UltimateStacker; +import com.songoda.ultimatestacker.settings.Settings; import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.entity.EntityType; import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; import org.bukkit.event.entity.EntityDeathEvent; import org.bukkit.inventory.ItemStack; +import org.bukkit.loot.LootTable; import java.util.ArrayList; import java.util.List; @@ -63,20 +71,71 @@ public class DropUtils { } private static void dropItems(List items, EntityDeathEvent event) { - for (ItemStack item : items) { - event.getDrops().add(item); + if (SongodaCore.isRegistered("UltimateStacker")) { + List stacks = new ArrayList<>(); + int maxSize = Settings.MAX_STACK_ITEMS.getInt()-64; + for (ItemStack item : items) { + StackedItem stack = stacks.stream().filter(stackedItem -> stackedItem.getItem().getType() == item.getType()).findFirst().orElse(null); + if (stack == null) { + stacks.add(new StackedItem(item, item.getAmount())); + continue; + } + int newAmount = stack.getAmount() + item.getAmount(); + while (newAmount > maxSize) { + newAmount -= maxSize; + stacks.add(new StackedItem(item, maxSize)); + } + stack.setamount(newAmount); + } + Bukkit.getScheduler().runTask(UltimateStacker.getInstance(), () -> { + for (StackedItem stack : stacks) { + UltimateStacker.spawnStackedItem(stack.getItem(), stack.getAmount(), event.getEntity().getLocation()); + } + }); + return; } + event.getDrops().addAll(items); } private static void runCommands(LivingEntity entity, List commands) { - for (String command : commands) { - if (entity.getKiller() != null) { - command = command.replace("%player%", entity.getKiller().getName()); - } + Bukkit.getScheduler().runTask(SongodaCore.getHijackedPlugin(), () -> { + for (String command : commands) { + if (entity.getKiller() != null) { + command = command.replace("%player%", entity.getKiller().getName()); + } - if (!command.contains("%player%")) { - Bukkit.dispatchCommand(Bukkit.getConsoleSender(), command); + if (!command.contains("%player%")) { + Bukkit.dispatchCommand(Bukkit.getConsoleSender(), command); + } } + }); + + } + + private static class StackedItem { + + private final ItemStack item; + private int amount; + + public StackedItem(ItemStack item, int amount) { + this.item = item; + this.amount = amount; + } + + public Material getMaterial() { + return item.getType(); + } + + public ItemStack getItem() { + return item; + } + + public int getAmount() { + return amount; + } + + public void setamount(int amount) { + this.amount = amount; } } } diff --git a/Core/src/main/java/com/songoda/core/nms/NmsManager.java b/Core/src/main/java/com/songoda/core/nms/NmsManager.java index b895353a..24c4939e 100644 --- a/Core/src/main/java/com/songoda/core/nms/NmsManager.java +++ b/Core/src/main/java/com/songoda/core/nms/NmsManager.java @@ -129,18 +129,24 @@ public class NmsManager { world = new com.songoda.core.nms.v1_18_R2.world.WorldCoreImpl(); break; case "v1_19_R1": - if (bukkitVersion.endsWith(".0")) { + if (bukkitVersion.endsWith(".0") || bukkitVersion.equals("1.19")) { player = new com.songoda.core.nms.v1_19_R1.entity.NMSPlayerImpl(); anvil = new com.songoda.core.nms.v1_19_R1.anvil.AnvilCore(); nbt = new com.songoda.core.nms.v1_19_R1.nbt.NBTCoreImpl(); world = new com.songoda.core.nms.v1_19_R1.world.WorldCoreImpl(); - }else{ + } else { player = new com.songoda.core.nms.v1_19_R1v2.entity.NMSPlayerImpl(); anvil = new com.songoda.core.nms.v1_19_R1v2.anvil.AnvilCore(); nbt = new com.songoda.core.nms.v1_19_R1v2.nbt.NBTCoreImpl(); world = new com.songoda.core.nms.v1_19_R1v2.world.WorldCoreImpl(); } break; + case "v1_19_R2": + player = new com.songoda.core.nms.v1_19_R2.entity.NMSPlayerImpl(); + anvil = new com.songoda.core.nms.v1_19_R2.anvil.AnvilCore(); + nbt = new com.songoda.core.nms.v1_19_R2.nbt.NBTCoreImpl(); + world = new com.songoda.core.nms.v1_19_R2.world.WorldCoreImpl(); + break; default: Logger.getLogger(NmsManager.class.getName()).log(Level.SEVERE, "Failed to load NMS for this server version: version {0} not found", serverPackageVersion); diff --git a/Core/src/main/java/com/songoda/core/utils/ItemUtils.java b/Core/src/main/java/com/songoda/core/utils/ItemUtils.java index e86f389a..05ebf2c1 100644 --- a/Core/src/main/java/com/songoda/core/utils/ItemUtils.java +++ b/Core/src/main/java/com/songoda/core/utils/ItemUtils.java @@ -35,6 +35,7 @@ import java.util.Iterator; import java.util.List; import java.util.Random; import java.util.UUID; +import java.util.concurrent.ThreadLocalRandom; import java.util.logging.Level; import java.util.logging.Logger; import java.util.stream.Stream; @@ -82,6 +83,7 @@ public class ItemUtils { } private static Method methodAsBukkitCopy, methodAsNMSCopy, methodA; + private static Object randomInstance; static { try { @@ -90,17 +92,20 @@ public class ItemUtils { Class clazzCraftItemStack = ClassMapping.CRAFT_ITEM_STACK.getClazz(); methodAsBukkitCopy = clazzCraftItemStack.getMethod("asBukkitCopy", clazzItemStack); - methodAsNMSCopy = clazzCraftItemStack.getMethod("asNMSCopy", ItemStack.class); + methodAsNMSCopy = MethodMapping.CB_ITEM_STACK__AS_NMS_COPY.getMethod(clazzCraftItemStack); if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_19)) { Class clazzRandomSource = ClassMapping.RANDOM_SOURCE.getClazz(); methodA = clazzEnchantmentManager.getMethod("a", clazzRandomSource.getMethod("c").getReturnType(), clazzItemStack, int.class, boolean.class); - }else if (ServerVersion.isServerVersion(ServerVersion.V1_8)) { + randomInstance = ClassMapping.SINGLE_THREADED_RANDOM_SOURCE.getClazz().getConstructor(long.class).newInstance(ThreadLocalRandom.current().nextLong()); + } else if (ServerVersion.isServerVersion(ServerVersion.V1_8)) { methodA = clazzEnchantmentManager.getMethod("a", Random.class, clazzItemStack, int.class); + randomInstance = new Random(); } else { methodA = clazzEnchantmentManager.getMethod("a", Random.class, clazzItemStack, int.class, boolean.class); + randomInstance = new Random(); } - } catch (NoSuchMethodException ex) { + } catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException ex) { ex.printStackTrace(); } } @@ -109,10 +114,12 @@ public class ItemUtils { try { Object nmsItemStack = methodAsNMSCopy.invoke(null, item); - if (ServerVersion.isServerVersion(ServerVersion.V1_8)) { - nmsItemStack = methodA.invoke(null, new Random(), nmsItemStack, level); + if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_19)) { + nmsItemStack = methodA.invoke(null, randomInstance, nmsItemStack, level, false); + } else if (ServerVersion.isServerVersion(ServerVersion.V1_8)) { + nmsItemStack = methodA.invoke(null, randomInstance, nmsItemStack, level); } else { - nmsItemStack = methodA.invoke(null, new Random(), nmsItemStack, level, false); + nmsItemStack = methodA.invoke(null, randomInstance, nmsItemStack, level, false); } item = (ItemStack) methodAsBukkitCopy.invoke(null, nmsItemStack); diff --git a/Core/src/main/java/com/songoda/core/utils/SongodaAuth.java b/Core/src/main/java/com/songoda/core/utils/SongodaAuth.java new file mode 100644 index 00000000..e486d097 --- /dev/null +++ b/Core/src/main/java/com/songoda/core/utils/SongodaAuth.java @@ -0,0 +1,116 @@ +package com.songoda.core.utils; + +import com.songoda.core.commands.AbstractCommand; +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.impl.client.HttpClients; +import org.bukkit.Bukkit; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.math.BigInteger; +import java.net.HttpURLConnection; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.security.MessageDigest; +import java.util.Properties; +import java.util.UUID; + +public class SongodaAuth { + + public static boolean isAuthorized(boolean allowOffline) { + String productId = "%%__PLUGIN__%%"; + try { + Integer.parseInt(productId); + } catch (NumberFormatException e) { + //Self compiled, return true + return true; + } + UUID uuid = getUUID(); + try { + URL url = new URL("https://marketplace.songoda.com/api/v2/products/license/validate"); + HttpURLConnection con = (HttpURLConnection)url.openConnection(); + con.setRequestMethod("POST"); + con.setRequestProperty("Content-Type", "application/json"); + con.setRequestProperty("Accept", "application/json"); + con.setDoOutput(true); + String jsonInputString = "{\"product_id\":" + productId + ",\"license\":\"" + uuid + "\",\"user_id\":\"%%__USER__%%\"}"; + try(OutputStream os = con.getOutputStream()) { + byte[] input = jsonInputString.getBytes(StandardCharsets.UTF_8); + os.write(input, 0, input.length); + } + + try(BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream(), StandardCharsets.UTF_8))) { + StringBuilder response = new StringBuilder(); + String responseLine = null; + while ((responseLine = br.readLine()) != null) { + response.append(responseLine.trim()); + } + JSONObject jsonObject = (JSONObject) new JSONParser().parse(response.toString()); + if (jsonObject.get("error") != null) { + //Got an error, return false and print error + Bukkit.getLogger().warning("Error validating license: " + jsonObject.get("error")); + return false; + } else { + return (boolean) jsonObject.get("valid"); + } + } + } catch (Exception e) { + return allowOffline; + } + } + + public static UUID getUUID() { + File serverProperties = new File(new File("."),"server.properties"); + Properties prop = new Properties(); + try { + prop.load(new FileReader(serverProperties)); + String uuid = prop.getProperty("uuid"); + if (uuid == null || uuid.isEmpty()) { + UUID newUUID = UUID.randomUUID(); + prop.setProperty("uuid", newUUID.toString()); + prop.store(new FileWriter(serverProperties), null); + return newUUID; + } else { + return UUID.fromString(uuid); + } + } catch (Exception ex) { + throw new RuntimeException("Could not fetch UUID for server", ex); + } + } + + public static String getIP() { + try { + URL url = new URL("https://marketplace.songoda.com/api/v2/products/license/ip"); + HttpURLConnection con = (HttpURLConnection)url.openConnection(); + con.setRequestMethod("GET"); + con.setRequestProperty("Accept", "application/json"); + con.setDoOutput(true); + try(BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream(), StandardCharsets.UTF_8))) { + StringBuilder response = new StringBuilder(); + String responseLine = null; + while ((responseLine = br.readLine()) != null) { + response.append(responseLine.trim()); + } + JSONParser parser = new JSONParser(); + JSONObject jsonObject = (JSONObject) parser.parse(response.toString()); + return jsonObject.get("ip").toString(); + } + } catch (Exception ex) { + throw new RuntimeException("Could not fetch IP address", ex); + } + } +} diff --git a/NMS/NMS-API/pom.xml b/NMS/NMS-API/pom.xml index c242b25a..9f837d2a 100644 --- a/NMS/NMS-API/pom.xml +++ b/NMS/NMS-API/pom.xml @@ -7,7 +7,7 @@ com.songoda SongodaCore-Modules - 2.6.16 + 2.6.18 ../../pom.xml diff --git a/NMS/NMS-API/src/main/java/com/songoda/core/nms/world/WorldCore.java b/NMS/NMS-API/src/main/java/com/songoda/core/nms/world/WorldCore.java index 75da36f8..bf5256ff 100644 --- a/NMS/NMS-API/src/main/java/com/songoda/core/nms/world/WorldCore.java +++ b/NMS/NMS-API/src/main/java/com/songoda/core/nms/world/WorldCore.java @@ -18,7 +18,7 @@ public interface WorldCore { SWorld getWorld(World world); - BBaseSpawner getBaseSpawner(CreatureSpawner spawner) throws NoSuchFieldException, IllegalAccessException; + BBaseSpawner getBaseSpawner(CreatureSpawner spawner) throws ReflectiveOperationException; /** * Performs random ticks on a specific chunks. @@ -28,7 +28,7 @@ public interface WorldCore { * @param bukkitChunk The chunk to tick * @param tickAmount The number of blocks to tick per ChunkSection, normally referred to as randomTickSpeed */ - void randomTickChunk(Chunk bukkitChunk, int tickAmount) throws NoSuchFieldException, IllegalAccessException; + void randomTickChunk(Chunk bukkitChunk, int tickAmount) throws ReflectiveOperationException; /** * Ticks all inactive spawners in a specific chunk ignoring the minimum required players within a specific range.
@@ -37,7 +37,7 @@ public interface WorldCore { * @param chunk The chunk to tick the spawners in * @param amount The amount of ticks to execute for each spawner */ - default void tickInactiveSpawners(Chunk chunk, int amount) throws NoSuchFieldException, IllegalAccessException, InvocationTargetException { + default void tickInactiveSpawners(Chunk chunk, int amount) throws ReflectiveOperationException { if (amount <= 0) return; for (BlockState tileEntity : chunk.getTileEntities()) { diff --git a/NMS/NMS-v1_10_R1/pom.xml b/NMS/NMS-v1_10_R1/pom.xml index c84341db..236fb363 100644 --- a/NMS/NMS-v1_10_R1/pom.xml +++ b/NMS/NMS-v1_10_R1/pom.xml @@ -7,7 +7,7 @@ com.songoda SongodaCore-Modules - 2.6.16 + 2.6.18 ../../pom.xml diff --git a/NMS/NMS-v1_10_R1/src/main/java/com/songoda/core/nms/v1_10_R1/nbt/NBTEntityImpl.java b/NMS/NMS-v1_10_R1/src/main/java/com/songoda/core/nms/v1_10_R1/nbt/NBTEntityImpl.java index 101ea777..9290ec04 100644 --- a/NMS/NMS-v1_10_R1/src/main/java/com/songoda/core/nms/v1_10_R1/nbt/NBTEntityImpl.java +++ b/NMS/NMS-v1_10_R1/src/main/java/com/songoda/core/nms/v1_10_R1/nbt/NBTEntityImpl.java @@ -21,6 +21,7 @@ public class NBTEntityImpl extends NBTCompoundImpl implements NBTEntity { @Override public org.bukkit.entity.Entity spawn(Location location) { String entityType = getNBTObject("entity_type").asString(); + getKeys().remove("UUID"); Entity spawned = ItemMonsterEgg.spawnCreature( // Changed since 1.14 ((CraftWorld) location.getWorld()).getHandle(), diff --git a/NMS/NMS-v1_11_R1/pom.xml b/NMS/NMS-v1_11_R1/pom.xml index 06747819..f59cc539 100644 --- a/NMS/NMS-v1_11_R1/pom.xml +++ b/NMS/NMS-v1_11_R1/pom.xml @@ -7,7 +7,7 @@ com.songoda SongodaCore-Modules - 2.6.16 + 2.6.18 ../../pom.xml diff --git a/NMS/NMS-v1_11_R1/src/main/java/com/songoda/core/nms/v1_11_R1/nbt/NBTEntityImpl.java b/NMS/NMS-v1_11_R1/src/main/java/com/songoda/core/nms/v1_11_R1/nbt/NBTEntityImpl.java index 59dce207..081e56e6 100644 --- a/NMS/NMS-v1_11_R1/src/main/java/com/songoda/core/nms/v1_11_R1/nbt/NBTEntityImpl.java +++ b/NMS/NMS-v1_11_R1/src/main/java/com/songoda/core/nms/v1_11_R1/nbt/NBTEntityImpl.java @@ -22,6 +22,7 @@ public class NBTEntityImpl extends NBTCompoundImpl implements NBTEntity { @Override public org.bukkit.entity.Entity spawn(Location location) { String entityType = getNBTObject("entity_type").asString(); + getKeys().remove("UUID"); Entity spawned = ItemMonsterEgg.spawnCreature( // Changed since 1.14 ((CraftWorld) location.getWorld()).getHandle(), diff --git a/NMS/NMS-v1_12_R1/pom.xml b/NMS/NMS-v1_12_R1/pom.xml index dc6a06c8..fcc3fa2c 100644 --- a/NMS/NMS-v1_12_R1/pom.xml +++ b/NMS/NMS-v1_12_R1/pom.xml @@ -7,7 +7,7 @@ com.songoda SongodaCore-Modules - 2.6.16 + 2.6.18 ../../pom.xml diff --git a/NMS/NMS-v1_12_R1/src/main/java/com/songoda/core/nms/v1_12_R1/nbt/NBTEntityImpl.java b/NMS/NMS-v1_12_R1/src/main/java/com/songoda/core/nms/v1_12_R1/nbt/NBTEntityImpl.java index 45aa80f4..16b499f7 100644 --- a/NMS/NMS-v1_12_R1/src/main/java/com/songoda/core/nms/v1_12_R1/nbt/NBTEntityImpl.java +++ b/NMS/NMS-v1_12_R1/src/main/java/com/songoda/core/nms/v1_12_R1/nbt/NBTEntityImpl.java @@ -22,6 +22,7 @@ public class NBTEntityImpl extends NBTCompoundImpl implements NBTEntity { @Override public org.bukkit.entity.Entity spawn(Location location) { String entityType = getNBTObject("entity_type").asString(); + getKeys().remove("UUID"); Entity spawned = ItemMonsterEgg.spawnCreature( // Changed since 1.14 ((CraftWorld) location.getWorld()).getHandle(), diff --git a/NMS/NMS-v1_13_R1/pom.xml b/NMS/NMS-v1_13_R1/pom.xml index cba76fb4..c933b9e4 100644 --- a/NMS/NMS-v1_13_R1/pom.xml +++ b/NMS/NMS-v1_13_R1/pom.xml @@ -7,7 +7,7 @@ com.songoda SongodaCore-Modules - 2.6.16 + 2.6.18 ../../pom.xml diff --git a/NMS/NMS-v1_13_R1/src/main/java/com/songoda/core/nms/v1_13_R1/nbt/NBTEntityImpl.java b/NMS/NMS-v1_13_R1/src/main/java/com/songoda/core/nms/v1_13_R1/nbt/NBTEntityImpl.java index ded0cccb..c5794391 100644 --- a/NMS/NMS-v1_13_R1/src/main/java/com/songoda/core/nms/v1_13_R1/nbt/NBTEntityImpl.java +++ b/NMS/NMS-v1_13_R1/src/main/java/com/songoda/core/nms/v1_13_R1/nbt/NBTEntityImpl.java @@ -24,6 +24,7 @@ public class NBTEntityImpl extends NBTCompoundImpl implements NBTEntity { @Override public org.bukkit.entity.Entity spawn(Location location) { String entityType = getNBTObject("entity_type").asString(); + getKeys().remove("UUID"); Optional> optionalEntity = Optional.ofNullable(EntityTypes.a(entityType)); // Changed since 1.13.2 if (optionalEntity.isPresent()) { diff --git a/NMS/NMS-v1_13_R2/pom.xml b/NMS/NMS-v1_13_R2/pom.xml index f230ae59..52d6a1f0 100644 --- a/NMS/NMS-v1_13_R2/pom.xml +++ b/NMS/NMS-v1_13_R2/pom.xml @@ -7,7 +7,7 @@ com.songoda SongodaCore-Modules - 2.6.16 + 2.6.18 ../../pom.xml diff --git a/NMS/NMS-v1_13_R2/src/main/java/com/songoda/core/nms/v1_13_R2/nbt/NBTEntityImpl.java b/NMS/NMS-v1_13_R2/src/main/java/com/songoda/core/nms/v1_13_R2/nbt/NBTEntityImpl.java index 58192c92..d43c78eb 100644 --- a/NMS/NMS-v1_13_R2/src/main/java/com/songoda/core/nms/v1_13_R2/nbt/NBTEntityImpl.java +++ b/NMS/NMS-v1_13_R2/src/main/java/com/songoda/core/nms/v1_13_R2/nbt/NBTEntityImpl.java @@ -24,6 +24,7 @@ public class NBTEntityImpl extends NBTCompoundImpl implements NBTEntity { @Override public org.bukkit.entity.Entity spawn(Location location) { String entityType = getNBTObject("entity_type").asString(); + getKeys().remove("UUID"); Optional> optionalEntity = Optional.ofNullable(EntityTypes.a(entityType)); // Changed since 1.13.2 if (optionalEntity.isPresent()) { diff --git a/NMS/NMS-v1_14_R1/pom.xml b/NMS/NMS-v1_14_R1/pom.xml index 804e8a9a..2263f18a 100644 --- a/NMS/NMS-v1_14_R1/pom.xml +++ b/NMS/NMS-v1_14_R1/pom.xml @@ -7,7 +7,7 @@ com.songoda SongodaCore-Modules - 2.6.16 + 2.6.18 ../../pom.xml diff --git a/NMS/NMS-v1_14_R1/src/main/java/com/songoda/core/nms/v1_14_R1/nbt/NBTEntityImpl.java b/NMS/NMS-v1_14_R1/src/main/java/com/songoda/core/nms/v1_14_R1/nbt/NBTEntityImpl.java index 8a272a67..d1e42d56 100644 --- a/NMS/NMS-v1_14_R1/src/main/java/com/songoda/core/nms/v1_14_R1/nbt/NBTEntityImpl.java +++ b/NMS/NMS-v1_14_R1/src/main/java/com/songoda/core/nms/v1_14_R1/nbt/NBTEntityImpl.java @@ -24,6 +24,7 @@ public class NBTEntityImpl extends NBTCompoundImpl implements NBTEntity { @Override public org.bukkit.entity.Entity spawn(Location location) { String entityType = getNBTObject("entity_type").asString(); + getKeys().remove("UUID"); Optional> optionalEntity = EntityTypes.a(entityType); if (optionalEntity.isPresent()) { diff --git a/NMS/NMS-v1_15_R1/pom.xml b/NMS/NMS-v1_15_R1/pom.xml index 696b50a0..5a7e4774 100644 --- a/NMS/NMS-v1_15_R1/pom.xml +++ b/NMS/NMS-v1_15_R1/pom.xml @@ -7,7 +7,7 @@ com.songoda SongodaCore-Modules - 2.6.16 + 2.6.18 ../../pom.xml diff --git a/NMS/NMS-v1_16_R1/pom.xml b/NMS/NMS-v1_16_R1/pom.xml index f101eb83..a94664ea 100644 --- a/NMS/NMS-v1_16_R1/pom.xml +++ b/NMS/NMS-v1_16_R1/pom.xml @@ -7,7 +7,7 @@ com.songoda SongodaCore-Modules - 2.6.16 + 2.6.18 ../../pom.xml diff --git a/NMS/NMS-v1_16_R1/src/main/java/com/songoda/core/nms/v1_16_R1/nbt/NBTEntityImpl.java b/NMS/NMS-v1_16_R1/src/main/java/com/songoda/core/nms/v1_16_R1/nbt/NBTEntityImpl.java index 2c29f250..6e88a4a2 100644 --- a/NMS/NMS-v1_16_R1/src/main/java/com/songoda/core/nms/v1_16_R1/nbt/NBTEntityImpl.java +++ b/NMS/NMS-v1_16_R1/src/main/java/com/songoda/core/nms/v1_16_R1/nbt/NBTEntityImpl.java @@ -24,6 +24,7 @@ public class NBTEntityImpl extends NBTCompoundImpl implements NBTEntity { @Override public org.bukkit.entity.Entity spawn(Location location) { String entityType = getNBTObject("entity_type").asString(); + getKeys().remove("UUID"); Optional> optionalEntity = EntityTypes.a(entityType); if (optionalEntity.isPresent()) { diff --git a/NMS/NMS-v1_16_R2/pom.xml b/NMS/NMS-v1_16_R2/pom.xml index 96bb63fa..99b7080b 100644 --- a/NMS/NMS-v1_16_R2/pom.xml +++ b/NMS/NMS-v1_16_R2/pom.xml @@ -7,7 +7,7 @@ com.songoda SongodaCore-Modules - 2.6.16 + 2.6.18 ../../pom.xml diff --git a/NMS/NMS-v1_16_R2/src/main/java/com/songoda/core/nms/v1_16_R2/nbt/NBTEntityImpl.java b/NMS/NMS-v1_16_R2/src/main/java/com/songoda/core/nms/v1_16_R2/nbt/NBTEntityImpl.java index 504b3ec5..1258ef25 100644 --- a/NMS/NMS-v1_16_R2/src/main/java/com/songoda/core/nms/v1_16_R2/nbt/NBTEntityImpl.java +++ b/NMS/NMS-v1_16_R2/src/main/java/com/songoda/core/nms/v1_16_R2/nbt/NBTEntityImpl.java @@ -24,6 +24,7 @@ public class NBTEntityImpl extends NBTCompoundImpl implements NBTEntity { @Override public org.bukkit.entity.Entity spawn(Location location) { String entityType = getNBTObject("entity_type").asString(); + getKeys().remove("UUID"); Optional> optionalEntity = EntityTypes.a(entityType); if (optionalEntity.isPresent()) { diff --git a/NMS/NMS-v1_16_R3/pom.xml b/NMS/NMS-v1_16_R3/pom.xml index 7069f4a6..3108af55 100644 --- a/NMS/NMS-v1_16_R3/pom.xml +++ b/NMS/NMS-v1_16_R3/pom.xml @@ -7,7 +7,7 @@ com.songoda SongodaCore-Modules - 2.6.16 + 2.6.18 ../../pom.xml diff --git a/NMS/NMS-v1_16_R3/src/main/java/com/songoda/core/nms/v1_16_R3/nbt/NBTEntityImpl.java b/NMS/NMS-v1_16_R3/src/main/java/com/songoda/core/nms/v1_16_R3/nbt/NBTEntityImpl.java index de9202e4..d3383570 100644 --- a/NMS/NMS-v1_16_R3/src/main/java/com/songoda/core/nms/v1_16_R3/nbt/NBTEntityImpl.java +++ b/NMS/NMS-v1_16_R3/src/main/java/com/songoda/core/nms/v1_16_R3/nbt/NBTEntityImpl.java @@ -24,6 +24,7 @@ public class NBTEntityImpl extends NBTCompoundImpl implements NBTEntity { @Override public org.bukkit.entity.Entity spawn(Location location) { String entityType = getNBTObject("entity_type").asString(); + getKeys().remove("UUID"); Optional> optionalEntity = EntityTypes.a(entityType); if (optionalEntity.isPresent()) { diff --git a/NMS/NMS-v1_17_R1/pom.xml b/NMS/NMS-v1_17_R1/pom.xml index 10b7af90..74182a43 100644 --- a/NMS/NMS-v1_17_R1/pom.xml +++ b/NMS/NMS-v1_17_R1/pom.xml @@ -7,7 +7,7 @@ com.songoda SongodaCore-Modules - 2.6.16 + 2.6.18 ../../pom.xml diff --git a/NMS/NMS-v1_17_R1/src/main/java/com/songoda/core/nms/v1_17_R1/nbt/NBTEntityImpl.java b/NMS/NMS-v1_17_R1/src/main/java/com/songoda/core/nms/v1_17_R1/nbt/NBTEntityImpl.java index 1ec46246..797e5fe8 100644 --- a/NMS/NMS-v1_17_R1/src/main/java/com/songoda/core/nms/v1_17_R1/nbt/NBTEntityImpl.java +++ b/NMS/NMS-v1_17_R1/src/main/java/com/songoda/core/nms/v1_17_R1/nbt/NBTEntityImpl.java @@ -24,6 +24,7 @@ public class NBTEntityImpl extends NBTCompoundImpl implements NBTEntity { @Override public org.bukkit.entity.Entity spawn(Location location) { String entityType = getNBTObject("entity_type").asString(); + getKeys().remove("UUID"); Optional> optionalEntity = EntityTypes.a(entityType); if (optionalEntity.isPresent()) { diff --git a/NMS/NMS-v1_18_R1/pom.xml b/NMS/NMS-v1_18_R1/pom.xml index 46303b82..c2523f17 100644 --- a/NMS/NMS-v1_18_R1/pom.xml +++ b/NMS/NMS-v1_18_R1/pom.xml @@ -19,23 +19,31 @@ com.songoda SongodaCore-Modules - 2.6.16 + 2.6.18 ../../pom.xml 17 17 + + 1.18-R0.1-SNAPSHOT SongodaCore-NMS-v1_18_R1 jar + + org.spigotmc + spigot-api + ${nms.ver} + provided + org.spigotmc spigot - 1.18 + 1.18-R0.1-SNAPSHOT provided diff --git a/NMS/NMS-v1_18_R1/src/main/java/com/songoda/core/nms/v1_18_R1/nbt/NBTEntityImpl.java b/NMS/NMS-v1_18_R1/src/main/java/com/songoda/core/nms/v1_18_R1/nbt/NBTEntityImpl.java index c8d7faee..7666db2d 100644 --- a/NMS/NMS-v1_18_R1/src/main/java/com/songoda/core/nms/v1_18_R1/nbt/NBTEntityImpl.java +++ b/NMS/NMS-v1_18_R1/src/main/java/com/songoda/core/nms/v1_18_R1/nbt/NBTEntityImpl.java @@ -24,6 +24,7 @@ public class NBTEntityImpl extends NBTCompoundImpl implements NBTEntity { @Override public org.bukkit.entity.Entity spawn(Location location) { String entityType = getNBTObject("entity_type").asString(); + getKeys().remove("UUID"); Optional> optionalEntity = EntityTypes.a(entityType); if (optionalEntity.isPresent()) { diff --git a/NMS/NMS-v1_18_R2/pom.xml b/NMS/NMS-v1_18_R2/pom.xml index eaa8147a..521397c0 100644 --- a/NMS/NMS-v1_18_R2/pom.xml +++ b/NMS/NMS-v1_18_R2/pom.xml @@ -60,7 +60,7 @@ com.songoda SongodaCore-Modules - 2.6.16 + 2.6.18 ../../pom.xml diff --git a/NMS/NMS-v1_18_R2/src/main/java/com/songoda/core/nms/v1_18_R2/nbt/NBTEntityImpl.java b/NMS/NMS-v1_18_R2/src/main/java/com/songoda/core/nms/v1_18_R2/nbt/NBTEntityImpl.java index cbbca061..797149fa 100644 --- a/NMS/NMS-v1_18_R2/src/main/java/com/songoda/core/nms/v1_18_R2/nbt/NBTEntityImpl.java +++ b/NMS/NMS-v1_18_R2/src/main/java/com/songoda/core/nms/v1_18_R2/nbt/NBTEntityImpl.java @@ -24,6 +24,7 @@ public class NBTEntityImpl extends NBTCompoundImpl implements NBTEntity { @Override public org.bukkit.entity.Entity spawn(Location location) { String entityType = getNBTObject("entity_type").asString(); + getKeys().remove("UUID"); Optional> optionalEntity = EntityType.byString(entityType); if (optionalEntity.isPresent()) { diff --git a/NMS/NMS-v1_19_R1/pom.xml b/NMS/NMS-v1_19_R1/pom.xml index 760111c5..f67d44b6 100644 --- a/NMS/NMS-v1_19_R1/pom.xml +++ b/NMS/NMS-v1_19_R1/pom.xml @@ -60,7 +60,7 @@ com.songoda SongodaCore-Modules - 2.6.16 + 2.6.18 ../../pom.xml diff --git a/NMS/NMS-v1_19_R1/src/main/java/com/songoda/core/nms/v1_19_R1/nbt/NBTEntityImpl.java b/NMS/NMS-v1_19_R1/src/main/java/com/songoda/core/nms/v1_19_R1/nbt/NBTEntityImpl.java index 3c768325..04fe3939 100644 --- a/NMS/NMS-v1_19_R1/src/main/java/com/songoda/core/nms/v1_19_R1/nbt/NBTEntityImpl.java +++ b/NMS/NMS-v1_19_R1/src/main/java/com/songoda/core/nms/v1_19_R1/nbt/NBTEntityImpl.java @@ -24,6 +24,7 @@ public class NBTEntityImpl extends NBTCompoundImpl implements NBTEntity { @Override public org.bukkit.entity.Entity spawn(Location location) { String entityType = getNBTObject("entity_type").asString(); + getKeys().remove("UUID"); Optional> optionalEntity = EntityType.byString(entityType); if (optionalEntity.isPresent()) { diff --git a/NMS/NMS-v1_19_R1/src/main/java/com/songoda/core/nms/v1_19_R1/world/SWorldImpl.java b/NMS/NMS-v1_19_R1/src/main/java/com/songoda/core/nms/v1_19_R1/world/SWorldImpl.java index 0706be94..d04a5e36 100644 --- a/NMS/NMS-v1_19_R1/src/main/java/com/songoda/core/nms/v1_19_R1/world/SWorldImpl.java +++ b/NMS/NMS-v1_19_R1/src/main/java/com/songoda/core/nms/v1_19_R1/world/SWorldImpl.java @@ -23,7 +23,7 @@ public class SWorldImpl implements SWorld { List result = new ArrayList<>(); ServerLevel worldServer = ((CraftWorld) world).getHandle(); - LevelEntityGetter entities = worldServer.entityManager.getEntityGetter(); + LevelEntityGetter entities = worldServer.getEntities(); entities.getAll().forEach((mcEnt) -> { org.bukkit.entity.Entity bukkitEntity = mcEnt.getBukkitEntity(); diff --git a/NMS/NMS-v1_19_R1v2/pom.xml b/NMS/NMS-v1_19_R1v2/pom.xml index f4bc6f69..f86f796c 100644 --- a/NMS/NMS-v1_19_R1v2/pom.xml +++ b/NMS/NMS-v1_19_R1v2/pom.xml @@ -60,7 +60,7 @@ com.songoda SongodaCore-Modules - 2.6.16 + 2.6.18 ../../pom.xml diff --git a/NMS/NMS-v1_19_R1v2/src/main/java/com/songoda/core/nms/v1_19_R1v2/nbt/NBTEntityImpl.java b/NMS/NMS-v1_19_R1v2/src/main/java/com/songoda/core/nms/v1_19_R1v2/nbt/NBTEntityImpl.java index cdc9c36b..cb9a39e4 100644 --- a/NMS/NMS-v1_19_R1v2/src/main/java/com/songoda/core/nms/v1_19_R1v2/nbt/NBTEntityImpl.java +++ b/NMS/NMS-v1_19_R1v2/src/main/java/com/songoda/core/nms/v1_19_R1v2/nbt/NBTEntityImpl.java @@ -24,6 +24,7 @@ public class NBTEntityImpl extends NBTCompoundImpl implements NBTEntity { @Override public org.bukkit.entity.Entity spawn(Location location) { String entityType = getNBTObject("entity_type").asString(); + getKeys().remove("UUID"); Optional> optionalEntity = EntityType.byString(entityType); if (optionalEntity.isPresent()) { diff --git a/NMS/NMS-v1_19_R1v2/src/main/java/com/songoda/core/nms/v1_19_R1v2/world/SWorldImpl.java b/NMS/NMS-v1_19_R1v2/src/main/java/com/songoda/core/nms/v1_19_R1v2/world/SWorldImpl.java index b4944be1..7ca2e85c 100644 --- a/NMS/NMS-v1_19_R1v2/src/main/java/com/songoda/core/nms/v1_19_R1v2/world/SWorldImpl.java +++ b/NMS/NMS-v1_19_R1v2/src/main/java/com/songoda/core/nms/v1_19_R1v2/world/SWorldImpl.java @@ -23,7 +23,7 @@ public class SWorldImpl implements SWorld { List result = new ArrayList<>(); ServerLevel worldServer = ((CraftWorld) world).getHandle(); - LevelEntityGetter entities = worldServer.entityManager.getEntityGetter(); + LevelEntityGetter entities = worldServer.getEntities(); entities.getAll().forEach((mcEnt) -> { org.bukkit.entity.Entity bukkitEntity = mcEnt.getBukkitEntity(); diff --git a/NMS/NMS-v1_19_R2/pom.xml b/NMS/NMS-v1_19_R2/pom.xml new file mode 100644 index 00000000..5f72ec24 --- /dev/null +++ b/NMS/NMS-v1_19_R2/pom.xml @@ -0,0 +1,105 @@ + + + 4.0.0 + + + + + org.apache.maven.plugins + maven-compiler-plugin + + ${java.version} + ${java.version} + + ${java.release} + + + + + net.md-5 + specialsource-maven-plugin + 1.2.4 + + + + remap-obf + package + + remap + + + + org.spigotmc:minecraft-server:${nms.ver}:txt:maps-mojang + true + org.spigotmc:spigot:${nms.ver}:jar:remapped-mojang + true + remapped-obf + + + + + remap-spigot + package + + remap + + + + ${project.build.directory}/${project.artifactId}-${project.version}-remapped-obf.jar + org.spigotmc:minecraft-server:${nms.ver}:csrg:maps-spigot + org.spigotmc:spigot:${nms.ver}:jar:remapped-obf + + + + + + + + + com.songoda + SongodaCore-Modules + 2.6.18 + ../../pom.xml + + + + 17 + 17 + + 1.19.3-R0.1-SNAPSHOT + + + SongodaCore-NMS-v1_19_R2 + jar + + + + org.spigotmc + spigot-api + ${nms.ver} + provided + + + + org.spigotmc + spigot + ${nms.ver} + provided + remapped-mojang + + + + ${project.groupId} + SongodaCore-NMS-API + ${project.version} + + + + ${project.groupId} + SongodaCore-Compatibility + ${project.version} + + + diff --git a/NMS/NMS-v1_19_R2/src/main/java/com/songoda/core/nms/v1_19_R2/anvil/AnvilCore.java b/NMS/NMS-v1_19_R2/src/main/java/com/songoda/core/nms/v1_19_R2/anvil/AnvilCore.java new file mode 100644 index 00000000..66ef90a6 --- /dev/null +++ b/NMS/NMS-v1_19_R2/src/main/java/com/songoda/core/nms/v1_19_R2/anvil/AnvilCore.java @@ -0,0 +1,21 @@ +package com.songoda.core.nms.v1_19_R2.anvil; + +import com.songoda.core.nms.anvil.CustomAnvil; +import net.minecraft.server.level.ServerPlayer; +import org.bukkit.craftbukkit.v1_19_R2.entity.CraftPlayer; +import org.bukkit.entity.Player; +import org.bukkit.inventory.InventoryHolder; + +public class AnvilCore implements com.songoda.core.nms.anvil.AnvilCore { + @Override + public CustomAnvil createAnvil(Player player) { + ServerPlayer p = ((CraftPlayer) player).getHandle(); + return new AnvilView(p.nextContainerCounter(), p, null); + } + + @Override + public CustomAnvil createAnvil(Player player, InventoryHolder holder) { + ServerPlayer p = ((CraftPlayer) player).getHandle(); + return new AnvilView(p.nextContainerCounter(), p, holder); + } +} diff --git a/NMS/NMS-v1_19_R2/src/main/java/com/songoda/core/nms/v1_19_R2/anvil/AnvilInventoryCustom.java b/NMS/NMS-v1_19_R2/src/main/java/com/songoda/core/nms/v1_19_R2/anvil/AnvilInventoryCustom.java new file mode 100644 index 00000000..e084ad4d --- /dev/null +++ b/NMS/NMS-v1_19_R2/src/main/java/com/songoda/core/nms/v1_19_R2/anvil/AnvilInventoryCustom.java @@ -0,0 +1,22 @@ +package com.songoda.core.nms.v1_19_R2.anvil; + +import net.minecraft.world.Container; +import net.minecraft.world.inventory.AnvilMenu; +import org.bukkit.Location; +import org.bukkit.craftbukkit.v1_19_R2.inventory.CraftInventoryAnvil; +import org.bukkit.inventory.InventoryHolder; + +public class AnvilInventoryCustom extends CraftInventoryAnvil { + final InventoryHolder holder; + + public AnvilInventoryCustom(InventoryHolder holder, Location location, Container inventory, Container resultInventory, AnvilMenu container) { + super(location, inventory, resultInventory, container); + + this.holder = holder; + } + + @Override + public InventoryHolder getHolder() { + return holder; + } +} diff --git a/NMS/NMS-v1_19_R2/src/main/java/com/songoda/core/nms/v1_19_R2/anvil/AnvilView.java b/NMS/NMS-v1_19_R2/src/main/java/com/songoda/core/nms/v1_19_R2/anvil/AnvilView.java new file mode 100644 index 00000000..4ec10d7c --- /dev/null +++ b/NMS/NMS-v1_19_R2/src/main/java/com/songoda/core/nms/v1_19_R2/anvil/AnvilView.java @@ -0,0 +1,216 @@ +package com.songoda.core.nms.v1_19_R2.anvil; + +import com.songoda.core.nms.anvil.CustomAnvil; +import com.songoda.core.nms.anvil.methods.AnvilTextChange; +import net.md_5.bungee.api.chat.TranslatableComponent; +import net.minecraft.core.BlockPos; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.network.chat.contents.TranslatableContents; +import net.minecraft.network.protocol.game.ClientboundOpenScreenPacket; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.Container; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.inventory.AnvilMenu; +import net.minecraft.world.inventory.ContainerLevelAccess; +import net.minecraft.world.inventory.ItemCombinerMenu; +import net.minecraft.world.inventory.MenuType; +import org.bukkit.Location; +import org.bukkit.craftbukkit.v1_19_R2.inventory.CraftInventoryView; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.InventoryHolder; +import org.bukkit.inventory.ItemStack; + +import java.lang.reflect.Field; +import java.util.logging.Level; +import java.util.logging.Logger; + +public class AnvilView extends AnvilMenu implements CustomAnvil { + private final ServerPlayer entity; + private final Inventory inventory; + private String customTitle = "Repairing"; + private int cost = -1; + private boolean canUse = true; + private AnvilTextChange textChange; + + // used for setting custom inventory + static Field mc_ContainerAnvil_repairInventory; // subcontainer with only the result + static Field mc_ContainerAnvil_resultInventory; // full inventory + static Field mc_ContainerAnvil_bukkitEntity; + + static { + try { + mc_ContainerAnvil_repairInventory = ItemCombinerMenu.class.getDeclaredField("p"); + mc_ContainerAnvil_repairInventory.setAccessible(true); + + mc_ContainerAnvil_resultInventory = ItemCombinerMenu.class.getDeclaredField("o"); + mc_ContainerAnvil_resultInventory.setAccessible(true); + + mc_ContainerAnvil_bukkitEntity = AnvilMenu.class.getDeclaredField("bukkitEntity"); + mc_ContainerAnvil_bukkitEntity.setAccessible(true); + } catch (Exception ex) { + Logger.getLogger(AnvilView.class.getName()).log(Level.SEVERE, "Anvil Setup Error", ex); + } + } + + // 1.14 also introduced a title field, also private, which can only be set once and can't be checked + static Field mc_Container_title; + + static { + try { + mc_Container_title = AbstractContainerMenu.class.getDeclaredField("title"); + mc_Container_title.setAccessible(true); + } catch (Exception ex) { + Logger.getLogger(AnvilView.class.getName()).log(Level.SEVERE, "Anvil Setup Error", ex); + } + } + + public AnvilView(int id, ServerPlayer entity, InventoryHolder holder) { + super(entity.nextContainerCounter(), entity.getInventory(), ContainerLevelAccess.create(entity.level, new BlockPos(0, 0, 0))); + + this.setTitle(MutableComponent.create(new TranslatableContents(customTitle != null ? customTitle : ""))); + this.checkReachable = false; + this.entity = entity; + + if (holder != null) { + this.inventory = getBukkitView(entity, holder).getTopInventory(); + } else { + this.inventory = getBukkitView().getTopInventory(); + } + } + + public CraftInventoryView getBukkitView(Player player, InventoryHolder holder) { + try { + AnvilInventoryCustom craftInventory = new AnvilInventoryCustom(holder, + new Location(entity.level.getWorld(), 0, 0, 0), + (Container) mc_ContainerAnvil_repairInventory.get(this), + (Container) mc_ContainerAnvil_resultInventory.get(this), this); + CraftInventoryView view = new CraftInventoryView(player.getBukkitEntity(), craftInventory, this); + mc_ContainerAnvil_bukkitEntity.set(this, view); + + return view; + } catch (Exception ex) { + Logger.getLogger(AnvilView.class.getName()).log(Level.SEVERE, "Anvil Setup Error", ex); + } + + return getBukkitView(); + } + + @Override + public boolean stillValid(Player entityHuman) { + return canUse; + } + + @Override + public void broadcastFullState() { + super.broadcastFullState(); + + if (cost >= 0) { + this.setLevelCost(cost); + } + + textChange.onChange(); + } + + @Override + public void update() { + broadcastFullState(); + } + + @Override + public String getRenameText() { + return this.itemName; + } + + @Override + public void setRenameText(String text) { + this.setItemName(text); + } + + @Override + public void setOnChange(AnvilTextChange handler) { + textChange = handler; + } + + @Override + public String getCustomTitle() { + return customTitle; + } + + @Override + public void setCustomTitle(String title) { + this.customTitle = title; + + try { + mc_Container_title.set(this, MutableComponent.create(new TranslatableContents(customTitle != null ? customTitle : ""))); + } catch (Exception ex) { + Logger.getLogger(AnvilView.class.getName()).log(Level.SEVERE, "Anvil Error", ex); + } + } + + @Override + public void setLevelCost(int cost) { + this.cost = cost; + } + + @Override + public int getLevelCost() { + if (cost >= 0) { + return cost; + } + + return this.getLevelCost(); + } + + @Override + public void setCanUse(boolean bool) { + this.canUse = bool; + } + + @Override + public ItemStack getLeftInput() { + return inventory.getItem(0); + } + + @Override + public ItemStack getRightInput() { + return inventory.getItem(1); + } + + @Override + public ItemStack getOutput() { + return inventory.getItem(2); + } + + @Override + public void setLeftInput(ItemStack item) { + inventory.setItem(0, item); + } + + @Override + public void setRightInput(ItemStack item) { + inventory.setItem(1, item); + } + + @Override + public void setOutput(ItemStack item) { + inventory.setItem(2, item); + } + + @Override + public Inventory getInventory() { + return inventory; + } + + @Override + public void open() { + // Send the packet + entity.connection.send(new ClientboundOpenScreenPacket(super.containerId, MenuType.ANVIL, MutableComponent.create(new TranslatableContents(customTitle != null ? customTitle : "")))); + + // Set their active container to this anvil + entity.containerMenu = this; + + // Add the slot listener + entity.initMenu(entity.containerMenu); + } +} diff --git a/NMS/NMS-v1_19_R2/src/main/java/com/songoda/core/nms/v1_19_R2/entity/NMSPlayerImpl.java b/NMS/NMS-v1_19_R2/src/main/java/com/songoda/core/nms/v1_19_R2/entity/NMSPlayerImpl.java new file mode 100644 index 00000000..0c4708b6 --- /dev/null +++ b/NMS/NMS-v1_19_R2/src/main/java/com/songoda/core/nms/v1_19_R2/entity/NMSPlayerImpl.java @@ -0,0 +1,13 @@ +package com.songoda.core.nms.v1_19_R2.entity; + +import com.songoda.core.nms.entity.NMSPlayer; +import net.minecraft.network.protocol.Packet; +import org.bukkit.craftbukkit.v1_19_R2.entity.CraftPlayer; +import org.bukkit.entity.Player; + +public class NMSPlayerImpl implements NMSPlayer { + @Override + public void sendPacket(Player p, Object packet) { + ((CraftPlayer) p).getHandle().connection.send((Packet) packet); + } +} diff --git a/NMS/NMS-v1_19_R2/src/main/java/com/songoda/core/nms/v1_19_R2/nbt/NBTCompoundImpl.java b/NMS/NMS-v1_19_R2/src/main/java/com/songoda/core/nms/v1_19_R2/nbt/NBTCompoundImpl.java new file mode 100644 index 00000000..2d4d5997 --- /dev/null +++ b/NMS/NMS-v1_19_R2/src/main/java/com/songoda/core/nms/v1_19_R2/nbt/NBTCompoundImpl.java @@ -0,0 +1,208 @@ +package com.songoda.core.nms.v1_19_R2.nbt; + +import com.songoda.core.nms.nbt.NBTCompound; +import com.songoda.core.nms.nbt.NBTObject; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtIo; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.Set; +import java.util.UUID; + +public class NBTCompoundImpl implements NBTCompound { + protected CompoundTag compound; + + protected NBTCompoundImpl(CompoundTag compound) { + this.compound = compound; + } + + public NBTCompoundImpl() { + this.compound = new CompoundTag(); + } + + @Override + public NBTCompound set(String tag, String s) { + compound.putString(tag, s); + return this; + } + + @Override + public NBTCompound set(String tag, boolean b) { + compound.putBoolean(tag, b); + return this; + } + + @Override + public NBTCompound set(String tag, int i) { + compound.putInt(tag, i); + return this; + } + + @Override + public NBTCompound set(String tag, double i) { + compound.putDouble(tag, i); + return this; + } + + @Override + public NBTCompound set(String tag, long l) { + compound.putLong(tag, l); + return this; + } + + @Override + public NBTCompound set(String tag, short s) { + compound.putShort(tag, s); + return this; + } + + @Override + public NBTCompound set(String tag, byte b) { + compound.putByte(tag, b); + return this; + } + + @Override + public NBTCompound set(String tag, int[] i) { + compound.putIntArray(tag, i); + return this; + } + + @Override + public NBTCompound set(String tag, byte[] b) { + compound.putByteArray(tag, b); + return this; + } + + @Override + public NBTCompound set(String tag, UUID u) { + compound.putUUID(tag, u); + return this; + } + + @Override + public NBTCompound remove(String tag) { + compound.remove(tag); + return this; + } + + @Override + public boolean has(String tag) { + return compound.contains(tag); + } + + @Override + public NBTObject getNBTObject(String tag) { + return new NBTObjectImpl(compound, tag); + } + + @Override + public String getString(String tag) { + return getNBTObject(tag).asString(); + } + + @Override + public boolean getBoolean(String tag) { + return getNBTObject(tag).asBoolean(); + } + + @Override + public int getInt(String tag) { + return getNBTObject(tag).asInt(); + } + + @Override + public double getDouble(String tag) { + return getNBTObject(tag).asDouble(); + } + + @Override + public long getLong(String tag) { + return getNBTObject(tag).asLong(); + } + + @Override + public short getShort(String tag) { + return getNBTObject(tag).asShort(); + } + + @Override + public byte getByte(String tag) { + return getNBTObject(tag).asByte(); + } + + @Override + public int[] getIntArray(String tag) { + return getNBTObject(tag).asIntArray(); + } + + @Override + public byte[] getByteArray(String tag) { + return getNBTObject(tag).asByteArray(); + } + + @Override + public NBTCompound getCompound(String tag) { + if (has(tag)) { + return getNBTObject(tag).asCompound(); + } + + CompoundTag newCompound = new CompoundTag(); + compound.put(tag, newCompound); + return new NBTCompoundImpl(newCompound); + } + + @Override + public Set getKeys() { + return compound.getAllKeys(); + } + + @Override + public Set getKeys(String tag) { + return compound.getCompound(tag).getAllKeys(); + } + + @Override + public byte[] serialize(String... exclusions) { + try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + ObjectOutputStream dataOutput = new ObjectOutputStream(outputStream)) { + addExtras(); + CompoundTag compound = this.compound.copy(); + + for (String exclusion : exclusions) { + compound.remove(exclusion); + } + + NbtIo.writeCompressed(compound, dataOutput); + + return outputStream.toByteArray(); + } catch (Exception ex) { + ex.printStackTrace(); + } + + return null; + } + + @Override + public void deSerialize(byte[] serialized) { + try (ByteArrayInputStream inputStream = new ByteArrayInputStream(serialized); + ObjectInputStream dataInput = new ObjectInputStream(inputStream)) { + compound = NbtIo.readCompressed(dataInput); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + @Override + public void addExtras() { + // None + } + + @Override + public String toString() { + return compound.toString(); + } +} diff --git a/NMS/NMS-v1_19_R2/src/main/java/com/songoda/core/nms/v1_19_R2/nbt/NBTCoreImpl.java b/NMS/NMS-v1_19_R2/src/main/java/com/songoda/core/nms/v1_19_R2/nbt/NBTCoreImpl.java new file mode 100644 index 00000000..4f195413 --- /dev/null +++ b/NMS/NMS-v1_19_R2/src/main/java/com/songoda/core/nms/v1_19_R2/nbt/NBTCoreImpl.java @@ -0,0 +1,38 @@ +package com.songoda.core.nms.v1_19_R2.nbt; + +import com.songoda.core.nms.nbt.NBTCore; +import com.songoda.core.nms.nbt.NBTEntity; +import com.songoda.core.nms.nbt.NBTItem; +import net.minecraft.nbt.CompoundTag; +import org.bukkit.craftbukkit.v1_19_R2.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_19_R2.inventory.CraftItemStack; +import org.bukkit.entity.Entity; +import org.bukkit.inventory.ItemStack; + +public class NBTCoreImpl implements NBTCore { + @Deprecated + @Override + public NBTItem of(ItemStack item) { + return new NBTItemImpl(CraftItemStack.asNMSCopy(item)); + } + + @Deprecated + @Override + public NBTItem newItem() { + return new NBTItemImpl(null); + } + + @Override + public NBTEntity of(Entity entity) { + net.minecraft.world.entity.Entity nmsEntity = ((CraftEntity) entity).getHandle(); + CompoundTag nbt = new CompoundTag(); + nmsEntity.saveWithoutId(nbt); + + return new NBTEntityImpl(nbt, nmsEntity); + } + + @Override + public NBTEntity newEntity() { + return new NBTEntityImpl(new CompoundTag(), null); + } +} diff --git a/NMS/NMS-v1_19_R2/src/main/java/com/songoda/core/nms/v1_19_R2/nbt/NBTEntityImpl.java b/NMS/NMS-v1_19_R2/src/main/java/com/songoda/core/nms/v1_19_R2/nbt/NBTEntityImpl.java new file mode 100644 index 00000000..d5db1d35 --- /dev/null +++ b/NMS/NMS-v1_19_R2/src/main/java/com/songoda/core/nms/v1_19_R2/nbt/NBTEntityImpl.java @@ -0,0 +1,67 @@ +package com.songoda.core.nms.v1_19_R2.nbt; + +import com.songoda.core.nms.nbt.NBTEntity; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Registry; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.MobSpawnType; +import org.bukkit.Location; +import org.bukkit.craftbukkit.v1_19_R2.CraftWorld; + +import java.util.Optional; + +public class NBTEntityImpl extends NBTCompoundImpl implements NBTEntity { + private Entity nmsEntity; + + public NBTEntityImpl(CompoundTag entityNBT, Entity nmsEntity) { + super(entityNBT); + + this.nmsEntity = nmsEntity; + } + + @Override + public org.bukkit.entity.Entity spawn(Location location) { + String entityType = getNBTObject("entity_type").asString(); + getKeys().remove("UUID"); + + Optional> optionalEntity = EntityType.byString(entityType); + if (optionalEntity.isPresent()) { + assert location.getWorld() != null; + + Entity spawned = optionalEntity.get().spawn( + ((CraftWorld) location.getWorld()).getHandle(), + compound, + null, + new BlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ()), + MobSpawnType.COMMAND, + true, + false + ); + + if (spawned != null) { + spawned.load(compound); + org.bukkit.entity.Entity entity = spawned.getBukkitEntity(); + entity.teleport(location); + nmsEntity = spawned; + + return entity; + } + } + + return null; + } + + @Override + public org.bukkit.entity.Entity reSpawn(Location location) { + nmsEntity.discard(); + return spawn(location); + } + + @Override + public void addExtras() { + compound.putString("entity_type", BuiltInRegistries.ENTITY_TYPE.getKey(nmsEntity.getType()).toString()); + } +} diff --git a/NMS/NMS-v1_19_R2/src/main/java/com/songoda/core/nms/v1_19_R2/nbt/NBTItemImpl.java b/NMS/NMS-v1_19_R2/src/main/java/com/songoda/core/nms/v1_19_R2/nbt/NBTItemImpl.java new file mode 100644 index 00000000..5ef6a7b1 --- /dev/null +++ b/NMS/NMS-v1_19_R2/src/main/java/com/songoda/core/nms/v1_19_R2/nbt/NBTItemImpl.java @@ -0,0 +1,24 @@ +package com.songoda.core.nms.v1_19_R2.nbt; + +import com.songoda.core.nms.nbt.NBTItem; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.item.ItemStack; +import org.bukkit.craftbukkit.v1_19_R2.inventory.CraftItemStack; + +public class NBTItemImpl extends NBTCompoundImpl implements NBTItem { + private final ItemStack nmsItem; + + public NBTItemImpl(ItemStack nmsItem) { + super(nmsItem != null && nmsItem.hasTag() ? nmsItem.getTag() : new CompoundTag()); + + this.nmsItem = nmsItem; + } + + public org.bukkit.inventory.ItemStack finish() { + if (nmsItem == null) { + return CraftItemStack.asBukkitCopy(ItemStack.of(compound)); + } + + return CraftItemStack.asBukkitCopy(nmsItem); + } +} diff --git a/NMS/NMS-v1_19_R2/src/main/java/com/songoda/core/nms/v1_19_R2/nbt/NBTObjectImpl.java b/NMS/NMS-v1_19_R2/src/main/java/com/songoda/core/nms/v1_19_R2/nbt/NBTObjectImpl.java new file mode 100644 index 00000000..b1e77f55 --- /dev/null +++ b/NMS/NMS-v1_19_R2/src/main/java/com/songoda/core/nms/v1_19_R2/nbt/NBTObjectImpl.java @@ -0,0 +1,72 @@ +package com.songoda.core.nms.v1_19_R2.nbt; + +import com.songoda.core.nms.nbt.NBTCompound; +import com.songoda.core.nms.nbt.NBTObject; +import net.minecraft.nbt.CompoundTag; + +import java.util.Set; + +public class NBTObjectImpl implements NBTObject { + private final CompoundTag compound; + private final String tag; + + public NBTObjectImpl(CompoundTag compound, String tag) { + this.compound = compound; + this.tag = tag; + } + + @Override + public String asString() { + return compound.getString(tag); + } + + @Override + public boolean asBoolean() { + return compound.getBoolean(tag); + } + + @Override + public int asInt() { + return compound.getInt(tag); + } + + @Override + public double asDouble() { + return compound.getDouble(tag); + } + + @Override + public long asLong() { + return compound.getLong(tag); + } + + @Override + public short asShort() { + return compound.getShort(tag); + } + + @Override + public byte asByte() { + return compound.getByte(tag); + } + + @Override + public int[] asIntArray() { + return compound.getIntArray(tag); + } + + @Override + public byte[] asByteArray() { + return compound.getByteArray(tag); + } + + @Override + public NBTCompound asCompound() { + return new NBTCompoundImpl(compound.getCompound(tag)); + } + + @Override + public Set getKeys() { + return compound.getAllKeys(); + } +} diff --git a/NMS/NMS-v1_19_R2/src/main/java/com/songoda/core/nms/v1_19_R2/world/SItemStackImpl.java b/NMS/NMS-v1_19_R2/src/main/java/com/songoda/core/nms/v1_19_R2/world/SItemStackImpl.java new file mode 100644 index 00000000..e4e0dde4 --- /dev/null +++ b/NMS/NMS-v1_19_R2/src/main/java/com/songoda/core/nms/v1_19_R2/world/SItemStackImpl.java @@ -0,0 +1,39 @@ +package com.songoda.core.nms.v1_19_R2.world; + +import com.songoda.core.nms.world.SItemStack; +import net.minecraft.core.particles.ItemParticleOption; +import net.minecraft.core.particles.ParticleTypes; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.phys.Vec3; +import org.bukkit.craftbukkit.v1_19_R2.entity.CraftPlayer; +import org.bukkit.craftbukkit.v1_19_R2.inventory.CraftItemStack; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +public class SItemStackImpl implements SItemStack { + private final ItemStack item; + + public SItemStackImpl(ItemStack item) { + this.item = item; + } + + @Override + public void breakItem(Player player, int amount) { + ServerPlayer entityPlayer = ((CraftPlayer) player).getHandle(); + + for (int i = 0; i < amount; ++i) { + Vec3 vec3d = new Vec3(((double) random.nextFloat() - 0.5D) * 0.1D, Math.random() * 0.1D + 0.1D, 0.0D); + vec3d = vec3d.xRot(-entityPlayer.getXRot() * 0.017453292F); + vec3d = vec3d.yRot(-entityPlayer.getYRot() * 0.017453292F); + + double d0 = (double) (-random.nextFloat()) * 0.6D - 0.3D; + + Vec3 vec3d1 = new Vec3(((double) random.nextFloat() - 0.5D) * 0.3D, d0, 0.6D); + vec3d1 = vec3d1.xRot(-entityPlayer.getXRot() * 0.017453292F); + vec3d1 = vec3d1.yRot(-entityPlayer.getYRot() * 0.017453292F); + vec3d1 = vec3d1.add(entityPlayer.getX(), entityPlayer.getEyeY(), entityPlayer.getZ()); + + entityPlayer.level.addParticle(new ItemParticleOption(ParticleTypes.ITEM, CraftItemStack.asNMSCopy(item)), vec3d1.x, vec3d1.y, vec3d1.z, vec3d.x, vec3d.y + 0.05D, vec3d.z); + } + } +} diff --git a/NMS/NMS-v1_19_R2/src/main/java/com/songoda/core/nms/v1_19_R2/world/SSpawnerImpl.java b/NMS/NMS-v1_19_R2/src/main/java/com/songoda/core/nms/v1_19_R2/world/SSpawnerImpl.java new file mode 100644 index 00000000..a9c93bee --- /dev/null +++ b/NMS/NMS-v1_19_R2/src/main/java/com/songoda/core/nms/v1_19_R2/world/SSpawnerImpl.java @@ -0,0 +1,132 @@ +package com.songoda.core.nms.v1_19_R2.world; + +import com.songoda.core.compatibility.CompatibleMaterial; +import com.songoda.core.compatibility.CompatibleParticleHandler; +import com.songoda.core.nms.world.SSpawner; +import com.songoda.core.nms.world.SpawnedEntity; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.RandomSource; +import net.minecraft.world.DifficultyInstance; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.Mob; +import net.minecraft.world.entity.MobSpawnType; +import net.minecraft.world.level.SpawnData; +import org.bukkit.Location; +import org.bukkit.block.BlockFace; +import org.bukkit.craftbukkit.v1_19_R2.CraftWorld; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.LivingEntity; +import org.bukkit.event.entity.CreatureSpawnEvent; + +import java.util.Optional; +import java.util.Set; + +public class SSpawnerImpl implements SSpawner { + private final Location spawnerLocation; + + public SSpawnerImpl(Location location) { + this.spawnerLocation = location; + } + + @Override + public LivingEntity spawnEntity(EntityType type, Location spawnerLocation) { + return spawnEntity(type, "EXPLOSION_NORMAL", null, null); + } + + @Override + public LivingEntity spawnEntity(EntityType type, String particleType, SpawnedEntity spawned, Set canSpawnOn) { + SpawnData data = new SpawnData(); + CompoundTag compound = data.getEntityToSpawn(); + + String name = type.name().toLowerCase().replace("snowman", "snow_golem") + .replace("mushroom_cow", "mooshroom"); + compound.putString("id", "minecraft:" + name); + + short spawnRange = 4; + for (int i = 0; i < 50; i++) { + assert spawnerLocation.getWorld() != null; + ServerLevel world = ((CraftWorld) spawnerLocation.getWorld()).getHandle(); + + RandomSource random = world.getRandom(); + double x = spawnerLocation.getX() + (random.nextDouble() - random.nextDouble()) * (double) spawnRange + 0.5D; + double y = spawnerLocation.getY() + random.nextInt(3) - 1; + double z = spawnerLocation.getZ() + (random.nextDouble() - random.nextDouble()) * (double) spawnRange + 0.5D; + + Optional optionalEntity = net.minecraft.world.entity.EntityType.create(compound, world); + if (optionalEntity.isEmpty()) continue; + + Entity entity = optionalEntity.get(); + entity.setPos(x, y, z); + + BlockPos position = entity.blockPosition(); + DifficultyInstance damageScaler = world.getCurrentDifficultyAt(position); + + if (!(entity instanceof Mob entityInsentient)) { + continue; + } + + Location spot = new Location(spawnerLocation.getWorld(), x, y, z); + + if (!canSpawn(world, entityInsentient, spot, canSpawnOn)) { + continue; + } + + entityInsentient.finalizeSpawn(world, damageScaler, MobSpawnType.SPAWNER, null, null); + + LivingEntity craftEntity = (LivingEntity) entity.getBukkitEntity(); + + if (spawned != null && !spawned.onSpawn(craftEntity)) { + return null; + } + + if (particleType != null) { + float xx = (float) (0 + (Math.random() * 1)); + float yy = (float) (0 + (Math.random() * 2)); + float zz = (float) (0 + (Math.random() * 1)); + + CompatibleParticleHandler.spawnParticles(CompatibleParticleHandler.ParticleType.getParticle(particleType), spot, 5, xx, yy, zz, 0); + } + + world.addFreshEntity(entity, CreatureSpawnEvent.SpawnReason.SPAWNER); + + spot.setYaw(random.nextFloat() * 360.0F); + craftEntity.teleport(spot); + + return craftEntity; + } + + return null; + } + + private boolean canSpawn(ServerLevel world, Mob entityInsentient, Location location, Set canSpawnOn) { + if (!world.noCollision(entityInsentient, entityInsentient.getBoundingBox())) { + return false; + } + + CompatibleMaterial spawnedIn = CompatibleMaterial.getMaterial(location.getBlock()); + CompatibleMaterial spawnedOn = CompatibleMaterial.getMaterial(location.getBlock().getRelative(BlockFace.DOWN)); + + if (spawnedIn == null || spawnedOn == null) { + return false; + } + + if (!spawnedIn.isAir() && + spawnedIn != CompatibleMaterial.WATER && + !spawnedIn.name().contains("PRESSURE") && + !spawnedIn.name().contains("SLAB")) { + return false; + } + + for (CompatibleMaterial material : canSpawnOn) { + if (material == null) continue; + + if (spawnedOn.equals(material) || material.isAir()) { + return true; + } + } + + return false; + } +} diff --git a/NMS/NMS-v1_19_R2/src/main/java/com/songoda/core/nms/v1_19_R2/world/SWorldImpl.java b/NMS/NMS-v1_19_R2/src/main/java/com/songoda/core/nms/v1_19_R2/world/SWorldImpl.java new file mode 100644 index 00000000..9aff266a --- /dev/null +++ b/NMS/NMS-v1_19_R2/src/main/java/com/songoda/core/nms/v1_19_R2/world/SWorldImpl.java @@ -0,0 +1,38 @@ +package com.songoda.core.nms.v1_19_R2.world; + +import com.songoda.core.nms.world.SWorld; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.level.entity.LevelEntityGetter; +import org.bukkit.World; +import org.bukkit.craftbukkit.v1_19_R2.CraftWorld; +import org.bukkit.entity.LivingEntity; + +import java.util.ArrayList; +import java.util.List; + +public class SWorldImpl implements SWorld { + private final World world; + + public SWorldImpl(World world) { + this.world = world; + } + + @Override + public List getLivingEntities() { + List result = new ArrayList<>(); + + ServerLevel worldServer = ((CraftWorld) world).getHandle(); + LevelEntityGetter entities = worldServer.getEntities(); + + entities.getAll().forEach((mcEnt) -> { + org.bukkit.entity.Entity bukkitEntity = mcEnt.getBukkitEntity(); + + if (bukkitEntity instanceof LivingEntity && bukkitEntity.isValid()) { + result.add((LivingEntity) bukkitEntity); + } + }); + + return result; + } +} diff --git a/NMS/NMS-v1_19_R2/src/main/java/com/songoda/core/nms/v1_19_R2/world/WorldCoreImpl.java b/NMS/NMS-v1_19_R2/src/main/java/com/songoda/core/nms/v1_19_R2/world/WorldCoreImpl.java new file mode 100644 index 00000000..c616f9ff --- /dev/null +++ b/NMS/NMS-v1_19_R2/src/main/java/com/songoda/core/nms/v1_19_R2/world/WorldCoreImpl.java @@ -0,0 +1,93 @@ +package com.songoda.core.nms.v1_19_R2.world; + +import com.songoda.core.nms.ReflectionUtils; +import com.songoda.core.nms.v1_19_R2.world.spawner.BBaseSpawnerImpl; +import com.songoda.core.nms.world.BBaseSpawner; +import com.songoda.core.nms.world.SItemStack; +import com.songoda.core.nms.world.SSpawner; +import com.songoda.core.nms.world.SWorld; +import com.songoda.core.nms.world.WorldCore; +import net.minecraft.core.BlockPos; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.profiling.ProfilerFiller; +import net.minecraft.world.level.BaseSpawner; +import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.chunk.LevelChunk; +import net.minecraft.world.level.chunk.LevelChunkSection; +import net.minecraft.world.level.material.FluidState; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.block.CreatureSpawner; +import org.bukkit.craftbukkit.v1_19_R2.CraftChunk; +import org.bukkit.inventory.ItemStack; + +public class WorldCoreImpl implements WorldCore { + @Override + public SSpawner getSpawner(CreatureSpawner spawner) { + return new SSpawnerImpl(spawner.getLocation()); + } + + @Override + public SSpawner getSpawner(Location location) { + return new SSpawnerImpl(location); + } + + @Override + public SItemStack getItemStack(ItemStack item) { + return new SItemStackImpl(item); + } + + @Override + public SWorld getWorld(World world) { + return new SWorldImpl(world); + } + + @Override + public BBaseSpawner getBaseSpawner(CreatureSpawner spawner) throws NoSuchFieldException, NoSuchMethodException, IllegalAccessException { + Object cTileEntity = ReflectionUtils.getFieldValue(spawner, "tileEntity"); + + return new BBaseSpawnerImpl(spawner, (BaseSpawner) ReflectionUtils.getFieldValue(cTileEntity, "a")); + } + + /** + * Method is based on {@link ServerLevel#tickChunk(LevelChunk, int)}. + */ + @Override + public void randomTickChunk(org.bukkit.Chunk bukkitChunk, int tickAmount) { + LevelChunk chunk = ((CraftChunk) bukkitChunk).getHandle(); + ServerLevel world = chunk.q; + ProfilerFiller gameProfilerFiller = world.getProfiler(); + + ChunkPos chunkCoordIntPair = chunk.getPos(); + int j = chunkCoordIntPair.getMinBlockX(); + int k = chunkCoordIntPair.getMinBlockZ(); + + gameProfilerFiller.popPush("tickBlocks"); + if (tickAmount > 0) { + LevelChunkSection[] aChunkSection = chunk.getSections(); + + for (LevelChunkSection chunkSection : aChunkSection) { + if (chunkSection.isRandomlyTicking()) { + int j1 = chunkSection.bottomBlockY(); + + for (int k1 = 0; k1 < tickAmount; ++k1) { + BlockPos blockposition2 = world.getBlockRandomPos(j, j1, k, 15); + gameProfilerFiller.push("randomTick"); + BlockState iBlockData1 = chunkSection.getBlockState(blockposition2.getX() - j, blockposition2.getY() - j1, blockposition2.getZ() - k); + if (iBlockData1.isRandomlyTicking()) { + iBlockData1.randomTick(world, blockposition2, world.random); + } + + FluidState fluid = iBlockData1.getFluidState(); + if (fluid.isRandomlyTicking()) { + fluid.randomTick(world, blockposition2, world.random); + } + + gameProfilerFiller.pop(); + } + } + } + } + } +} diff --git a/NMS/NMS-v1_19_R2/src/main/java/com/songoda/core/nms/v1_19_R2/world/spawner/BBaseSpawnerImpl.java b/NMS/NMS-v1_19_R2/src/main/java/com/songoda/core/nms/v1_19_R2/world/spawner/BBaseSpawnerImpl.java new file mode 100644 index 00000000..c3365c6a --- /dev/null +++ b/NMS/NMS-v1_19_R2/src/main/java/com/songoda/core/nms/v1_19_R2/world/spawner/BBaseSpawnerImpl.java @@ -0,0 +1,214 @@ +package com.songoda.core.nms.v1_19_R2.world.spawner; + +import com.songoda.core.nms.world.BBaseSpawner; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.ListTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.RandomSource; +import net.minecraft.util.random.WeightedEntry; +import net.minecraft.world.Difficulty; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.Mob; +import net.minecraft.world.entity.MobSpawnType; +import net.minecraft.world.entity.SpawnPlacements; +import net.minecraft.world.level.BaseSpawner; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LightLayer; +import net.minecraft.world.level.SpawnData; +import net.minecraft.world.level.gameevent.GameEvent; +import net.minecraft.world.phys.AABB; +import org.bukkit.block.CreatureSpawner; +import org.bukkit.craftbukkit.v1_19_R2.CraftWorld; +import org.bukkit.craftbukkit.v1_19_R2.block.CraftCreatureSpawner; +import org.bukkit.craftbukkit.v1_19_R2.event.CraftEventFactory; +import org.bukkit.event.entity.CreatureSpawnEvent; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Optional; + +public class BBaseSpawnerImpl implements BBaseSpawner { + private final CreatureSpawner bukkitSpawner; + private final BaseSpawner spawner; + + private final Method setNextSpawnDataMethod; + private final Method getOrCreateNextSpawnDataMethod; + + public BBaseSpawnerImpl(CreatureSpawner bukkitSpawner, BaseSpawner spawner) throws NoSuchMethodException { + this.bukkitSpawner = bukkitSpawner; + this.spawner = spawner; + + this.setNextSpawnDataMethod = this.spawner.getClass().getDeclaredMethod("a", Level.class, BlockPos.class, SpawnData.class); + if (!this.setNextSpawnDataMethod.canAccess(this.spawner)) { + this.setNextSpawnDataMethod.setAccessible(true); + } + + this.getOrCreateNextSpawnDataMethod = this.spawner.getClass().getSuperclass().getDeclaredMethod("b", Level.class, RandomSource.class, BlockPos.class); + if (!this.getOrCreateNextSpawnDataMethod.canAccess(this.spawner)) { + this.getOrCreateNextSpawnDataMethod.setAccessible(true); + } + } + + /** + * This method is based on {@link BaseSpawner#isNearPlayer(Level, BlockPos)}. + */ + @SuppressWarnings("JavadocReference") + @Override + public boolean isNearPlayer() { + BlockPos bPos = getBlockPosition(); + return getWorld().hasNearbyAlivePlayer( + (double) bPos.getX() + 0.5, + (double) bPos.getY() + 0.5, + (double) bPos.getZ() + 0.5, + this.spawner.requiredPlayerRange + ); + } + + /** + * This method is based on {@link BaseSpawner#serverTick(ServerLevel, BlockPos)}. + */ + @Override + public void tick() throws InvocationTargetException, IllegalAccessException { + ServerLevel world = getWorld(); + BlockPos bPos = getBlockPosition(); + + if (this.spawner.spawnDelay == -1) { + this.delay(world, bPos); + } + + if (this.spawner.spawnDelay > 0) { + --this.spawner.spawnDelay; + } else { + boolean flag = false; + RandomSource randomsource = world.getRandom(); + SpawnData mobspawnerdata = (SpawnData) this.getOrCreateNextSpawnDataMethod.invoke(this.spawner, world, randomsource, bPos); + int i = 0; + + while (true) { + if (i >= this.spawner.spawnCount) { + if (flag) { + this.delay(world, bPos); + } + break; + } + + CompoundTag nbttagcompound = mobspawnerdata.getEntityToSpawn(); + Optional> optional = EntityType.by(nbttagcompound); + if (optional.isEmpty()) { + this.delay(world, bPos); + return; + } + + ListTag nbttaglist = nbttagcompound.getList("Pos", 6); + int j = nbttaglist.size(); + double d0 = j >= 1 ? nbttaglist.getDouble(0) : (double) bPos.getX() + (randomsource.nextDouble() - randomsource.nextDouble()) * (double) this.spawner.spawnRange + 0.5; + double d1 = j >= 2 ? nbttaglist.getDouble(1) : (double) (bPos.getY() + randomsource.nextInt(3) - 1); + double d2 = j >= 3 ? nbttaglist.getDouble(2) : (double) bPos.getZ() + (randomsource.nextDouble() - randomsource.nextDouble()) * (double) this.spawner.spawnRange + 0.5; + if (world.noCollision(optional.get().getAABB(d0, d1, d2))) { + label128: + { + BlockPos blockposition1 = new BlockPos(d0, d1, d2); + if (mobspawnerdata.getCustomSpawnRules().isPresent()) { + if (!optional.get().getCategory().isFriendly() && world.getDifficulty() == Difficulty.PEACEFUL) { + break label128; + } + + SpawnData.CustomSpawnRules mobspawnerdata_a = mobspawnerdata.getCustomSpawnRules().get(); + if (!mobspawnerdata_a.blockLightLimit().isValueInRange(world.getBrightness(LightLayer.BLOCK, blockposition1)) || !mobspawnerdata_a.skyLightLimit().isValueInRange(world.getBrightness(LightLayer.SKY, blockposition1))) { + break label128; + } + } else if (!SpawnPlacements.checkSpawnRules(optional.get(), world, MobSpawnType.SPAWNER, blockposition1, world.getRandom())) { + break label128; + } + + Entity entity = EntityType.loadEntityRecursive(nbttagcompound, world, (entity1) -> { + entity1.moveTo(d0, d1, d2, entity1.getYRot(), entity1.getXRot()); + return entity1; + }); + if (entity == null) { + this.delay(world, bPos); + return; + } + + int k = world.getEntitiesOfClass(entity.getClass(), (new AABB(bPos.getX(), bPos.getY(), bPos.getZ(), bPos.getX() + 1, bPos.getY() + 1, bPos.getZ() + 1)).inflate(this.spawner.spawnRange)).size(); + if (k >= this.spawner.maxNearbyEntities) { + this.delay(world, bPos); + return; + } + + entity.moveTo(entity.getX(), entity.getY(), entity.getZ(), randomsource.nextFloat() * 360.0F, 0.0F); + if (entity instanceof Mob entityinsentient) { + if (mobspawnerdata.getCustomSpawnRules().isEmpty() && !entityinsentient.checkSpawnRules(world, MobSpawnType.SPAWNER) || !entityinsentient.checkSpawnObstruction(world)) { + break label128; + } + + if (mobspawnerdata.getEntityToSpawn().size() == 1 && mobspawnerdata.getEntityToSpawn().contains("id", 8)) { + ((Mob) entity).finalizeSpawn(world, world.getCurrentDifficultyAt(entity.blockPosition()), MobSpawnType.SPAWNER, null, null); + } + + if (entityinsentient.level.spigotConfig.nerfSpawnerMobs) { + entityinsentient.aware = false; + } + } + + if (CraftEventFactory.callSpawnerSpawnEvent(entity, bPos).isCancelled()) { + Entity vehicle = entity.getVehicle(); + if (vehicle != null) { + vehicle.discard(); + } + + for (Entity passenger : entity.getIndirectPassengers()) { + passenger.discard(); + } + } else { + if (!world.tryAddFreshEntityWithPassengers(entity, CreatureSpawnEvent.SpawnReason.SPAWNER)) { + this.delay(world, bPos); + return; + } + + world.levelEvent(2004, bPos, 0); + world.gameEvent(entity, GameEvent.ENTITY_PLACE, blockposition1); + if (entity instanceof Mob) { + ((Mob) entity).spawnAnim(); + } + + flag = true; + } + } + } + + ++i; + } + } + } + + /** + * This method is based on {@link BaseSpawner#delay(Level, BlockPos)}. + */ + @SuppressWarnings("JavadocReference") + private void delay(ServerLevel world, BlockPos bPos) throws InvocationTargetException, IllegalAccessException { + RandomSource randomsource = world.random; + if (this.spawner.maxSpawnDelay <= this.spawner.minSpawnDelay) { + this.spawner.spawnDelay = this.spawner.minSpawnDelay; + } else { + this.spawner.spawnDelay = this.spawner.minSpawnDelay + randomsource.nextInt(this.spawner.maxSpawnDelay - this.spawner.minSpawnDelay); + } + + Optional> weightedEntry = this.spawner.spawnPotentials.getRandom(randomsource); + if (weightedEntry.isPresent()) { + this.setNextSpawnDataMethod.invoke(this.spawner, world, bPos, weightedEntry.get().getData()); + } + + this.spawner.broadcastEvent(world, bPos, 1); + } + + private ServerLevel getWorld() { + return ((CraftWorld) this.bukkitSpawner.getWorld()).getHandle(); + } + + private BlockPos getBlockPosition() { + return ((CraftCreatureSpawner) this.bukkitSpawner).getPosition(); + } +} diff --git a/NMS/NMS-v1_8_R1/pom.xml b/NMS/NMS-v1_8_R1/pom.xml index c801ffed..923e9bde 100644 --- a/NMS/NMS-v1_8_R1/pom.xml +++ b/NMS/NMS-v1_8_R1/pom.xml @@ -7,7 +7,7 @@ com.songoda SongodaCore-Modules - 2.6.16 + 2.6.18 ../../pom.xml diff --git a/NMS/NMS-v1_8_R1/src/main/java/com/songoda/core/nms/v1_8_R1/nbt/NBTEntityImpl.java b/NMS/NMS-v1_8_R1/src/main/java/com/songoda/core/nms/v1_8_R1/nbt/NBTEntityImpl.java index d793ef3e..b2e4f094 100644 --- a/NMS/NMS-v1_8_R1/src/main/java/com/songoda/core/nms/v1_8_R1/nbt/NBTEntityImpl.java +++ b/NMS/NMS-v1_8_R1/src/main/java/com/songoda/core/nms/v1_8_R1/nbt/NBTEntityImpl.java @@ -35,6 +35,7 @@ public class NBTEntityImpl extends NBTCompoundImpl implements NBTEntity { @Override public org.bukkit.entity.Entity spawn(Location location) { String entityType = getNBTObject("entity_type").asString(); + getKeys().remove("UUID"); try { Entity spawned = ItemMonsterEgg.spawnCreature( // Changed since 1.14 diff --git a/NMS/NMS-v1_8_R2/pom.xml b/NMS/NMS-v1_8_R2/pom.xml index e3977c88..4e4778c0 100644 --- a/NMS/NMS-v1_8_R2/pom.xml +++ b/NMS/NMS-v1_8_R2/pom.xml @@ -7,7 +7,7 @@ com.songoda SongodaCore-Modules - 2.6.16 + 2.6.18 ../../pom.xml diff --git a/NMS/NMS-v1_8_R2/src/main/java/com/songoda/core/nms/v1_8_R2/nbt/NBTEntityImpl.java b/NMS/NMS-v1_8_R2/src/main/java/com/songoda/core/nms/v1_8_R2/nbt/NBTEntityImpl.java index 6114833b..87417d09 100644 --- a/NMS/NMS-v1_8_R2/src/main/java/com/songoda/core/nms/v1_8_R2/nbt/NBTEntityImpl.java +++ b/NMS/NMS-v1_8_R2/src/main/java/com/songoda/core/nms/v1_8_R2/nbt/NBTEntityImpl.java @@ -35,6 +35,7 @@ public class NBTEntityImpl extends NBTCompoundImpl implements NBTEntity { @Override public org.bukkit.entity.Entity spawn(Location location) { String entityType = getNBTObject("entity_type").asString(); + getKeys().remove("UUID"); try { Entity spawned = ItemMonsterEgg.spawnCreature( // Changed since 1.14 diff --git a/NMS/NMS-v1_8_R3/pom.xml b/NMS/NMS-v1_8_R3/pom.xml index 4f4b8938..e3783b2d 100644 --- a/NMS/NMS-v1_8_R3/pom.xml +++ b/NMS/NMS-v1_8_R3/pom.xml @@ -7,7 +7,7 @@ com.songoda SongodaCore-Modules - 2.6.16 + 2.6.18 ../../pom.xml diff --git a/NMS/NMS-v1_8_R3/src/main/java/com/songoda/core/nms/v1_8_R3/nbt/NBTEntityImpl.java b/NMS/NMS-v1_8_R3/src/main/java/com/songoda/core/nms/v1_8_R3/nbt/NBTEntityImpl.java index 29d726f7..31cbb092 100644 --- a/NMS/NMS-v1_8_R3/src/main/java/com/songoda/core/nms/v1_8_R3/nbt/NBTEntityImpl.java +++ b/NMS/NMS-v1_8_R3/src/main/java/com/songoda/core/nms/v1_8_R3/nbt/NBTEntityImpl.java @@ -36,6 +36,7 @@ public class NBTEntityImpl extends NBTCompoundImpl implements NBTEntity { @Override public org.bukkit.entity.Entity spawn(Location location) { String entityType = getNBTObject("entity_type").asString(); + getKeys().remove("UUID"); try { Entity spawned = ItemMonsterEgg.spawnCreature( // Changed since 1.14 diff --git a/NMS/NMS-v1_9_R1/pom.xml b/NMS/NMS-v1_9_R1/pom.xml index 65ab22c2..b79c0b28 100644 --- a/NMS/NMS-v1_9_R1/pom.xml +++ b/NMS/NMS-v1_9_R1/pom.xml @@ -7,7 +7,7 @@ com.songoda SongodaCore-Modules - 2.6.16 + 2.6.18 ../../pom.xml diff --git a/NMS/NMS-v1_9_R1/src/main/java/com/songoda/core/nms/v1_9_R1/nbt/NBTEntityImpl.java b/NMS/NMS-v1_9_R1/src/main/java/com/songoda/core/nms/v1_9_R1/nbt/NBTEntityImpl.java index f5341176..956b901f 100644 --- a/NMS/NMS-v1_9_R1/src/main/java/com/songoda/core/nms/v1_9_R1/nbt/NBTEntityImpl.java +++ b/NMS/NMS-v1_9_R1/src/main/java/com/songoda/core/nms/v1_9_R1/nbt/NBTEntityImpl.java @@ -21,6 +21,7 @@ public class NBTEntityImpl extends NBTCompoundImpl implements NBTEntity { @Override public org.bukkit.entity.Entity spawn(Location location) { String entityType = getNBTObject("entity_type").asString(); + getKeys().remove("UUID"); Entity spawned = ItemMonsterEgg.spawnCreature( // Changed since 1.14 ((CraftWorld) location.getWorld()).getHandle(), diff --git a/NMS/NMS-v1_9_R2/pom.xml b/NMS/NMS-v1_9_R2/pom.xml index cb6bea89..eb1e3117 100644 --- a/NMS/NMS-v1_9_R2/pom.xml +++ b/NMS/NMS-v1_9_R2/pom.xml @@ -7,7 +7,7 @@ com.songoda SongodaCore-Modules - 2.6.16 + 2.6.18 ../../pom.xml diff --git a/NMS/NMS-v1_9_R2/src/main/java/com/songoda/core/nms/v1_9_R2/nbt/NBTEntityImpl.java b/NMS/NMS-v1_9_R2/src/main/java/com/songoda/core/nms/v1_9_R2/nbt/NBTEntityImpl.java index 5c705453..d626b22d 100644 --- a/NMS/NMS-v1_9_R2/src/main/java/com/songoda/core/nms/v1_9_R2/nbt/NBTEntityImpl.java +++ b/NMS/NMS-v1_9_R2/src/main/java/com/songoda/core/nms/v1_9_R2/nbt/NBTEntityImpl.java @@ -21,6 +21,7 @@ public class NBTEntityImpl extends NBTCompoundImpl implements NBTEntity { @Override public org.bukkit.entity.Entity spawn(Location location) { String entityType = getNBTObject("entity_type").asString(); + getKeys().remove("UUID"); Entity spawned = ItemMonsterEgg.spawnCreature( // Changed since 1.14 ((CraftWorld) location.getWorld()).getHandle(), diff --git a/pom.xml b/pom.xml index c7fc73b5..5a4f40a9 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.songoda SongodaCore-Modules - 2.6.16 + 2.6.18 pom @@ -48,6 +48,7 @@ NMS/NMS-v1_18_R2 NMS/NMS-v1_19_R1 NMS/NMS-v1_19_R1v2 + NMS/NMS-v1_19_R2 @@ -142,6 +143,16 @@ jitpack.io https://jitpack.io/ + + + enginehub-repo + https://maven.enginehub.org/repo/ + + + + papermc + https://repo.papermc.io/repository/maven-public/ +