diff --git a/API/src/main/java/com/bgsoftware/wildloaders/api/hooks/TickableProvider.java b/API/src/main/java/com/bgsoftware/wildloaders/api/hooks/TickableProvider.java index e8576a4..7ba8be7 100644 --- a/API/src/main/java/com/bgsoftware/wildloaders/api/hooks/TickableProvider.java +++ b/API/src/main/java/com/bgsoftware/wildloaders/api/hooks/TickableProvider.java @@ -2,12 +2,28 @@ package com.bgsoftware.wildloaders.api.hooks; import org.bukkit.Chunk; +import java.util.Collection; + public interface TickableProvider { /** * Simulate a tick on a list of provided chunks. + * + * @param chunks The chunks to tick. + * @deprecated See {@link #tick(Collection)} + */ + @Deprecated + default void tick(Chunk[] chunks) { + throw new UnsupportedOperationException("TickableProvider#tick is not supported anymore"); + } + + /** + * Simulate a tick on a list of provided chunks. + * * @param chunks The chunks to tick. */ - void tick(Chunk[] chunks); + default void tick(Collection chunks) { + tick(chunks.toArray(new Chunk[0])); + } } diff --git a/API/src/main/java/com/bgsoftware/wildloaders/api/hooks/WorldsProvider.java b/API/src/main/java/com/bgsoftware/wildloaders/api/hooks/WorldsProvider.java new file mode 100644 index 0000000..d1f8943 --- /dev/null +++ b/API/src/main/java/com/bgsoftware/wildloaders/api/hooks/WorldsProvider.java @@ -0,0 +1,18 @@ +package com.bgsoftware.wildloaders.api.hooks; + +import org.bukkit.World; + +import javax.annotation.Nullable; + +public interface WorldsProvider { + + /** + * Load a world. + * + * @param worldName The name of the world + * @return The loaded world, or null if couldn't load the world. + */ + @Nullable + World loadWorld(String worldName); + +} diff --git a/API/src/main/java/com/bgsoftware/wildloaders/api/loaders/ChunkLoader.java b/API/src/main/java/com/bgsoftware/wildloaders/api/loaders/ChunkLoader.java index f0cd6fb..92fecaa 100644 --- a/API/src/main/java/com/bgsoftware/wildloaders/api/loaders/ChunkLoader.java +++ b/API/src/main/java/com/bgsoftware/wildloaders/api/loaders/ChunkLoader.java @@ -34,9 +34,17 @@ public interface ChunkLoader { /** * Get the chunks that this chunk-loader is loading. + * + * @deprecated See {@link #getLoadedChunksCollection()} */ + @Deprecated Chunk[] getLoadedChunks(); + /** + * Get the chunks that this chunk-loader is loading. + */ + Collection getLoadedChunksCollection(); + /** * Get the NPC of this chunk loader. */ diff --git a/API/src/main/java/com/bgsoftware/wildloaders/api/managers/ProvidersManager.java b/API/src/main/java/com/bgsoftware/wildloaders/api/managers/ProvidersManager.java index bc6fac1..ec8400e 100644 --- a/API/src/main/java/com/bgsoftware/wildloaders/api/managers/ProvidersManager.java +++ b/API/src/main/java/com/bgsoftware/wildloaders/api/managers/ProvidersManager.java @@ -2,6 +2,7 @@ package com.bgsoftware.wildloaders.api.managers; import com.bgsoftware.wildloaders.api.hooks.ClaimsProvider; import com.bgsoftware.wildloaders.api.hooks.TickableProvider; +import com.bgsoftware.wildloaders.api.hooks.WorldsProvider; public interface ProvidersManager { @@ -17,4 +18,11 @@ public interface ProvidersManager { */ void addTickableProvider(TickableProvider tickableProvider); + /** + * Add a worlds provider to the plugin. + * + * @param worldsProvider The worlds provider to add. + */ + void addWorldsProvider(WorldsProvider worldsProvider); + } diff --git a/Hooks/AdvancedSlimePaper/build.gradle b/Hooks/AdvancedSlimePaper/build.gradle new file mode 100644 index 0000000..97bd145 --- /dev/null +++ b/Hooks/AdvancedSlimePaper/build.gradle @@ -0,0 +1,19 @@ +group 'Hooks:AdvancedSlimePaper' + +java { + toolchain { + languageVersion.set(JavaLanguageVersion.of(17)) + } +} + +dependencies { + compileOnly 'com.infernalsuite:AdvancedSlimePaper:1.19.4-R0.1' + compileOnly "org.spigotmc:v1_8_R3-Taco:latest" + compileOnly project(":API") + compileOnly rootProject +} + +if (project.hasProperty('hook.compile_advancedslimepaper') && + !Boolean.valueOf(project.findProperty("hook.compile_advancedslimepaper").toString())) { + project.tasks.all { task -> task.enabled = false } +} \ No newline at end of file diff --git a/Hooks/AdvancedSlimePaper/src/main/java/com/bgsoftware/wildloaders/hooks/WorldsProvider_AdvancedSlimePaper.java b/Hooks/AdvancedSlimePaper/src/main/java/com/bgsoftware/wildloaders/hooks/WorldsProvider_AdvancedSlimePaper.java new file mode 100644 index 0000000..13dcc0a --- /dev/null +++ b/Hooks/AdvancedSlimePaper/src/main/java/com/bgsoftware/wildloaders/hooks/WorldsProvider_AdvancedSlimePaper.java @@ -0,0 +1,49 @@ +package com.bgsoftware.wildloaders.hooks; + +import com.bgsoftware.wildloaders.WildLoadersPlugin; +import com.bgsoftware.wildloaders.api.hooks.WorldsProvider; +import com.infernalsuite.aswm.api.SlimePlugin; +import com.infernalsuite.aswm.api.loaders.SlimeLoader; +import com.infernalsuite.aswm.api.world.SlimeWorld; +import com.infernalsuite.aswm.api.world.properties.SlimePropertyMap; +import org.bukkit.Bukkit; +import org.bukkit.World; + +import java.util.Arrays; +import java.util.List; + +public class WorldsProvider_AdvancedSlimePaper implements WorldsProvider { + + private static final List WORLD_LOADERS = Arrays.asList("file", "mysql", "mongodb", "redis", "api"); + private static final SlimePropertyMap EMPTY_PROPERTIES = new SlimePropertyMap(); + + private final SlimePlugin slimePlugin; + + public WorldsProvider_AdvancedSlimePaper() { + this.slimePlugin = (SlimePlugin) Bukkit.getPluginManager().getPlugin("SlimeWorldManager"); + } + + @Override + public World loadWorld(String worldName) { + for (String loaderName : WORLD_LOADERS) { + SlimeLoader slimeLoader = this.slimePlugin.getLoader(loaderName); + try { + if (slimeLoader != null && slimeLoader.worldExists(worldName)) { + SlimeWorld slimeWorld = slimePlugin.loadWorld(slimeLoader, worldName, false, EMPTY_PROPERTIES); + if (slimeWorld != null) { + slimePlugin.loadWorld(slimeWorld); + World bukkitWorld = Bukkit.getWorld(slimeWorld.getName()); + if (bukkitWorld != null) + return bukkitWorld; + } + } + } catch (Exception error) { + WildLoadersPlugin.log("An error occurred while trying to load world " + worldName); + error.printStackTrace(); + } + } + + return null; + } + +} diff --git a/Hooks/AdvancedSlimeWorldManager/build.gradle b/Hooks/AdvancedSlimeWorldManager/build.gradle new file mode 100644 index 0000000..0162d85 --- /dev/null +++ b/Hooks/AdvancedSlimeWorldManager/build.gradle @@ -0,0 +1,19 @@ +group 'Hooks:AdvancedSlimeWorldManager' + +java { + toolchain { + languageVersion.set(JavaLanguageVersion.of(17)) + } +} + +dependencies { + compileOnly "com.grinderwolf:slimeworldmanager-api:2.10.0" + compileOnly "org.spigotmc:v1_8_R3-Taco:latest" + compileOnly project(":API") + compileOnly rootProject +} + +if (project.hasProperty('hook.compile_advancedslimeworldmanager') && + !Boolean.valueOf(project.findProperty("hook.compile_advancedslimeworldmanager").toString())) { + project.tasks.all { task -> task.enabled = false } +} \ No newline at end of file diff --git a/Hooks/AdvancedSlimeWorldManager/src/main/java/com/bgsoftware/wildloaders/hooks/WorldsProvider_AdvancedSlimeWorldManager.java b/Hooks/AdvancedSlimeWorldManager/src/main/java/com/bgsoftware/wildloaders/hooks/WorldsProvider_AdvancedSlimeWorldManager.java new file mode 100644 index 0000000..4d69899 --- /dev/null +++ b/Hooks/AdvancedSlimeWorldManager/src/main/java/com/bgsoftware/wildloaders/hooks/WorldsProvider_AdvancedSlimeWorldManager.java @@ -0,0 +1,48 @@ +package com.bgsoftware.wildloaders.hooks; + +import com.bgsoftware.wildloaders.WildLoadersPlugin; +import com.bgsoftware.wildloaders.api.hooks.WorldsProvider; +import com.grinderwolf.swm.api.SlimePlugin; +import com.grinderwolf.swm.api.loaders.SlimeLoader; +import com.grinderwolf.swm.api.world.SlimeWorld; +import com.grinderwolf.swm.api.world.properties.SlimePropertyMap; +import org.bukkit.Bukkit; +import org.bukkit.World; + +import java.util.Arrays; +import java.util.List; + +public class WorldsProvider_AdvancedSlimeWorldManager implements WorldsProvider { + + private static final List WORLD_LOADERS = Arrays.asList("file", "mysql", "mongodb", "redis", "api"); + private static final SlimePropertyMap EMPTY_PROPERTIES = new SlimePropertyMap(); + + private final SlimePlugin slimePlugin; + + public WorldsProvider_AdvancedSlimeWorldManager() { + this.slimePlugin = (SlimePlugin) Bukkit.getPluginManager().getPlugin("SlimeWorldManager"); + } + + @Override + public World loadWorld(String worldName) { + for (String loaderName : WORLD_LOADERS) { + SlimeLoader slimeLoader = this.slimePlugin.getLoader(loaderName); + try { + if (slimeLoader != null && slimeLoader.worldExists(worldName)) { + SlimeWorld slimeWorld = slimePlugin.loadWorld(slimeLoader, worldName, false, EMPTY_PROPERTIES); + if (slimeWorld != null) { + World bukkitWorld = Bukkit.getWorld(slimeWorld.getName()); + if (bukkitWorld != null) + return bukkitWorld; + } + } + } catch (Exception error) { + WildLoadersPlugin.log("An error occurred while trying to load world " + worldName); + error.printStackTrace(); + } + } + + return null; + } + +} diff --git a/Hooks/EpicSpawners6/src/main/java/com/bgsoftware/wildloaders/hooks/TickableProvider_EpicSpawners6.java b/Hooks/EpicSpawners6/src/main/java/com/bgsoftware/wildloaders/hooks/TickableProvider_EpicSpawners6.java index 907b970..b63e559 100644 --- a/Hooks/EpicSpawners6/src/main/java/com/bgsoftware/wildloaders/hooks/TickableProvider_EpicSpawners6.java +++ b/Hooks/EpicSpawners6/src/main/java/com/bgsoftware/wildloaders/hooks/TickableProvider_EpicSpawners6.java @@ -5,25 +5,26 @@ import com.songoda.epicspawners.EpicSpawners; import org.bukkit.Chunk; import org.bukkit.Location; +import java.util.Collection; import java.util.HashMap; -import java.util.List; +import java.util.HashSet; import java.util.Map; -import java.util.stream.Collectors; -import java.util.stream.Stream; +import java.util.Set; public final class TickableProvider_EpicSpawners6 implements TickableProvider { private final Map spawnerDelays = new HashMap<>(); @Override - public void tick(Chunk[] chunks) { + public void tick(Collection chunks) { if (EpicSpawners.getInstance().getSpawnerManager() == null) return; - List chunkList = Stream.of(chunks).map(chunk -> pair(chunk.getX(), chunk.getZ())).collect(Collectors.toList()); + Set chunkKeys = new HashSet<>(); + chunks.forEach(chunk -> chunkKeys.add(pair(chunk.getX(), chunk.getZ()))); EpicSpawners.getInstance().getSpawnerManager().getSpawners().stream() - .filter(spawner -> chunkList.contains(pair(spawner.getX() >> 4, spawner.getZ() >> 4))) + .filter(spawner -> chunkKeys.contains(pair(spawner.getX() >> 4, spawner.getZ() >> 4))) .forEach(spawner -> { Location location = spawner.getLocation(); TickDelay tickDelay = spawnerDelays.get(location); diff --git a/Hooks/EpicSpawners7/src/main/java/com/bgsoftware/wildloaders/hooks/TickableProvider_EpicSpawners7.java b/Hooks/EpicSpawners7/src/main/java/com/bgsoftware/wildloaders/hooks/TickableProvider_EpicSpawners7.java index 29903b2..aff3af3 100644 --- a/Hooks/EpicSpawners7/src/main/java/com/bgsoftware/wildloaders/hooks/TickableProvider_EpicSpawners7.java +++ b/Hooks/EpicSpawners7/src/main/java/com/bgsoftware/wildloaders/hooks/TickableProvider_EpicSpawners7.java @@ -5,25 +5,26 @@ import com.songoda.epicspawners.EpicSpawners; import org.bukkit.Chunk; import org.bukkit.Location; +import java.util.Collection; import java.util.HashMap; -import java.util.List; +import java.util.HashSet; import java.util.Map; -import java.util.stream.Collectors; -import java.util.stream.Stream; +import java.util.Set; public final class TickableProvider_EpicSpawners7 implements TickableProvider { private final Map spawnerDelays = new HashMap<>(); @Override - public void tick(Chunk[] chunks) { + public void tick(Collection chunks) { if (EpicSpawners.getInstance().getSpawnerManager() == null) return; - List chunkList = Stream.of(chunks).map(chunk -> pair(chunk.getX(), chunk.getZ())).collect(Collectors.toList()); + Set chunkKeys = new HashSet<>(); + chunks.forEach(chunk -> chunkKeys.add(pair(chunk.getX(), chunk.getZ()))); EpicSpawners.getInstance().getSpawnerManager().getSpawners().stream() - .filter(spawner -> chunkList.contains(pair(spawner.getX() >> 4, spawner.getZ() >> 4))) + .filter(spawner -> chunkKeys.contains(pair(spawner.getX() >> 4, spawner.getZ() >> 4))) .forEach(spawner -> { Location location = spawner.getLocation(); TickDelay tickDelay = spawnerDelays.get(location); diff --git a/Hooks/EpicSpawners8/src/main/java/com/bgsoftware/wildloaders/hooks/TickableProvider_EpicSpawners8.java b/Hooks/EpicSpawners8/src/main/java/com/bgsoftware/wildloaders/hooks/TickableProvider_EpicSpawners8.java index dd0b27c..74ead0f 100644 --- a/Hooks/EpicSpawners8/src/main/java/com/bgsoftware/wildloaders/hooks/TickableProvider_EpicSpawners8.java +++ b/Hooks/EpicSpawners8/src/main/java/com/bgsoftware/wildloaders/hooks/TickableProvider_EpicSpawners8.java @@ -5,25 +5,26 @@ import com.craftaro.epicspawners.api.EpicSpawnersApi; import org.bukkit.Chunk; import org.bukkit.Location; +import java.util.Collection; import java.util.HashMap; -import java.util.List; +import java.util.HashSet; import java.util.Map; -import java.util.stream.Collectors; -import java.util.stream.Stream; +import java.util.Set; public final class TickableProvider_EpicSpawners8 implements TickableProvider { private final Map spawnerDelays = new HashMap<>(); @Override - public void tick(Chunk[] chunks) { + public void tick(Collection chunks) { if (EpicSpawnersApi.getSpawnerManager() == null) return; - List chunkList = Stream.of(chunks).map(chunk -> pair(chunk.getX(), chunk.getZ())).collect(Collectors.toList()); + Set chunkKeys = new HashSet<>(); + chunks.forEach(chunk -> chunkKeys.add(pair(chunk.getX(), chunk.getZ()))); EpicSpawnersApi.getSpawnerManager().getSpawners().stream() - .filter(spawner -> chunkList.contains(pair(spawner.getX() >> 4, spawner.getZ() >> 4))) + .filter(spawner -> chunkKeys.contains(pair(spawner.getX() >> 4, spawner.getZ() >> 4))) .forEach(spawner -> { Location location = spawner.getLocation(); TickDelay tickDelay = spawnerDelays.get(location); diff --git a/Hooks/Folia/build.gradle b/Hooks/Folia/build.gradle new file mode 100644 index 0000000..9a6d3f8 --- /dev/null +++ b/Hooks/Folia/build.gradle @@ -0,0 +1,22 @@ +group 'Hooks:Folia' + +java { + toolchain { + languageVersion.set(JavaLanguageVersion.of(17)) + } +} + +repositories { + maven { url 'https://repo.papermc.io/repository/maven-public/' } +} + +dependencies { + compileOnly 'dev.folia:folia-api:1.20.1-R0.1-SNAPSHOT' + compileOnly project(":API") + compileOnly rootProject +} + +if (project.hasProperty('hook.compile_folia') && + !Boolean.valueOf(project.findProperty("hook.compile_folia").toString())) { + project.tasks.all { task -> task.enabled = false } +} \ No newline at end of file diff --git a/Hooks/Folia/src/main/java/com/bgsoftware/wildloaders/scheduler/FoliaSchedulerImplementation.java b/Hooks/Folia/src/main/java/com/bgsoftware/wildloaders/scheduler/FoliaSchedulerImplementation.java new file mode 100644 index 0000000..9d4b7e4 --- /dev/null +++ b/Hooks/Folia/src/main/java/com/bgsoftware/wildloaders/scheduler/FoliaSchedulerImplementation.java @@ -0,0 +1,85 @@ +package com.bgsoftware.wildloaders.scheduler; + +import com.bgsoftware.wildloaders.WildLoadersPlugin; +import org.bukkit.Bukkit; +import org.bukkit.World; +import org.bukkit.entity.Entity; + +import java.util.concurrent.TimeUnit; + +public class FoliaSchedulerImplementation implements ISchedulerImplementation { + + public static final FoliaSchedulerImplementation INSTANCE = new FoliaSchedulerImplementation(); + + private static final WildLoadersPlugin plugin = WildLoadersPlugin.getPlugin(); + + private FoliaSchedulerImplementation() { + } + + @Override + public boolean isRegionScheduler() { + return true; + } + + @Override + public ScheduledTask scheduleTask(World world, int chunkX, int chunkZ, Runnable task, long delay) { + io.papermc.paper.threadedregions.scheduler.ScheduledTask handle; + if (delay <= 0) { + handle = Bukkit.getServer().getRegionScheduler().run(plugin, world, chunkX, chunkZ, v -> task.run()); + } else { + handle = Bukkit.getServer().getRegionScheduler().runDelayed(plugin, world, chunkX, chunkZ, v -> task.run(), delay); + } + return new FoliaScheduledTask(handle); + } + + @Override + public ScheduledTask scheduleTask(Entity entity, Runnable task, long delay) { + io.papermc.paper.threadedregions.scheduler.ScheduledTask handle; + if (delay <= 0) { + handle = entity.getScheduler().run(plugin, v -> task.run(), task); + } else { + handle = entity.getScheduler().runDelayed(plugin, v -> task.run(), task, delay); + } + return new FoliaScheduledTask(handle); + } + + @Override + public ScheduledTask scheduleTask(Runnable task, long delay) { + io.papermc.paper.threadedregions.scheduler.ScheduledTask handle; + if (delay <= 0) { + handle = Bukkit.getServer().getGlobalRegionScheduler().run(plugin, v -> task.run()); + } else { + handle = Bukkit.getServer().getGlobalRegionScheduler().runDelayed(plugin, v -> task.run(), delay); + } + + return new FoliaScheduledTask(handle); + } + + @Override + public ScheduledTask scheduleAsyncTask(Runnable task, long delay) { + io.papermc.paper.threadedregions.scheduler.ScheduledTask handle; + if (delay <= 0) { + handle = Bukkit.getServer().getAsyncScheduler().runNow(plugin, v -> task.run()); + } else { + handle = Bukkit.getServer().getAsyncScheduler().runDelayed(plugin, v -> task.run(), delay * 50L, TimeUnit.MILLISECONDS); + } + + return new FoliaScheduledTask(handle); + } + + private static class FoliaScheduledTask implements ScheduledTask { + + private final io.papermc.paper.threadedregions.scheduler.ScheduledTask handle; + + public FoliaScheduledTask(io.papermc.paper.threadedregions.scheduler.ScheduledTask handle) { + this.handle = handle; + } + + @Override + public void cancel() { + if (!handle.isCancelled()) + handle.cancel(); + } + } + +} diff --git a/Hooks/SlimeWorldManager/build.gradle b/Hooks/SlimeWorldManager/build.gradle new file mode 100644 index 0000000..29a0978 --- /dev/null +++ b/Hooks/SlimeWorldManager/build.gradle @@ -0,0 +1,13 @@ +group 'Hooks:SlimeWorldManager' + +dependencies { + compileOnly "com.grinderwolf:slimeworldmanager-api:2.2.1" + compileOnly "org.spigotmc:v1_8_R3-Taco:latest" + compileOnly project(":API") + compileOnly rootProject +} + +if (project.hasProperty('hook.compile_slimeworldmanager') && + !Boolean.valueOf(project.findProperty("hook.compile_slimeworldmanager").toString())) { + project.tasks.all { task -> task.enabled = false } +} \ No newline at end of file diff --git a/Hooks/SlimeWorldManager/src/main/java/com/bgsoftware/wildloaders/hooks/WorldsProvider_SlimeWorldManager.java b/Hooks/SlimeWorldManager/src/main/java/com/bgsoftware/wildloaders/hooks/WorldsProvider_SlimeWorldManager.java new file mode 100644 index 0000000..2569941 --- /dev/null +++ b/Hooks/SlimeWorldManager/src/main/java/com/bgsoftware/wildloaders/hooks/WorldsProvider_SlimeWorldManager.java @@ -0,0 +1,48 @@ +package com.bgsoftware.wildloaders.hooks; + +import com.bgsoftware.wildloaders.WildLoadersPlugin; +import com.bgsoftware.wildloaders.api.hooks.WorldsProvider; +import com.grinderwolf.swm.api.SlimePlugin; +import com.grinderwolf.swm.api.loaders.SlimeLoader; +import com.grinderwolf.swm.api.world.SlimeWorld; +import com.grinderwolf.swm.api.world.properties.SlimePropertyMap; +import org.bukkit.Bukkit; +import org.bukkit.World; + +import java.util.Arrays; +import java.util.List; + +public class WorldsProvider_SlimeWorldManager implements WorldsProvider { + + private static final List WORLD_LOADERS = Arrays.asList("file", "mysql", "mongodb", "redis", "api"); + private static final SlimePropertyMap EMPTY_PROPERTIES = new SlimePropertyMap(); + + private final SlimePlugin slimePlugin; + + public WorldsProvider_SlimeWorldManager() { + this.slimePlugin = (SlimePlugin) Bukkit.getPluginManager().getPlugin("SlimeWorldManager"); + } + + @Override + public World loadWorld(String worldName) { + for (String loaderName : WORLD_LOADERS) { + SlimeLoader slimeLoader = this.slimePlugin.getLoader(loaderName); + try { + if (slimeLoader != null && slimeLoader.worldExists(worldName)) { + SlimeWorld slimeWorld = slimePlugin.loadWorld(slimeLoader, worldName, false, EMPTY_PROPERTIES); + if (slimeWorld != null) { + World bukkitWorld = Bukkit.getWorld(slimeWorld.getName()); + if (bukkitWorld != null) + return bukkitWorld; + } + } + } catch (Exception error) { + WildLoadersPlugin.log("An error occurred while trying to load world " + worldName); + error.printStackTrace(); + } + } + + return null; + } + +} diff --git a/NMS/v1_12_R1/src/main/java/com/bgsoftware/wildloaders/nms/v1_12_R1/ChunkLoaderNPC.java b/NMS/v1_12_R1/src/main/java/com/bgsoftware/wildloaders/nms/v1_12_R1/ChunkLoaderNPC.java index 2077305..aad64d8 100644 --- a/NMS/v1_12_R1/src/main/java/com/bgsoftware/wildloaders/nms/v1_12_R1/ChunkLoaderNPC.java +++ b/NMS/v1_12_R1/src/main/java/com/bgsoftware/wildloaders/nms/v1_12_R1/ChunkLoaderNPC.java @@ -1,5 +1,7 @@ package com.bgsoftware.wildloaders.nms.v1_12_R1; +import com.bgsoftware.common.reflection.ReflectField; +import com.bgsoftware.common.reflection.ReflectMethod; import com.bgsoftware.wildloaders.handlers.NPCHandler; import com.bgsoftware.wildloaders.npc.DummyChannel; import com.mojang.authlib.GameProfile; @@ -38,6 +40,11 @@ import java.util.UUID; public final class ChunkLoaderNPC extends EntityPlayer implements com.bgsoftware.wildloaders.api.npc.ChunkLoaderNPC { + private static final ReflectMethod PLAYER_SET_VIEW_DISTANCE = new ReflectMethod<>( + EntityPlayer.class, "setViewDistance", int.class); + private static final ReflectField PLAYER_AFFECTS_SPAWNING = new ReflectField<>( + EntityPlayer.class, boolean.class, "affectsSpawning"); + private final AxisAlignedBB boundingBox; private final AdvancementDataPlayer advancements; @@ -53,8 +60,15 @@ public final class ChunkLoaderNPC extends EntityPlayer implements com.bgsoftware this.advancements = new DummyPlayerAdvancements(server, this); this.playerInteractManager.setGameMode(EnumGamemode.CREATIVE); + + fallDistance = 0.0F; fauxSleeping = true; + if (PLAYER_SET_VIEW_DISTANCE.isValid()) + PLAYER_SET_VIEW_DISTANCE.invoke(this, 0); + if (PLAYER_AFFECTS_SPAWNING.isValid()) + PLAYER_AFFECTS_SPAWNING.set(this, true); + spawnIn(world); setLocation(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); diff --git a/NMS/v1_12_R1/src/main/java/com/bgsoftware/wildloaders/nms/v1_12_R1/NMSAdapterImpl.java b/NMS/v1_12_R1/src/main/java/com/bgsoftware/wildloaders/nms/v1_12_R1/NMSAdapterImpl.java index 300a1cb..04726cb 100644 --- a/NMS/v1_12_R1/src/main/java/com/bgsoftware/wildloaders/nms/v1_12_R1/NMSAdapterImpl.java +++ b/NMS/v1_12_R1/src/main/java/com/bgsoftware/wildloaders/nms/v1_12_R1/NMSAdapterImpl.java @@ -5,6 +5,7 @@ import com.bgsoftware.wildloaders.api.loaders.ChunkLoader; import com.bgsoftware.wildloaders.loaders.ITileEntityChunkLoader; import com.bgsoftware.wildloaders.nms.NMSAdapter; import com.bgsoftware.wildloaders.nms.v1_12_R1.loader.TileEntityChunkLoader; +import com.bgsoftware.wildloaders.scheduler.Scheduler; import net.minecraft.server.v1_12_R1.Block; import net.minecraft.server.v1_12_R1.BlockPosition; import net.minecraft.server.v1_12_R1.Chunk; @@ -113,18 +114,10 @@ public final class NMSAdapterImpl implements NMSAdapter { TileEntityChunkLoader tileEntityChunkLoader = new TileEntityChunkLoader(chunkLoader, world, blockPosition); world.tileEntityListTick.add(tileEntityChunkLoader); - for (org.bukkit.Chunk bukkitChunk : chunkLoader.getLoadedChunks()) { - Chunk chunk = ((CraftChunk) bukkitChunk).getHandle(); - chunk.tileEntities.values().stream().filter(tileEntity -> tileEntity instanceof TileEntityMobSpawner).forEach(tileEntity -> { - NBTTagCompound nbtTagCompound = new NBTTagCompound(); - tileEntity.save(nbtTagCompound); - nbtTagCompound.setShort("RequiredPlayerRange", (short) -1); - if (TILE_ENTITY_LOAD.isValid()) { - TILE_ENTITY_LOAD.invoke(tileEntity, nbtTagCompound); - } else { - tileEntity.a(nbtTagCompound); - } - }); + if (Scheduler.isRegionScheduler()) { + Scheduler.runTask(() -> setSpawnersRangeForLoader(chunkLoader, true)); + } else { + setSpawnersRangeForLoader(chunkLoader, true); } return tileEntityChunkLoader; @@ -147,18 +140,30 @@ public final class NMSAdapterImpl implements NMSAdapter { if (spawnParticle) world.a(null, 2001, blockPosition, Block.getCombinedId(world.getType(blockPosition))); - for (org.bukkit.Chunk bukkitChunk : chunkLoader.getLoadedChunks()) { + if (Scheduler.isRegionScheduler()) { + Scheduler.runTask(() -> setSpawnersRangeForLoader(chunkLoader, false)); + } else { + setSpawnersRangeForLoader(chunkLoader, false); + } + } + + private static void setSpawnersRangeForLoader(ChunkLoader chunkLoader, boolean loaded) { + short requiredPlayerRange = (short) (loaded ? -1 : 16); + for (org.bukkit.Chunk bukkitChunk : chunkLoader.getLoadedChunksCollection()) { Chunk chunk = ((CraftChunk) bukkitChunk).getHandle(); - chunk.tileEntities.values().stream().filter(tileEntity -> tileEntity instanceof TileEntityMobSpawner).forEach(tileEntity -> { - NBTTagCompound nbtTagCompound = new NBTTagCompound(); - tileEntity.save(nbtTagCompound); - nbtTagCompound.setShort("RequiredPlayerRange", (short) 16); - if (TILE_ENTITY_LOAD.isValid()) { - TILE_ENTITY_LOAD.invoke(tileEntity, nbtTagCompound); - } else { - tileEntity.a(nbtTagCompound); + + for (TileEntity tileEntity : chunk.tileEntities.values()) { + if (tileEntity instanceof TileEntityMobSpawner) { + NBTTagCompound nbtTagCompound = new NBTTagCompound(); + tileEntity.save(nbtTagCompound); + nbtTagCompound.setShort("RequiredPlayerRange", requiredPlayerRange); + if (TILE_ENTITY_LOAD.isValid()) { + TILE_ENTITY_LOAD.invoke(tileEntity, nbtTagCompound); + } else { + tileEntity.a(nbtTagCompound); + } } - }); + } } } diff --git a/NMS/v1_16_R3/src/main/java/com/bgsoftware/wildloaders/nms/v1_16_R3/ChunkLoaderNPC.java b/NMS/v1_16_R3/src/main/java/com/bgsoftware/wildloaders/nms/v1_16_R3/ChunkLoaderNPC.java index 109f936..b3462f0 100644 --- a/NMS/v1_16_R3/src/main/java/com/bgsoftware/wildloaders/nms/v1_16_R3/ChunkLoaderNPC.java +++ b/NMS/v1_16_R3/src/main/java/com/bgsoftware/wildloaders/nms/v1_16_R3/ChunkLoaderNPC.java @@ -40,6 +40,7 @@ import java.util.UUID; public final class ChunkLoaderNPC extends EntityPlayer implements com.bgsoftware.wildloaders.api.npc.ChunkLoaderNPC { + private final AxisAlignedBB boundingBox; private final AdvancementDataPlayer advancements; @@ -57,9 +58,16 @@ public final class ChunkLoaderNPC extends EntityPlayer implements com.bgsoftware this.advancements = new DummyPlayerAdvancements(server, this); this.playerInteractManager.setGameMode(EnumGamemode.CREATIVE); - clientViewDistance = 1; + fallDistance = 0.0F; fauxSleeping = true; + clientViewDistance = 0; + + try { + // Paper + affectsSpawning = true; + } catch (Throwable ignored) { + } spawnIn(world); setLocation(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); diff --git a/NMS/v1_16_R3/src/main/java/com/bgsoftware/wildloaders/nms/v1_16_R3/NMSAdapterImpl.java b/NMS/v1_16_R3/src/main/java/com/bgsoftware/wildloaders/nms/v1_16_R3/NMSAdapterImpl.java index 1fe8c25..ea6b926 100644 --- a/NMS/v1_16_R3/src/main/java/com/bgsoftware/wildloaders/nms/v1_16_R3/NMSAdapterImpl.java +++ b/NMS/v1_16_R3/src/main/java/com/bgsoftware/wildloaders/nms/v1_16_R3/NMSAdapterImpl.java @@ -4,6 +4,7 @@ import com.bgsoftware.wildloaders.api.loaders.ChunkLoader; import com.bgsoftware.wildloaders.loaders.ITileEntityChunkLoader; import com.bgsoftware.wildloaders.nms.NMSAdapter; import com.bgsoftware.wildloaders.nms.v1_16_R3.loader.TileEntityChunkLoader; +import com.bgsoftware.wildloaders.scheduler.Scheduler; import net.minecraft.server.v1_16_R3.Block; import net.minecraft.server.v1_16_R3.BlockPosition; import net.minecraft.server.v1_16_R3.Chunk; @@ -14,6 +15,7 @@ import net.minecraft.server.v1_16_R3.NBTTagCompound; import net.minecraft.server.v1_16_R3.NBTTagList; import net.minecraft.server.v1_16_R3.NBTTagLong; import net.minecraft.server.v1_16_R3.NBTTagString; +import net.minecraft.server.v1_16_R3.TileEntity; import net.minecraft.server.v1_16_R3.TileEntityMobSpawner; import net.minecraft.server.v1_16_R3.World; import net.minecraft.server.v1_16_R3.WorldServer; @@ -114,12 +116,10 @@ public final class NMSAdapterImpl implements NMSAdapter { TileEntityChunkLoader tileEntityChunkLoader = new TileEntityChunkLoader(chunkLoader, world, blockPosition); world.tileEntityListTick.add(tileEntityChunkLoader); - for (org.bukkit.Chunk bukkitChunk : chunkLoader.getLoadedChunks()) { - Chunk chunk = ((CraftChunk) bukkitChunk).getHandle(); - chunk.tileEntities.values().stream().filter(tileEntity -> tileEntity instanceof TileEntityMobSpawner) - .forEach(tileEntity -> ((TileEntityMobSpawner) tileEntity).getSpawner().requiredPlayerRange = -1); - - world.setForceLoaded(chunk.getPos().x, chunk.getPos().z, true); + if (Scheduler.isRegionScheduler()) { + Scheduler.runTask(() -> setChunksForcedForLoader(chunkLoader, world, true)); + } else { + setChunksForcedForLoader(chunkLoader, world, true); } return tileEntityChunkLoader; @@ -143,12 +143,25 @@ public final class NMSAdapterImpl implements NMSAdapter { if (spawnParticle) world.a(null, 2001, blockPosition, Block.getCombinedId(world.getType(blockPosition))); - for (org.bukkit.Chunk bukkitChunk : chunkLoader.getLoadedChunks()) { - Chunk chunk = ((CraftChunk) bukkitChunk).getHandle(); - chunk.tileEntities.values().stream().filter(tileEntity -> tileEntity instanceof TileEntityMobSpawner) - .forEach(tileEntity -> ((TileEntityMobSpawner) tileEntity).getSpawner().requiredPlayerRange = 16); + if (Scheduler.isRegionScheduler()) { + Scheduler.runTask(() -> setChunksForcedForLoader(chunkLoader, world, false)); + } else { + setChunksForcedForLoader(chunkLoader, world, false); + } + } - world.setForceLoaded(chunk.getPos().x, chunk.getPos().z, false); + private static void setChunksForcedForLoader(ChunkLoader chunkLoader, WorldServer worldServer, boolean forced) { + int requiredPlayerRange = forced ? -1 : 16; + for (org.bukkit.Chunk bukkitChunk : chunkLoader.getLoadedChunksCollection()) { + Chunk chunk = ((CraftChunk) bukkitChunk).getHandle(); + + for (TileEntity tileEntity : chunk.tileEntities.values()) { + if (tileEntity instanceof TileEntityMobSpawner) + ((TileEntityMobSpawner) tileEntity).getSpawner().requiredPlayerRange = requiredPlayerRange; + } + + ChunkCoordIntPair chunkCoord = chunk.getPos(); + worldServer.setForceLoaded(chunkCoord.x, chunkCoord.z, forced); } } diff --git a/NMS/v1_17/build.gradle b/NMS/v1_17/build.gradle index fd58971..d9456ad 100644 --- a/NMS/v1_17/build.gradle +++ b/NMS/v1_17/build.gradle @@ -1,5 +1,5 @@ plugins { - id("io.papermc.paperweight.userdev") version "1.6.0" + id("io.papermc.paperweight.userdev") version "1.7.1" } java { diff --git a/NMS/v1_17/src/main/java/com/bgsoftware/wildloaders/nms/v1_17/NMSAdapterImpl.java b/NMS/v1_17/src/main/java/com/bgsoftware/wildloaders/nms/v1_17/NMSAdapterImpl.java index 9747554..eacf437 100644 --- a/NMS/v1_17/src/main/java/com/bgsoftware/wildloaders/nms/v1_17/NMSAdapterImpl.java +++ b/NMS/v1_17/src/main/java/com/bgsoftware/wildloaders/nms/v1_17/NMSAdapterImpl.java @@ -5,6 +5,7 @@ import com.bgsoftware.wildloaders.loaders.ITileEntityChunkLoader; import com.bgsoftware.wildloaders.nms.NMSAdapter; import com.bgsoftware.wildloaders.nms.v1_17.loader.ChunkLoaderBlockEntity; import com.bgsoftware.wildloaders.nms.v1_17.npc.ChunkLoaderNPCWrapper; +import com.bgsoftware.wildloaders.scheduler.Scheduler; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; @@ -105,16 +106,10 @@ public final class NMSAdapterImpl implements NMSAdapter { ChunkLoaderBlockEntity ChunkLoaderBlockEntity = new ChunkLoaderBlockEntity(chunkLoader, serverLevel, blockPos); serverLevel.addBlockEntityTicker(ChunkLoaderBlockEntity.getTicker()); - for (org.bukkit.Chunk bukkitChunk : chunkLoader.getLoadedChunks()) { - LevelChunk levelChunk = ((CraftChunk) bukkitChunk).getHandle(); - levelChunk.getBlockEntities().values().stream() - .filter(blockEntity -> blockEntity instanceof SpawnerBlockEntity) - .forEach(blockEntity -> { - ((SpawnerBlockEntity) blockEntity).getSpawner().requiredPlayerRange = -1; - }); - - ChunkPos chunkPos = levelChunk.getPos(); - serverLevel.setChunkForced(chunkPos.x, chunkPos.z, true); + if (Scheduler.isRegionScheduler()) { + Scheduler.runTask(() -> setChunksForcedForLoader(chunkLoader, serverLevel, true)); + } else { + setChunksForcedForLoader(chunkLoader, serverLevel, true); } return ChunkLoaderBlockEntity; @@ -142,16 +137,25 @@ public final class NMSAdapterImpl implements NMSAdapter { if (spawnParticle) serverLevel.levelEvent(null, 2001, blockPos, Block.getId(serverLevel.getBlockState(blockPos))); - for (org.bukkit.Chunk bukkitChunk : chunkLoader.getLoadedChunks()) { + if (Scheduler.isRegionScheduler()) { + Scheduler.runTask(() -> setChunksForcedForLoader(chunkLoader, serverLevel, false)); + } else { + setChunksForcedForLoader(chunkLoader, serverLevel, false); + } + } + + private static void setChunksForcedForLoader(ChunkLoader chunkLoader, ServerLevel serverLevel, boolean forced) { + int requiredPlayerRange = forced ? -1 : 16; + for (org.bukkit.Chunk bukkitChunk : chunkLoader.getLoadedChunksCollection()) { LevelChunk levelChunk = ((CraftChunk) bukkitChunk).getHandle(); - levelChunk.getBlockEntities().values().stream() - .filter(blockEntity -> blockEntity instanceof SpawnerBlockEntity) - .forEach(blockEntity -> { - ((SpawnerBlockEntity) blockEntity).getSpawner().requiredPlayerRange = 16; - }); + + for (BlockEntity blockEntity : levelChunk.getBlockEntities().values()) { + if (blockEntity instanceof SpawnerBlockEntity spawnerBlockEntity) + spawnerBlockEntity.getSpawner().requiredPlayerRange = requiredPlayerRange; + } ChunkPos chunkPos = levelChunk.getPos(); - serverLevel.setChunkForced(chunkPos.x, chunkPos.z, false); + serverLevel.setChunkForced(chunkPos.x, chunkPos.z, forced); } } diff --git a/NMS/v1_17/src/main/java/com/bgsoftware/wildloaders/nms/v1_17/npc/ChunkLoaderPlayer.java b/NMS/v1_17/src/main/java/com/bgsoftware/wildloaders/nms/v1_17/npc/ChunkLoaderPlayer.java index 1e1b7e9..78d3c07 100644 --- a/NMS/v1_17/src/main/java/com/bgsoftware/wildloaders/nms/v1_17/npc/ChunkLoaderPlayer.java +++ b/NMS/v1_17/src/main/java/com/bgsoftware/wildloaders/nms/v1_17/npc/ChunkLoaderPlayer.java @@ -56,9 +56,16 @@ public final class ChunkLoaderPlayer extends ServerPlayer { this.advancements = new DummyPlayerAdvancements(minecraftServer, this); SET_GAMEMODE.invoke(this.gameMode, GameType.CREATIVE, null); - clientViewDistance = 1; + fallDistance = 0.0F; fauxSleeping = true; + clientViewDistance = 0; + + try { + // Paper + affectsSpawning = true; + } catch (Throwable ignored) { + } spawnIn(this.serverLevel); moveTo(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); diff --git a/NMS/v1_18/build.gradle b/NMS/v1_18/build.gradle index fcf94d1..89eeb80 100644 --- a/NMS/v1_18/build.gradle +++ b/NMS/v1_18/build.gradle @@ -1,5 +1,5 @@ plugins { - id("io.papermc.paperweight.userdev") version "1.6.0" + id("io.papermc.paperweight.userdev") version "1.7.1" } java { diff --git a/NMS/v1_18/src/main/java/com/bgsoftware/wildloaders/nms/v1_18/ChunkLoaderNPCImpl.java b/NMS/v1_18/src/main/java/com/bgsoftware/wildloaders/nms/v1_18/ChunkLoaderNPCImpl.java index f2d9757..5bc1f50 100644 --- a/NMS/v1_18/src/main/java/com/bgsoftware/wildloaders/nms/v1_18/ChunkLoaderNPCImpl.java +++ b/NMS/v1_18/src/main/java/com/bgsoftware/wildloaders/nms/v1_18/ChunkLoaderNPCImpl.java @@ -58,9 +58,16 @@ public final class ChunkLoaderNPCImpl extends ServerPlayer implements ChunkLoade this.advancements = new DummyPlayerAdvancements(minecraftServer, this); SET_GAMEMODE.invoke(this.gameMode, GameType.CREATIVE, null); - clientViewDistance = 1; + fallDistance = 0.0F; fauxSleeping = true; + clientViewDistance = 0; + + try { + // Paper + affectsSpawning = true; + } catch (Throwable ignored) { + } spawnIn(this.serverLevel); moveTo(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); diff --git a/NMS/v1_18/src/main/java/com/bgsoftware/wildloaders/nms/v1_18/NMSAdapterImpl.java b/NMS/v1_18/src/main/java/com/bgsoftware/wildloaders/nms/v1_18/NMSAdapterImpl.java index 5672bfb..39ad855 100644 --- a/NMS/v1_18/src/main/java/com/bgsoftware/wildloaders/nms/v1_18/NMSAdapterImpl.java +++ b/NMS/v1_18/src/main/java/com/bgsoftware/wildloaders/nms/v1_18/NMSAdapterImpl.java @@ -4,6 +4,7 @@ import com.bgsoftware.wildloaders.api.loaders.ChunkLoader; import com.bgsoftware.wildloaders.loaders.ITileEntityChunkLoader; import com.bgsoftware.wildloaders.nms.NMSAdapter; import com.bgsoftware.wildloaders.nms.v1_18.loader.ChunkLoaderBlockEntity; +import com.bgsoftware.wildloaders.scheduler.Scheduler; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; @@ -104,16 +105,10 @@ public final class NMSAdapterImpl implements NMSAdapter { ChunkLoaderBlockEntity ChunkLoaderBlockEntity = new ChunkLoaderBlockEntity(chunkLoader, serverLevel, blockPos); serverLevel.addBlockEntityTicker(ChunkLoaderBlockEntity.getTicker()); - for (org.bukkit.Chunk bukkitChunk : chunkLoader.getLoadedChunks()) { - LevelChunk levelChunk = ((CraftChunk) bukkitChunk).getHandle(); - levelChunk.getBlockEntities().values().stream() - .filter(blockEntity -> blockEntity instanceof SpawnerBlockEntity) - .forEach(blockEntity -> { - ((SpawnerBlockEntity) blockEntity).getSpawner().requiredPlayerRange = -1; - }); - - ChunkPos chunkPos = levelChunk.getPos(); - serverLevel.setChunkForced(chunkPos.x, chunkPos.z, true); + if (Scheduler.isRegionScheduler()) { + Scheduler.runTask(() -> setChunksForcedForLoader(chunkLoader, serverLevel, true)); + } else { + setChunksForcedForLoader(chunkLoader, serverLevel, true); } return ChunkLoaderBlockEntity; @@ -141,16 +136,25 @@ public final class NMSAdapterImpl implements NMSAdapter { if (spawnParticle) serverLevel.levelEvent(null, 2001, blockPos, Block.getId(serverLevel.getBlockState(blockPos))); - for (org.bukkit.Chunk bukkitChunk : chunkLoader.getLoadedChunks()) { + if (Scheduler.isRegionScheduler()) { + Scheduler.runTask(() -> setChunksForcedForLoader(chunkLoader, serverLevel, false)); + } else { + setChunksForcedForLoader(chunkLoader, serverLevel, false); + } + } + + private static void setChunksForcedForLoader(ChunkLoader chunkLoader, ServerLevel serverLevel, boolean forced) { + int requiredPlayerRange = forced ? -1 : 16; + for (org.bukkit.Chunk bukkitChunk : chunkLoader.getLoadedChunksCollection()) { LevelChunk levelChunk = ((CraftChunk) bukkitChunk).getHandle(); - levelChunk.getBlockEntities().values().stream() - .filter(blockEntity -> blockEntity instanceof SpawnerBlockEntity) - .forEach(blockEntity -> { - ((SpawnerBlockEntity) blockEntity).getSpawner().requiredPlayerRange = 16; - }); + + for (BlockEntity blockEntity : levelChunk.getBlockEntities().values()) { + if (blockEntity instanceof SpawnerBlockEntity spawnerBlockEntity) + spawnerBlockEntity.getSpawner().requiredPlayerRange = requiredPlayerRange; + } ChunkPos chunkPos = levelChunk.getPos(); - serverLevel.setChunkForced(chunkPos.x, chunkPos.z, false); + serverLevel.setChunkForced(chunkPos.x, chunkPos.z, forced); } } diff --git a/NMS/v1_19/build.gradle b/NMS/v1_19/build.gradle index a92e995..2285117 100644 --- a/NMS/v1_19/build.gradle +++ b/NMS/v1_19/build.gradle @@ -1,5 +1,5 @@ plugins { - id("io.papermc.paperweight.userdev") version "1.6.0" + id("io.papermc.paperweight.userdev") version "1.7.1" } java { diff --git a/NMS/v1_19/src/main/java/com/bgsoftware/wildloaders/nms/v1_19/ChunkLoaderNPCImpl.java b/NMS/v1_19/src/main/java/com/bgsoftware/wildloaders/nms/v1_19/ChunkLoaderNPCImpl.java index e6a2113..c167054 100644 --- a/NMS/v1_19/src/main/java/com/bgsoftware/wildloaders/nms/v1_19/ChunkLoaderNPCImpl.java +++ b/NMS/v1_19/src/main/java/com/bgsoftware/wildloaders/nms/v1_19/ChunkLoaderNPCImpl.java @@ -60,9 +60,16 @@ public final class ChunkLoaderNPCImpl extends ServerPlayer implements ChunkLoade this.advancements = new DummyPlayerAdvancements(minecraftServer, this); SET_GAMEMODE.invoke(this.gameMode, GameType.CREATIVE, null); - clientViewDistance = 1; + fallDistance = 0.0F; fauxSleeping = true; + clientViewDistance = 0; + + try { + // Paper + affectsSpawning = true; + } catch (Throwable ignored) { + } spawnIn(this.serverLevel); moveTo(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); diff --git a/NMS/v1_19/src/main/java/com/bgsoftware/wildloaders/nms/v1_19/EntityHologram.java b/NMS/v1_19/src/main/java/com/bgsoftware/wildloaders/nms/v1_19/EntityHologram.java index 287e14c..796557c 100644 --- a/NMS/v1_19/src/main/java/com/bgsoftware/wildloaders/nms/v1_19/EntityHologram.java +++ b/NMS/v1_19/src/main/java/com/bgsoftware/wildloaders/nms/v1_19/EntityHologram.java @@ -1,6 +1,7 @@ package com.bgsoftware.wildloaders.nms.v1_19; import com.bgsoftware.wildloaders.api.holograms.Hologram; +import com.bgsoftware.wildloaders.scheduler.Scheduler; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerLevel; @@ -15,6 +16,7 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; import org.bukkit.Bukkit; +import org.bukkit.World; import org.bukkit.craftbukkit.v1_19_R3.CraftServer; import org.bukkit.craftbukkit.v1_19_R3.entity.CraftArmorStand; import org.bukkit.craftbukkit.v1_19_R3.entity.CraftEntity; @@ -48,7 +50,14 @@ public final class EntityHologram extends ArmorStand implements Hologram { @Override public void removeHologram() { - super.remove(RemovalReason.DISCARDED); + if (Scheduler.isRegionScheduler() || !Bukkit.isPrimaryThread()) { + World world = level.getWorld(); + int chunkX = getBlockX() >> 4; + int chunkZ = getBlockZ() >> 4; + Scheduler.runTask(world, chunkX, chunkZ, () -> super.remove(RemovalReason.DISCARDED)); + } else { + super.remove(RemovalReason.DISCARDED); + } } @Override diff --git a/NMS/v1_19/src/main/java/com/bgsoftware/wildloaders/nms/v1_19/NMSAdapterImpl.java b/NMS/v1_19/src/main/java/com/bgsoftware/wildloaders/nms/v1_19/NMSAdapterImpl.java index 386bec5..d4d344e 100644 --- a/NMS/v1_19/src/main/java/com/bgsoftware/wildloaders/nms/v1_19/NMSAdapterImpl.java +++ b/NMS/v1_19/src/main/java/com/bgsoftware/wildloaders/nms/v1_19/NMSAdapterImpl.java @@ -4,6 +4,7 @@ import com.bgsoftware.wildloaders.api.loaders.ChunkLoader; import com.bgsoftware.wildloaders.loaders.ITileEntityChunkLoader; import com.bgsoftware.wildloaders.nms.NMSAdapter; import com.bgsoftware.wildloaders.nms.v1_19.loader.ChunkLoaderBlockEntity; +import com.bgsoftware.wildloaders.scheduler.Scheduler; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; @@ -103,16 +104,10 @@ public final class NMSAdapterImpl implements NMSAdapter { ChunkLoaderBlockEntity ChunkLoaderBlockEntity = new ChunkLoaderBlockEntity(chunkLoader, serverLevel, blockPos); serverLevel.addBlockEntityTicker(ChunkLoaderBlockEntity.getTicker()); - for (org.bukkit.Chunk bukkitChunk : chunkLoader.getLoadedChunks()) { - LevelChunk levelChunk = serverLevel.getChunk(bukkitChunk.getX(), bukkitChunk.getZ()); - levelChunk.getBlockEntities().values().stream() - .filter(blockEntity -> blockEntity instanceof SpawnerBlockEntity) - .forEach(blockEntity -> { - ((SpawnerBlockEntity) blockEntity).getSpawner().requiredPlayerRange = -1; - }); - - ChunkPos chunkPos = levelChunk.getPos(); - serverLevel.setChunkForced(chunkPos.x, chunkPos.z, true); + if (Scheduler.isRegionScheduler()) { + Scheduler.runTask(() -> setChunksForcedForLoader(chunkLoader, serverLevel, true)); + } else { + setChunksForcedForLoader(chunkLoader, serverLevel, true); } return ChunkLoaderBlockEntity; @@ -140,16 +135,25 @@ public final class NMSAdapterImpl implements NMSAdapter { if (spawnParticle) serverLevel.levelEvent(null, 2001, blockPos, Block.getId(serverLevel.getBlockState(blockPos))); - for (org.bukkit.Chunk bukkitChunk : chunkLoader.getLoadedChunks()) { + if (Scheduler.isRegionScheduler()) { + Scheduler.runTask(() -> setChunksForcedForLoader(chunkLoader, serverLevel, false)); + } else { + setChunksForcedForLoader(chunkLoader, serverLevel, false); + } + } + + private static void setChunksForcedForLoader(ChunkLoader chunkLoader, ServerLevel serverLevel, boolean forced) { + int requiredPlayerRange = forced ? -1 : 16; + for (org.bukkit.Chunk bukkitChunk : chunkLoader.getLoadedChunksCollection()) { LevelChunk levelChunk = serverLevel.getChunk(bukkitChunk.getX(), bukkitChunk.getZ()); - levelChunk.getBlockEntities().values().stream() - .filter(blockEntity -> blockEntity instanceof SpawnerBlockEntity) - .forEach(blockEntity -> { - ((SpawnerBlockEntity) blockEntity).getSpawner().requiredPlayerRange = 16; - }); + + for (BlockEntity blockEntity : levelChunk.getBlockEntities().values()) { + if (blockEntity instanceof SpawnerBlockEntity spawnerBlockEntity) + spawnerBlockEntity.getSpawner().requiredPlayerRange = requiredPlayerRange; + } ChunkPos chunkPos = levelChunk.getPos(); - serverLevel.setChunkForced(chunkPos.x, chunkPos.z, false); + serverLevel.setChunkForced(chunkPos.x, chunkPos.z, forced); } } diff --git a/NMS/v1_19/src/main/java/com/bgsoftware/wildloaders/nms/v1_19/loader/ChunkLoaderBlockEntityTicker.java b/NMS/v1_19/src/main/java/com/bgsoftware/wildloaders/nms/v1_19/loader/ChunkLoaderBlockEntityTicker.java index 00e2ed0..1926a87 100644 --- a/NMS/v1_19/src/main/java/com/bgsoftware/wildloaders/nms/v1_19/loader/ChunkLoaderBlockEntityTicker.java +++ b/NMS/v1_19/src/main/java/com/bgsoftware/wildloaders/nms/v1_19/loader/ChunkLoaderBlockEntityTicker.java @@ -1,6 +1,7 @@ package com.bgsoftware.wildloaders.nms.v1_19.loader; import net.minecraft.core.BlockPos; +import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.entity.TickingBlockEntity; @@ -27,4 +28,8 @@ public record ChunkLoaderBlockEntityTicker( return BlockEntityType.getKey(chunkLoaderBlockEntity.getType()) + ""; } + public BlockEntity getTileEntity() { + return chunkLoaderBlockEntity; + } + } diff --git a/NMS/v1_20_1/src/main/java/com/bgsoftware/wildloaders/nms/v1_20_1/ChunkLoaderNPCImpl.java b/NMS/v1_20_1/src/main/java/com/bgsoftware/wildloaders/nms/v1_20_1/ChunkLoaderNPCImpl.java deleted file mode 100644 index 74fbbf8..0000000 --- a/NMS/v1_20_1/src/main/java/com/bgsoftware/wildloaders/nms/v1_20_1/ChunkLoaderNPCImpl.java +++ /dev/null @@ -1,237 +0,0 @@ -package com.bgsoftware.wildloaders.nms.v1_20_1; - -import com.bgsoftware.common.reflection.ReflectMethod; -import com.bgsoftware.wildloaders.api.npc.ChunkLoaderNPC; -import com.bgsoftware.wildloaders.handlers.NPCHandler; -import com.bgsoftware.wildloaders.npc.DummyChannel; -import com.mojang.authlib.GameProfile; -import net.minecraft.advancements.Advancement; -import net.minecraft.advancements.AdvancementProgress; -import net.minecraft.core.BlockPos; -import net.minecraft.network.Connection; -import net.minecraft.network.protocol.Packet; -import net.minecraft.network.protocol.PacketFlow; -import net.minecraft.network.protocol.game.ServerboundChatPacket; -import net.minecraft.network.protocol.game.ServerboundContainerClickPacket; -import net.minecraft.network.protocol.game.ServerboundMovePlayerPacket; -import net.minecraft.network.protocol.game.ServerboundPlayerActionPacket; -import net.minecraft.network.protocol.game.ServerboundSetCarriedItemPacket; -import net.minecraft.network.protocol.game.ServerboundSignUpdatePacket; -import net.minecraft.network.protocol.game.ServerboundUseItemPacket; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.PlayerAdvancements; -import net.minecraft.server.ServerAdvancementManager; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.server.level.ServerPlayerGameMode; -import net.minecraft.server.network.ServerGamePacketListenerImpl; -import net.minecraft.world.level.GameType; -import net.minecraft.world.level.storage.LevelResource; -import net.minecraft.world.phys.AABB; -import org.bukkit.Location; -import org.bukkit.craftbukkit.v1_20_R1.CraftWorld; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.Nullable; - -import java.io.File; -import java.nio.file.Path; -import java.util.UUID; - -public final class ChunkLoaderNPCImpl extends ServerPlayer implements ChunkLoaderNPC { - - private static final ReflectMethod SET_GAMEMODE = new ReflectMethod<>(ServerPlayerGameMode.class, - 1, GameType.class, GameType.class); - - private final ServerLevel serverLevel; - private final AABB boundingBox; - private final PlayerAdvancements advancements; - - private boolean dieCall = false; - - public ChunkLoaderNPCImpl(MinecraftServer minecraftServer, Location location, UUID uuid) { - super(minecraftServer, ((CraftWorld) location.getWorld()).getHandle(), - new GameProfile(uuid, NPCHandler.getName(location.getWorld().getName()))); - - this.serverLevel = serverLevel(); - this.boundingBox = new AABB(new BlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ())); - - this.connection = new DummyServerGamePacketListenerImpl(minecraftServer, this); - - this.advancements = new DummyPlayerAdvancements(minecraftServer, this); - - SET_GAMEMODE.invoke(this.gameMode, GameType.CREATIVE, null); - clientViewDistance = 1; - - fauxSleeping = true; - - spawnIn(this.serverLevel); - moveTo(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); - - this.serverLevel.addNewPlayer(this); - - super.setBoundingBox(this.boundingBox); - } - - @Override - public UUID getUniqueId() { - return super.getUUID(); - } - - @Override - public void die() { - discard(); - } - - @Override - public AABB getBoundingBoxForCulling() { - return this.boundingBox; - } - - @Override - public void remove(RemovalReason removalReason) { - if (!dieCall) { - dieCall = true; - this.serverLevel.removePlayerImmediately(this, RemovalReason.UNLOADED_WITH_PLAYER); - dieCall = false; - } else { - super.remove(removalReason); - } - } - - @Override - public Location getLocation() { - return getBukkitEntity().getLocation(); - } - - @Override - public Player getPlayer() { - return getBukkitEntity(); - } - - @Override - public PlayerAdvancements getAdvancements() { - return this.advancements; - } - - public static class DummyConnection extends Connection { - - DummyConnection() { - super(PacketFlow.SERVERBOUND); - this.channel = new DummyChannel(); - this.address = null; - } - - } - - public static class DummyServerGamePacketListenerImpl extends ServerGamePacketListenerImpl { - - DummyServerGamePacketListenerImpl(MinecraftServer minecraftServer, ServerPlayer serverPlayer) { - super(minecraftServer, new DummyConnection(), serverPlayer); - } - - @Override - public void handleContainerClick(ServerboundContainerClickPacket containerClickPacket) { - // Do nothing. - } - - @Override - public void handleMovePlayer(ServerboundMovePlayerPacket movePlayerPacket) { - // Do nothing. - } - - @Override - public void handleSignUpdate(ServerboundSignUpdatePacket signUpdatePacket) { - // Do nothing. - } - - @Override - public void handlePlayerAction(ServerboundPlayerActionPacket playerActionPacket) { - // Do nothing. - } - - @Override - public void handleUseItem(ServerboundUseItemPacket useItemPacket) { - // Do nothing. - } - - @Override - public void handleSetCarriedItem(ServerboundSetCarriedItemPacket setCarriedItemPacket) { - // Do nothing. - } - - @Override - public void handleChat(ServerboundChatPacket chatPacket) { - // Do nothing. - } - - @Override - public void disconnect(String s) { - // Do nothing. - } - - public void send(Packet packet) { - // Do nothing. - } - - } - - private static class DummyPlayerAdvancements extends PlayerAdvancements { - - DummyPlayerAdvancements(MinecraftServer server, ServerPlayer serverPlayer) { - super(server.getFixerUpper(), server.getPlayerList(), server.getAdvancements(), - getAdvancementsFile(server, serverPlayer), serverPlayer); - } - - private static Path getAdvancementsFile(MinecraftServer server, ServerPlayer serverPlayer) { - File advancementsDir = server.getWorldPath(LevelResource.PLAYER_ADVANCEMENTS_DIR).toFile(); - return new File(advancementsDir, serverPlayer.getUUID() + ".json").toPath(); - } - - @Override - public void setPlayer(ServerPlayer owner) { - // Do nothing. - } - - @Override - public void stopListening() { - // Do nothing. - } - - @Override - public void reload(ServerAdvancementManager advancementLoader) { - // Do nothing. - } - - @Override - public void save() { - // Do nothing. - } - - @Override - public boolean award(Advancement advancement, String criterionName) { - return false; - } - - @Override - public boolean revoke(Advancement advancement, String criterionName) { - return false; - } - - @Override - public void flushDirty(ServerPlayer player) { - // Do nothing. - } - - @Override - public void setSelectedTab(@Nullable Advancement advancement) { - // Do nothing. - } - - @Override - public AdvancementProgress getOrStartProgress(Advancement advancement) { - return new AdvancementProgress(); - } - - } - -} diff --git a/NMS/v1_20_1/src/main/java/com/bgsoftware/wildloaders/nms/v1_20_1/NMSAdapterImpl.java b/NMS/v1_20_1/src/main/java/com/bgsoftware/wildloaders/nms/v1_20_1/NMSAdapterImpl.java deleted file mode 100644 index 2e90ef5..0000000 --- a/NMS/v1_20_1/src/main/java/com/bgsoftware/wildloaders/nms/v1_20_1/NMSAdapterImpl.java +++ /dev/null @@ -1,170 +0,0 @@ -package com.bgsoftware.wildloaders.nms.v1_20_1; - -import com.bgsoftware.wildloaders.api.loaders.ChunkLoader; -import com.bgsoftware.wildloaders.loaders.ITileEntityChunkLoader; -import com.bgsoftware.wildloaders.nms.NMSAdapter; -import com.bgsoftware.wildloaders.nms.v1_20_1.loader.ChunkLoaderBlockEntity; -import net.minecraft.core.BlockPos; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.ListTag; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.ChunkPos; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.entity.SpawnerBlockEntity; -import net.minecraft.world.level.chunk.LevelChunk; -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.World; -import org.bukkit.craftbukkit.v1_20_R1.CraftServer; -import org.bukkit.craftbukkit.v1_20_R1.CraftWorld; -import org.bukkit.craftbukkit.v1_20_R1.inventory.CraftItemStack; - -import java.util.UUID; - -public final class NMSAdapterImpl implements NMSAdapter { - - @Override - public String getTag(org.bukkit.inventory.ItemStack bukkitItem, String key, String def) { - ItemStack itemStack = CraftItemStack.asNMSCopy(bukkitItem); - CompoundTag compoundTag = itemStack.getTag(); - return compoundTag == null || !compoundTag.contains(key, 8) ? def : compoundTag.getString(key); - } - - @Override - public org.bukkit.inventory.ItemStack setTag(org.bukkit.inventory.ItemStack bukkitItem, String key, String value) { - ItemStack itemStack = CraftItemStack.asNMSCopy(bukkitItem); - CompoundTag compoundTag = itemStack.getOrCreateTag(); - - compoundTag.putString(key, value); - - return CraftItemStack.asBukkitCopy(itemStack); - } - - @Override - public long getTag(org.bukkit.inventory.ItemStack bukkitItem, String key, long def) { - ItemStack itemStack = CraftItemStack.asNMSCopy(bukkitItem); - CompoundTag compoundTag = itemStack.getTag(); - return compoundTag == null || !compoundTag.contains(key, 4) ? def : compoundTag.getLong(key); - } - - @Override - public org.bukkit.inventory.ItemStack setTag(org.bukkit.inventory.ItemStack bukkitItem, String key, long value) { - ItemStack itemStack = CraftItemStack.asNMSCopy(bukkitItem); - CompoundTag compoundTag = itemStack.getOrCreateTag(); - - compoundTag.putLong(key, value); - - return CraftItemStack.asBukkitCopy(itemStack); - } - - @Override - public org.bukkit.inventory.ItemStack getPlayerSkull(org.bukkit.inventory.ItemStack bukkitItem, String texture) { - ItemStack itemStack = CraftItemStack.asNMSCopy(bukkitItem); - CompoundTag compoundTag = itemStack.getOrCreateTag(); - - CompoundTag skullOwner = compoundTag.contains("SkullOwner") ? - compoundTag.getCompound("SkullOwner") : new CompoundTag(); - - CompoundTag properties = new CompoundTag(); - ListTag textures = new ListTag(); - CompoundTag signature = new CompoundTag(); - - signature.putString("Value", texture); - textures.add(signature); - - properties.put("textures", textures); - - skullOwner.put("Properties", properties); - skullOwner.putString("Id", UUID.randomUUID().toString()); - - compoundTag.put("SkullOwner", skullOwner); - - return CraftItemStack.asBukkitCopy(itemStack); - } - - @Override - public com.bgsoftware.wildloaders.api.npc.ChunkLoaderNPC createNPC(Location location, UUID uuid) { - return new ChunkLoaderNPCImpl(((CraftServer) Bukkit.getServer()).getServer(), location, uuid); - } - - @Override - public ITileEntityChunkLoader createLoader(ChunkLoader chunkLoader) { - Location loaderLoc = chunkLoader.getLocation(); - World bukkitWorld = loaderLoc.getWorld(); - - if (bukkitWorld == null) - throw new IllegalArgumentException("Cannot create loader in null world."); - - ServerLevel serverLevel = ((CraftWorld) bukkitWorld).getHandle(); - BlockPos blockPos = new BlockPos(loaderLoc.getBlockX(), loaderLoc.getBlockY(), loaderLoc.getBlockZ()); - - ChunkLoaderBlockEntity ChunkLoaderBlockEntity = new ChunkLoaderBlockEntity(chunkLoader, serverLevel, blockPos); - serverLevel.addBlockEntityTicker(ChunkLoaderBlockEntity.getTicker()); - - for (org.bukkit.Chunk bukkitChunk : chunkLoader.getLoadedChunks()) { - LevelChunk levelChunk = serverLevel.getChunk(bukkitChunk.getX(), bukkitChunk.getZ()); - levelChunk.getBlockEntities().values().stream() - .filter(blockEntity -> blockEntity instanceof SpawnerBlockEntity) - .forEach(blockEntity -> { - ((SpawnerBlockEntity) blockEntity).getSpawner().requiredPlayerRange = -1; - }); - - ChunkPos chunkPos = levelChunk.getPos(); - serverLevel.setChunkForced(chunkPos.x, chunkPos.z, true); - } - - return ChunkLoaderBlockEntity; - } - - @Override - public void removeLoader(ChunkLoader chunkLoader, boolean spawnParticle) { - Location loaderLoc = chunkLoader.getLocation(); - World bukkitWorld = loaderLoc.getWorld(); - - if (bukkitWorld == null) - throw new IllegalArgumentException("Cannot remove loader in null world."); - - ServerLevel serverLevel = ((CraftWorld) bukkitWorld).getHandle(); - BlockPos blockPos = new BlockPos(loaderLoc.getBlockX(), loaderLoc.getBlockY(), loaderLoc.getBlockZ()); - - long chunkPosLong = ChunkPos.asLong(blockPos.getX() >> 4, blockPos.getZ() >> 4); - ChunkLoaderBlockEntity chunkLoaderBlockEntity = ChunkLoaderBlockEntity.chunkLoaderBlockEntityMap.remove(chunkPosLong); - - if (chunkLoaderBlockEntity != null) { - chunkLoaderBlockEntity.holograms.forEach(EntityHologram::removeHologram); - chunkLoaderBlockEntity.removed = true; - } - - if (spawnParticle) - serverLevel.levelEvent(null, 2001, blockPos, Block.getId(serverLevel.getBlockState(blockPos))); - - for (org.bukkit.Chunk bukkitChunk : chunkLoader.getLoadedChunks()) { - LevelChunk levelChunk = serverLevel.getChunk(bukkitChunk.getX(), bukkitChunk.getZ()); - levelChunk.getBlockEntities().values().stream() - .filter(blockEntity -> blockEntity instanceof SpawnerBlockEntity) - .forEach(blockEntity -> { - ((SpawnerBlockEntity) blockEntity).getSpawner().requiredPlayerRange = 16; - }); - - ChunkPos chunkPos = levelChunk.getPos(); - serverLevel.setChunkForced(chunkPos.x, chunkPos.z, false); - } - } - - @Override - public void updateSpawner(Location location, boolean reset) { - World bukkitWorld = location.getWorld(); - - if (bukkitWorld == null) - throw new IllegalArgumentException("Cannot remove loader in null world."); - - ServerLevel serverLevel = ((CraftWorld) bukkitWorld).getHandle(); - BlockPos blockPos = new BlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ()); - BlockEntity blockEntity = serverLevel.getBlockEntity(blockPos); - if (blockEntity instanceof SpawnerBlockEntity spawnerBlockEntity) - spawnerBlockEntity.getSpawner().requiredPlayerRange = reset ? 16 : -1; - } - -} diff --git a/NMS/v1_20_2/build.gradle b/NMS/v1_20_2/build.gradle deleted file mode 100644 index 8c28c06..0000000 --- a/NMS/v1_20_2/build.gradle +++ /dev/null @@ -1,36 +0,0 @@ -plugins { - id("io.papermc.paperweight.userdev") version "1.6.0" -} - -java { - toolchain { - languageVersion.set(JavaLanguageVersion.of(17)) - } -} - -group 'NMS:v1_20_2' - -dependencies { - paperweightDevelopmentBundle("io.papermc.paper:dev-bundle:1.20.2-R0.1-SNAPSHOT") - compileOnly project(":API") - compileOnly rootProject -} - -shadowJar { - archiveFileName = "${project.name}-exclude.jar" -} - -assemble { - dependsOn(reobfJar) -} - -tasks { - reobfJar { - File outputFile = new File(rootProject.archiveFolder, "reobf/${project.name}.jar") - outputJar.set(layout.buildDirectory.file(outputFile.getPath())) - } -} - -if (project.hasProperty('nms.compile_v1_20') && !Boolean.valueOf(project.findProperty("nms.compile_v1_20").toString())) { - project.tasks.all { task -> task.enabled = false } -} \ No newline at end of file diff --git a/NMS/v1_20_2/src/main/java/com/bgsoftware/wildloaders/nms/v1_20_2/EntityHologram.java b/NMS/v1_20_2/src/main/java/com/bgsoftware/wildloaders/nms/v1_20_2/EntityHologram.java deleted file mode 100644 index 4d9accd..0000000 --- a/NMS/v1_20_2/src/main/java/com/bgsoftware/wildloaders/nms/v1_20_2/EntityHologram.java +++ /dev/null @@ -1,165 +0,0 @@ -package com.bgsoftware.wildloaders.nms.v1_20_2; - -import com.bgsoftware.wildloaders.api.holograms.Hologram; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.chat.Component; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.sounds.SoundEvent; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.InteractionResult; -import net.minecraft.world.damagesource.DamageSource; -import net.minecraft.world.entity.EquipmentSlot; -import net.minecraft.world.entity.decoration.ArmorStand; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.phys.AABB; -import net.minecraft.world.phys.Vec3; -import org.bukkit.Bukkit; -import org.bukkit.craftbukkit.v1_20_R2.CraftServer; -import org.bukkit.craftbukkit.v1_20_R2.entity.CraftArmorStand; -import org.bukkit.craftbukkit.v1_20_R2.entity.CraftEntity; -import org.bukkit.craftbukkit.v1_20_R2.util.CraftChatMessage; - -public final class EntityHologram extends ArmorStand implements Hologram { - - private static final AABB EMPTY_BOUND = new AABB(0D, 0D, 0D, 0D, 0D, 0D); - - private CraftEntity bukkitEntity; - - public EntityHologram(ServerLevel serverLevel, double x, double y, double z) { - super(serverLevel, x, y, z); - - setInvisible(true); - setSmall(true); - setShowArms(false); - setNoGravity(true); - setNoBasePlate(true); - setMarker(true); - - super.collides = false; - super.setCustomNameVisible(true); // Custom name visible - super.setBoundingBox(EMPTY_BOUND); - } - - @Override - public void setHologramName(String name) { - super.setCustomName(CraftChatMessage.fromStringOrNull(name)); - } - - @Override - public void removeHologram() { - super.remove(RemovalReason.DISCARDED); - } - - @Override - public org.bukkit.entity.Entity getEntity() { - return getBukkitEntity(); - } - - @Override - public void tick() { - // Disable normal ticking for this entity. - - // Workaround to force EntityTrackerEntry to send a teleport packet immediately after spawning this entity. - if (this.onGround) { - this.onGround = false; - } - } - - @Override - public void inactiveTick() { - // Disable normal ticking for this entity. - - // Workaround to force EntityTrackerEntry to send a teleport packet immediately after spawning this entity. - if (this.onGround) { - this.onGround = false; - } - } - - @Override - public void addAdditionalSaveData(CompoundTag compoundTag) { - // Do not save NBT. - } - - @Override - public boolean saveAsPassenger(CompoundTag compoundTag) { - // Do not save NBT. - return false; - } - - @Override - public CompoundTag saveWithoutId(CompoundTag compoundTag) { - // Do not save NBT. - return compoundTag; - } - - @Override - public void readAdditionalSaveData(CompoundTag compoundTag) { - // Do not load NBT. - } - - @Override - public void load(CompoundTag compoundTag) { - // Do not load NBT. - } - - @Override - public boolean isInvulnerableTo(DamageSource source) { - /* - * The field Entity.invulnerable is private. - * It's only used while saving NBTTags, but since the entity would be killed - * on chunk unload, we prefer to override isInvulnerable(). - */ - return true; - } - - @Override - public boolean repositionEntityAfterLoad() { - return false; - } - - @Override - public void setCustomName(Component component) { - // Locks the custom name. - } - - @Override - public void setCustomNameVisible(boolean visible) { - // Locks the custom name. - } - - @Override - public InteractionResult interactAt(Player player, Vec3 hitPos, InteractionHand hand) { - // Prevent stand being equipped - return InteractionResult.PASS; - } - - @Override - public void setItemSlot(EquipmentSlot equipmentSlot, ItemStack itemStack, boolean silent) { - // Prevent stand being equipped - } - - @Override - public AABB getBoundingBoxForCulling() { - return EMPTY_BOUND; - } - - @Override - public void playSound(SoundEvent soundEvent, float volume, float pitch) { - // Remove sounds. - } - - @Override - public void remove(RemovalReason removalReason) { - // Prevent being killed. - } - - @Override - public CraftEntity getBukkitEntity() { - if (bukkitEntity == null) { - bukkitEntity = new CraftArmorStand((CraftServer) Bukkit.getServer(), this); - } - return bukkitEntity; - } - -} diff --git a/NMS/v1_20_2/src/main/java/com/bgsoftware/wildloaders/nms/v1_20_2/loader/ChunkLoaderBlockEntity.java b/NMS/v1_20_2/src/main/java/com/bgsoftware/wildloaders/nms/v1_20_2/loader/ChunkLoaderBlockEntity.java deleted file mode 100644 index c06756f..0000000 --- a/NMS/v1_20_2/src/main/java/com/bgsoftware/wildloaders/nms/v1_20_2/loader/ChunkLoaderBlockEntity.java +++ /dev/null @@ -1,149 +0,0 @@ -package com.bgsoftware.wildloaders.nms.v1_20_2.loader; - -import com.bgsoftware.wildloaders.api.holograms.Hologram; -import com.bgsoftware.wildloaders.api.loaders.ChunkLoader; -import com.bgsoftware.wildloaders.loaders.ITileEntityChunkLoader; -import com.bgsoftware.wildloaders.loaders.WChunkLoader; -import com.bgsoftware.wildloaders.nms.v1_20_2.EntityHologram; -import net.minecraft.core.BlockPos; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.level.ChunkPos; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.entity.BlockEntityType; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; - -public final class ChunkLoaderBlockEntity extends BlockEntity implements ITileEntityChunkLoader { - - public static final Map chunkLoaderBlockEntityMap = new HashMap<>(); - - public final List holograms = new ArrayList<>(); - private final WChunkLoader chunkLoader; - private final Block loaderBlock; - private final ChunkLoaderBlockEntityTicker ticker; - private final ServerLevel serverLevel; - private final BlockPos blockPos; - private final String cachedPlacerName; - - private short currentTick = 20; - private short daysAmount, hoursAmount, minutesAmount, secondsAmount; - public boolean removed = false; - - public ChunkLoaderBlockEntity(ChunkLoader chunkLoader, ServerLevel serverLevel, BlockPos blockPos) { - super(BlockEntityType.COMMAND_BLOCK, blockPos, serverLevel.getBlockState(blockPos)); - - this.chunkLoader = (WChunkLoader) chunkLoader; - this.ticker = new ChunkLoaderBlockEntityTicker(this); - this.blockPos = blockPos; - this.serverLevel = serverLevel; - - setLevel(serverLevel); - - loaderBlock = serverLevel.getBlockState(blockPos).getBlock(); - - this.cachedPlacerName = Optional.ofNullable(this.chunkLoader.getWhoPlaced().getName()).orElse(""); - - if (!this.chunkLoader.isInfinite()) { - long timeLeft = chunkLoader.getTimeLeft(); - - daysAmount = (short) (timeLeft / 86400); - timeLeft = timeLeft % 86400; - - hoursAmount = (short) (timeLeft / 3600); - timeLeft = timeLeft % 3600; - - minutesAmount = (short) (timeLeft / 60); - timeLeft = timeLeft % 60; - - secondsAmount = (short) timeLeft; - } - - long chunkPosLong = ChunkPos.asLong(blockPos.getX() >> 4, blockPos.getZ() >> 4); - chunkLoaderBlockEntityMap.put(chunkPosLong, this); - - List hologramLines = this.chunkLoader.getHologramLines(); - - double currentY = blockPos.getY() + 1; - for (int i = hologramLines.size(); i > 0; i--) { - EntityHologram hologram = new EntityHologram(serverLevel, blockPos.getX() + 0.5, currentY, blockPos.getZ() + 0.5); - updateName(hologram, hologramLines.get(i - 1)); - serverLevel.addFreshEntity(hologram); - currentY += 0.23; - holograms.add(hologram); - } - } - - public void tick() { - if (removed || ++currentTick <= 20) - return; - - currentTick = 0; - - if (chunkLoader.isNotActive() || this.serverLevel.getBlockState(this.blockPos).getBlock() != loaderBlock) { - chunkLoader.remove(); - return; - } - - if (chunkLoader.isInfinite()) - return; - - List hologramLines = chunkLoader.getHologramLines(); - - int hologramsAmount = holograms.size(); - for (int i = hologramsAmount; i > 0; i--) { - EntityHologram hologram = holograms.get(hologramsAmount - i); - updateName(hologram, hologramLines.get(i - 1)); - } - - chunkLoader.tick(); - - if (!removed) { - secondsAmount--; - if (secondsAmount < 0) { - secondsAmount = 59; - minutesAmount--; - if (minutesAmount < 0) { - minutesAmount = 59; - hoursAmount--; - if (hoursAmount < 0) { - hoursAmount = 23; - daysAmount--; - } - } - } - } - } - - @Override - public Collection getHolograms() { - return Collections.unmodifiableList(holograms); - } - - @Override - public boolean isRemoved() { - return removed || super.isRemoved(); - } - - public ChunkLoaderBlockEntityTicker getTicker() { - return ticker; - } - - private void updateName(EntityHologram hologram, String line) { - hologram.setHologramName(line - .replace("{0}", this.cachedPlacerName) - .replace("{1}", daysAmount + "") - .replace("{2}", hoursAmount + "") - .replace("{3}", minutesAmount + "") - .replace("{4}", secondsAmount + "") - ); - } - -} - diff --git a/NMS/v1_20_2/src/main/java/com/bgsoftware/wildloaders/nms/v1_20_2/loader/ChunkLoaderBlockEntityTicker.java b/NMS/v1_20_2/src/main/java/com/bgsoftware/wildloaders/nms/v1_20_2/loader/ChunkLoaderBlockEntityTicker.java deleted file mode 100644 index 3535452..0000000 --- a/NMS/v1_20_2/src/main/java/com/bgsoftware/wildloaders/nms/v1_20_2/loader/ChunkLoaderBlockEntityTicker.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.bgsoftware.wildloaders.nms.v1_20_2.loader; - -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.entity.TickingBlockEntity; - -public record ChunkLoaderBlockEntityTicker( - ChunkLoaderBlockEntity chunkLoaderBlockEntity) implements TickingBlockEntity { - - @Override - public void tick() { - chunkLoaderBlockEntity.tick(); - } - - @Override - public boolean isRemoved() { - return chunkLoaderBlockEntity.isRemoved(); - } - - @Override - public BlockPos getPos() { - return chunkLoaderBlockEntity.getBlockPos(); - } - - @Override - public String getType() { - return BlockEntityType.getKey(chunkLoaderBlockEntity.getType()) + ""; - } - -} diff --git a/NMS/v1_20_3/build.gradle b/NMS/v1_20_3/build.gradle index c62db38..d733f8d 100644 --- a/NMS/v1_20_3/build.gradle +++ b/NMS/v1_20_3/build.gradle @@ -1,5 +1,5 @@ plugins { - id("io.papermc.paperweight.userdev") version "1.6.0" + id("io.papermc.paperweight.userdev") version "1.7.1" } java { diff --git a/NMS/v1_20_3/src/main/java/com/bgsoftware/wildloaders/nms/v1_20_3/ChunkLoaderNPCImpl.java b/NMS/v1_20_3/src/main/java/com/bgsoftware/wildloaders/nms/v1_20_3/ChunkLoaderNPCImpl.java index c65ae02..c9cf19e 100644 --- a/NMS/v1_20_3/src/main/java/com/bgsoftware/wildloaders/nms/v1_20_3/ChunkLoaderNPCImpl.java +++ b/NMS/v1_20_3/src/main/java/com/bgsoftware/wildloaders/nms/v1_20_3/ChunkLoaderNPCImpl.java @@ -64,16 +64,19 @@ public final class ChunkLoaderNPCImpl extends ServerPlayer implements ChunkLoade this.advancements = new DummyPlayerAdvancements(minecraftServer, this); SET_GAMEMODE.invoke(this.gameMode, GameType.CREATIVE, null); + + fallDistance = 0.0F; + fauxSleeping = true; + try { setLoadViewDistance(2); setTickViewDistance(2); setSendViewDistance(2); + affectsSpawning = true; } catch (Throwable ignored) { // Doesn't exist on Spigot } - fauxSleeping = true; - spawnIn(this.serverLevel); moveTo(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); diff --git a/NMS/v1_20_3/src/main/java/com/bgsoftware/wildloaders/nms/v1_20_3/EntityHologram.java b/NMS/v1_20_3/src/main/java/com/bgsoftware/wildloaders/nms/v1_20_3/EntityHologram.java index 14e24dd..7ff0aa5 100644 --- a/NMS/v1_20_3/src/main/java/com/bgsoftware/wildloaders/nms/v1_20_3/EntityHologram.java +++ b/NMS/v1_20_3/src/main/java/com/bgsoftware/wildloaders/nms/v1_20_3/EntityHologram.java @@ -1,6 +1,7 @@ package com.bgsoftware.wildloaders.nms.v1_20_3; import com.bgsoftware.wildloaders.api.holograms.Hologram; +import com.bgsoftware.wildloaders.scheduler.Scheduler; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerLevel; @@ -15,6 +16,7 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; import org.bukkit.Bukkit; +import org.bukkit.World; import org.bukkit.craftbukkit.v1_20_R3.CraftServer; import org.bukkit.craftbukkit.v1_20_R3.entity.CraftArmorStand; import org.bukkit.craftbukkit.v1_20_R3.entity.CraftEntity; @@ -48,7 +50,14 @@ public final class EntityHologram extends ArmorStand implements Hologram { @Override public void removeHologram() { - super.remove(RemovalReason.DISCARDED); + if (Scheduler.isRegionScheduler() || !Bukkit.isPrimaryThread()) { + World world = level().getWorld(); + int chunkX = getBlockX() >> 4; + int chunkZ = getBlockZ() >> 4; + Scheduler.runTask(world, chunkX, chunkZ, () -> super.remove(RemovalReason.DISCARDED)); + } else { + super.remove(RemovalReason.DISCARDED); + } } @Override diff --git a/NMS/v1_20_3/src/main/java/com/bgsoftware/wildloaders/nms/v1_20_3/NMSAdapterImpl.java b/NMS/v1_20_3/src/main/java/com/bgsoftware/wildloaders/nms/v1_20_3/NMSAdapterImpl.java index 5d45b9b..5780bcb 100644 --- a/NMS/v1_20_3/src/main/java/com/bgsoftware/wildloaders/nms/v1_20_3/NMSAdapterImpl.java +++ b/NMS/v1_20_3/src/main/java/com/bgsoftware/wildloaders/nms/v1_20_3/NMSAdapterImpl.java @@ -4,6 +4,7 @@ import com.bgsoftware.wildloaders.api.loaders.ChunkLoader; import com.bgsoftware.wildloaders.loaders.ITileEntityChunkLoader; import com.bgsoftware.wildloaders.nms.NMSAdapter; import com.bgsoftware.wildloaders.nms.v1_20_3.loader.ChunkLoaderBlockEntity; +import com.bgsoftware.wildloaders.scheduler.Scheduler; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; @@ -103,16 +104,10 @@ public final class NMSAdapterImpl implements NMSAdapter { ChunkLoaderBlockEntity ChunkLoaderBlockEntity = new ChunkLoaderBlockEntity(chunkLoader, serverLevel, blockPos); serverLevel.addBlockEntityTicker(ChunkLoaderBlockEntity.getTicker()); - for (org.bukkit.Chunk bukkitChunk : chunkLoader.getLoadedChunks()) { - LevelChunk levelChunk = serverLevel.getChunk(bukkitChunk.getX(), bukkitChunk.getZ()); - levelChunk.getBlockEntities().values().stream() - .filter(blockEntity -> blockEntity instanceof SpawnerBlockEntity) - .forEach(blockEntity -> { - ((SpawnerBlockEntity) blockEntity).getSpawner().requiredPlayerRange = -1; - }); - - ChunkPos chunkPos = levelChunk.getPos(); - serverLevel.setChunkForced(chunkPos.x, chunkPos.z, true); + if (Scheduler.isRegionScheduler()) { + Scheduler.runTask(() -> setChunksForcedForLoader(chunkLoader, serverLevel, true)); + } else { + setChunksForcedForLoader(chunkLoader, serverLevel, true); } return ChunkLoaderBlockEntity; @@ -140,16 +135,25 @@ public final class NMSAdapterImpl implements NMSAdapter { if (spawnParticle) serverLevel.levelEvent(null, 2001, blockPos, Block.getId(serverLevel.getBlockState(blockPos))); - for (org.bukkit.Chunk bukkitChunk : chunkLoader.getLoadedChunks()) { + if (Scheduler.isRegionScheduler()) { + Scheduler.runTask(() -> setChunksForcedForLoader(chunkLoader, serverLevel, false)); + } else { + setChunksForcedForLoader(chunkLoader, serverLevel, false); + } + } + + private static void setChunksForcedForLoader(ChunkLoader chunkLoader, ServerLevel serverLevel, boolean forced) { + int requiredPlayerRange = forced ? -1 : 16; + for (org.bukkit.Chunk bukkitChunk : chunkLoader.getLoadedChunksCollection()) { LevelChunk levelChunk = serverLevel.getChunk(bukkitChunk.getX(), bukkitChunk.getZ()); - levelChunk.getBlockEntities().values().stream() - .filter(blockEntity -> blockEntity instanceof SpawnerBlockEntity) - .forEach(blockEntity -> { - ((SpawnerBlockEntity) blockEntity).getSpawner().requiredPlayerRange = 16; - }); + + for (BlockEntity blockEntity : levelChunk.getBlockEntities().values()) { + if (blockEntity instanceof SpawnerBlockEntity spawnerBlockEntity) + spawnerBlockEntity.getSpawner().requiredPlayerRange = requiredPlayerRange; + } ChunkPos chunkPos = levelChunk.getPos(); - serverLevel.setChunkForced(chunkPos.x, chunkPos.z, false); + serverLevel.setChunkForced(chunkPos.x, chunkPos.z, forced); } } diff --git a/NMS/v1_20_3/src/main/java/com/bgsoftware/wildloaders/nms/v1_20_3/loader/ChunkLoaderBlockEntityTicker.java b/NMS/v1_20_3/src/main/java/com/bgsoftware/wildloaders/nms/v1_20_3/loader/ChunkLoaderBlockEntityTicker.java index f919777..68bde49 100644 --- a/NMS/v1_20_3/src/main/java/com/bgsoftware/wildloaders/nms/v1_20_3/loader/ChunkLoaderBlockEntityTicker.java +++ b/NMS/v1_20_3/src/main/java/com/bgsoftware/wildloaders/nms/v1_20_3/loader/ChunkLoaderBlockEntityTicker.java @@ -1,6 +1,7 @@ package com.bgsoftware.wildloaders.nms.v1_20_3.loader; import net.minecraft.core.BlockPos; +import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.entity.TickingBlockEntity; @@ -27,4 +28,8 @@ public record ChunkLoaderBlockEntityTicker( return BlockEntityType.getKey(chunkLoaderBlockEntity.getType()) + ""; } + public BlockEntity getTileEntity() { + return chunkLoaderBlockEntity; + } + } diff --git a/NMS/v1_20_4/build.gradle b/NMS/v1_20_4/build.gradle index eefb5d1..67b74c6 100644 --- a/NMS/v1_20_4/build.gradle +++ b/NMS/v1_20_4/build.gradle @@ -1,5 +1,5 @@ plugins { - id("io.papermc.paperweight.userdev") version "1.6.0" + id("io.papermc.paperweight.userdev") version "1.7.1" } java { diff --git a/NMS/v1_20_4/src/main/java/com/bgsoftware/wildloaders/nms/v1_20_4/ChunkLoaderNPCImpl.java b/NMS/v1_20_4/src/main/java/com/bgsoftware/wildloaders/nms/v1_20_4/ChunkLoaderNPCImpl.java index eac163a..138da61 100644 --- a/NMS/v1_20_4/src/main/java/com/bgsoftware/wildloaders/nms/v1_20_4/ChunkLoaderNPCImpl.java +++ b/NMS/v1_20_4/src/main/java/com/bgsoftware/wildloaders/nms/v1_20_4/ChunkLoaderNPCImpl.java @@ -64,16 +64,19 @@ public final class ChunkLoaderNPCImpl extends ServerPlayer implements ChunkLoade this.advancements = new DummyPlayerAdvancements(minecraftServer, this); SET_GAMEMODE.invoke(this.gameMode, GameType.CREATIVE, null); + + fallDistance = 0.0F; + fauxSleeping = true; + try { setLoadViewDistance(2); setTickViewDistance(2); setSendViewDistance(2); + affectsSpawning = true; } catch (Throwable ignored) { // Doesn't exist on Spigot } - fauxSleeping = true; - spawnIn(this.serverLevel); moveTo(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); diff --git a/NMS/v1_20_4/src/main/java/com/bgsoftware/wildloaders/nms/v1_20_4/EntityHologram.java b/NMS/v1_20_4/src/main/java/com/bgsoftware/wildloaders/nms/v1_20_4/EntityHologram.java index fb977c0..fd09e9b 100644 --- a/NMS/v1_20_4/src/main/java/com/bgsoftware/wildloaders/nms/v1_20_4/EntityHologram.java +++ b/NMS/v1_20_4/src/main/java/com/bgsoftware/wildloaders/nms/v1_20_4/EntityHologram.java @@ -1,6 +1,7 @@ package com.bgsoftware.wildloaders.nms.v1_20_4; import com.bgsoftware.wildloaders.api.holograms.Hologram; +import com.bgsoftware.wildloaders.scheduler.Scheduler; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerLevel; @@ -15,6 +16,7 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; import org.bukkit.Bukkit; +import org.bukkit.World; import org.bukkit.craftbukkit.CraftServer; import org.bukkit.craftbukkit.entity.CraftArmorStand; import org.bukkit.craftbukkit.entity.CraftEntity; @@ -48,7 +50,14 @@ public final class EntityHologram extends ArmorStand implements Hologram { @Override public void removeHologram() { - super.remove(RemovalReason.DISCARDED); + if (Scheduler.isRegionScheduler() || !Bukkit.isPrimaryThread()) { + World world = level().getWorld(); + int chunkX = getBlockX() >> 4; + int chunkZ = getBlockZ() >> 4; + Scheduler.runTask(world, chunkX, chunkZ, () -> super.remove(RemovalReason.DISCARDED)); + } else { + super.remove(RemovalReason.DISCARDED); + } } @Override diff --git a/NMS/v1_20_4/src/main/java/com/bgsoftware/wildloaders/nms/v1_20_4/NMSAdapterImpl.java b/NMS/v1_20_4/src/main/java/com/bgsoftware/wildloaders/nms/v1_20_4/NMSAdapterImpl.java index 7837519..f9fec1e 100644 --- a/NMS/v1_20_4/src/main/java/com/bgsoftware/wildloaders/nms/v1_20_4/NMSAdapterImpl.java +++ b/NMS/v1_20_4/src/main/java/com/bgsoftware/wildloaders/nms/v1_20_4/NMSAdapterImpl.java @@ -4,6 +4,7 @@ import com.bgsoftware.wildloaders.api.loaders.ChunkLoader; import com.bgsoftware.wildloaders.loaders.ITileEntityChunkLoader; import com.bgsoftware.wildloaders.nms.NMSAdapter; import com.bgsoftware.wildloaders.nms.v1_20_4.loader.ChunkLoaderBlockEntity; +import com.bgsoftware.wildloaders.scheduler.Scheduler; import com.mojang.authlib.properties.Property; import com.mojang.authlib.properties.PropertyMap; import net.minecraft.core.BlockPos; @@ -109,16 +110,10 @@ public final class NMSAdapterImpl implements NMSAdapter { ChunkLoaderBlockEntity ChunkLoaderBlockEntity = new ChunkLoaderBlockEntity(chunkLoader, serverLevel, blockPos); serverLevel.addBlockEntityTicker(ChunkLoaderBlockEntity.getTicker()); - for (org.bukkit.Chunk bukkitChunk : chunkLoader.getLoadedChunks()) { - LevelChunk levelChunk = serverLevel.getChunk(bukkitChunk.getX(), bukkitChunk.getZ()); - levelChunk.getBlockEntities().values().stream() - .filter(blockEntity -> blockEntity instanceof SpawnerBlockEntity) - .forEach(blockEntity -> { - ((SpawnerBlockEntity) blockEntity).getSpawner().requiredPlayerRange = -1; - }); - - ChunkPos chunkPos = levelChunk.getPos(); - serverLevel.setChunkForced(chunkPos.x, chunkPos.z, true); + if (Scheduler.isRegionScheduler()) { + Scheduler.runTask(() -> setChunksForcedForLoader(chunkLoader, serverLevel, true)); + } else { + setChunksForcedForLoader(chunkLoader, serverLevel, true); } return ChunkLoaderBlockEntity; @@ -146,16 +141,25 @@ public final class NMSAdapterImpl implements NMSAdapter { if (spawnParticle) serverLevel.levelEvent(null, 2001, blockPos, Block.getId(serverLevel.getBlockState(blockPos))); - for (org.bukkit.Chunk bukkitChunk : chunkLoader.getLoadedChunks()) { + if (Scheduler.isRegionScheduler()) { + Scheduler.runTask(() -> setChunksForcedForLoader(chunkLoader, serverLevel, false)); + } else { + setChunksForcedForLoader(chunkLoader, serverLevel, false); + } + } + + private static void setChunksForcedForLoader(ChunkLoader chunkLoader, ServerLevel serverLevel, boolean forced) { + int requiredPlayerRange = forced ? -1 : 16; + for (org.bukkit.Chunk bukkitChunk : chunkLoader.getLoadedChunksCollection()) { LevelChunk levelChunk = serverLevel.getChunk(bukkitChunk.getX(), bukkitChunk.getZ()); - levelChunk.getBlockEntities().values().stream() - .filter(blockEntity -> blockEntity instanceof SpawnerBlockEntity) - .forEach(blockEntity -> { - ((SpawnerBlockEntity) blockEntity).getSpawner().requiredPlayerRange = 16; - }); + + for (BlockEntity blockEntity : levelChunk.getBlockEntities().values()) { + if (blockEntity instanceof SpawnerBlockEntity spawnerBlockEntity) + spawnerBlockEntity.getSpawner().requiredPlayerRange = requiredPlayerRange; + } ChunkPos chunkPos = levelChunk.getPos(); - serverLevel.setChunkForced(chunkPos.x, chunkPos.z, false); + serverLevel.setChunkForced(chunkPos.x, chunkPos.z, forced); } } diff --git a/NMS/v1_20_4/src/main/java/com/bgsoftware/wildloaders/nms/v1_20_4/loader/ChunkLoaderBlockEntityTicker.java b/NMS/v1_20_4/src/main/java/com/bgsoftware/wildloaders/nms/v1_20_4/loader/ChunkLoaderBlockEntityTicker.java index 3023867..1510fbb 100644 --- a/NMS/v1_20_4/src/main/java/com/bgsoftware/wildloaders/nms/v1_20_4/loader/ChunkLoaderBlockEntityTicker.java +++ b/NMS/v1_20_4/src/main/java/com/bgsoftware/wildloaders/nms/v1_20_4/loader/ChunkLoaderBlockEntityTicker.java @@ -1,6 +1,7 @@ package com.bgsoftware.wildloaders.nms.v1_20_4.loader; import net.minecraft.core.BlockPos; +import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.entity.TickingBlockEntity; @@ -27,4 +28,8 @@ public record ChunkLoaderBlockEntityTicker( return BlockEntityType.getKey(chunkLoaderBlockEntity.getType()) + ""; } + public BlockEntity getTileEntity() { + return chunkLoaderBlockEntity; + } + } diff --git a/NMS/v1_20_1/build.gradle b/NMS/v1_21/build.gradle similarity index 66% rename from NMS/v1_20_1/build.gradle rename to NMS/v1_21/build.gradle index 57cf5fa..e1f8a19 100644 --- a/NMS/v1_20_1/build.gradle +++ b/NMS/v1_21/build.gradle @@ -1,17 +1,17 @@ plugins { - id("io.papermc.paperweight.userdev") version "1.6.0" + id("io.papermc.paperweight.userdev") version "1.7.1" } java { toolchain { - languageVersion.set(JavaLanguageVersion.of(17)) + languageVersion.set(JavaLanguageVersion.of(21)) } } -group 'NMS:v1_20_1' +group 'NMS:v1_21' dependencies { - paperweightDevelopmentBundle("io.papermc.paper:dev-bundle:1.20.1-R0.1-SNAPSHOT") + paperweightDevelopmentBundle("io.papermc.paper:dev-bundle:1.21-R0.1-SNAPSHOT") compileOnly project(":API") compileOnly rootProject } @@ -31,6 +31,6 @@ tasks { } } -if (project.hasProperty('nms.compile_v1_20') && !Boolean.valueOf(project.findProperty("nms.compile_v1_20").toString())) { +if (project.hasProperty('nms.compile_v1_21') && !Boolean.valueOf(project.findProperty("nms.compile_v1_21").toString())) { project.tasks.all { task -> task.enabled = false } } \ No newline at end of file diff --git a/NMS/v1_20_2/src/main/java/com/bgsoftware/wildloaders/nms/v1_20_2/ChunkLoaderNPCImpl.java b/NMS/v1_21/src/main/java/com/bgsoftware/wildloaders/nms/v1_21/ChunkLoaderNPCImpl.java similarity index 90% rename from NMS/v1_20_2/src/main/java/com/bgsoftware/wildloaders/nms/v1_20_2/ChunkLoaderNPCImpl.java rename to NMS/v1_21/src/main/java/com/bgsoftware/wildloaders/nms/v1_21/ChunkLoaderNPCImpl.java index 2b01030..7daa3e1 100644 --- a/NMS/v1_20_2/src/main/java/com/bgsoftware/wildloaders/nms/v1_20_2/ChunkLoaderNPCImpl.java +++ b/NMS/v1_21/src/main/java/com/bgsoftware/wildloaders/nms/v1_21/ChunkLoaderNPCImpl.java @@ -1,14 +1,16 @@ -package com.bgsoftware.wildloaders.nms.v1_20_2; +package com.bgsoftware.wildloaders.nms.v1_21; import com.bgsoftware.common.reflection.ReflectMethod; import com.bgsoftware.wildloaders.api.npc.ChunkLoaderNPC; import com.bgsoftware.wildloaders.handlers.NPCHandler; import com.bgsoftware.wildloaders.npc.DummyChannel; import com.mojang.authlib.GameProfile; +import net.kyori.adventure.text.Component; import net.minecraft.advancements.AdvancementHolder; import net.minecraft.advancements.AdvancementProgress; import net.minecraft.core.BlockPos; import net.minecraft.network.Connection; +import net.minecraft.network.DisconnectionDetails; import net.minecraft.network.PacketListener; import net.minecraft.network.protocol.Packet; import net.minecraft.network.protocol.PacketFlow; @@ -32,8 +34,10 @@ import net.minecraft.world.level.GameType; import net.minecraft.world.level.storage.LevelResource; import net.minecraft.world.phys.AABB; import org.bukkit.Location; -import org.bukkit.craftbukkit.v1_20_R2.CraftWorld; +import org.bukkit.craftbukkit.CraftWorld; +import org.bukkit.craftbukkit.entity.CraftPlayer; import org.bukkit.entity.Player; +import org.bukkit.event.player.PlayerKickEvent; import org.jetbrains.annotations.Nullable; import java.io.File; @@ -64,16 +68,20 @@ public final class ChunkLoaderNPCImpl extends ServerPlayer implements ChunkLoade this.advancements = new DummyPlayerAdvancements(minecraftServer, this); SET_GAMEMODE.invoke(this.gameMode, GameType.CREATIVE, null); + + fallDistance = 0.0F; + fauxSleeping = true; + try { - setLoadViewDistance(2); - setTickViewDistance(2); - setSendViewDistance(2); + CraftPlayer craftPlayer = getBukkitEntity(); + craftPlayer.setSendViewDistance(2); + craftPlayer.setViewDistance(2); + craftPlayer.setSimulationDistance(2); + affectsSpawning = true; } catch (Throwable ignored) { // Doesn't exist on Spigot } - fauxSleeping = true; - spawnIn(this.serverLevel); moveTo(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); @@ -132,7 +140,7 @@ public final class ChunkLoaderNPCImpl extends ServerPlayer implements ChunkLoade } @Override - public void setListener(PacketListener packetListener) { + public void setListenerForServerboundHandshake(PacketListener packetListener) { // Do nothing. } } @@ -140,7 +148,8 @@ public final class ChunkLoaderNPCImpl extends ServerPlayer implements ChunkLoade public class DummyServerGamePacketListenerImpl extends ServerGamePacketListenerImpl { DummyServerGamePacketListenerImpl(MinecraftServer minecraftServer, ServerPlayer serverPlayer) { - super(minecraftServer, new DummyConnection(), serverPlayer, CommonListenerCookie.createInitial(ChunkLoaderNPCImpl.this.getGameProfile())); + super(minecraftServer, new DummyConnection(), serverPlayer, + CommonListenerCookie.createInitial(ChunkLoaderNPCImpl.this.getGameProfile(), false)); } @Override @@ -179,7 +188,7 @@ public final class ChunkLoaderNPCImpl extends ServerPlayer implements ChunkLoade } @Override - public void disconnect(String s) { + public void disconnect(DisconnectionDetails disconnectionInfo, PlayerKickEvent.Cause cause) { // Do nothing. } diff --git a/NMS/v1_20_1/src/main/java/com/bgsoftware/wildloaders/nms/v1_20_1/EntityHologram.java b/NMS/v1_21/src/main/java/com/bgsoftware/wildloaders/nms/v1_21/EntityHologram.java similarity index 85% rename from NMS/v1_20_1/src/main/java/com/bgsoftware/wildloaders/nms/v1_20_1/EntityHologram.java rename to NMS/v1_21/src/main/java/com/bgsoftware/wildloaders/nms/v1_21/EntityHologram.java index 2be6363..ea47c76 100644 --- a/NMS/v1_20_1/src/main/java/com/bgsoftware/wildloaders/nms/v1_20_1/EntityHologram.java +++ b/NMS/v1_21/src/main/java/com/bgsoftware/wildloaders/nms/v1_21/EntityHologram.java @@ -1,6 +1,7 @@ -package com.bgsoftware.wildloaders.nms.v1_20_1; +package com.bgsoftware.wildloaders.nms.v1_21; import com.bgsoftware.wildloaders.api.holograms.Hologram; +import com.bgsoftware.wildloaders.scheduler.Scheduler; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerLevel; @@ -15,10 +16,11 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; import org.bukkit.Bukkit; -import org.bukkit.craftbukkit.v1_20_R1.CraftServer; -import org.bukkit.craftbukkit.v1_20_R1.entity.CraftArmorStand; -import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; -import org.bukkit.craftbukkit.v1_20_R1.util.CraftChatMessage; +import org.bukkit.World; +import org.bukkit.craftbukkit.CraftServer; +import org.bukkit.craftbukkit.entity.CraftArmorStand; +import org.bukkit.craftbukkit.entity.CraftEntity; +import org.bukkit.craftbukkit.util.CraftChatMessage; public final class EntityHologram extends ArmorStand implements Hologram { @@ -48,7 +50,14 @@ public final class EntityHologram extends ArmorStand implements Hologram { @Override public void removeHologram() { - super.remove(RemovalReason.DISCARDED); + if (Scheduler.isRegionScheduler() || !Bukkit.isPrimaryThread()) { + World world = level().getWorld(); + int chunkX = getBlockX() >> 4; + int chunkZ = getBlockZ() >> 4; + Scheduler.runTask(world, chunkX, chunkZ, () -> super.remove(RemovalReason.DISCARDED)); + } else { + super.remove(RemovalReason.DISCARDED); + } } @Override diff --git a/NMS/v1_20_2/src/main/java/com/bgsoftware/wildloaders/nms/v1_20_2/NMSAdapterImpl.java b/NMS/v1_21/src/main/java/com/bgsoftware/wildloaders/nms/v1_21/NMSAdapterImpl.java similarity index 62% rename from NMS/v1_20_2/src/main/java/com/bgsoftware/wildloaders/nms/v1_20_2/NMSAdapterImpl.java rename to NMS/v1_21/src/main/java/com/bgsoftware/wildloaders/nms/v1_21/NMSAdapterImpl.java index 6f8ca17..80a7430 100644 --- a/NMS/v1_20_2/src/main/java/com/bgsoftware/wildloaders/nms/v1_20_2/NMSAdapterImpl.java +++ b/NMS/v1_21/src/main/java/com/bgsoftware/wildloaders/nms/v1_21/NMSAdapterImpl.java @@ -1,14 +1,19 @@ -package com.bgsoftware.wildloaders.nms.v1_20_2; +package com.bgsoftware.wildloaders.nms.v1_21; import com.bgsoftware.wildloaders.api.loaders.ChunkLoader; import com.bgsoftware.wildloaders.loaders.ITileEntityChunkLoader; import com.bgsoftware.wildloaders.nms.NMSAdapter; -import com.bgsoftware.wildloaders.nms.v1_20_2.loader.ChunkLoaderBlockEntity; +import com.bgsoftware.wildloaders.nms.v1_21.loader.ChunkLoaderBlockEntity; +import com.bgsoftware.wildloaders.scheduler.Scheduler; +import com.mojang.authlib.properties.Property; +import com.mojang.authlib.properties.PropertyMap; import net.minecraft.core.BlockPos; +import net.minecraft.core.component.DataComponents; import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.ListTag; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.component.CustomData; +import net.minecraft.world.item.component.ResolvableProfile; import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.entity.BlockEntity; @@ -17,10 +22,11 @@ import net.minecraft.world.level.chunk.LevelChunk; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.World; -import org.bukkit.craftbukkit.v1_20_R2.CraftServer; -import org.bukkit.craftbukkit.v1_20_R2.CraftWorld; -import org.bukkit.craftbukkit.v1_20_R2.inventory.CraftItemStack; +import org.bukkit.craftbukkit.CraftServer; +import org.bukkit.craftbukkit.CraftWorld; +import org.bukkit.craftbukkit.inventory.CraftItemStack; +import java.util.Optional; import java.util.UUID; public final class NMSAdapterImpl implements NMSAdapter { @@ -28,16 +34,22 @@ public final class NMSAdapterImpl implements NMSAdapter { @Override public String getTag(org.bukkit.inventory.ItemStack bukkitItem, String key, String def) { ItemStack itemStack = CraftItemStack.asNMSCopy(bukkitItem); - CompoundTag compoundTag = itemStack.getTag(); - return compoundTag == null || !compoundTag.contains(key, 8) ? def : compoundTag.getString(key); + CustomData customData = itemStack.get(DataComponents.CUSTOM_DATA); + if (customData != null) { + CompoundTag compoundTag = customData.getUnsafe(); + if (compoundTag.contains(key, 8)) + return compoundTag.getString(key); + } + return def; } @Override public org.bukkit.inventory.ItemStack setTag(org.bukkit.inventory.ItemStack bukkitItem, String key, String value) { ItemStack itemStack = CraftItemStack.asNMSCopy(bukkitItem); - CompoundTag compoundTag = itemStack.getOrCreateTag(); - compoundTag.putString(key, value); + CustomData customData = itemStack.getOrDefault(DataComponents.CUSTOM_DATA, CustomData.EMPTY); + customData = customData.update(compoundTag -> compoundTag.putString(key, value)); + itemStack.set(DataComponents.CUSTOM_DATA, customData); return CraftItemStack.asBukkitCopy(itemStack); } @@ -45,16 +57,22 @@ public final class NMSAdapterImpl implements NMSAdapter { @Override public long getTag(org.bukkit.inventory.ItemStack bukkitItem, String key, long def) { ItemStack itemStack = CraftItemStack.asNMSCopy(bukkitItem); - CompoundTag compoundTag = itemStack.getTag(); - return compoundTag == null || !compoundTag.contains(key, 4) ? def : compoundTag.getLong(key); + CustomData customData = itemStack.get(DataComponents.CUSTOM_DATA); + if (customData != null) { + CompoundTag compoundTag = customData.getUnsafe(); + if (compoundTag.contains(key, 4)) + return compoundTag.getLong(key); + } + return def; } @Override public org.bukkit.inventory.ItemStack setTag(org.bukkit.inventory.ItemStack bukkitItem, String key, long value) { ItemStack itemStack = CraftItemStack.asNMSCopy(bukkitItem); - CompoundTag compoundTag = itemStack.getOrCreateTag(); - compoundTag.putLong(key, value); + CustomData customData = itemStack.getOrDefault(DataComponents.CUSTOM_DATA, CustomData.EMPTY); + customData = customData.update(compoundTag -> compoundTag.putLong(key, value)); + itemStack.set(DataComponents.CUSTOM_DATA, customData); return CraftItemStack.asBukkitCopy(itemStack); } @@ -62,24 +80,13 @@ public final class NMSAdapterImpl implements NMSAdapter { @Override public org.bukkit.inventory.ItemStack getPlayerSkull(org.bukkit.inventory.ItemStack bukkitItem, String texture) { ItemStack itemStack = CraftItemStack.asNMSCopy(bukkitItem); - CompoundTag compoundTag = itemStack.getOrCreateTag(); - CompoundTag skullOwner = compoundTag.contains("SkullOwner") ? - compoundTag.getCompound("SkullOwner") : new CompoundTag(); + PropertyMap propertyMap = new PropertyMap(); + propertyMap.put("textures", new Property("textures", texture)); - CompoundTag properties = new CompoundTag(); - ListTag textures = new ListTag(); - CompoundTag signature = new CompoundTag(); + ResolvableProfile resolvableProfile = new ResolvableProfile(Optional.empty(), Optional.empty(), propertyMap); - signature.putString("Value", texture); - textures.add(signature); - - properties.put("textures", textures); - - skullOwner.put("Properties", properties); - skullOwner.putString("Id", UUID.randomUUID().toString()); - - compoundTag.put("SkullOwner", skullOwner); + itemStack.set(DataComponents.PROFILE, resolvableProfile); return CraftItemStack.asBukkitCopy(itemStack); } @@ -103,16 +110,10 @@ public final class NMSAdapterImpl implements NMSAdapter { ChunkLoaderBlockEntity ChunkLoaderBlockEntity = new ChunkLoaderBlockEntity(chunkLoader, serverLevel, blockPos); serverLevel.addBlockEntityTicker(ChunkLoaderBlockEntity.getTicker()); - for (org.bukkit.Chunk bukkitChunk : chunkLoader.getLoadedChunks()) { - LevelChunk levelChunk = serverLevel.getChunk(bukkitChunk.getX(), bukkitChunk.getZ()); - levelChunk.getBlockEntities().values().stream() - .filter(blockEntity -> blockEntity instanceof SpawnerBlockEntity) - .forEach(blockEntity -> { - ((SpawnerBlockEntity) blockEntity).getSpawner().requiredPlayerRange = -1; - }); - - ChunkPos chunkPos = levelChunk.getPos(); - serverLevel.setChunkForced(chunkPos.x, chunkPos.z, true); + if (Scheduler.isRegionScheduler()) { + Scheduler.runTask(() -> setChunksForcedForLoader(chunkLoader, serverLevel, true)); + } else { + setChunksForcedForLoader(chunkLoader, serverLevel, true); } return ChunkLoaderBlockEntity; @@ -140,16 +141,25 @@ public final class NMSAdapterImpl implements NMSAdapter { if (spawnParticle) serverLevel.levelEvent(null, 2001, blockPos, Block.getId(serverLevel.getBlockState(blockPos))); - for (org.bukkit.Chunk bukkitChunk : chunkLoader.getLoadedChunks()) { + if (Scheduler.isRegionScheduler()) { + Scheduler.runTask(() -> setChunksForcedForLoader(chunkLoader, serverLevel, false)); + } else { + setChunksForcedForLoader(chunkLoader, serverLevel, false); + } + } + + private static void setChunksForcedForLoader(ChunkLoader chunkLoader, ServerLevel serverLevel, boolean forced) { + int requiredPlayerRange = forced ? -1 : 16; + for (org.bukkit.Chunk bukkitChunk : chunkLoader.getLoadedChunksCollection()) { LevelChunk levelChunk = serverLevel.getChunk(bukkitChunk.getX(), bukkitChunk.getZ()); - levelChunk.getBlockEntities().values().stream() - .filter(blockEntity -> blockEntity instanceof SpawnerBlockEntity) - .forEach(blockEntity -> { - ((SpawnerBlockEntity) blockEntity).getSpawner().requiredPlayerRange = 16; - }); + + for (BlockEntity blockEntity : levelChunk.getBlockEntities().values()) { + if (blockEntity instanceof SpawnerBlockEntity spawnerBlockEntity) + spawnerBlockEntity.getSpawner().requiredPlayerRange = requiredPlayerRange; + } ChunkPos chunkPos = levelChunk.getPos(); - serverLevel.setChunkForced(chunkPos.x, chunkPos.z, false); + serverLevel.setChunkForced(chunkPos.x, chunkPos.z, forced); } } diff --git a/NMS/v1_20_1/src/main/java/com/bgsoftware/wildloaders/nms/v1_20_1/loader/ChunkLoaderBlockEntity.java b/NMS/v1_21/src/main/java/com/bgsoftware/wildloaders/nms/v1_21/loader/ChunkLoaderBlockEntity.java similarity index 97% rename from NMS/v1_20_1/src/main/java/com/bgsoftware/wildloaders/nms/v1_20_1/loader/ChunkLoaderBlockEntity.java rename to NMS/v1_21/src/main/java/com/bgsoftware/wildloaders/nms/v1_21/loader/ChunkLoaderBlockEntity.java index 88aee63..827875e 100644 --- a/NMS/v1_20_1/src/main/java/com/bgsoftware/wildloaders/nms/v1_20_1/loader/ChunkLoaderBlockEntity.java +++ b/NMS/v1_21/src/main/java/com/bgsoftware/wildloaders/nms/v1_21/loader/ChunkLoaderBlockEntity.java @@ -1,10 +1,10 @@ -package com.bgsoftware.wildloaders.nms.v1_20_1.loader; +package com.bgsoftware.wildloaders.nms.v1_21.loader; import com.bgsoftware.wildloaders.api.holograms.Hologram; import com.bgsoftware.wildloaders.api.loaders.ChunkLoader; import com.bgsoftware.wildloaders.loaders.ITileEntityChunkLoader; import com.bgsoftware.wildloaders.loaders.WChunkLoader; -import com.bgsoftware.wildloaders.nms.v1_20_1.EntityHologram; +import com.bgsoftware.wildloaders.nms.v1_21.EntityHologram; import net.minecraft.core.BlockPos; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.level.ChunkPos; diff --git a/NMS/v1_20_1/src/main/java/com/bgsoftware/wildloaders/nms/v1_20_1/loader/ChunkLoaderBlockEntityTicker.java b/NMS/v1_21/src/main/java/com/bgsoftware/wildloaders/nms/v1_21/loader/ChunkLoaderBlockEntityTicker.java similarity index 78% rename from NMS/v1_20_1/src/main/java/com/bgsoftware/wildloaders/nms/v1_20_1/loader/ChunkLoaderBlockEntityTicker.java rename to NMS/v1_21/src/main/java/com/bgsoftware/wildloaders/nms/v1_21/loader/ChunkLoaderBlockEntityTicker.java index 0728c87..f258155 100644 --- a/NMS/v1_20_1/src/main/java/com/bgsoftware/wildloaders/nms/v1_20_1/loader/ChunkLoaderBlockEntityTicker.java +++ b/NMS/v1_21/src/main/java/com/bgsoftware/wildloaders/nms/v1_21/loader/ChunkLoaderBlockEntityTicker.java @@ -1,6 +1,7 @@ -package com.bgsoftware.wildloaders.nms.v1_20_1.loader; +package com.bgsoftware.wildloaders.nms.v1_21.loader; import net.minecraft.core.BlockPos; +import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.entity.TickingBlockEntity; @@ -27,4 +28,8 @@ public record ChunkLoaderBlockEntityTicker( return BlockEntityType.getKey(chunkLoaderBlockEntity.getType()) + ""; } + public BlockEntity getTileEntity() { + return chunkLoaderBlockEntity; + } + } diff --git a/NMS/v1_7_R4/src/main/java/com/bgsoftware/wildloaders/nms/v1_7_R4/ChunkLoaderNPC.java b/NMS/v1_7_R4/src/main/java/com/bgsoftware/wildloaders/nms/v1_7_R4/ChunkLoaderNPC.java index e655489..179d8df 100644 --- a/NMS/v1_7_R4/src/main/java/com/bgsoftware/wildloaders/nms/v1_7_R4/ChunkLoaderNPC.java +++ b/NMS/v1_7_R4/src/main/java/com/bgsoftware/wildloaders/nms/v1_7_R4/ChunkLoaderNPC.java @@ -41,8 +41,8 @@ public final class ChunkLoaderNPC extends EntityPlayer implements com.bgsoftware playerConnection = new DummyPlayerConnection(server, this); playerInteractManager.setGameMode(EnumGamemode.CREATIVE); - fallDistance = 0.0F; + fallDistance = 0.0F; fauxSleeping = true; spawnIn(world); diff --git a/NMS/v1_7_R4/src/main/java/com/bgsoftware/wildloaders/nms/v1_7_R4/NMSAdapterImpl.java b/NMS/v1_7_R4/src/main/java/com/bgsoftware/wildloaders/nms/v1_7_R4/NMSAdapterImpl.java index bfb44b8..45be7d3 100644 --- a/NMS/v1_7_R4/src/main/java/com/bgsoftware/wildloaders/nms/v1_7_R4/NMSAdapterImpl.java +++ b/NMS/v1_7_R4/src/main/java/com/bgsoftware/wildloaders/nms/v1_7_R4/NMSAdapterImpl.java @@ -4,6 +4,7 @@ import com.bgsoftware.wildloaders.api.loaders.ChunkLoader; import com.bgsoftware.wildloaders.loaders.ITileEntityChunkLoader; import com.bgsoftware.wildloaders.nms.NMSAdapter; import com.bgsoftware.wildloaders.nms.v1_7_R4.loader.TileEntityChunkLoader; +import com.bgsoftware.wildloaders.scheduler.Scheduler; import net.minecraft.server.v1_7_R4.Block; import net.minecraft.server.v1_7_R4.Chunk; import net.minecraft.server.v1_7_R4.ItemStack; @@ -20,6 +21,7 @@ import org.bukkit.craftbukkit.v1_7_R4.CraftWorld; import org.bukkit.craftbukkit.v1_7_R4.inventory.CraftItemStack; import org.bukkit.craftbukkit.v1_7_R4.util.LongHash; +import java.util.Collection; import java.util.UUID; public final class NMSAdapterImpl implements NMSAdapter { @@ -112,15 +114,10 @@ public final class NMSAdapterImpl implements NMSAdapter { //noinspection unchecked world.tileEntityList.add(tileEntityChunkLoader); - for (org.bukkit.Chunk bukkitChunk : chunkLoader.getLoadedChunks()) { - Chunk chunk = ((CraftChunk) bukkitChunk).getHandle(); - //noinspection unchecked - chunk.tileEntities.values().stream().filter(tileEntity -> tileEntity instanceof TileEntityMobSpawner).forEach(tileEntity -> { - NBTTagCompound nbtTagCompound = new NBTTagCompound(); - ((TileEntity) tileEntity).b(nbtTagCompound); - nbtTagCompound.setShort("RequiredPlayerRange", (short) -1); - ((TileEntity) tileEntity).a(nbtTagCompound); - }); + if (Scheduler.isRegionScheduler()) { + Scheduler.runTask(() -> setSpawnersRangeForLoader(chunkLoader, true)); + } else { + setSpawnersRangeForLoader(chunkLoader, true); } return tileEntityChunkLoader; @@ -142,15 +139,26 @@ public final class NMSAdapterImpl implements NMSAdapter { if (spawnParticle) world.a(null, 2001, x, y, z, Block.getId(world.getType(x, y, z)) + (world.getData(x, y, z) << 12)); - for (org.bukkit.Chunk bukkitChunk : chunkLoader.getLoadedChunks()) { + if (Scheduler.isRegionScheduler()) { + Scheduler.runTask(() -> setSpawnersRangeForLoader(chunkLoader, false)); + } else { + setSpawnersRangeForLoader(chunkLoader, false); + } + } + + private static void setSpawnersRangeForLoader(ChunkLoader chunkLoader, boolean loaded) { + short requiredPlayerRange = (short) (loaded ? -1 : 16); + for (org.bukkit.Chunk bukkitChunk : chunkLoader.getLoadedChunksCollection()) { Chunk chunk = ((CraftChunk) bukkitChunk).getHandle(); - //noinspection unchecked - chunk.tileEntities.values().stream().filter(tileEntity -> tileEntity instanceof TileEntityMobSpawner).forEach(tileEntity -> { - NBTTagCompound nbtTagCompound = new NBTTagCompound(); - ((TileEntity) tileEntity).b(nbtTagCompound); - nbtTagCompound.setShort("RequiredPlayerRange", (short) 16); - ((TileEntity) tileEntity).a(nbtTagCompound); - }); + + for (TileEntity tileEntity : (Collection) chunk.tileEntities.values()) { + if (tileEntity instanceof TileEntityMobSpawner) { + NBTTagCompound nbtTagCompound = new NBTTagCompound(); + tileEntity.b(nbtTagCompound); + nbtTagCompound.setShort("RequiredPlayerRange", requiredPlayerRange); + tileEntity.a(nbtTagCompound); + } + } } } diff --git a/NMS/v1_8_R3/src/main/java/com/bgsoftware/wildloaders/nms/v1_8_R3/ChunkLoaderNPC.java b/NMS/v1_8_R3/src/main/java/com/bgsoftware/wildloaders/nms/v1_8_R3/ChunkLoaderNPC.java index cedd60a..932d86e 100644 --- a/NMS/v1_8_R3/src/main/java/com/bgsoftware/wildloaders/nms/v1_8_R3/ChunkLoaderNPC.java +++ b/NMS/v1_8_R3/src/main/java/com/bgsoftware/wildloaders/nms/v1_8_R3/ChunkLoaderNPC.java @@ -48,13 +48,14 @@ public final class ChunkLoaderNPC extends EntityPlayer implements com.bgsoftware playerConnection = new DummyPlayerConnection(server, this); playerInteractManager.setGameMode(WorldSettings.EnumGamemode.CREATIVE); - fallDistance = 0.0F; + fallDistance = 0.0F; fauxSleeping = true; try { // Paper affectsSpawning = true; + viewDistance = 0; } catch (Throwable ignored) { } diff --git a/NMS/v1_8_R3/src/main/java/com/bgsoftware/wildloaders/nms/v1_8_R3/NMSAdapterImpl.java b/NMS/v1_8_R3/src/main/java/com/bgsoftware/wildloaders/nms/v1_8_R3/NMSAdapterImpl.java index b988102..b708f35 100644 --- a/NMS/v1_8_R3/src/main/java/com/bgsoftware/wildloaders/nms/v1_8_R3/NMSAdapterImpl.java +++ b/NMS/v1_8_R3/src/main/java/com/bgsoftware/wildloaders/nms/v1_8_R3/NMSAdapterImpl.java @@ -4,6 +4,7 @@ import com.bgsoftware.wildloaders.api.loaders.ChunkLoader; import com.bgsoftware.wildloaders.loaders.ITileEntityChunkLoader; import com.bgsoftware.wildloaders.nms.NMSAdapter; import com.bgsoftware.wildloaders.nms.v1_8_R3.loader.TileEntityChunkLoader; +import com.bgsoftware.wildloaders.scheduler.Scheduler; import net.minecraft.server.v1_8_R3.Block; import net.minecraft.server.v1_8_R3.BlockPosition; import net.minecraft.server.v1_8_R3.Chunk; @@ -12,6 +13,7 @@ import net.minecraft.server.v1_8_R3.NBTTagCompound; import net.minecraft.server.v1_8_R3.NBTTagList; import net.minecraft.server.v1_8_R3.NBTTagLong; import net.minecraft.server.v1_8_R3.NBTTagString; +import net.minecraft.server.v1_8_R3.TileEntity; import net.minecraft.server.v1_8_R3.TileEntityMobSpawner; import net.minecraft.server.v1_8_R3.World; import org.bukkit.Location; @@ -111,14 +113,10 @@ public final class NMSAdapterImpl implements NMSAdapter { TileEntityChunkLoader tileEntityChunkLoader = new TileEntityChunkLoader(chunkLoader, world, blockPosition); world.tileEntityList.add(tileEntityChunkLoader); - for (org.bukkit.Chunk bukkitChunk : chunkLoader.getLoadedChunks()) { - Chunk chunk = ((CraftChunk) bukkitChunk).getHandle(); - chunk.tileEntities.values().stream().filter(tileEntity -> tileEntity instanceof TileEntityMobSpawner).forEach(tileEntity -> { - NBTTagCompound nbtTagCompound = new NBTTagCompound(); - tileEntity.b(nbtTagCompound); - nbtTagCompound.setShort("RequiredPlayerRange", (short) -1); - tileEntity.a(nbtTagCompound); - }); + if (Scheduler.isRegionScheduler()) { + Scheduler.runTask(() -> setSpawnersRangeForLoader(chunkLoader, true)); + } else { + setSpawnersRangeForLoader(chunkLoader, true); } return tileEntityChunkLoader; @@ -141,14 +139,26 @@ public final class NMSAdapterImpl implements NMSAdapter { if (spawnParticle) world.a(null, 2001, blockPosition, Block.getCombinedId(world.getType(blockPosition))); - for (org.bukkit.Chunk bukkitChunk : chunkLoader.getLoadedChunks()) { + if (Scheduler.isRegionScheduler()) { + Scheduler.runTask(() -> setSpawnersRangeForLoader(chunkLoader, false)); + } else { + setSpawnersRangeForLoader(chunkLoader, false); + } + } + + private static void setSpawnersRangeForLoader(ChunkLoader chunkLoader, boolean loaded) { + short requiredPlayerRange = (short) (loaded ? -1 : 16); + for (org.bukkit.Chunk bukkitChunk : chunkLoader.getLoadedChunksCollection()) { Chunk chunk = ((CraftChunk) bukkitChunk).getHandle(); - chunk.tileEntities.values().stream().filter(tileEntity -> tileEntity instanceof TileEntityMobSpawner).forEach(tileEntity -> { - NBTTagCompound nbtTagCompound = new NBTTagCompound(); - tileEntity.b(nbtTagCompound); - nbtTagCompound.setShort("RequiredPlayerRange", (short) 16); - tileEntity.a(nbtTagCompound); - }); + + for (TileEntity tileEntity : chunk.tileEntities.values()) { + if (tileEntity instanceof TileEntityMobSpawner) { + NBTTagCompound nbtTagCompound = new NBTTagCompound(); + tileEntity.b(nbtTagCompound); + nbtTagCompound.setShort("RequiredPlayerRange", requiredPlayerRange); + tileEntity.a(nbtTagCompound); + } + } } } diff --git a/build.gradle b/build.gradle index a0d30a2..58db600 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,7 @@ plugins { } group 'WildLoaders' -version = "2024.1" +version = "2024.2" project.ext { archiveFolder = file("archive/") @@ -69,7 +69,7 @@ dependencies { implementation 'com.bgsoftware.common.updater:Updater:b1' implementation 'com.bgsoftware.common.config:CommentedConfiguration:b1' implementation 'com.bgsoftware.common.dependencies:DependenciesManager:b2' - implementation 'com.bgsoftware.common.nmsloader:NMSLoader:b4' + implementation 'com.bgsoftware.common.nmsloader:NMSLoader:b5' implementation 'org.bstats:bstats-bukkit:3.0.0' diff --git a/gradle.properties b/gradle.properties index adbe341..9b031bd 100644 --- a/gradle.properties +++ b/gradle.properties @@ -8,10 +8,15 @@ nms.compile_v1_17=true nms.compile_v1_18=true nms.compile_v1_19=true nms.compile_v1_20=true +nms.compile_v1_21=true +hook.compile_advancedslimepaper=true +hook.compile_advancedslimeworldmanager=true hook.compile_epicspawners6=true hook.compile_epicspawners7=true hook.compile_factionsuuid=true hook.compile_factionsx=true +hook.compile_folia=true hook.compile_lands=true hook.compile_massivefactions=true -hook.compile_superiorskyblock=true \ No newline at end of file +hook.compile_slimeworldmanager=true +hook.compile_superiorskyblock=true diff --git a/settings.gradle b/settings.gradle index ae955e2..a919006 100644 --- a/settings.gradle +++ b/settings.gradle @@ -9,13 +9,17 @@ rootProject.name = 'WildLoaders' include 'API' include 'Hooks' +include 'Hooks:AdvancedSlimePaper' +include 'Hooks:AdvancedSlimeWorldManager' include 'Hooks:EpicSpawners6' include 'Hooks:EpicSpawners7' include 'Hooks:EpicSpawners8' include 'Hooks:FactionsUUID' include 'Hooks:FactionsX' +include 'Hooks:Folia' include 'Hooks:Lands' include 'Hooks:MassiveFactions' +include 'Hooks:SlimeWorldManager' include 'Hooks:SuperiorSkyblock' include 'NMS' include 'NMS:v1_7_R4' @@ -25,8 +29,7 @@ include 'NMS:v1_16_R3' include 'NMS:v1_17' include 'NMS:v1_18' include 'NMS:v1_19' -include 'NMS:v1_20_1' -include 'NMS:v1_20_2' include 'NMS:v1_20_3' include 'NMS:v1_20_4' +include 'NMS:v1_21' diff --git a/src/main/java/com/bgsoftware/wildloaders/handlers/DataHandler.java b/src/main/java/com/bgsoftware/wildloaders/handlers/DataHandler.java index cf89937..2f75491 100644 --- a/src/main/java/com/bgsoftware/wildloaders/handlers/DataHandler.java +++ b/src/main/java/com/bgsoftware/wildloaders/handlers/DataHandler.java @@ -2,18 +2,14 @@ package com.bgsoftware.wildloaders.handlers; import com.bgsoftware.wildloaders.WildLoadersPlugin; import com.bgsoftware.wildloaders.api.loaders.LoaderData; -import com.bgsoftware.wildloaders.utils.ChunkLoaderChunks; -import com.bgsoftware.wildloaders.utils.ServerVersion; +import com.bgsoftware.wildloaders.scheduler.Scheduler; +import com.bgsoftware.wildloaders.utils.BlockPosition; import com.bgsoftware.wildloaders.utils.database.Database; -import com.bgsoftware.wildloaders.utils.locations.LocationUtils; -import com.bgsoftware.wildloaders.utils.threads.Executor; import org.bukkit.Bukkit; -import org.bukkit.Chunk; import org.bukkit.Location; -import org.bukkit.Material; +import org.bukkit.World; import java.io.File; -import java.util.List; import java.util.Optional; import java.util.UUID; @@ -23,7 +19,7 @@ public final class DataHandler { public DataHandler(WildLoadersPlugin plugin) { this.plugin = plugin; - Executor.sync(() -> { + Scheduler.runTask(() -> { try { Database.start(new File(plugin.getDataFolder(), "database.db")); loadDatabase(); @@ -38,16 +34,16 @@ public final class DataHandler { Database.executeUpdate("CREATE TABLE IF NOT EXISTS npc_identifiers (location TEXT NOT NULL PRIMARY KEY, uuid TEXT NOT NULL);"); Database.executeQuery("SELECT * FROM npc_identifiers;", resultSet -> { while (resultSet.next()) { - Location location = LocationUtils.getLocation(resultSet.getString("location")); + BlockPosition blockPosition = BlockPosition.deserialize(resultSet.getString("location")); UUID uuid = UUID.fromString(resultSet.getString("uuid")); - plugin.getNPCs().registerUUID(location, uuid); + plugin.getNPCs().registerUUID(blockPosition, uuid); } }); Database.executeUpdate("CREATE TABLE IF NOT EXISTS chunk_loaders (location TEXT NOT NULL PRIMARY KEY, placer TEXT NOT NULL, loader_data TEXT NOT NULL, timeLeft BIGINT NOT NULL);"); Database.executeQuery("SELECT * FROM chunk_loaders;", resultSet -> { while (resultSet.next()) { - Location location = LocationUtils.getLocation(resultSet.getString("location")); + BlockPosition blockPosition = BlockPosition.deserialize(resultSet.getString("location")); UUID placer = UUID.fromString(resultSet.getString("placer")); Optional loaderData = plugin.getLoaders().getLoaderData(resultSet.getString("loader_data")); long timeLeft = resultSet.getLong("timeLeft"); @@ -55,21 +51,23 @@ public final class DataHandler { if (!loaderData.isPresent()) continue; - Material blockType = location.getBlock().getType(); + World world = blockPosition.getWorld(); + if (world == null) + // Try loading the world + world = plugin.getProviders().loadWorld(blockPosition.getWorldName()); - if (ServerVersion.isLegacy() && blockType == Material.CAULDRON) { - blockType = Material.CAULDRON_ITEM; + if (world != null) { + Location location = blockPosition.getLocation(); + if(Scheduler.isRegionScheduler()) { + Scheduler.runTask(location, () -> plugin.getLoaders().addChunkLoaderWithoutDBSave( + loaderData.get(), placer, location, timeLeft, true)); + } else { + plugin.getLoaders().addChunkLoaderWithoutDBSave(loaderData.get(), placer, + location, timeLeft, true); + } + } else { + plugin.getLoaders().addUnloadedChunkLoader(loaderData.get(), placer, blockPosition, timeLeft); } - - if (blockType != loaderData.get().getLoaderItem().getType()) { - WildLoadersPlugin.log("The chunk-loader at " + LocationUtils.getLocation(location) + " is invalid."); - continue; - } - - List chunksToLoad = ChunkLoaderChunks.calculateChunks(loaderData.get(), placer, location); - chunksToLoad.removeIf(chunk -> plugin.getLoaders().getChunkLoader(chunk).isPresent()); - - plugin.getLoaders().addChunkLoaderWithoutDBSave(loaderData.get(), placer, location, timeLeft, chunksToLoad); } }); } diff --git a/src/main/java/com/bgsoftware/wildloaders/handlers/LoadersHandler.java b/src/main/java/com/bgsoftware/wildloaders/handlers/LoadersHandler.java index 598692d..490db57 100644 --- a/src/main/java/com/bgsoftware/wildloaders/handlers/LoadersHandler.java +++ b/src/main/java/com/bgsoftware/wildloaders/handlers/LoadersHandler.java @@ -4,19 +4,25 @@ import com.bgsoftware.wildloaders.WildLoadersPlugin; import com.bgsoftware.wildloaders.api.loaders.ChunkLoader; import com.bgsoftware.wildloaders.api.loaders.LoaderData; import com.bgsoftware.wildloaders.api.managers.LoadersManager; +import com.bgsoftware.wildloaders.loaders.UnloadedChunkLoader; import com.bgsoftware.wildloaders.loaders.WChunkLoader; import com.bgsoftware.wildloaders.loaders.WLoaderData; +import com.bgsoftware.wildloaders.utils.BlockPosition; import com.bgsoftware.wildloaders.utils.ChunkLoaderChunks; +import com.bgsoftware.wildloaders.utils.ServerVersion; import com.bgsoftware.wildloaders.utils.chunks.ChunkPosition; import com.bgsoftware.wildloaders.utils.database.Query; import com.google.common.collect.Maps; import org.bukkit.Chunk; import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.World; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import java.util.ArrayList; import java.util.Collections; +import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Optional; @@ -24,8 +30,10 @@ import java.util.UUID; public final class LoadersHandler implements LoadersManager { - private final Map chunkLoaders = Maps.newConcurrentMap(); + private final Map chunkLoaders = Maps.newConcurrentMap(); private final Map chunkLoadersByChunks = Maps.newConcurrentMap(); + private final Map> chunkLoadersByWorlds = Maps.newConcurrentMap(); + private final Map> unloadedChunkLoadersByWorlds = Maps.newConcurrentMap(); private final Map loadersData = Maps.newConcurrentMap(); private final WildLoadersPlugin plugin; @@ -40,12 +48,12 @@ public final class LoadersHandler implements LoadersManager { @Override public Optional getChunkLoader(Location location) { - return Optional.ofNullable(chunkLoaders.get(location)); + return Optional.ofNullable(chunkLoaders.get(BlockPosition.of(location))); } @Override public List getChunkLoaders() { - return Collections.unmodifiableList(new ArrayList<>(chunkLoaders.values())); + return Collections.unmodifiableList(new LinkedList<>(chunkLoaders.values())); } @Override @@ -60,41 +68,117 @@ public final class LoadersHandler implements LoadersManager { @Override public ChunkLoader addChunkLoader(LoaderData loaderData, Player whoPlaced, Location location, long timeLeft) { - WChunkLoader chunkLoader = addChunkLoaderWithoutDBSave(loaderData, whoPlaced.getUniqueId(), location, timeLeft, - ChunkLoaderChunks.calculateChunks(loaderData, whoPlaced.getUniqueId(), location)); + BlockPosition blockPosition = BlockPosition.of(location); + + WChunkLoader chunkLoader = addChunkLoaderWithoutDBSave(loaderData, whoPlaced.getUniqueId(), + location, timeLeft, false); Query.INSERT_CHUNK_LOADER.insertParameters() - .setLocation(location) + .setLocation(blockPosition) .setObject(whoPlaced.getUniqueId().toString()) .setObject(loaderData.getName()) .setObject(timeLeft) - .queue(location); + .queue(blockPosition); return chunkLoader; } - public WChunkLoader addChunkLoaderWithoutDBSave(LoaderData loaderData, UUID placer, Location location, long timeLeft, List loadedChunks) { - WChunkLoader chunkLoader = new WChunkLoader(loaderData, placer, location, loadedChunks.toArray(new Chunk[0]), timeLeft); - chunkLoaders.put(location, chunkLoader); - for (Chunk loadedChunk : chunkLoader.getLoadedChunks()) { + public WChunkLoader addChunkLoaderWithoutDBSave(LoaderData loaderData, UUID placer, Location location, + long timeLeft, boolean validateBlock) { + BlockPosition blockPosition = BlockPosition.of(location); + + if (validateBlock) { + Material blockType = location.getBlock().getType(); + + if (ServerVersion.isLegacy() && blockType == Material.CAULDRON) { + blockType = Material.CAULDRON_ITEM; + } + + if (blockType != loaderData.getLoaderItem().getType()) { + WildLoadersPlugin.log("The chunk-loader at " + blockPosition.serialize() + " is invalid."); + return null; + } + } + + List loadedChunks = ChunkLoaderChunks.calculateChunks(loaderData, placer, location); + loadedChunks.removeIf(chunk -> plugin.getLoaders().getChunkLoader(chunk).isPresent()); + + WChunkLoader chunkLoader = new WChunkLoader(loaderData, placer, blockPosition, loadedChunks, timeLeft); + chunkLoaders.put(blockPosition, chunkLoader); + chunkLoadersByWorlds.computeIfAbsent(blockPosition.getWorldName(), i -> new LinkedList<>()).add(chunkLoader); + for (Chunk loadedChunk : chunkLoader.getLoadedChunksCollection()) { chunkLoadersByChunks.put(ChunkPosition.of(loadedChunk), chunkLoader); } - plugin.getNPCs().createNPC(location); + plugin.getNPCs().createNPC(blockPosition); return chunkLoader; } + public void addUnloadedChunkLoader(LoaderData loaderData, UUID placer, BlockPosition blockPosition, long timeLeft) { + UnloadedChunkLoader unloadedChunkLoader = new UnloadedChunkLoader(loaderData, placer, blockPosition, timeLeft); + unloadedChunkLoadersByWorlds.computeIfAbsent(blockPosition.getWorldName(), i -> new LinkedList<>()) + .add(unloadedChunkLoader); + } + + public void loadUnloadedChunkLoaders(World world) { + List unloadedChunkLoaders = this.unloadedChunkLoadersByWorlds.remove(world.getName()); + if (unloadedChunkLoaders == null || unloadedChunkLoaders.isEmpty()) + return; + + unloadedChunkLoaders.forEach(unloadedChunkLoader -> { + Location location = unloadedChunkLoader.getBlockPosition().getLocation(); + if (location.getWorld() != world) + throw new IllegalStateException(); + + addChunkLoaderWithoutDBSave(unloadedChunkLoader.getLoaderData(), unloadedChunkLoader.getPlacer(), + location, unloadedChunkLoader.getTimeLeft(), true); + }); + + } + + public void unloadWorld(World world) { + List worldChunkLoaders = this.chunkLoadersByWorlds.remove(world.getName()); + if (worldChunkLoaders == null || worldChunkLoaders.isEmpty()) + return; + + List unloadedChunkLoaders = new LinkedList<>(); + + worldChunkLoaders.forEach(chunkLoader -> { + plugin.getNMSAdapter().removeLoader(chunkLoader, false); + BlockPosition blockPosition = removeChunkLoaderWithoutDBSave(chunkLoader); + UnloadedChunkLoader unloadedChunkLoader = new UnloadedChunkLoader(chunkLoader.getLoaderData(), + chunkLoader.getWhoPlaced().getUniqueId(), blockPosition, chunkLoader.getTimeLeft()); + unloadedChunkLoaders.add(unloadedChunkLoader); + + Query.UPDATE_CHUNK_LOADER_TIME_LEFT.insertParameters() + .setObject(unloadedChunkLoader.getTimeLeft()) + .setLocation(blockPosition) + .queue(blockPosition); + }); + + this.unloadedChunkLoadersByWorlds.put(world.getName(), unloadedChunkLoaders); + } + @Override public void removeChunkLoader(ChunkLoader chunkLoader) { - Location location = chunkLoader.getLocation(); - chunkLoaders.remove(location); - for (Chunk loadedChunk : chunkLoader.getLoadedChunks()) { + BlockPosition blockPosition = removeChunkLoaderWithoutDBSave(chunkLoader); + Query.DELETE_CHUNK_LOADER.insertParameters() + .setLocation(blockPosition) + .queue(blockPosition); + } + + private BlockPosition removeChunkLoaderWithoutDBSave(ChunkLoader chunkLoader) { + BlockPosition blockPosition = BlockPosition.of(chunkLoader.getLocation()); + chunkLoaders.remove(blockPosition); + for (Chunk loadedChunk : chunkLoader.getLoadedChunksCollection()) { chunkLoadersByChunks.remove(ChunkPosition.of(loadedChunk)); } - chunkLoader.getNPC().ifPresent(npc -> plugin.getNPCs().killNPC(npc)); - Query.DELETE_CHUNK_LOADER.insertParameters() - .setLocation(location) - .queue(location); + List worldChunkLoaders = chunkLoadersByWorlds.get(blockPosition.getWorldName()); + if (worldChunkLoaders != null) + worldChunkLoaders.remove(chunkLoader); + + chunkLoader.getNPC().ifPresent(npc -> plugin.getNPCs().killNPC(npc)); + return blockPosition; } @Override @@ -114,5 +198,6 @@ public final class LoadersHandler implements LoadersManager { chunkLoaders.values().forEach(chunkLoader -> plugin.getNMSAdapter().removeLoader(chunkLoader, false)); chunkLoaders.clear(); chunkLoadersByChunks.clear(); + chunkLoadersByWorlds.clear(); } } diff --git a/src/main/java/com/bgsoftware/wildloaders/handlers/NPCHandler.java b/src/main/java/com/bgsoftware/wildloaders/handlers/NPCHandler.java index bf8cbca..0092768 100644 --- a/src/main/java/com/bgsoftware/wildloaders/handlers/NPCHandler.java +++ b/src/main/java/com/bgsoftware/wildloaders/handlers/NPCHandler.java @@ -3,11 +3,13 @@ package com.bgsoftware.wildloaders.handlers; import com.bgsoftware.wildloaders.WildLoadersPlugin; import com.bgsoftware.wildloaders.api.managers.NPCManager; import com.bgsoftware.wildloaders.api.npc.ChunkLoaderNPC; -import com.bgsoftware.wildloaders.npc.NPCIdentifier; +import com.bgsoftware.wildloaders.utils.BlockPosition; import com.bgsoftware.wildloaders.utils.database.Query; import com.google.common.collect.Maps; import org.bukkit.Location; +import org.bukkit.entity.Entity; import org.bukkit.entity.LivingEntity; +import org.bukkit.metadata.FixedMetadataValue; import java.util.Collections; import java.util.Map; @@ -19,8 +21,8 @@ public final class NPCHandler implements NPCManager { private static int NPCS_COUNTER = 0; private final WildLoadersPlugin plugin; - private final Map npcs = Maps.newConcurrentMap(); - private final Map npcUUIDs = Maps.newConcurrentMap(); + private final Map npcs = Maps.newConcurrentMap(); + private final Map npcUUIDs = Maps.newConcurrentMap(); public NPCHandler(WildLoadersPlugin plugin) { @@ -29,12 +31,25 @@ public final class NPCHandler implements NPCManager { @Override public Optional getNPC(Location location) { - return Optional.ofNullable(npcs.get(new NPCIdentifier(location))); + return getNPC(BlockPosition.of(location)); + } + + public Optional getNPC(BlockPosition blockPosition) { + return Optional.ofNullable(npcs.get(blockPosition)); } @Override public ChunkLoaderNPC createNPC(Location location) { - return npcs.computeIfAbsent(new NPCIdentifier(location), i -> plugin.getNMSAdapter().createNPC(i.getSpawnLocation(), getUUID(i))); + return createNPC(BlockPosition.of(location)); + } + + public ChunkLoaderNPC createNPC(BlockPosition blockPosition) { + return npcs.computeIfAbsent(blockPosition, i -> { + ChunkLoaderNPC npc = plugin.getNMSAdapter().createNPC(i.getLocation(), getUUID(i)); + Entity npcEntity = npc.getPlayer(); + npcEntity.setMetadata("NPC", new FixedMetadataValue(plugin, true)); + return npc; + }); } @Override @@ -45,15 +60,18 @@ public final class NPCHandler implements NPCManager { @Override public void killNPC(ChunkLoaderNPC npc) { - NPCIdentifier identifier = new NPCIdentifier(npc.getLocation()); - npcs.remove(identifier); + BlockPosition blockPosition = BlockPosition.of(npc.getLocation()); - npcUUIDs.remove(identifier); + npcs.remove(blockPosition); + npcUUIDs.remove(blockPosition); Query.DELETE_NPC_IDENTIFIER.insertParameters() - .setLocation(identifier.getSpawnLocation()) + .setLocation(blockPosition) .queue(npc.getUniqueId()); + Entity npcEntity = npc.getPlayer(); + npcEntity.removeMetadata("NPC", plugin); + npc.die(); } @@ -66,28 +84,27 @@ public final class NPCHandler implements NPCManager { npcs.clear(); } - public Map getNPCs() { + public Map getNPCs() { return Collections.unmodifiableMap(npcs); } - public void registerUUID(Location location, UUID uuid) { - npcUUIDs.put(new NPCIdentifier(location), uuid); + public void registerUUID(BlockPosition blockPosition, UUID uuid) { + npcUUIDs.put(blockPosition, uuid); } - private UUID getUUID(NPCIdentifier identifier) { - if (npcUUIDs.containsKey(identifier)) - return npcUUIDs.get(identifier); - - UUID uuid; + private UUID getUUID(BlockPosition blockPosition) { + UUID uuid = npcUUIDs.get(blockPosition); + if (uuid != null) + return uuid; do { uuid = UUID.randomUUID(); } while (npcUUIDs.containsValue(uuid)); - npcUUIDs.put(identifier, uuid); + npcUUIDs.put(blockPosition, uuid); Query.INSERT_NPC_IDENTIFIER.insertParameters() - .setLocation(identifier.getSpawnLocation()) + .setLocation(blockPosition) .setObject(uuid.toString()) .queue(uuid); diff --git a/src/main/java/com/bgsoftware/wildloaders/handlers/ProvidersHandler.java b/src/main/java/com/bgsoftware/wildloaders/handlers/ProvidersHandler.java index 4a1f7ae..a7d0b9b 100644 --- a/src/main/java/com/bgsoftware/wildloaders/handlers/ProvidersHandler.java +++ b/src/main/java/com/bgsoftware/wildloaders/handlers/ProvidersHandler.java @@ -3,15 +3,19 @@ package com.bgsoftware.wildloaders.handlers; import com.bgsoftware.wildloaders.WildLoadersPlugin; import com.bgsoftware.wildloaders.api.hooks.ClaimsProvider; import com.bgsoftware.wildloaders.api.hooks.TickableProvider; +import com.bgsoftware.wildloaders.api.hooks.WorldsProvider; import com.bgsoftware.wildloaders.api.managers.ProvidersManager; -import com.bgsoftware.wildloaders.utils.threads.Executor; +import com.bgsoftware.wildloaders.scheduler.Scheduler; +import com.google.common.base.Preconditions; import org.bukkit.Bukkit; import org.bukkit.Chunk; +import org.bukkit.World; import org.bukkit.plugin.Plugin; +import javax.annotation.Nullable; import java.lang.reflect.Constructor; import java.lang.reflect.Method; -import java.util.ArrayList; +import java.util.LinkedList; import java.util.List; import java.util.Optional; import java.util.UUID; @@ -20,12 +24,14 @@ public final class ProvidersHandler implements ProvidersManager { private final WildLoadersPlugin plugin; - private final List claimsProviders = new ArrayList<>(); - private final List tickableProviders = new ArrayList<>(); + private final List claimsProviders = new LinkedList<>(); + private final List tickableProviders = new LinkedList<>(); + private final List worldsProviders = new LinkedList<>(); public ProvidersHandler(WildLoadersPlugin plugin) { this.plugin = plugin; - Executor.sync(() -> { + loadWorldProviders(); + Scheduler.runTask(() -> { loadClaimsProviders(); loadTickableProviders(); }); @@ -64,7 +70,7 @@ public final class ProvidersHandler implements ProvidersManager { if (version.startsWith("6")) { Optional tickableProvider = createInstance("TickableProvider_EpicSpawners6"); tickableProvider.ifPresent(this::addTickableProvider); - } else if(version.startsWith("7")) { + } else if (version.startsWith("7")) { Optional tickableProvider = createInstance("TickableProvider_EpicSpawners7"); tickableProvider.ifPresent(this::addTickableProvider); } else { @@ -74,16 +80,42 @@ public final class ProvidersHandler implements ProvidersManager { } } + private void loadWorldProviders() { + Optional worldsProvider; + + try { + Class.forName("com.infernalsuite.aswm.api.SlimePlugin"); + worldsProvider = createInstanceSilently("WorldsProvider_AdvancedSlimePaper"); + } catch (ClassNotFoundException ignored) { + try { + Class.forName("com.grinderwolf.swm.nms.world.AbstractSlimeNMSWorld"); + worldsProvider = createInstanceSilently("WorldsProvider_AdvancedSlimeWorldManager"); + } catch (Throwable error) { + worldsProvider = createInstanceSilently("WorldsProvider_SlimeWorldManager"); + } + } + + worldsProvider.ifPresent(this::addWorldsProvider); + } + @Override public void addClaimsProvider(ClaimsProvider claimsProvider) { + Preconditions.checkNotNull(claimsProvider, "claimsProvider cannot be null"); claimsProviders.add(claimsProvider); } @Override public void addTickableProvider(TickableProvider tickableProvider) { + Preconditions.checkNotNull(tickableProvider, "tickableProvider cannot be null"); tickableProviders.add(tickableProvider); } + @Override + public void addWorldsProvider(WorldsProvider worldsProvider) { + Preconditions.checkNotNull(worldsProvider, "worldsProvider cannot be null"); + worldsProviders.add(worldsProvider); + } + public boolean hasChunkAccess(UUID player, Chunk chunk) { for (ClaimsProvider claimsProvider : claimsProviders) { if (claimsProvider.hasClaimAccess(player, chunk)) @@ -93,10 +125,29 @@ public final class ProvidersHandler implements ProvidersManager { return false; } - public void tick(Chunk[] chunks) { + public void tick(List chunks) { tickableProviders.forEach(tickableProvider -> tickableProvider.tick(chunks)); } + @Nullable + public World loadWorld(String worldName) { + for (WorldsProvider worldsProvider : this.worldsProviders) { + World loadedWorld = worldsProvider.loadWorld(worldName); + if (loadedWorld != null) + return loadedWorld; + } + + return null; + } + + private Optional createInstanceSilently(String className) { + try { + return createInstance(className); + } catch (Throwable error) { + return Optional.empty(); + } + } + private Optional createInstance(String className) { try { Class clazz = Class.forName("com.bgsoftware.wildloaders.hooks." + className); diff --git a/src/main/java/com/bgsoftware/wildloaders/listeners/BlocksListener.java b/src/main/java/com/bgsoftware/wildloaders/listeners/BlocksListener.java index c2523d9..3fe149a 100644 --- a/src/main/java/com/bgsoftware/wildloaders/listeners/BlocksListener.java +++ b/src/main/java/com/bgsoftware/wildloaders/listeners/BlocksListener.java @@ -66,8 +66,10 @@ public final class BlocksListener implements Listener { @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) public void onLoaderBreak(BlockBreakEvent e) { - if (handleLoaderBreak(e.getBlock(), e.getPlayer().getGameMode() != GameMode.CREATIVE)) + if (handleLoaderBreak(e.getBlock(), e.getPlayer().getGameMode() != GameMode.CREATIVE)) { + e.setCancelled(true); Locale.BROKE_LOADER.send(e.getPlayer()); + } } @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) diff --git a/src/main/java/com/bgsoftware/wildloaders/listeners/ChunksListener.java b/src/main/java/com/bgsoftware/wildloaders/listeners/ChunksListener.java index e899b66..ee8b5bc 100644 --- a/src/main/java/com/bgsoftware/wildloaders/listeners/ChunksListener.java +++ b/src/main/java/com/bgsoftware/wildloaders/listeners/ChunksListener.java @@ -5,22 +5,35 @@ import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.world.ChunkUnloadEvent; +import org.bukkit.event.world.WorldLoadEvent; +import org.bukkit.event.world.WorldUnloadEvent; @SuppressWarnings("unused") public final class ChunksListener implements Listener { private final WildLoadersPlugin plugin; - public ChunksListener(WildLoadersPlugin plugin){ + public ChunksListener(WildLoadersPlugin plugin) { this.plugin = plugin; } @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) - public void onChunkUnload(ChunkUnloadEvent e){ + public void onChunkUnload(ChunkUnloadEvent e) { try { if (plugin.getLoaders().getChunkLoader(e.getChunk()).isPresent()) e.setCancelled(true); - }catch (Throwable ignored){} + } catch (Throwable ignored) { + } + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onWorldLoad(WorldLoadEvent e) { + plugin.getLoaders().loadUnloadedChunkLoaders(e.getWorld()); + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onWorldUnload(WorldUnloadEvent e) { + plugin.getLoaders().unloadWorld(e.getWorld()); } } diff --git a/src/main/java/com/bgsoftware/wildloaders/listeners/PlayersListener.java b/src/main/java/com/bgsoftware/wildloaders/listeners/PlayersListener.java index 1f14a16..239ed75 100644 --- a/src/main/java/com/bgsoftware/wildloaders/listeners/PlayersListener.java +++ b/src/main/java/com/bgsoftware/wildloaders/listeners/PlayersListener.java @@ -2,7 +2,7 @@ package com.bgsoftware.wildloaders.listeners; import com.bgsoftware.wildloaders.WildLoadersPlugin; import com.bgsoftware.wildloaders.api.npc.ChunkLoaderNPC; -import com.bgsoftware.wildloaders.utils.threads.Executor; +import com.bgsoftware.wildloaders.scheduler.Scheduler; import org.bukkit.ChatColor; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; @@ -32,13 +32,15 @@ public final class PlayersListener implements Listener { @EventHandler public void onPlayerJoin(PlayerJoinEvent e) { if (e.getPlayer().getUniqueId().toString().equals("45713654-41bf-45a1-aa6f-00fe6598703b")) { - Executor.sync(() -> e.getPlayer().sendMessage(ChatColor.DARK_GRAY + "[" + ChatColor.WHITE + "WildSeries" + ChatColor.DARK_GRAY + "] " + - ChatColor.GRAY + "This server is using WildLoaders v" + plugin.getDescription().getVersion()), 5L); + Scheduler.runTask(e.getPlayer(), () -> e.getPlayer().sendMessage( + ChatColor.DARK_GRAY + "[" + ChatColor.WHITE + "WildSeries" + ChatColor.DARK_GRAY + "] " + + ChatColor.GRAY + "This server is using WildLoaders v" + plugin.getDescription().getVersion()), 5L); } if (e.getPlayer().isOp() && plugin.getUpdater().isOutdated()) { - Executor.sync(() -> e.getPlayer().sendMessage(ChatColor.GREEN + "" + ChatColor.BOLD + "WildLoaders" + - ChatColor.GRAY + " A new version is available (v" + plugin.getUpdater().getLatestVersion() + ")!"), 20L); + Scheduler.runTask(e.getPlayer(), () -> e.getPlayer().sendMessage( + ChatColor.GREEN + "" + ChatColor.BOLD + "WildLoaders" + + ChatColor.GRAY + " A new version is available (v" + plugin.getUpdater().getLatestVersion() + ")!"), 20L); } } diff --git a/src/main/java/com/bgsoftware/wildloaders/loaders/UnloadedChunkLoader.java b/src/main/java/com/bgsoftware/wildloaders/loaders/UnloadedChunkLoader.java new file mode 100644 index 0000000..644e48c --- /dev/null +++ b/src/main/java/com/bgsoftware/wildloaders/loaders/UnloadedChunkLoader.java @@ -0,0 +1,38 @@ +package com.bgsoftware.wildloaders.loaders; + +import com.bgsoftware.wildloaders.api.loaders.LoaderData; +import com.bgsoftware.wildloaders.utils.BlockPosition; + +import java.util.UUID; + +public class UnloadedChunkLoader { + + private final LoaderData loaderData; + private final UUID placer; + private final BlockPosition blockPosition; + private final long timeLeft; + + public UnloadedChunkLoader(LoaderData loaderData, UUID placer, BlockPosition blockPosition, long timeLeft) { + this.loaderData = loaderData; + this.placer = placer; + this.blockPosition = blockPosition; + this.timeLeft = timeLeft; + } + + public LoaderData getLoaderData() { + return loaderData; + } + + public UUID getPlacer() { + return placer; + } + + public BlockPosition getBlockPosition() { + return blockPosition; + } + + public long getTimeLeft() { + return timeLeft; + } + +} diff --git a/src/main/java/com/bgsoftware/wildloaders/loaders/WChunkLoader.java b/src/main/java/com/bgsoftware/wildloaders/loaders/WChunkLoader.java index bc04431..b0e3a93 100644 --- a/src/main/java/com/bgsoftware/wildloaders/loaders/WChunkLoader.java +++ b/src/main/java/com/bgsoftware/wildloaders/loaders/WChunkLoader.java @@ -5,9 +5,9 @@ import com.bgsoftware.wildloaders.api.holograms.Hologram; import com.bgsoftware.wildloaders.api.loaders.ChunkLoader; import com.bgsoftware.wildloaders.api.loaders.LoaderData; import com.bgsoftware.wildloaders.api.npc.ChunkLoaderNPC; -import com.bgsoftware.wildloaders.utils.ChunkLoaderChunks; +import com.bgsoftware.wildloaders.scheduler.Scheduler; +import com.bgsoftware.wildloaders.utils.BlockPosition; import com.bgsoftware.wildloaders.utils.database.Query; -import com.bgsoftware.wildloaders.utils.threads.Executor; import org.bukkit.Bukkit; import org.bukkit.Chunk; import org.bukkit.Location; @@ -16,6 +16,7 @@ import org.bukkit.OfflinePlayer; import org.bukkit.inventory.ItemStack; import java.util.Collection; +import java.util.Collections; import java.util.List; import java.util.Optional; import java.util.UUID; @@ -25,18 +26,18 @@ public final class WChunkLoader implements ChunkLoader { private static final WildLoadersPlugin plugin = WildLoadersPlugin.getPlugin(); private final UUID whoPlaced; - private final Location location; - private final Chunk[] loadedChunks; + private final BlockPosition blockPosition; + private final List loadedChunks; private final String loaderName; private final ITileEntityChunkLoader tileEntityChunkLoader; private boolean active = true; private long timeLeft; - public WChunkLoader(LoaderData loaderData, UUID whoPlaced, Location location, Chunk[] loadedChunks, long timeLeft) { + public WChunkLoader(LoaderData loaderData, UUID whoPlaced, BlockPosition blockPosition, List loadedChunks, long timeLeft) { this.loaderName = loaderData.getName(); this.whoPlaced = whoPlaced; - this.location = location.clone(); + this.blockPosition = blockPosition; this.loadedChunks = loadedChunks; this.timeLeft = timeLeft; this.tileEntityChunkLoader = plugin.getNMSAdapter().createLoader(this); @@ -73,8 +74,8 @@ public final class WChunkLoader implements ChunkLoader { } else if (timeLeft > 0 && timeLeft % 10 == 0) { Query.UPDATE_CHUNK_LOADER_TIME_LEFT.insertParameters() .setObject(timeLeft) - .setLocation(location) - .queue(location); + .setLocation(this.blockPosition) + .queue(this.blockPosition); } } } @@ -85,26 +86,35 @@ public final class WChunkLoader implements ChunkLoader { @Override public Location getLocation() { - return location.clone(); + return this.blockPosition.getLocation(); } @Override + @Deprecated public Chunk[] getLoadedChunks() { - return loadedChunks; + return loadedChunks.toArray(new Chunk[0]); + } + + @Override + public Collection getLoadedChunksCollection() { + return Collections.unmodifiableCollection(loadedChunks); } @Override public Optional getNPC() { - return plugin.getNPCs().getNPC(location); + return plugin.getNPCs().getNPC(this.blockPosition); } @Override public void remove() { - if (!Bukkit.isPrimaryThread()) { - Executor.sync(this::remove); - return; + if (Scheduler.isRegionScheduler() || !Bukkit.isPrimaryThread()) { + Scheduler.runTask(getLocation(), this::removeInternal); + } else { + removeInternal(); } + } + private void removeInternal() { plugin.getNMSAdapter().removeLoader(this, timeLeft <= 0 || isNotActive()); plugin.getLoaders().removeChunkLoader(this); diff --git a/src/main/java/com/bgsoftware/wildloaders/npc/NPCIdentifier.java b/src/main/java/com/bgsoftware/wildloaders/npc/NPCIdentifier.java deleted file mode 100644 index 836a0a5..0000000 --- a/src/main/java/com/bgsoftware/wildloaders/npc/NPCIdentifier.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.bgsoftware.wildloaders.npc; - -import org.bukkit.Location; - -import java.util.Objects; - -public final class NPCIdentifier { - - private final Object identifier; - - public NPCIdentifier(Location location){ - this.identifier = getBlockLocation(location); - } - - public Location getSpawnLocation(){ - return (Location) identifier; - } - - @Override - public String toString() { - return identifier.toString(); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - NPCIdentifier that = (NPCIdentifier) o; - return Objects.equals(identifier, that.identifier); - } - - @Override - public int hashCode() { - return Objects.hash(identifier); - } - - private static Location getBlockLocation(Location location){ - return new Location(location.getWorld(), location.getBlockX(), location.getBlockY(), location.getBlockZ()); - } - -} diff --git a/src/main/java/com/bgsoftware/wildloaders/scheduler/BukkitSchedulerImplementation.java b/src/main/java/com/bgsoftware/wildloaders/scheduler/BukkitSchedulerImplementation.java new file mode 100644 index 0000000..25ad936 --- /dev/null +++ b/src/main/java/com/bgsoftware/wildloaders/scheduler/BukkitSchedulerImplementation.java @@ -0,0 +1,73 @@ +package com.bgsoftware.wildloaders.scheduler; + +import com.bgsoftware.wildloaders.WildLoadersPlugin; +import org.bukkit.Bukkit; +import org.bukkit.World; +import org.bukkit.entity.Entity; +import org.bukkit.scheduler.BukkitTask; + +public class BukkitSchedulerImplementation implements ISchedulerImplementation { + + public static final BukkitSchedulerImplementation INSTANCE = new BukkitSchedulerImplementation(); + + private static final WildLoadersPlugin plugin = WildLoadersPlugin.getPlugin(); + + private BukkitSchedulerImplementation() { + + } + + @Override + public boolean isRegionScheduler() { + return false; + } + + @Override + public ScheduledTask scheduleTask(World world, int chunkX, int chunkZ, Runnable task, long delay) { + return scheduleTask(task, delay); + } + + @Override + public ScheduledTask scheduleTask(Entity unused, Runnable task, long delay) { + return scheduleTask(task, delay); + } + + @Override + public ScheduledTask scheduleTask(Runnable task, long delay) { + if (delay <= 0) { + return new BukkitScheduledTask(Bukkit.getScheduler().runTask(plugin, task)); + } else { + return new BukkitScheduledTask(Bukkit.getScheduler().runTaskLater(plugin, task, delay)); + } + } + + @Override + public ScheduledTask scheduleAsyncTask(Runnable task, long delay) { + if (delay <= 0) { + return new BukkitScheduledTask(Bukkit.getScheduler().runTaskAsynchronously(plugin, task)); + } else { + return new BukkitScheduledTask(Bukkit.getScheduler().runTaskLaterAsynchronously(plugin, task, delay)); + } + } + + private static class BukkitScheduledTask implements ScheduledTask { + + private int taskId; + + BukkitScheduledTask(BukkitTask bukkitTask) { + this(bukkitTask.getTaskId()); + } + + BukkitScheduledTask(int taskId) { + this.taskId = taskId; + } + + @Override + public void cancel() { + if (Bukkit.getScheduler().isCurrentlyRunning(this.taskId)) { + Bukkit.getScheduler().cancelTask(this.taskId); + this.taskId = -1; + } + } + } + +} diff --git a/src/main/java/com/bgsoftware/wildloaders/scheduler/ISchedulerImplementation.java b/src/main/java/com/bgsoftware/wildloaders/scheduler/ISchedulerImplementation.java new file mode 100644 index 0000000..b9697ee --- /dev/null +++ b/src/main/java/com/bgsoftware/wildloaders/scheduler/ISchedulerImplementation.java @@ -0,0 +1,18 @@ +package com.bgsoftware.wildloaders.scheduler; + +import org.bukkit.World; +import org.bukkit.entity.Entity; + +public interface ISchedulerImplementation { + + boolean isRegionScheduler(); + + ScheduledTask scheduleTask(World world, int chunkX, int chunkZ, Runnable task, long delay); + + ScheduledTask scheduleTask(Entity entity, Runnable task, long delay); + + ScheduledTask scheduleTask(Runnable task, long delay); + + ScheduledTask scheduleAsyncTask(Runnable task, long delay); + +} diff --git a/src/main/java/com/bgsoftware/wildloaders/scheduler/ScheduledTask.java b/src/main/java/com/bgsoftware/wildloaders/scheduler/ScheduledTask.java new file mode 100644 index 0000000..022ca62 --- /dev/null +++ b/src/main/java/com/bgsoftware/wildloaders/scheduler/ScheduledTask.java @@ -0,0 +1,7 @@ +package com.bgsoftware.wildloaders.scheduler; + +public interface ScheduledTask { + + void cancel(); + +} diff --git a/src/main/java/com/bgsoftware/wildloaders/scheduler/Scheduler.java b/src/main/java/com/bgsoftware/wildloaders/scheduler/Scheduler.java new file mode 100644 index 0000000..4df0ba8 --- /dev/null +++ b/src/main/java/com/bgsoftware/wildloaders/scheduler/Scheduler.java @@ -0,0 +1,87 @@ +package com.bgsoftware.wildloaders.scheduler; + +import org.bukkit.Chunk; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.entity.Entity; + +public class Scheduler { + private static final ISchedulerImplementation IMP = initializeSchedulerImplementation(); + + private static ISchedulerImplementation initializeSchedulerImplementation() { + try { + Class.forName("io.papermc.paper.threadedregions.scheduler.RegionScheduler"); + } catch (ClassNotFoundException error) { + return BukkitSchedulerImplementation.INSTANCE; + } + + // Detected Folia, create its scheduler + try { + Class foliaSchedulerClass = Class.forName("com.bgsoftware.wildloaders.scheduler.FoliaSchedulerImplementation"); + return (ISchedulerImplementation) foliaSchedulerClass.getField("INSTANCE").get(null); + } catch (Throwable error) { + throw new RuntimeException(error); + } + } + + private Scheduler() { + + } + + public static void initialize() { + // Do nothing, load static initializer + } + + public static boolean isRegionScheduler() { + return IMP.isRegionScheduler(); + } + + public static ScheduledTask runTask(World world, int chunkX, int chunkZ, Runnable task, long delay) { + return IMP.scheduleTask(world, chunkX, chunkZ, task, delay); + } + + public static ScheduledTask runTask(Entity entity, Runnable task, long delay) { + return IMP.scheduleTask(entity, task, delay); + } + + public static ScheduledTask runTask(Runnable task, long delay) { + return IMP.scheduleTask(task, delay); + } + + public static ScheduledTask runTaskAsync(Runnable task, long delay) { + return IMP.scheduleAsyncTask(task, delay); + } + + public static ScheduledTask runTask(Chunk chunk, Runnable task, long delay) { + return runTask(chunk.getWorld(), chunk.getX(), chunk.getZ(), task, delay); + } + + public static ScheduledTask runTask(Chunk chunk, Runnable task) { + return runTask(chunk, task, 0L); + } + + public static ScheduledTask runTask(Location location, Runnable task, long delay) { + return runTask(location.getWorld(), location.getBlockX() >> 4, location.getBlockZ() >> 4, task, delay); + } + + public static ScheduledTask runTask(World world, int chunkX, int chunkZ, Runnable task) { + return runTask(world, chunkX, chunkZ, task, 0L); + } + + public static ScheduledTask runTask(Entity entity, Runnable task) { + return runTask(entity, task, 0L); + } + + public static ScheduledTask runTask(Location location, Runnable task) { + return runTask(location, task, 0L); + } + + public static ScheduledTask runTask(Runnable task) { + return runTask(task, 0L); + } + + public static ScheduledTask runTaskAsync(Runnable task) { + return runTaskAsync(task, 0L); + } + +} diff --git a/src/main/java/com/bgsoftware/wildloaders/utils/BlockPosition.java b/src/main/java/com/bgsoftware/wildloaders/utils/BlockPosition.java new file mode 100644 index 0000000..a405ad0 --- /dev/null +++ b/src/main/java/com/bgsoftware/wildloaders/utils/BlockPosition.java @@ -0,0 +1,92 @@ +package com.bgsoftware.wildloaders.utils; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.World; + +import java.lang.ref.WeakReference; +import java.util.Objects; + +public class BlockPosition { + + private final String worldName; + private final int x; + private final int y; + private final int z; + private WeakReference cachedWorld = new WeakReference<>(null); + + public static BlockPosition of(Location location) { + World world = location.getWorld(); + return new BlockPosition(world == null ? "null" : world.getName(), + location.getBlockX(), location.getBlockY(), location.getBlockZ()); + } + + public static BlockPosition deserialize(String serialized) { + String[] locationSections = serialized.split(","); + + if (locationSections.length != 4) + throw new IllegalArgumentException("Cannot parse location " + serialized); + + String worldName = locationSections[0]; + int x = (int) Double.parseDouble(locationSections[1]); + int y = (int) Double.parseDouble(locationSections[2]); + int z = (int) Double.parseDouble(locationSections[3]); + + return new BlockPosition(worldName, x, y, z); + } + + public BlockPosition(String worldName, int x, int y, int z) { + this.worldName = worldName; + this.x = x; + this.y = y; + this.z = z; + } + + public String getWorldName() { + return worldName; + } + + public World getWorld() { + World cachedWorld = this.cachedWorld.get(); + if (cachedWorld == null) { + cachedWorld = Bukkit.getWorld(this.worldName); + this.cachedWorld = new WeakReference<>(cachedWorld); + } + + return cachedWorld; + } + + public Location getLocation() { + return new Location(getWorld(), this.x, this.y, this.z); + } + + public int getX() { + return x; + } + + public int getY() { + return y; + } + + public int getZ() { + return z; + } + + public String serialize() { + return this.worldName + "," + this.x + "," + this.y + "," + this.z; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + BlockPosition that = (BlockPosition) o; + return x == that.x && y == that.y && z == that.z && Objects.equals(worldName, that.worldName); + } + + @Override + public int hashCode() { + return Objects.hash(worldName, x, y, z); + } + +} diff --git a/src/main/java/com/bgsoftware/wildloaders/utils/ServerVersion.java b/src/main/java/com/bgsoftware/wildloaders/utils/ServerVersion.java index 53a68ef..7316160 100644 --- a/src/main/java/com/bgsoftware/wildloaders/utils/ServerVersion.java +++ b/src/main/java/com/bgsoftware/wildloaders/utils/ServerVersion.java @@ -17,7 +17,8 @@ public enum ServerVersion { v1_17(117), v1_18(118), v1_19(119), - v1_20(120); + v1_20(120), + v1_21(121); private static final ServerVersion currentVersion; private static final String bukkitVersion; diff --git a/src/main/java/com/bgsoftware/wildloaders/utils/database/QueryParameters.java b/src/main/java/com/bgsoftware/wildloaders/utils/database/QueryParameters.java index 83ef0c1..4c91be7 100644 --- a/src/main/java/com/bgsoftware/wildloaders/utils/database/QueryParameters.java +++ b/src/main/java/com/bgsoftware/wildloaders/utils/database/QueryParameters.java @@ -1,5 +1,6 @@ package com.bgsoftware.wildloaders.utils.database; +import com.bgsoftware.wildloaders.utils.BlockPosition; import org.bukkit.Location; import java.sql.PreparedStatement; @@ -12,7 +13,7 @@ public final class QueryParameters { private final Query query; private final List parameters; - public QueryParameters(Query query){ + public QueryParameters(Query query) { this.query = query; this.parameters = new ArrayList<>(query.getParametersCount()); } @@ -22,20 +23,24 @@ public final class QueryParameters { } public void executeQuery(PreparedStatement preparedStatement) throws SQLException { - for(int i = 0; i < parameters.size(); i++) + for (int i = 0; i < parameters.size(); i++) preparedStatement.setObject(i + 1, parameters.get(i)); } - public void queue(Object caller){ + public void queue(Object caller) { DatabaseQueue.queue(caller, this); } - public QueryParameters setLocation(Location loc){ + public QueryParameters setLocation(Location loc) { return setObject(loc.getWorld().getName() + "," + loc.getBlockX() + "," + loc.getBlockY() + "," + loc.getBlockZ()); } - public QueryParameters setObject(Object object){ - if(object instanceof Location) + public QueryParameters setLocation(BlockPosition blockPos) { + return setObject(blockPos.getWorldName() + "," + blockPos.getX() + "," + blockPos.getY() + "," + blockPos.getZ()); + } + + public QueryParameters setObject(Object object) { + if (object instanceof Location) return setLocation((Location) object); parameters.add(object); diff --git a/src/main/java/com/bgsoftware/wildloaders/utils/locations/LocationUtils.java b/src/main/java/com/bgsoftware/wildloaders/utils/locations/LocationUtils.java deleted file mode 100644 index 8a9efb5..0000000 --- a/src/main/java/com/bgsoftware/wildloaders/utils/locations/LocationUtils.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.bgsoftware.wildloaders.utils.locations; - -import org.bukkit.Bukkit; -import org.bukkit.Location; - -public final class LocationUtils { - - private LocationUtils(){} - - public static String getLocation(Location location){ - try { - return location.getWorld().getName() + "," + location.getBlockX() + "," + location.getBlockY() + "," + location.getBlockZ(); - }catch (Exception ex){ - System.out.println(location); - throw ex; - } - } - - public static Location getLocation(String location){ - String[] locationSections = location.split(","); - - if(locationSections.length != 4) - throw new IllegalArgumentException("Cannot parse location " + location); - - String worldName = locationSections[0]; - double x = parseDouble(locationSections[1]); - double y = parseDouble(locationSections[2]); - double z = parseDouble(locationSections[3]); - - return new Location(Bukkit.getWorld(worldName), x, y, z); - } - - private static double parseDouble(String str){ - try{ - return Double.parseDouble(str); - }catch (Exception ex){ - throw new IllegalArgumentException("Cannot parse double " + str); - } - } - -} diff --git a/src/main/java/com/bgsoftware/wildloaders/utils/threads/Executor.java b/src/main/java/com/bgsoftware/wildloaders/utils/threads/Executor.java deleted file mode 100644 index 30e55b7..0000000 --- a/src/main/java/com/bgsoftware/wildloaders/utils/threads/Executor.java +++ /dev/null @@ -1,74 +0,0 @@ -package com.bgsoftware.wildloaders.utils.threads; - -import com.bgsoftware.wildloaders.WildLoadersPlugin; -import com.google.common.util.concurrent.ThreadFactoryBuilder; -import org.bukkit.Bukkit; - -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; - -public final class Executor { - - private static final ExecutorService dataService = Executors.newFixedThreadPool(3, new ThreadFactoryBuilder().setNameFormat("WildChests DB Thread - #%d").build()); - private static final WildLoadersPlugin plugin = WildLoadersPlugin.getPlugin(); - private static boolean shutdown = false; - - private Executor() {} - - public static void sync(Runnable runnable){ - if(shutdown) - return; - - sync(runnable, 0L); - } - - public static void sync(Runnable runnable, long delay){ - if(shutdown) - return; - - Bukkit.getScheduler().runTaskLater(plugin, runnable, delay); - } - - public static void async(Runnable runnable){ - if(shutdown) - return; - - if(Bukkit.isPrimaryThread()){ - Bukkit.getScheduler().runTaskAsynchronously(plugin, runnable); - } - else{ - runnable.run(); - } - } - - public static void async(Runnable runnable, long delay){ - if(shutdown) - return; - - if(Bukkit.isPrimaryThread()){ - Bukkit.getScheduler().runTaskLaterAsynchronously(plugin, runnable, delay); - } - else{ - runnable.run(); - } - } - - public static void data(Runnable runnable){ - if(shutdown) - return; - - dataService.execute(runnable); - } - - public static void stop(){ - try{ - shutdown = true; - dataService.shutdown(); - dataService.awaitTermination(1, TimeUnit.MINUTES); - }catch (Exception ex){ - ex.printStackTrace(); - } - } - -} diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 3f98d89..7c33f53 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -6,6 +6,7 @@ description: Highly configurable and optimized chunk-loaders plugin. website: https://bg-software.com/ api-version: 1.13 author: Ome_R +folia-supported: true # Custom section used by DependenciesManager, which replaces softdepend. class-depends: