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.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/
+