Merge branch 'dev'

This commit is contained in:
OmerBenGera 2024-08-03 22:23:29 +03:00
commit f5bfbe2281
79 changed files with 1406 additions and 1304 deletions

View File

@ -2,12 +2,28 @@ package com.bgsoftware.wildloaders.api.hooks;
import org.bukkit.Chunk; import org.bukkit.Chunk;
import java.util.Collection;
public interface TickableProvider { public interface TickableProvider {
/** /**
* Simulate a tick on a list of provided chunks. * 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. * @param chunks The chunks to tick.
*/ */
void tick(Chunk[] chunks); default void tick(Collection<Chunk> chunks) {
tick(chunks.toArray(new Chunk[0]));
}
} }

View File

@ -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);
}

View File

@ -34,9 +34,17 @@ public interface ChunkLoader {
/** /**
* Get the chunks that this chunk-loader is loading. * Get the chunks that this chunk-loader is loading.
*
* @deprecated See {@link #getLoadedChunksCollection()}
*/ */
@Deprecated
Chunk[] getLoadedChunks(); Chunk[] getLoadedChunks();
/**
* Get the chunks that this chunk-loader is loading.
*/
Collection<Chunk> getLoadedChunksCollection();
/** /**
* Get the NPC of this chunk loader. * Get the NPC of this chunk loader.
*/ */

View File

@ -2,6 +2,7 @@ package com.bgsoftware.wildloaders.api.managers;
import com.bgsoftware.wildloaders.api.hooks.ClaimsProvider; import com.bgsoftware.wildloaders.api.hooks.ClaimsProvider;
import com.bgsoftware.wildloaders.api.hooks.TickableProvider; import com.bgsoftware.wildloaders.api.hooks.TickableProvider;
import com.bgsoftware.wildloaders.api.hooks.WorldsProvider;
public interface ProvidersManager { public interface ProvidersManager {
@ -17,4 +18,11 @@ public interface ProvidersManager {
*/ */
void addTickableProvider(TickableProvider tickableProvider); void addTickableProvider(TickableProvider tickableProvider);
/**
* Add a worlds provider to the plugin.
*
* @param worldsProvider The worlds provider to add.
*/
void addWorldsProvider(WorldsProvider worldsProvider);
} }

View File

@ -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 }
}

View File

@ -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<String> 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;
}
}

View File

@ -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 }
}

View File

@ -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<String> 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;
}
}

View File

@ -5,25 +5,26 @@ import com.songoda.epicspawners.EpicSpawners;
import org.bukkit.Chunk; import org.bukkit.Chunk;
import org.bukkit.Location; import org.bukkit.Location;
import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.stream.Collectors; import java.util.Set;
import java.util.stream.Stream;
public final class TickableProvider_EpicSpawners6 implements TickableProvider { public final class TickableProvider_EpicSpawners6 implements TickableProvider {
private final Map<Location, TickDelay> spawnerDelays = new HashMap<>(); private final Map<Location, TickDelay> spawnerDelays = new HashMap<>();
@Override @Override
public void tick(Chunk[] chunks) { public void tick(Collection<Chunk> chunks) {
if (EpicSpawners.getInstance().getSpawnerManager() == null) if (EpicSpawners.getInstance().getSpawnerManager() == null)
return; return;
List<Long> chunkList = Stream.of(chunks).map(chunk -> pair(chunk.getX(), chunk.getZ())).collect(Collectors.toList()); Set<Long> chunkKeys = new HashSet<>();
chunks.forEach(chunk -> chunkKeys.add(pair(chunk.getX(), chunk.getZ())));
EpicSpawners.getInstance().getSpawnerManager().getSpawners().stream() 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 -> { .forEach(spawner -> {
Location location = spawner.getLocation(); Location location = spawner.getLocation();
TickDelay tickDelay = spawnerDelays.get(location); TickDelay tickDelay = spawnerDelays.get(location);

View File

@ -5,25 +5,26 @@ import com.songoda.epicspawners.EpicSpawners;
import org.bukkit.Chunk; import org.bukkit.Chunk;
import org.bukkit.Location; import org.bukkit.Location;
import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.stream.Collectors; import java.util.Set;
import java.util.stream.Stream;
public final class TickableProvider_EpicSpawners7 implements TickableProvider { public final class TickableProvider_EpicSpawners7 implements TickableProvider {
private final Map<Location, TickDelay> spawnerDelays = new HashMap<>(); private final Map<Location, TickDelay> spawnerDelays = new HashMap<>();
@Override @Override
public void tick(Chunk[] chunks) { public void tick(Collection<Chunk> chunks) {
if (EpicSpawners.getInstance().getSpawnerManager() == null) if (EpicSpawners.getInstance().getSpawnerManager() == null)
return; return;
List<Long> chunkList = Stream.of(chunks).map(chunk -> pair(chunk.getX(), chunk.getZ())).collect(Collectors.toList()); Set<Long> chunkKeys = new HashSet<>();
chunks.forEach(chunk -> chunkKeys.add(pair(chunk.getX(), chunk.getZ())));
EpicSpawners.getInstance().getSpawnerManager().getSpawners().stream() 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 -> { .forEach(spawner -> {
Location location = spawner.getLocation(); Location location = spawner.getLocation();
TickDelay tickDelay = spawnerDelays.get(location); TickDelay tickDelay = spawnerDelays.get(location);

View File

@ -5,25 +5,26 @@ import com.craftaro.epicspawners.api.EpicSpawnersApi;
import org.bukkit.Chunk; import org.bukkit.Chunk;
import org.bukkit.Location; import org.bukkit.Location;
import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.stream.Collectors; import java.util.Set;
import java.util.stream.Stream;
public final class TickableProvider_EpicSpawners8 implements TickableProvider { public final class TickableProvider_EpicSpawners8 implements TickableProvider {
private final Map<Location, TickDelay> spawnerDelays = new HashMap<>(); private final Map<Location, TickDelay> spawnerDelays = new HashMap<>();
@Override @Override
public void tick(Chunk[] chunks) { public void tick(Collection<Chunk> chunks) {
if (EpicSpawnersApi.getSpawnerManager() == null) if (EpicSpawnersApi.getSpawnerManager() == null)
return; return;
List<Long> chunkList = Stream.of(chunks).map(chunk -> pair(chunk.getX(), chunk.getZ())).collect(Collectors.toList()); Set<Long> chunkKeys = new HashSet<>();
chunks.forEach(chunk -> chunkKeys.add(pair(chunk.getX(), chunk.getZ())));
EpicSpawnersApi.getSpawnerManager().getSpawners().stream() 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 -> { .forEach(spawner -> {
Location location = spawner.getLocation(); Location location = spawner.getLocation();
TickDelay tickDelay = spawnerDelays.get(location); TickDelay tickDelay = spawnerDelays.get(location);

22
Hooks/Folia/build.gradle Normal file
View File

@ -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 }
}

View File

@ -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();
}
}
}

View File

@ -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 }
}

View File

@ -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<String> 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;
}
}

View File

@ -1,5 +1,7 @@
package com.bgsoftware.wildloaders.nms.v1_12_R1; 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.handlers.NPCHandler;
import com.bgsoftware.wildloaders.npc.DummyChannel; import com.bgsoftware.wildloaders.npc.DummyChannel;
import com.mojang.authlib.GameProfile; 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 { public final class ChunkLoaderNPC extends EntityPlayer implements com.bgsoftware.wildloaders.api.npc.ChunkLoaderNPC {
private static final ReflectMethod<Void> PLAYER_SET_VIEW_DISTANCE = new ReflectMethod<>(
EntityPlayer.class, "setViewDistance", int.class);
private static final ReflectField<Boolean> PLAYER_AFFECTS_SPAWNING = new ReflectField<>(
EntityPlayer.class, boolean.class, "affectsSpawning");
private final AxisAlignedBB boundingBox; private final AxisAlignedBB boundingBox;
private final AdvancementDataPlayer advancements; private final AdvancementDataPlayer advancements;
@ -53,8 +60,15 @@ public final class ChunkLoaderNPC extends EntityPlayer implements com.bgsoftware
this.advancements = new DummyPlayerAdvancements(server, this); this.advancements = new DummyPlayerAdvancements(server, this);
this.playerInteractManager.setGameMode(EnumGamemode.CREATIVE); this.playerInteractManager.setGameMode(EnumGamemode.CREATIVE);
fallDistance = 0.0F;
fauxSleeping = true; 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); spawnIn(world);
setLocation(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); setLocation(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());

View File

@ -5,6 +5,7 @@ import com.bgsoftware.wildloaders.api.loaders.ChunkLoader;
import com.bgsoftware.wildloaders.loaders.ITileEntityChunkLoader; import com.bgsoftware.wildloaders.loaders.ITileEntityChunkLoader;
import com.bgsoftware.wildloaders.nms.NMSAdapter; import com.bgsoftware.wildloaders.nms.NMSAdapter;
import com.bgsoftware.wildloaders.nms.v1_12_R1.loader.TileEntityChunkLoader; 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.Block;
import net.minecraft.server.v1_12_R1.BlockPosition; import net.minecraft.server.v1_12_R1.BlockPosition;
import net.minecraft.server.v1_12_R1.Chunk; 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); TileEntityChunkLoader tileEntityChunkLoader = new TileEntityChunkLoader(chunkLoader, world, blockPosition);
world.tileEntityListTick.add(tileEntityChunkLoader); world.tileEntityListTick.add(tileEntityChunkLoader);
for (org.bukkit.Chunk bukkitChunk : chunkLoader.getLoadedChunks()) { if (Scheduler.isRegionScheduler()) {
Chunk chunk = ((CraftChunk) bukkitChunk).getHandle(); Scheduler.runTask(() -> setSpawnersRangeForLoader(chunkLoader, true));
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 { } else {
tileEntity.a(nbtTagCompound); setSpawnersRangeForLoader(chunkLoader, true);
}
});
} }
return tileEntityChunkLoader; return tileEntityChunkLoader;
@ -147,18 +140,30 @@ public final class NMSAdapterImpl implements NMSAdapter {
if (spawnParticle) if (spawnParticle)
world.a(null, 2001, blockPosition, Block.getCombinedId(world.getType(blockPosition))); 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 chunk = ((CraftChunk) bukkitChunk).getHandle();
chunk.tileEntities.values().stream().filter(tileEntity -> tileEntity instanceof TileEntityMobSpawner).forEach(tileEntity -> {
for (TileEntity tileEntity : chunk.tileEntities.values()) {
if (tileEntity instanceof TileEntityMobSpawner) {
NBTTagCompound nbtTagCompound = new NBTTagCompound(); NBTTagCompound nbtTagCompound = new NBTTagCompound();
tileEntity.save(nbtTagCompound); tileEntity.save(nbtTagCompound);
nbtTagCompound.setShort("RequiredPlayerRange", (short) 16); nbtTagCompound.setShort("RequiredPlayerRange", requiredPlayerRange);
if (TILE_ENTITY_LOAD.isValid()) { if (TILE_ENTITY_LOAD.isValid()) {
TILE_ENTITY_LOAD.invoke(tileEntity, nbtTagCompound); TILE_ENTITY_LOAD.invoke(tileEntity, nbtTagCompound);
} else { } else {
tileEntity.a(nbtTagCompound); tileEntity.a(nbtTagCompound);
} }
}); }
}
} }
} }

View File

@ -40,6 +40,7 @@ import java.util.UUID;
public final class ChunkLoaderNPC extends EntityPlayer implements com.bgsoftware.wildloaders.api.npc.ChunkLoaderNPC { public final class ChunkLoaderNPC extends EntityPlayer implements com.bgsoftware.wildloaders.api.npc.ChunkLoaderNPC {
private final AxisAlignedBB boundingBox; private final AxisAlignedBB boundingBox;
private final AdvancementDataPlayer advancements; private final AdvancementDataPlayer advancements;
@ -57,9 +58,16 @@ public final class ChunkLoaderNPC extends EntityPlayer implements com.bgsoftware
this.advancements = new DummyPlayerAdvancements(server, this); this.advancements = new DummyPlayerAdvancements(server, this);
this.playerInteractManager.setGameMode(EnumGamemode.CREATIVE); this.playerInteractManager.setGameMode(EnumGamemode.CREATIVE);
clientViewDistance = 1;
fallDistance = 0.0F;
fauxSleeping = true; fauxSleeping = true;
clientViewDistance = 0;
try {
// Paper
affectsSpawning = true;
} catch (Throwable ignored) {
}
spawnIn(world); spawnIn(world);
setLocation(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); setLocation(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());

View File

@ -4,6 +4,7 @@ import com.bgsoftware.wildloaders.api.loaders.ChunkLoader;
import com.bgsoftware.wildloaders.loaders.ITileEntityChunkLoader; import com.bgsoftware.wildloaders.loaders.ITileEntityChunkLoader;
import com.bgsoftware.wildloaders.nms.NMSAdapter; import com.bgsoftware.wildloaders.nms.NMSAdapter;
import com.bgsoftware.wildloaders.nms.v1_16_R3.loader.TileEntityChunkLoader; 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.Block;
import net.minecraft.server.v1_16_R3.BlockPosition; import net.minecraft.server.v1_16_R3.BlockPosition;
import net.minecraft.server.v1_16_R3.Chunk; 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.NBTTagList;
import net.minecraft.server.v1_16_R3.NBTTagLong; import net.minecraft.server.v1_16_R3.NBTTagLong;
import net.minecraft.server.v1_16_R3.NBTTagString; 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.TileEntityMobSpawner;
import net.minecraft.server.v1_16_R3.World; import net.minecraft.server.v1_16_R3.World;
import net.minecraft.server.v1_16_R3.WorldServer; 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); TileEntityChunkLoader tileEntityChunkLoader = new TileEntityChunkLoader(chunkLoader, world, blockPosition);
world.tileEntityListTick.add(tileEntityChunkLoader); world.tileEntityListTick.add(tileEntityChunkLoader);
for (org.bukkit.Chunk bukkitChunk : chunkLoader.getLoadedChunks()) { if (Scheduler.isRegionScheduler()) {
Chunk chunk = ((CraftChunk) bukkitChunk).getHandle(); Scheduler.runTask(() -> setChunksForcedForLoader(chunkLoader, world, true));
chunk.tileEntities.values().stream().filter(tileEntity -> tileEntity instanceof TileEntityMobSpawner) } else {
.forEach(tileEntity -> ((TileEntityMobSpawner) tileEntity).getSpawner().requiredPlayerRange = -1); setChunksForcedForLoader(chunkLoader, world, true);
world.setForceLoaded(chunk.getPos().x, chunk.getPos().z, true);
} }
return tileEntityChunkLoader; return tileEntityChunkLoader;
@ -143,12 +143,25 @@ public final class NMSAdapterImpl implements NMSAdapter {
if (spawnParticle) if (spawnParticle)
world.a(null, 2001, blockPosition, Block.getCombinedId(world.getType(blockPosition))); world.a(null, 2001, blockPosition, Block.getCombinedId(world.getType(blockPosition)));
for (org.bukkit.Chunk bukkitChunk : chunkLoader.getLoadedChunks()) { if (Scheduler.isRegionScheduler()) {
Chunk chunk = ((CraftChunk) bukkitChunk).getHandle(); Scheduler.runTask(() -> setChunksForcedForLoader(chunkLoader, world, false));
chunk.tileEntities.values().stream().filter(tileEntity -> tileEntity instanceof TileEntityMobSpawner) } else {
.forEach(tileEntity -> ((TileEntityMobSpawner) tileEntity).getSpawner().requiredPlayerRange = 16); 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);
} }
} }

View File

@ -1,5 +1,5 @@
plugins { plugins {
id("io.papermc.paperweight.userdev") version "1.6.0" id("io.papermc.paperweight.userdev") version "1.7.1"
} }
java { java {

View File

@ -5,6 +5,7 @@ import com.bgsoftware.wildloaders.loaders.ITileEntityChunkLoader;
import com.bgsoftware.wildloaders.nms.NMSAdapter; import com.bgsoftware.wildloaders.nms.NMSAdapter;
import com.bgsoftware.wildloaders.nms.v1_17.loader.ChunkLoaderBlockEntity; import com.bgsoftware.wildloaders.nms.v1_17.loader.ChunkLoaderBlockEntity;
import com.bgsoftware.wildloaders.nms.v1_17.npc.ChunkLoaderNPCWrapper; import com.bgsoftware.wildloaders.nms.v1_17.npc.ChunkLoaderNPCWrapper;
import com.bgsoftware.wildloaders.scheduler.Scheduler;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag; import net.minecraft.nbt.ListTag;
@ -105,16 +106,10 @@ public final class NMSAdapterImpl implements NMSAdapter {
ChunkLoaderBlockEntity ChunkLoaderBlockEntity = new ChunkLoaderBlockEntity(chunkLoader, serverLevel, blockPos); ChunkLoaderBlockEntity ChunkLoaderBlockEntity = new ChunkLoaderBlockEntity(chunkLoader, serverLevel, blockPos);
serverLevel.addBlockEntityTicker(ChunkLoaderBlockEntity.getTicker()); serverLevel.addBlockEntityTicker(ChunkLoaderBlockEntity.getTicker());
for (org.bukkit.Chunk bukkitChunk : chunkLoader.getLoadedChunks()) { if (Scheduler.isRegionScheduler()) {
LevelChunk levelChunk = ((CraftChunk) bukkitChunk).getHandle(); Scheduler.runTask(() -> setChunksForcedForLoader(chunkLoader, serverLevel, true));
levelChunk.getBlockEntities().values().stream() } else {
.filter(blockEntity -> blockEntity instanceof SpawnerBlockEntity) setChunksForcedForLoader(chunkLoader, serverLevel, true);
.forEach(blockEntity -> {
((SpawnerBlockEntity) blockEntity).getSpawner().requiredPlayerRange = -1;
});
ChunkPos chunkPos = levelChunk.getPos();
serverLevel.setChunkForced(chunkPos.x, chunkPos.z, true);
} }
return ChunkLoaderBlockEntity; return ChunkLoaderBlockEntity;
@ -142,16 +137,25 @@ public final class NMSAdapterImpl implements NMSAdapter {
if (spawnParticle) if (spawnParticle)
serverLevel.levelEvent(null, 2001, blockPos, Block.getId(serverLevel.getBlockState(blockPos))); 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 levelChunk = ((CraftChunk) bukkitChunk).getHandle();
levelChunk.getBlockEntities().values().stream()
.filter(blockEntity -> blockEntity instanceof SpawnerBlockEntity) for (BlockEntity blockEntity : levelChunk.getBlockEntities().values()) {
.forEach(blockEntity -> { if (blockEntity instanceof SpawnerBlockEntity spawnerBlockEntity)
((SpawnerBlockEntity) blockEntity).getSpawner().requiredPlayerRange = 16; spawnerBlockEntity.getSpawner().requiredPlayerRange = requiredPlayerRange;
}); }
ChunkPos chunkPos = levelChunk.getPos(); ChunkPos chunkPos = levelChunk.getPos();
serverLevel.setChunkForced(chunkPos.x, chunkPos.z, false); serverLevel.setChunkForced(chunkPos.x, chunkPos.z, forced);
} }
} }

View File

@ -56,9 +56,16 @@ public final class ChunkLoaderPlayer extends ServerPlayer {
this.advancements = new DummyPlayerAdvancements(minecraftServer, this); this.advancements = new DummyPlayerAdvancements(minecraftServer, this);
SET_GAMEMODE.invoke(this.gameMode, GameType.CREATIVE, null); SET_GAMEMODE.invoke(this.gameMode, GameType.CREATIVE, null);
clientViewDistance = 1;
fallDistance = 0.0F;
fauxSleeping = true; fauxSleeping = true;
clientViewDistance = 0;
try {
// Paper
affectsSpawning = true;
} catch (Throwable ignored) {
}
spawnIn(this.serverLevel); spawnIn(this.serverLevel);
moveTo(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); moveTo(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());

View File

@ -1,5 +1,5 @@
plugins { plugins {
id("io.papermc.paperweight.userdev") version "1.6.0" id("io.papermc.paperweight.userdev") version "1.7.1"
} }
java { java {

View File

@ -58,9 +58,16 @@ public final class ChunkLoaderNPCImpl extends ServerPlayer implements ChunkLoade
this.advancements = new DummyPlayerAdvancements(minecraftServer, this); this.advancements = new DummyPlayerAdvancements(minecraftServer, this);
SET_GAMEMODE.invoke(this.gameMode, GameType.CREATIVE, null); SET_GAMEMODE.invoke(this.gameMode, GameType.CREATIVE, null);
clientViewDistance = 1;
fallDistance = 0.0F;
fauxSleeping = true; fauxSleeping = true;
clientViewDistance = 0;
try {
// Paper
affectsSpawning = true;
} catch (Throwable ignored) {
}
spawnIn(this.serverLevel); spawnIn(this.serverLevel);
moveTo(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); moveTo(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());

View File

@ -4,6 +4,7 @@ import com.bgsoftware.wildloaders.api.loaders.ChunkLoader;
import com.bgsoftware.wildloaders.loaders.ITileEntityChunkLoader; import com.bgsoftware.wildloaders.loaders.ITileEntityChunkLoader;
import com.bgsoftware.wildloaders.nms.NMSAdapter; import com.bgsoftware.wildloaders.nms.NMSAdapter;
import com.bgsoftware.wildloaders.nms.v1_18.loader.ChunkLoaderBlockEntity; import com.bgsoftware.wildloaders.nms.v1_18.loader.ChunkLoaderBlockEntity;
import com.bgsoftware.wildloaders.scheduler.Scheduler;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag; import net.minecraft.nbt.ListTag;
@ -104,16 +105,10 @@ public final class NMSAdapterImpl implements NMSAdapter {
ChunkLoaderBlockEntity ChunkLoaderBlockEntity = new ChunkLoaderBlockEntity(chunkLoader, serverLevel, blockPos); ChunkLoaderBlockEntity ChunkLoaderBlockEntity = new ChunkLoaderBlockEntity(chunkLoader, serverLevel, blockPos);
serverLevel.addBlockEntityTicker(ChunkLoaderBlockEntity.getTicker()); serverLevel.addBlockEntityTicker(ChunkLoaderBlockEntity.getTicker());
for (org.bukkit.Chunk bukkitChunk : chunkLoader.getLoadedChunks()) { if (Scheduler.isRegionScheduler()) {
LevelChunk levelChunk = ((CraftChunk) bukkitChunk).getHandle(); Scheduler.runTask(() -> setChunksForcedForLoader(chunkLoader, serverLevel, true));
levelChunk.getBlockEntities().values().stream() } else {
.filter(blockEntity -> blockEntity instanceof SpawnerBlockEntity) setChunksForcedForLoader(chunkLoader, serverLevel, true);
.forEach(blockEntity -> {
((SpawnerBlockEntity) blockEntity).getSpawner().requiredPlayerRange = -1;
});
ChunkPos chunkPos = levelChunk.getPos();
serverLevel.setChunkForced(chunkPos.x, chunkPos.z, true);
} }
return ChunkLoaderBlockEntity; return ChunkLoaderBlockEntity;
@ -141,16 +136,25 @@ public final class NMSAdapterImpl implements NMSAdapter {
if (spawnParticle) if (spawnParticle)
serverLevel.levelEvent(null, 2001, blockPos, Block.getId(serverLevel.getBlockState(blockPos))); 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 levelChunk = ((CraftChunk) bukkitChunk).getHandle();
levelChunk.getBlockEntities().values().stream()
.filter(blockEntity -> blockEntity instanceof SpawnerBlockEntity) for (BlockEntity blockEntity : levelChunk.getBlockEntities().values()) {
.forEach(blockEntity -> { if (blockEntity instanceof SpawnerBlockEntity spawnerBlockEntity)
((SpawnerBlockEntity) blockEntity).getSpawner().requiredPlayerRange = 16; spawnerBlockEntity.getSpawner().requiredPlayerRange = requiredPlayerRange;
}); }
ChunkPos chunkPos = levelChunk.getPos(); ChunkPos chunkPos = levelChunk.getPos();
serverLevel.setChunkForced(chunkPos.x, chunkPos.z, false); serverLevel.setChunkForced(chunkPos.x, chunkPos.z, forced);
} }
} }

View File

@ -1,5 +1,5 @@
plugins { plugins {
id("io.papermc.paperweight.userdev") version "1.6.0" id("io.papermc.paperweight.userdev") version "1.7.1"
} }
java { java {

View File

@ -60,9 +60,16 @@ public final class ChunkLoaderNPCImpl extends ServerPlayer implements ChunkLoade
this.advancements = new DummyPlayerAdvancements(minecraftServer, this); this.advancements = new DummyPlayerAdvancements(minecraftServer, this);
SET_GAMEMODE.invoke(this.gameMode, GameType.CREATIVE, null); SET_GAMEMODE.invoke(this.gameMode, GameType.CREATIVE, null);
clientViewDistance = 1;
fallDistance = 0.0F;
fauxSleeping = true; fauxSleeping = true;
clientViewDistance = 0;
try {
// Paper
affectsSpawning = true;
} catch (Throwable ignored) {
}
spawnIn(this.serverLevel); spawnIn(this.serverLevel);
moveTo(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); moveTo(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());

View File

@ -1,6 +1,7 @@
package com.bgsoftware.wildloaders.nms.v1_19; package com.bgsoftware.wildloaders.nms.v1_19;
import com.bgsoftware.wildloaders.api.holograms.Hologram; import com.bgsoftware.wildloaders.api.holograms.Hologram;
import com.bgsoftware.wildloaders.scheduler.Scheduler;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerLevel; 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.AABB;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.craftbukkit.v1_19_R3.CraftServer; 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.CraftArmorStand;
import org.bukkit.craftbukkit.v1_19_R3.entity.CraftEntity; import org.bukkit.craftbukkit.v1_19_R3.entity.CraftEntity;
@ -48,8 +50,15 @@ public final class EntityHologram extends ArmorStand implements Hologram {
@Override @Override
public void removeHologram() { public void removeHologram() {
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); super.remove(RemovalReason.DISCARDED);
} }
}
@Override @Override
public org.bukkit.entity.Entity getEntity() { public org.bukkit.entity.Entity getEntity() {

View File

@ -4,6 +4,7 @@ import com.bgsoftware.wildloaders.api.loaders.ChunkLoader;
import com.bgsoftware.wildloaders.loaders.ITileEntityChunkLoader; import com.bgsoftware.wildloaders.loaders.ITileEntityChunkLoader;
import com.bgsoftware.wildloaders.nms.NMSAdapter; import com.bgsoftware.wildloaders.nms.NMSAdapter;
import com.bgsoftware.wildloaders.nms.v1_19.loader.ChunkLoaderBlockEntity; import com.bgsoftware.wildloaders.nms.v1_19.loader.ChunkLoaderBlockEntity;
import com.bgsoftware.wildloaders.scheduler.Scheduler;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag; import net.minecraft.nbt.ListTag;
@ -103,16 +104,10 @@ public final class NMSAdapterImpl implements NMSAdapter {
ChunkLoaderBlockEntity ChunkLoaderBlockEntity = new ChunkLoaderBlockEntity(chunkLoader, serverLevel, blockPos); ChunkLoaderBlockEntity ChunkLoaderBlockEntity = new ChunkLoaderBlockEntity(chunkLoader, serverLevel, blockPos);
serverLevel.addBlockEntityTicker(ChunkLoaderBlockEntity.getTicker()); serverLevel.addBlockEntityTicker(ChunkLoaderBlockEntity.getTicker());
for (org.bukkit.Chunk bukkitChunk : chunkLoader.getLoadedChunks()) { if (Scheduler.isRegionScheduler()) {
LevelChunk levelChunk = serverLevel.getChunk(bukkitChunk.getX(), bukkitChunk.getZ()); Scheduler.runTask(() -> setChunksForcedForLoader(chunkLoader, serverLevel, true));
levelChunk.getBlockEntities().values().stream() } else {
.filter(blockEntity -> blockEntity instanceof SpawnerBlockEntity) setChunksForcedForLoader(chunkLoader, serverLevel, true);
.forEach(blockEntity -> {
((SpawnerBlockEntity) blockEntity).getSpawner().requiredPlayerRange = -1;
});
ChunkPos chunkPos = levelChunk.getPos();
serverLevel.setChunkForced(chunkPos.x, chunkPos.z, true);
} }
return ChunkLoaderBlockEntity; return ChunkLoaderBlockEntity;
@ -140,16 +135,25 @@ public final class NMSAdapterImpl implements NMSAdapter {
if (spawnParticle) if (spawnParticle)
serverLevel.levelEvent(null, 2001, blockPos, Block.getId(serverLevel.getBlockState(blockPos))); 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 levelChunk = serverLevel.getChunk(bukkitChunk.getX(), bukkitChunk.getZ());
levelChunk.getBlockEntities().values().stream()
.filter(blockEntity -> blockEntity instanceof SpawnerBlockEntity) for (BlockEntity blockEntity : levelChunk.getBlockEntities().values()) {
.forEach(blockEntity -> { if (blockEntity instanceof SpawnerBlockEntity spawnerBlockEntity)
((SpawnerBlockEntity) blockEntity).getSpawner().requiredPlayerRange = 16; spawnerBlockEntity.getSpawner().requiredPlayerRange = requiredPlayerRange;
}); }
ChunkPos chunkPos = levelChunk.getPos(); ChunkPos chunkPos = levelChunk.getPos();
serverLevel.setChunkForced(chunkPos.x, chunkPos.z, false); serverLevel.setChunkForced(chunkPos.x, chunkPos.z, forced);
} }
} }

View File

@ -1,6 +1,7 @@
package com.bgsoftware.wildloaders.nms.v1_19.loader; package com.bgsoftware.wildloaders.nms.v1_19.loader;
import net.minecraft.core.BlockPos; 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.BlockEntityType;
import net.minecraft.world.level.block.entity.TickingBlockEntity; import net.minecraft.world.level.block.entity.TickingBlockEntity;
@ -27,4 +28,8 @@ public record ChunkLoaderBlockEntityTicker(
return BlockEntityType.getKey(chunkLoaderBlockEntity.getType()) + ""; return BlockEntityType.getKey(chunkLoaderBlockEntity.getType()) + "";
} }
public BlockEntity getTileEntity() {
return chunkLoaderBlockEntity;
}
} }

View File

@ -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<Void> 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();
}
}
}

View File

@ -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;
}
}

View File

@ -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 }
}

View File

@ -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;
}
}

View File

@ -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<Long, ChunkLoaderBlockEntity> chunkLoaderBlockEntityMap = new HashMap<>();
public final List<EntityHologram> 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<String> 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<String> 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<Hologram> 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 + "")
);
}
}

View File

@ -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()) + "";
}
}

View File

@ -1,5 +1,5 @@
plugins { plugins {
id("io.papermc.paperweight.userdev") version "1.6.0" id("io.papermc.paperweight.userdev") version "1.7.1"
} }
java { java {

View File

@ -64,16 +64,19 @@ public final class ChunkLoaderNPCImpl extends ServerPlayer implements ChunkLoade
this.advancements = new DummyPlayerAdvancements(minecraftServer, this); this.advancements = new DummyPlayerAdvancements(minecraftServer, this);
SET_GAMEMODE.invoke(this.gameMode, GameType.CREATIVE, null); SET_GAMEMODE.invoke(this.gameMode, GameType.CREATIVE, null);
fallDistance = 0.0F;
fauxSleeping = true;
try { try {
setLoadViewDistance(2); setLoadViewDistance(2);
setTickViewDistance(2); setTickViewDistance(2);
setSendViewDistance(2); setSendViewDistance(2);
affectsSpawning = true;
} catch (Throwable ignored) { } catch (Throwable ignored) {
// Doesn't exist on Spigot // Doesn't exist on Spigot
} }
fauxSleeping = true;
spawnIn(this.serverLevel); spawnIn(this.serverLevel);
moveTo(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); moveTo(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());

View File

@ -1,6 +1,7 @@
package com.bgsoftware.wildloaders.nms.v1_20_3; package com.bgsoftware.wildloaders.nms.v1_20_3;
import com.bgsoftware.wildloaders.api.holograms.Hologram; import com.bgsoftware.wildloaders.api.holograms.Hologram;
import com.bgsoftware.wildloaders.scheduler.Scheduler;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerLevel; 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.AABB;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.craftbukkit.v1_20_R3.CraftServer; 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.CraftArmorStand;
import org.bukkit.craftbukkit.v1_20_R3.entity.CraftEntity; import org.bukkit.craftbukkit.v1_20_R3.entity.CraftEntity;
@ -48,8 +50,15 @@ public final class EntityHologram extends ArmorStand implements Hologram {
@Override @Override
public void removeHologram() { public void removeHologram() {
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); super.remove(RemovalReason.DISCARDED);
} }
}
@Override @Override
public org.bukkit.entity.Entity getEntity() { public org.bukkit.entity.Entity getEntity() {

View File

@ -4,6 +4,7 @@ import com.bgsoftware.wildloaders.api.loaders.ChunkLoader;
import com.bgsoftware.wildloaders.loaders.ITileEntityChunkLoader; import com.bgsoftware.wildloaders.loaders.ITileEntityChunkLoader;
import com.bgsoftware.wildloaders.nms.NMSAdapter; import com.bgsoftware.wildloaders.nms.NMSAdapter;
import com.bgsoftware.wildloaders.nms.v1_20_3.loader.ChunkLoaderBlockEntity; import com.bgsoftware.wildloaders.nms.v1_20_3.loader.ChunkLoaderBlockEntity;
import com.bgsoftware.wildloaders.scheduler.Scheduler;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag; import net.minecraft.nbt.ListTag;
@ -103,16 +104,10 @@ public final class NMSAdapterImpl implements NMSAdapter {
ChunkLoaderBlockEntity ChunkLoaderBlockEntity = new ChunkLoaderBlockEntity(chunkLoader, serverLevel, blockPos); ChunkLoaderBlockEntity ChunkLoaderBlockEntity = new ChunkLoaderBlockEntity(chunkLoader, serverLevel, blockPos);
serverLevel.addBlockEntityTicker(ChunkLoaderBlockEntity.getTicker()); serverLevel.addBlockEntityTicker(ChunkLoaderBlockEntity.getTicker());
for (org.bukkit.Chunk bukkitChunk : chunkLoader.getLoadedChunks()) { if (Scheduler.isRegionScheduler()) {
LevelChunk levelChunk = serverLevel.getChunk(bukkitChunk.getX(), bukkitChunk.getZ()); Scheduler.runTask(() -> setChunksForcedForLoader(chunkLoader, serverLevel, true));
levelChunk.getBlockEntities().values().stream() } else {
.filter(blockEntity -> blockEntity instanceof SpawnerBlockEntity) setChunksForcedForLoader(chunkLoader, serverLevel, true);
.forEach(blockEntity -> {
((SpawnerBlockEntity) blockEntity).getSpawner().requiredPlayerRange = -1;
});
ChunkPos chunkPos = levelChunk.getPos();
serverLevel.setChunkForced(chunkPos.x, chunkPos.z, true);
} }
return ChunkLoaderBlockEntity; return ChunkLoaderBlockEntity;
@ -140,16 +135,25 @@ public final class NMSAdapterImpl implements NMSAdapter {
if (spawnParticle) if (spawnParticle)
serverLevel.levelEvent(null, 2001, blockPos, Block.getId(serverLevel.getBlockState(blockPos))); 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 levelChunk = serverLevel.getChunk(bukkitChunk.getX(), bukkitChunk.getZ());
levelChunk.getBlockEntities().values().stream()
.filter(blockEntity -> blockEntity instanceof SpawnerBlockEntity) for (BlockEntity blockEntity : levelChunk.getBlockEntities().values()) {
.forEach(blockEntity -> { if (blockEntity instanceof SpawnerBlockEntity spawnerBlockEntity)
((SpawnerBlockEntity) blockEntity).getSpawner().requiredPlayerRange = 16; spawnerBlockEntity.getSpawner().requiredPlayerRange = requiredPlayerRange;
}); }
ChunkPos chunkPos = levelChunk.getPos(); ChunkPos chunkPos = levelChunk.getPos();
serverLevel.setChunkForced(chunkPos.x, chunkPos.z, false); serverLevel.setChunkForced(chunkPos.x, chunkPos.z, forced);
} }
} }

View File

@ -1,6 +1,7 @@
package com.bgsoftware.wildloaders.nms.v1_20_3.loader; package com.bgsoftware.wildloaders.nms.v1_20_3.loader;
import net.minecraft.core.BlockPos; 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.BlockEntityType;
import net.minecraft.world.level.block.entity.TickingBlockEntity; import net.minecraft.world.level.block.entity.TickingBlockEntity;
@ -27,4 +28,8 @@ public record ChunkLoaderBlockEntityTicker(
return BlockEntityType.getKey(chunkLoaderBlockEntity.getType()) + ""; return BlockEntityType.getKey(chunkLoaderBlockEntity.getType()) + "";
} }
public BlockEntity getTileEntity() {
return chunkLoaderBlockEntity;
}
} }

View File

@ -1,5 +1,5 @@
plugins { plugins {
id("io.papermc.paperweight.userdev") version "1.6.0" id("io.papermc.paperweight.userdev") version "1.7.1"
} }
java { java {

View File

@ -64,16 +64,19 @@ public final class ChunkLoaderNPCImpl extends ServerPlayer implements ChunkLoade
this.advancements = new DummyPlayerAdvancements(minecraftServer, this); this.advancements = new DummyPlayerAdvancements(minecraftServer, this);
SET_GAMEMODE.invoke(this.gameMode, GameType.CREATIVE, null); SET_GAMEMODE.invoke(this.gameMode, GameType.CREATIVE, null);
fallDistance = 0.0F;
fauxSleeping = true;
try { try {
setLoadViewDistance(2); setLoadViewDistance(2);
setTickViewDistance(2); setTickViewDistance(2);
setSendViewDistance(2); setSendViewDistance(2);
affectsSpawning = true;
} catch (Throwable ignored) { } catch (Throwable ignored) {
// Doesn't exist on Spigot // Doesn't exist on Spigot
} }
fauxSleeping = true;
spawnIn(this.serverLevel); spawnIn(this.serverLevel);
moveTo(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); moveTo(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());

View File

@ -1,6 +1,7 @@
package com.bgsoftware.wildloaders.nms.v1_20_4; package com.bgsoftware.wildloaders.nms.v1_20_4;
import com.bgsoftware.wildloaders.api.holograms.Hologram; import com.bgsoftware.wildloaders.api.holograms.Hologram;
import com.bgsoftware.wildloaders.scheduler.Scheduler;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerLevel; 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.AABB;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.craftbukkit.CraftServer; import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.craftbukkit.entity.CraftArmorStand; import org.bukkit.craftbukkit.entity.CraftArmorStand;
import org.bukkit.craftbukkit.entity.CraftEntity; import org.bukkit.craftbukkit.entity.CraftEntity;
@ -48,8 +50,15 @@ public final class EntityHologram extends ArmorStand implements Hologram {
@Override @Override
public void removeHologram() { public void removeHologram() {
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); super.remove(RemovalReason.DISCARDED);
} }
}
@Override @Override
public org.bukkit.entity.Entity getEntity() { public org.bukkit.entity.Entity getEntity() {

View File

@ -4,6 +4,7 @@ import com.bgsoftware.wildloaders.api.loaders.ChunkLoader;
import com.bgsoftware.wildloaders.loaders.ITileEntityChunkLoader; import com.bgsoftware.wildloaders.loaders.ITileEntityChunkLoader;
import com.bgsoftware.wildloaders.nms.NMSAdapter; import com.bgsoftware.wildloaders.nms.NMSAdapter;
import com.bgsoftware.wildloaders.nms.v1_20_4.loader.ChunkLoaderBlockEntity; 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.Property;
import com.mojang.authlib.properties.PropertyMap; import com.mojang.authlib.properties.PropertyMap;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
@ -109,16 +110,10 @@ public final class NMSAdapterImpl implements NMSAdapter {
ChunkLoaderBlockEntity ChunkLoaderBlockEntity = new ChunkLoaderBlockEntity(chunkLoader, serverLevel, blockPos); ChunkLoaderBlockEntity ChunkLoaderBlockEntity = new ChunkLoaderBlockEntity(chunkLoader, serverLevel, blockPos);
serverLevel.addBlockEntityTicker(ChunkLoaderBlockEntity.getTicker()); serverLevel.addBlockEntityTicker(ChunkLoaderBlockEntity.getTicker());
for (org.bukkit.Chunk bukkitChunk : chunkLoader.getLoadedChunks()) { if (Scheduler.isRegionScheduler()) {
LevelChunk levelChunk = serverLevel.getChunk(bukkitChunk.getX(), bukkitChunk.getZ()); Scheduler.runTask(() -> setChunksForcedForLoader(chunkLoader, serverLevel, true));
levelChunk.getBlockEntities().values().stream() } else {
.filter(blockEntity -> blockEntity instanceof SpawnerBlockEntity) setChunksForcedForLoader(chunkLoader, serverLevel, true);
.forEach(blockEntity -> {
((SpawnerBlockEntity) blockEntity).getSpawner().requiredPlayerRange = -1;
});
ChunkPos chunkPos = levelChunk.getPos();
serverLevel.setChunkForced(chunkPos.x, chunkPos.z, true);
} }
return ChunkLoaderBlockEntity; return ChunkLoaderBlockEntity;
@ -146,16 +141,25 @@ public final class NMSAdapterImpl implements NMSAdapter {
if (spawnParticle) if (spawnParticle)
serverLevel.levelEvent(null, 2001, blockPos, Block.getId(serverLevel.getBlockState(blockPos))); 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 levelChunk = serverLevel.getChunk(bukkitChunk.getX(), bukkitChunk.getZ());
levelChunk.getBlockEntities().values().stream()
.filter(blockEntity -> blockEntity instanceof SpawnerBlockEntity) for (BlockEntity blockEntity : levelChunk.getBlockEntities().values()) {
.forEach(blockEntity -> { if (blockEntity instanceof SpawnerBlockEntity spawnerBlockEntity)
((SpawnerBlockEntity) blockEntity).getSpawner().requiredPlayerRange = 16; spawnerBlockEntity.getSpawner().requiredPlayerRange = requiredPlayerRange;
}); }
ChunkPos chunkPos = levelChunk.getPos(); ChunkPos chunkPos = levelChunk.getPos();
serverLevel.setChunkForced(chunkPos.x, chunkPos.z, false); serverLevel.setChunkForced(chunkPos.x, chunkPos.z, forced);
} }
} }

View File

@ -1,6 +1,7 @@
package com.bgsoftware.wildloaders.nms.v1_20_4.loader; package com.bgsoftware.wildloaders.nms.v1_20_4.loader;
import net.minecraft.core.BlockPos; 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.BlockEntityType;
import net.minecraft.world.level.block.entity.TickingBlockEntity; import net.minecraft.world.level.block.entity.TickingBlockEntity;
@ -27,4 +28,8 @@ public record ChunkLoaderBlockEntityTicker(
return BlockEntityType.getKey(chunkLoaderBlockEntity.getType()) + ""; return BlockEntityType.getKey(chunkLoaderBlockEntity.getType()) + "";
} }
public BlockEntity getTileEntity() {
return chunkLoaderBlockEntity;
}
} }

View File

@ -1,17 +1,17 @@
plugins { plugins {
id("io.papermc.paperweight.userdev") version "1.6.0" id("io.papermc.paperweight.userdev") version "1.7.1"
} }
java { java {
toolchain { toolchain {
languageVersion.set(JavaLanguageVersion.of(17)) languageVersion.set(JavaLanguageVersion.of(21))
} }
} }
group 'NMS:v1_20_1' group 'NMS:v1_21'
dependencies { 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 project(":API")
compileOnly rootProject 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 } project.tasks.all { task -> task.enabled = false }
} }

View File

@ -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.common.reflection.ReflectMethod;
import com.bgsoftware.wildloaders.api.npc.ChunkLoaderNPC; import com.bgsoftware.wildloaders.api.npc.ChunkLoaderNPC;
import com.bgsoftware.wildloaders.handlers.NPCHandler; import com.bgsoftware.wildloaders.handlers.NPCHandler;
import com.bgsoftware.wildloaders.npc.DummyChannel; import com.bgsoftware.wildloaders.npc.DummyChannel;
import com.mojang.authlib.GameProfile; import com.mojang.authlib.GameProfile;
import net.kyori.adventure.text.Component;
import net.minecraft.advancements.AdvancementHolder; import net.minecraft.advancements.AdvancementHolder;
import net.minecraft.advancements.AdvancementProgress; import net.minecraft.advancements.AdvancementProgress;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.network.Connection; import net.minecraft.network.Connection;
import net.minecraft.network.DisconnectionDetails;
import net.minecraft.network.PacketListener; import net.minecraft.network.PacketListener;
import net.minecraft.network.protocol.Packet; import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.PacketFlow; 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.level.storage.LevelResource;
import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.AABB;
import org.bukkit.Location; 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.entity.Player;
import org.bukkit.event.player.PlayerKickEvent;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.io.File; import java.io.File;
@ -64,16 +68,20 @@ public final class ChunkLoaderNPCImpl extends ServerPlayer implements ChunkLoade
this.advancements = new DummyPlayerAdvancements(minecraftServer, this); this.advancements = new DummyPlayerAdvancements(minecraftServer, this);
SET_GAMEMODE.invoke(this.gameMode, GameType.CREATIVE, null); SET_GAMEMODE.invoke(this.gameMode, GameType.CREATIVE, null);
fallDistance = 0.0F;
fauxSleeping = true;
try { try {
setLoadViewDistance(2); CraftPlayer craftPlayer = getBukkitEntity();
setTickViewDistance(2); craftPlayer.setSendViewDistance(2);
setSendViewDistance(2); craftPlayer.setViewDistance(2);
craftPlayer.setSimulationDistance(2);
affectsSpawning = true;
} catch (Throwable ignored) { } catch (Throwable ignored) {
// Doesn't exist on Spigot // Doesn't exist on Spigot
} }
fauxSleeping = true;
spawnIn(this.serverLevel); spawnIn(this.serverLevel);
moveTo(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); moveTo(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
@ -132,7 +140,7 @@ public final class ChunkLoaderNPCImpl extends ServerPlayer implements ChunkLoade
} }
@Override @Override
public void setListener(PacketListener packetListener) { public void setListenerForServerboundHandshake(PacketListener packetListener) {
// Do nothing. // Do nothing.
} }
} }
@ -140,7 +148,8 @@ public final class ChunkLoaderNPCImpl extends ServerPlayer implements ChunkLoade
public class DummyServerGamePacketListenerImpl extends ServerGamePacketListenerImpl { public class DummyServerGamePacketListenerImpl extends ServerGamePacketListenerImpl {
DummyServerGamePacketListenerImpl(MinecraftServer minecraftServer, ServerPlayer serverPlayer) { 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 @Override
@ -179,7 +188,7 @@ public final class ChunkLoaderNPCImpl extends ServerPlayer implements ChunkLoade
} }
@Override @Override
public void disconnect(String s) { public void disconnect(DisconnectionDetails disconnectionInfo, PlayerKickEvent.Cause cause) {
// Do nothing. // Do nothing.
} }

View File

@ -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.api.holograms.Hologram;
import com.bgsoftware.wildloaders.scheduler.Scheduler;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerLevel; 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.AABB;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.v1_20_R1.CraftServer; import org.bukkit.World;
import org.bukkit.craftbukkit.v1_20_R1.entity.CraftArmorStand; import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; import org.bukkit.craftbukkit.entity.CraftArmorStand;
import org.bukkit.craftbukkit.v1_20_R1.util.CraftChatMessage; import org.bukkit.craftbukkit.entity.CraftEntity;
import org.bukkit.craftbukkit.util.CraftChatMessage;
public final class EntityHologram extends ArmorStand implements Hologram { public final class EntityHologram extends ArmorStand implements Hologram {
@ -48,8 +50,15 @@ public final class EntityHologram extends ArmorStand implements Hologram {
@Override @Override
public void removeHologram() { public void removeHologram() {
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); super.remove(RemovalReason.DISCARDED);
} }
}
@Override @Override
public org.bukkit.entity.Entity getEntity() { public org.bukkit.entity.Entity getEntity() {

View File

@ -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.api.loaders.ChunkLoader;
import com.bgsoftware.wildloaders.loaders.ITileEntityChunkLoader; import com.bgsoftware.wildloaders.loaders.ITileEntityChunkLoader;
import com.bgsoftware.wildloaders.nms.NMSAdapter; 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.BlockPos;
import net.minecraft.core.component.DataComponents;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.item.ItemStack; 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.ChunkPos;
import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntity; 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.Bukkit;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.craftbukkit.v1_20_R2.CraftServer; import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.craftbukkit.v1_20_R2.CraftWorld; import org.bukkit.craftbukkit.CraftWorld;
import org.bukkit.craftbukkit.v1_20_R2.inventory.CraftItemStack; import org.bukkit.craftbukkit.inventory.CraftItemStack;
import java.util.Optional;
import java.util.UUID; import java.util.UUID;
public final class NMSAdapterImpl implements NMSAdapter { public final class NMSAdapterImpl implements NMSAdapter {
@ -28,16 +34,22 @@ public final class NMSAdapterImpl implements NMSAdapter {
@Override @Override
public String getTag(org.bukkit.inventory.ItemStack bukkitItem, String key, String def) { public String getTag(org.bukkit.inventory.ItemStack bukkitItem, String key, String def) {
ItemStack itemStack = CraftItemStack.asNMSCopy(bukkitItem); ItemStack itemStack = CraftItemStack.asNMSCopy(bukkitItem);
CompoundTag compoundTag = itemStack.getTag(); CustomData customData = itemStack.get(DataComponents.CUSTOM_DATA);
return compoundTag == null || !compoundTag.contains(key, 8) ? def : compoundTag.getString(key); if (customData != null) {
CompoundTag compoundTag = customData.getUnsafe();
if (compoundTag.contains(key, 8))
return compoundTag.getString(key);
}
return def;
} }
@Override @Override
public org.bukkit.inventory.ItemStack setTag(org.bukkit.inventory.ItemStack bukkitItem, String key, String value) { public org.bukkit.inventory.ItemStack setTag(org.bukkit.inventory.ItemStack bukkitItem, String key, String value) {
ItemStack itemStack = CraftItemStack.asNMSCopy(bukkitItem); 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); return CraftItemStack.asBukkitCopy(itemStack);
} }
@ -45,16 +57,22 @@ public final class NMSAdapterImpl implements NMSAdapter {
@Override @Override
public long getTag(org.bukkit.inventory.ItemStack bukkitItem, String key, long def) { public long getTag(org.bukkit.inventory.ItemStack bukkitItem, String key, long def) {
ItemStack itemStack = CraftItemStack.asNMSCopy(bukkitItem); ItemStack itemStack = CraftItemStack.asNMSCopy(bukkitItem);
CompoundTag compoundTag = itemStack.getTag(); CustomData customData = itemStack.get(DataComponents.CUSTOM_DATA);
return compoundTag == null || !compoundTag.contains(key, 4) ? def : compoundTag.getLong(key); if (customData != null) {
CompoundTag compoundTag = customData.getUnsafe();
if (compoundTag.contains(key, 4))
return compoundTag.getLong(key);
}
return def;
} }
@Override @Override
public org.bukkit.inventory.ItemStack setTag(org.bukkit.inventory.ItemStack bukkitItem, String key, long value) { public org.bukkit.inventory.ItemStack setTag(org.bukkit.inventory.ItemStack bukkitItem, String key, long value) {
ItemStack itemStack = CraftItemStack.asNMSCopy(bukkitItem); 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); return CraftItemStack.asBukkitCopy(itemStack);
} }
@ -62,24 +80,13 @@ public final class NMSAdapterImpl implements NMSAdapter {
@Override @Override
public org.bukkit.inventory.ItemStack getPlayerSkull(org.bukkit.inventory.ItemStack bukkitItem, String texture) { public org.bukkit.inventory.ItemStack getPlayerSkull(org.bukkit.inventory.ItemStack bukkitItem, String texture) {
ItemStack itemStack = CraftItemStack.asNMSCopy(bukkitItem); ItemStack itemStack = CraftItemStack.asNMSCopy(bukkitItem);
CompoundTag compoundTag = itemStack.getOrCreateTag();
CompoundTag skullOwner = compoundTag.contains("SkullOwner") ? PropertyMap propertyMap = new PropertyMap();
compoundTag.getCompound("SkullOwner") : new CompoundTag(); propertyMap.put("textures", new Property("textures", texture));
CompoundTag properties = new CompoundTag(); ResolvableProfile resolvableProfile = new ResolvableProfile(Optional.empty(), Optional.empty(), propertyMap);
ListTag textures = new ListTag();
CompoundTag signature = new CompoundTag();
signature.putString("Value", texture); itemStack.set(DataComponents.PROFILE, resolvableProfile);
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); return CraftItemStack.asBukkitCopy(itemStack);
} }
@ -103,16 +110,10 @@ public final class NMSAdapterImpl implements NMSAdapter {
ChunkLoaderBlockEntity ChunkLoaderBlockEntity = new ChunkLoaderBlockEntity(chunkLoader, serverLevel, blockPos); ChunkLoaderBlockEntity ChunkLoaderBlockEntity = new ChunkLoaderBlockEntity(chunkLoader, serverLevel, blockPos);
serverLevel.addBlockEntityTicker(ChunkLoaderBlockEntity.getTicker()); serverLevel.addBlockEntityTicker(ChunkLoaderBlockEntity.getTicker());
for (org.bukkit.Chunk bukkitChunk : chunkLoader.getLoadedChunks()) { if (Scheduler.isRegionScheduler()) {
LevelChunk levelChunk = serverLevel.getChunk(bukkitChunk.getX(), bukkitChunk.getZ()); Scheduler.runTask(() -> setChunksForcedForLoader(chunkLoader, serverLevel, true));
levelChunk.getBlockEntities().values().stream() } else {
.filter(blockEntity -> blockEntity instanceof SpawnerBlockEntity) setChunksForcedForLoader(chunkLoader, serverLevel, true);
.forEach(blockEntity -> {
((SpawnerBlockEntity) blockEntity).getSpawner().requiredPlayerRange = -1;
});
ChunkPos chunkPos = levelChunk.getPos();
serverLevel.setChunkForced(chunkPos.x, chunkPos.z, true);
} }
return ChunkLoaderBlockEntity; return ChunkLoaderBlockEntity;
@ -140,16 +141,25 @@ public final class NMSAdapterImpl implements NMSAdapter {
if (spawnParticle) if (spawnParticle)
serverLevel.levelEvent(null, 2001, blockPos, Block.getId(serverLevel.getBlockState(blockPos))); 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 levelChunk = serverLevel.getChunk(bukkitChunk.getX(), bukkitChunk.getZ());
levelChunk.getBlockEntities().values().stream()
.filter(blockEntity -> blockEntity instanceof SpawnerBlockEntity) for (BlockEntity blockEntity : levelChunk.getBlockEntities().values()) {
.forEach(blockEntity -> { if (blockEntity instanceof SpawnerBlockEntity spawnerBlockEntity)
((SpawnerBlockEntity) blockEntity).getSpawner().requiredPlayerRange = 16; spawnerBlockEntity.getSpawner().requiredPlayerRange = requiredPlayerRange;
}); }
ChunkPos chunkPos = levelChunk.getPos(); ChunkPos chunkPos = levelChunk.getPos();
serverLevel.setChunkForced(chunkPos.x, chunkPos.z, false); serverLevel.setChunkForced(chunkPos.x, chunkPos.z, forced);
} }
} }

View File

@ -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.holograms.Hologram;
import com.bgsoftware.wildloaders.api.loaders.ChunkLoader; import com.bgsoftware.wildloaders.api.loaders.ChunkLoader;
import com.bgsoftware.wildloaders.loaders.ITileEntityChunkLoader; import com.bgsoftware.wildloaders.loaders.ITileEntityChunkLoader;
import com.bgsoftware.wildloaders.loaders.WChunkLoader; 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.core.BlockPos;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.ChunkPos;

View File

@ -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.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.BlockEntityType;
import net.minecraft.world.level.block.entity.TickingBlockEntity; import net.minecraft.world.level.block.entity.TickingBlockEntity;
@ -27,4 +28,8 @@ public record ChunkLoaderBlockEntityTicker(
return BlockEntityType.getKey(chunkLoaderBlockEntity.getType()) + ""; return BlockEntityType.getKey(chunkLoaderBlockEntity.getType()) + "";
} }
public BlockEntity getTileEntity() {
return chunkLoaderBlockEntity;
}
} }

View File

@ -41,8 +41,8 @@ public final class ChunkLoaderNPC extends EntityPlayer implements com.bgsoftware
playerConnection = new DummyPlayerConnection(server, this); playerConnection = new DummyPlayerConnection(server, this);
playerInteractManager.setGameMode(EnumGamemode.CREATIVE); playerInteractManager.setGameMode(EnumGamemode.CREATIVE);
fallDistance = 0.0F;
fallDistance = 0.0F;
fauxSleeping = true; fauxSleeping = true;
spawnIn(world); spawnIn(world);

View File

@ -4,6 +4,7 @@ import com.bgsoftware.wildloaders.api.loaders.ChunkLoader;
import com.bgsoftware.wildloaders.loaders.ITileEntityChunkLoader; import com.bgsoftware.wildloaders.loaders.ITileEntityChunkLoader;
import com.bgsoftware.wildloaders.nms.NMSAdapter; import com.bgsoftware.wildloaders.nms.NMSAdapter;
import com.bgsoftware.wildloaders.nms.v1_7_R4.loader.TileEntityChunkLoader; 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.Block;
import net.minecraft.server.v1_7_R4.Chunk; import net.minecraft.server.v1_7_R4.Chunk;
import net.minecraft.server.v1_7_R4.ItemStack; 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.inventory.CraftItemStack;
import org.bukkit.craftbukkit.v1_7_R4.util.LongHash; import org.bukkit.craftbukkit.v1_7_R4.util.LongHash;
import java.util.Collection;
import java.util.UUID; import java.util.UUID;
public final class NMSAdapterImpl implements NMSAdapter { public final class NMSAdapterImpl implements NMSAdapter {
@ -112,15 +114,10 @@ public final class NMSAdapterImpl implements NMSAdapter {
//noinspection unchecked //noinspection unchecked
world.tileEntityList.add(tileEntityChunkLoader); world.tileEntityList.add(tileEntityChunkLoader);
for (org.bukkit.Chunk bukkitChunk : chunkLoader.getLoadedChunks()) { if (Scheduler.isRegionScheduler()) {
Chunk chunk = ((CraftChunk) bukkitChunk).getHandle(); Scheduler.runTask(() -> setSpawnersRangeForLoader(chunkLoader, true));
//noinspection unchecked } else {
chunk.tileEntities.values().stream().filter(tileEntity -> tileEntity instanceof TileEntityMobSpawner).forEach(tileEntity -> { setSpawnersRangeForLoader(chunkLoader, true);
NBTTagCompound nbtTagCompound = new NBTTagCompound();
((TileEntity) tileEntity).b(nbtTagCompound);
nbtTagCompound.setShort("RequiredPlayerRange", (short) -1);
((TileEntity) tileEntity).a(nbtTagCompound);
});
} }
return tileEntityChunkLoader; return tileEntityChunkLoader;
@ -142,15 +139,26 @@ public final class NMSAdapterImpl implements NMSAdapter {
if (spawnParticle) if (spawnParticle)
world.a(null, 2001, x, y, z, Block.getId(world.getType(x, y, z)) + (world.getData(x, y, z) << 12)); 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(); Chunk chunk = ((CraftChunk) bukkitChunk).getHandle();
//noinspection unchecked
chunk.tileEntities.values().stream().filter(tileEntity -> tileEntity instanceof TileEntityMobSpawner).forEach(tileEntity -> { for (TileEntity tileEntity : (Collection<TileEntity>) chunk.tileEntities.values()) {
if (tileEntity instanceof TileEntityMobSpawner) {
NBTTagCompound nbtTagCompound = new NBTTagCompound(); NBTTagCompound nbtTagCompound = new NBTTagCompound();
((TileEntity) tileEntity).b(nbtTagCompound); tileEntity.b(nbtTagCompound);
nbtTagCompound.setShort("RequiredPlayerRange", (short) 16); nbtTagCompound.setShort("RequiredPlayerRange", requiredPlayerRange);
((TileEntity) tileEntity).a(nbtTagCompound); tileEntity.a(nbtTagCompound);
}); }
}
} }
} }

View File

@ -48,13 +48,14 @@ public final class ChunkLoaderNPC extends EntityPlayer implements com.bgsoftware
playerConnection = new DummyPlayerConnection(server, this); playerConnection = new DummyPlayerConnection(server, this);
playerInteractManager.setGameMode(WorldSettings.EnumGamemode.CREATIVE); playerInteractManager.setGameMode(WorldSettings.EnumGamemode.CREATIVE);
fallDistance = 0.0F;
fallDistance = 0.0F;
fauxSleeping = true; fauxSleeping = true;
try { try {
// Paper // Paper
affectsSpawning = true; affectsSpawning = true;
viewDistance = 0;
} catch (Throwable ignored) { } catch (Throwable ignored) {
} }

View File

@ -4,6 +4,7 @@ import com.bgsoftware.wildloaders.api.loaders.ChunkLoader;
import com.bgsoftware.wildloaders.loaders.ITileEntityChunkLoader; import com.bgsoftware.wildloaders.loaders.ITileEntityChunkLoader;
import com.bgsoftware.wildloaders.nms.NMSAdapter; import com.bgsoftware.wildloaders.nms.NMSAdapter;
import com.bgsoftware.wildloaders.nms.v1_8_R3.loader.TileEntityChunkLoader; 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.Block;
import net.minecraft.server.v1_8_R3.BlockPosition; import net.minecraft.server.v1_8_R3.BlockPosition;
import net.minecraft.server.v1_8_R3.Chunk; 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.NBTTagList;
import net.minecraft.server.v1_8_R3.NBTTagLong; import net.minecraft.server.v1_8_R3.NBTTagLong;
import net.minecraft.server.v1_8_R3.NBTTagString; 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.TileEntityMobSpawner;
import net.minecraft.server.v1_8_R3.World; import net.minecraft.server.v1_8_R3.World;
import org.bukkit.Location; import org.bukkit.Location;
@ -111,14 +113,10 @@ public final class NMSAdapterImpl implements NMSAdapter {
TileEntityChunkLoader tileEntityChunkLoader = new TileEntityChunkLoader(chunkLoader, world, blockPosition); TileEntityChunkLoader tileEntityChunkLoader = new TileEntityChunkLoader(chunkLoader, world, blockPosition);
world.tileEntityList.add(tileEntityChunkLoader); world.tileEntityList.add(tileEntityChunkLoader);
for (org.bukkit.Chunk bukkitChunk : chunkLoader.getLoadedChunks()) { if (Scheduler.isRegionScheduler()) {
Chunk chunk = ((CraftChunk) bukkitChunk).getHandle(); Scheduler.runTask(() -> setSpawnersRangeForLoader(chunkLoader, true));
chunk.tileEntities.values().stream().filter(tileEntity -> tileEntity instanceof TileEntityMobSpawner).forEach(tileEntity -> { } else {
NBTTagCompound nbtTagCompound = new NBTTagCompound(); setSpawnersRangeForLoader(chunkLoader, true);
tileEntity.b(nbtTagCompound);
nbtTagCompound.setShort("RequiredPlayerRange", (short) -1);
tileEntity.a(nbtTagCompound);
});
} }
return tileEntityChunkLoader; return tileEntityChunkLoader;
@ -141,14 +139,26 @@ public final class NMSAdapterImpl implements NMSAdapter {
if (spawnParticle) if (spawnParticle)
world.a(null, 2001, blockPosition, Block.getCombinedId(world.getType(blockPosition))); 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 chunk = ((CraftChunk) bukkitChunk).getHandle();
chunk.tileEntities.values().stream().filter(tileEntity -> tileEntity instanceof TileEntityMobSpawner).forEach(tileEntity -> {
for (TileEntity tileEntity : chunk.tileEntities.values()) {
if (tileEntity instanceof TileEntityMobSpawner) {
NBTTagCompound nbtTagCompound = new NBTTagCompound(); NBTTagCompound nbtTagCompound = new NBTTagCompound();
tileEntity.b(nbtTagCompound); tileEntity.b(nbtTagCompound);
nbtTagCompound.setShort("RequiredPlayerRange", (short) 16); nbtTagCompound.setShort("RequiredPlayerRange", requiredPlayerRange);
tileEntity.a(nbtTagCompound); tileEntity.a(nbtTagCompound);
}); }
}
} }
} }

View File

@ -5,7 +5,7 @@ plugins {
} }
group 'WildLoaders' group 'WildLoaders'
version = "2024.1" version = "2024.2"
project.ext { project.ext {
archiveFolder = file("archive/") archiveFolder = file("archive/")
@ -69,7 +69,7 @@ dependencies {
implementation 'com.bgsoftware.common.updater:Updater:b1' implementation 'com.bgsoftware.common.updater:Updater:b1'
implementation 'com.bgsoftware.common.config:CommentedConfiguration:b1' implementation 'com.bgsoftware.common.config:CommentedConfiguration:b1'
implementation 'com.bgsoftware.common.dependencies:DependenciesManager:b2' 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' implementation 'org.bstats:bstats-bukkit:3.0.0'

View File

@ -8,10 +8,15 @@ nms.compile_v1_17=true
nms.compile_v1_18=true nms.compile_v1_18=true
nms.compile_v1_19=true nms.compile_v1_19=true
nms.compile_v1_20=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_epicspawners6=true
hook.compile_epicspawners7=true hook.compile_epicspawners7=true
hook.compile_factionsuuid=true hook.compile_factionsuuid=true
hook.compile_factionsx=true hook.compile_factionsx=true
hook.compile_folia=true
hook.compile_lands=true hook.compile_lands=true
hook.compile_massivefactions=true hook.compile_massivefactions=true
hook.compile_slimeworldmanager=true
hook.compile_superiorskyblock=true hook.compile_superiorskyblock=true

View File

@ -9,13 +9,17 @@ rootProject.name = 'WildLoaders'
include 'API' include 'API'
include 'Hooks' include 'Hooks'
include 'Hooks:AdvancedSlimePaper'
include 'Hooks:AdvancedSlimeWorldManager'
include 'Hooks:EpicSpawners6' include 'Hooks:EpicSpawners6'
include 'Hooks:EpicSpawners7' include 'Hooks:EpicSpawners7'
include 'Hooks:EpicSpawners8' include 'Hooks:EpicSpawners8'
include 'Hooks:FactionsUUID' include 'Hooks:FactionsUUID'
include 'Hooks:FactionsX' include 'Hooks:FactionsX'
include 'Hooks:Folia'
include 'Hooks:Lands' include 'Hooks:Lands'
include 'Hooks:MassiveFactions' include 'Hooks:MassiveFactions'
include 'Hooks:SlimeWorldManager'
include 'Hooks:SuperiorSkyblock' include 'Hooks:SuperiorSkyblock'
include 'NMS' include 'NMS'
include 'NMS:v1_7_R4' include 'NMS:v1_7_R4'
@ -25,8 +29,7 @@ include 'NMS:v1_16_R3'
include 'NMS:v1_17' include 'NMS:v1_17'
include 'NMS:v1_18' include 'NMS:v1_18'
include 'NMS:v1_19' include 'NMS:v1_19'
include 'NMS:v1_20_1'
include 'NMS:v1_20_2'
include 'NMS:v1_20_3' include 'NMS:v1_20_3'
include 'NMS:v1_20_4' include 'NMS:v1_20_4'
include 'NMS:v1_21'

View File

@ -2,18 +2,14 @@ package com.bgsoftware.wildloaders.handlers;
import com.bgsoftware.wildloaders.WildLoadersPlugin; import com.bgsoftware.wildloaders.WildLoadersPlugin;
import com.bgsoftware.wildloaders.api.loaders.LoaderData; import com.bgsoftware.wildloaders.api.loaders.LoaderData;
import com.bgsoftware.wildloaders.utils.ChunkLoaderChunks; import com.bgsoftware.wildloaders.scheduler.Scheduler;
import com.bgsoftware.wildloaders.utils.ServerVersion; import com.bgsoftware.wildloaders.utils.BlockPosition;
import com.bgsoftware.wildloaders.utils.database.Database; 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.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Material; import org.bukkit.World;
import java.io.File; import java.io.File;
import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.UUID; import java.util.UUID;
@ -23,7 +19,7 @@ public final class DataHandler {
public DataHandler(WildLoadersPlugin plugin) { public DataHandler(WildLoadersPlugin plugin) {
this.plugin = plugin; this.plugin = plugin;
Executor.sync(() -> { Scheduler.runTask(() -> {
try { try {
Database.start(new File(plugin.getDataFolder(), "database.db")); Database.start(new File(plugin.getDataFolder(), "database.db"));
loadDatabase(); 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.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 -> { Database.executeQuery("SELECT * FROM npc_identifiers;", resultSet -> {
while (resultSet.next()) { while (resultSet.next()) {
Location location = LocationUtils.getLocation(resultSet.getString("location")); BlockPosition blockPosition = BlockPosition.deserialize(resultSet.getString("location"));
UUID uuid = UUID.fromString(resultSet.getString("uuid")); 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.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 -> { Database.executeQuery("SELECT * FROM chunk_loaders;", resultSet -> {
while (resultSet.next()) { while (resultSet.next()) {
Location location = LocationUtils.getLocation(resultSet.getString("location")); BlockPosition blockPosition = BlockPosition.deserialize(resultSet.getString("location"));
UUID placer = UUID.fromString(resultSet.getString("placer")); UUID placer = UUID.fromString(resultSet.getString("placer"));
Optional<LoaderData> loaderData = plugin.getLoaders().getLoaderData(resultSet.getString("loader_data")); Optional<LoaderData> loaderData = plugin.getLoaders().getLoaderData(resultSet.getString("loader_data"));
long timeLeft = resultSet.getLong("timeLeft"); long timeLeft = resultSet.getLong("timeLeft");
@ -55,21 +51,23 @@ public final class DataHandler {
if (!loaderData.isPresent()) if (!loaderData.isPresent())
continue; 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) { if (world != null) {
blockType = Material.CAULDRON_ITEM; 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 {
if (blockType != loaderData.get().getLoaderItem().getType()) { plugin.getLoaders().addUnloadedChunkLoader(loaderData.get(), placer, blockPosition, timeLeft);
WildLoadersPlugin.log("The chunk-loader at " + LocationUtils.getLocation(location) + " is invalid.");
continue;
} }
List<Chunk> chunksToLoad = ChunkLoaderChunks.calculateChunks(loaderData.get(), placer, location);
chunksToLoad.removeIf(chunk -> plugin.getLoaders().getChunkLoader(chunk).isPresent());
plugin.getLoaders().addChunkLoaderWithoutDBSave(loaderData.get(), placer, location, timeLeft, chunksToLoad);
} }
}); });
} }

View File

@ -4,19 +4,25 @@ import com.bgsoftware.wildloaders.WildLoadersPlugin;
import com.bgsoftware.wildloaders.api.loaders.ChunkLoader; import com.bgsoftware.wildloaders.api.loaders.ChunkLoader;
import com.bgsoftware.wildloaders.api.loaders.LoaderData; import com.bgsoftware.wildloaders.api.loaders.LoaderData;
import com.bgsoftware.wildloaders.api.managers.LoadersManager; import com.bgsoftware.wildloaders.api.managers.LoadersManager;
import com.bgsoftware.wildloaders.loaders.UnloadedChunkLoader;
import com.bgsoftware.wildloaders.loaders.WChunkLoader; import com.bgsoftware.wildloaders.loaders.WChunkLoader;
import com.bgsoftware.wildloaders.loaders.WLoaderData; import com.bgsoftware.wildloaders.loaders.WLoaderData;
import com.bgsoftware.wildloaders.utils.BlockPosition;
import com.bgsoftware.wildloaders.utils.ChunkLoaderChunks; import com.bgsoftware.wildloaders.utils.ChunkLoaderChunks;
import com.bgsoftware.wildloaders.utils.ServerVersion;
import com.bgsoftware.wildloaders.utils.chunks.ChunkPosition; import com.bgsoftware.wildloaders.utils.chunks.ChunkPosition;
import com.bgsoftware.wildloaders.utils.database.Query; import com.bgsoftware.wildloaders.utils.database.Query;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import org.bukkit.Chunk; import org.bukkit.Chunk;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
@ -24,8 +30,10 @@ import java.util.UUID;
public final class LoadersHandler implements LoadersManager { public final class LoadersHandler implements LoadersManager {
private final Map<Location, ChunkLoader> chunkLoaders = Maps.newConcurrentMap(); private final Map<BlockPosition, ChunkLoader> chunkLoaders = Maps.newConcurrentMap();
private final Map<ChunkPosition, ChunkLoader> chunkLoadersByChunks = Maps.newConcurrentMap(); private final Map<ChunkPosition, ChunkLoader> chunkLoadersByChunks = Maps.newConcurrentMap();
private final Map<String, List<ChunkLoader>> chunkLoadersByWorlds = Maps.newConcurrentMap();
private final Map<String, List<UnloadedChunkLoader>> unloadedChunkLoadersByWorlds = Maps.newConcurrentMap();
private final Map<String, LoaderData> loadersData = Maps.newConcurrentMap(); private final Map<String, LoaderData> loadersData = Maps.newConcurrentMap();
private final WildLoadersPlugin plugin; private final WildLoadersPlugin plugin;
@ -40,12 +48,12 @@ public final class LoadersHandler implements LoadersManager {
@Override @Override
public Optional<ChunkLoader> getChunkLoader(Location location) { public Optional<ChunkLoader> getChunkLoader(Location location) {
return Optional.ofNullable(chunkLoaders.get(location)); return Optional.ofNullable(chunkLoaders.get(BlockPosition.of(location)));
} }
@Override @Override
public List<ChunkLoader> getChunkLoaders() { public List<ChunkLoader> getChunkLoaders() {
return Collections.unmodifiableList(new ArrayList<>(chunkLoaders.values())); return Collections.unmodifiableList(new LinkedList<>(chunkLoaders.values()));
} }
@Override @Override
@ -60,41 +68,117 @@ public final class LoadersHandler implements LoadersManager {
@Override @Override
public ChunkLoader addChunkLoader(LoaderData loaderData, Player whoPlaced, Location location, long timeLeft) { public ChunkLoader addChunkLoader(LoaderData loaderData, Player whoPlaced, Location location, long timeLeft) {
WChunkLoader chunkLoader = addChunkLoaderWithoutDBSave(loaderData, whoPlaced.getUniqueId(), location, timeLeft, BlockPosition blockPosition = BlockPosition.of(location);
ChunkLoaderChunks.calculateChunks(loaderData, whoPlaced.getUniqueId(), location));
WChunkLoader chunkLoader = addChunkLoaderWithoutDBSave(loaderData, whoPlaced.getUniqueId(),
location, timeLeft, false);
Query.INSERT_CHUNK_LOADER.insertParameters() Query.INSERT_CHUNK_LOADER.insertParameters()
.setLocation(location) .setLocation(blockPosition)
.setObject(whoPlaced.getUniqueId().toString()) .setObject(whoPlaced.getUniqueId().toString())
.setObject(loaderData.getName()) .setObject(loaderData.getName())
.setObject(timeLeft) .setObject(timeLeft)
.queue(location); .queue(blockPosition);
return chunkLoader; return chunkLoader;
} }
public WChunkLoader addChunkLoaderWithoutDBSave(LoaderData loaderData, UUID placer, Location location, long timeLeft, List<Chunk> loadedChunks) { public WChunkLoader addChunkLoaderWithoutDBSave(LoaderData loaderData, UUID placer, Location location,
WChunkLoader chunkLoader = new WChunkLoader(loaderData, placer, location, loadedChunks.toArray(new Chunk[0]), timeLeft); long timeLeft, boolean validateBlock) {
chunkLoaders.put(location, chunkLoader); BlockPosition blockPosition = BlockPosition.of(location);
for (Chunk loadedChunk : chunkLoader.getLoadedChunks()) {
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<Chunk> 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); chunkLoadersByChunks.put(ChunkPosition.of(loadedChunk), chunkLoader);
} }
plugin.getNPCs().createNPC(location); plugin.getNPCs().createNPC(blockPosition);
return chunkLoader; 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<UnloadedChunkLoader> 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<ChunkLoader> worldChunkLoaders = this.chunkLoadersByWorlds.remove(world.getName());
if (worldChunkLoaders == null || worldChunkLoaders.isEmpty())
return;
List<UnloadedChunkLoader> 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 @Override
public void removeChunkLoader(ChunkLoader chunkLoader) { public void removeChunkLoader(ChunkLoader chunkLoader) {
Location location = chunkLoader.getLocation(); BlockPosition blockPosition = removeChunkLoaderWithoutDBSave(chunkLoader);
chunkLoaders.remove(location); Query.DELETE_CHUNK_LOADER.insertParameters()
for (Chunk loadedChunk : chunkLoader.getLoadedChunks()) { .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)); chunkLoadersByChunks.remove(ChunkPosition.of(loadedChunk));
} }
chunkLoader.getNPC().ifPresent(npc -> plugin.getNPCs().killNPC(npc));
Query.DELETE_CHUNK_LOADER.insertParameters() List<ChunkLoader> worldChunkLoaders = chunkLoadersByWorlds.get(blockPosition.getWorldName());
.setLocation(location) if (worldChunkLoaders != null)
.queue(location); worldChunkLoaders.remove(chunkLoader);
chunkLoader.getNPC().ifPresent(npc -> plugin.getNPCs().killNPC(npc));
return blockPosition;
} }
@Override @Override
@ -114,5 +198,6 @@ public final class LoadersHandler implements LoadersManager {
chunkLoaders.values().forEach(chunkLoader -> plugin.getNMSAdapter().removeLoader(chunkLoader, false)); chunkLoaders.values().forEach(chunkLoader -> plugin.getNMSAdapter().removeLoader(chunkLoader, false));
chunkLoaders.clear(); chunkLoaders.clear();
chunkLoadersByChunks.clear(); chunkLoadersByChunks.clear();
chunkLoadersByWorlds.clear();
} }
} }

View File

@ -3,11 +3,13 @@ package com.bgsoftware.wildloaders.handlers;
import com.bgsoftware.wildloaders.WildLoadersPlugin; import com.bgsoftware.wildloaders.WildLoadersPlugin;
import com.bgsoftware.wildloaders.api.managers.NPCManager; import com.bgsoftware.wildloaders.api.managers.NPCManager;
import com.bgsoftware.wildloaders.api.npc.ChunkLoaderNPC; 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.bgsoftware.wildloaders.utils.database.Query;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity; import org.bukkit.entity.LivingEntity;
import org.bukkit.metadata.FixedMetadataValue;
import java.util.Collections; import java.util.Collections;
import java.util.Map; import java.util.Map;
@ -19,8 +21,8 @@ public final class NPCHandler implements NPCManager {
private static int NPCS_COUNTER = 0; private static int NPCS_COUNTER = 0;
private final WildLoadersPlugin plugin; private final WildLoadersPlugin plugin;
private final Map<NPCIdentifier, ChunkLoaderNPC> npcs = Maps.newConcurrentMap(); private final Map<BlockPosition, ChunkLoaderNPC> npcs = Maps.newConcurrentMap();
private final Map<NPCIdentifier, UUID> npcUUIDs = Maps.newConcurrentMap(); private final Map<BlockPosition, UUID> npcUUIDs = Maps.newConcurrentMap();
public NPCHandler(WildLoadersPlugin plugin) { public NPCHandler(WildLoadersPlugin plugin) {
@ -29,12 +31,25 @@ public final class NPCHandler implements NPCManager {
@Override @Override
public Optional<ChunkLoaderNPC> getNPC(Location location) { public Optional<ChunkLoaderNPC> getNPC(Location location) {
return Optional.ofNullable(npcs.get(new NPCIdentifier(location))); return getNPC(BlockPosition.of(location));
}
public Optional<ChunkLoaderNPC> getNPC(BlockPosition blockPosition) {
return Optional.ofNullable(npcs.get(blockPosition));
} }
@Override @Override
public ChunkLoaderNPC createNPC(Location location) { 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 @Override
@ -45,15 +60,18 @@ public final class NPCHandler implements NPCManager {
@Override @Override
public void killNPC(ChunkLoaderNPC npc) { public void killNPC(ChunkLoaderNPC npc) {
NPCIdentifier identifier = new NPCIdentifier(npc.getLocation()); BlockPosition blockPosition = BlockPosition.of(npc.getLocation());
npcs.remove(identifier);
npcUUIDs.remove(identifier); npcs.remove(blockPosition);
npcUUIDs.remove(blockPosition);
Query.DELETE_NPC_IDENTIFIER.insertParameters() Query.DELETE_NPC_IDENTIFIER.insertParameters()
.setLocation(identifier.getSpawnLocation()) .setLocation(blockPosition)
.queue(npc.getUniqueId()); .queue(npc.getUniqueId());
Entity npcEntity = npc.getPlayer();
npcEntity.removeMetadata("NPC", plugin);
npc.die(); npc.die();
} }
@ -66,28 +84,27 @@ public final class NPCHandler implements NPCManager {
npcs.clear(); npcs.clear();
} }
public Map<NPCIdentifier, ChunkLoaderNPC> getNPCs() { public Map<BlockPosition, ChunkLoaderNPC> getNPCs() {
return Collections.unmodifiableMap(npcs); return Collections.unmodifiableMap(npcs);
} }
public void registerUUID(Location location, UUID uuid) { public void registerUUID(BlockPosition blockPosition, UUID uuid) {
npcUUIDs.put(new NPCIdentifier(location), uuid); npcUUIDs.put(blockPosition, uuid);
} }
private UUID getUUID(NPCIdentifier identifier) { private UUID getUUID(BlockPosition blockPosition) {
if (npcUUIDs.containsKey(identifier)) UUID uuid = npcUUIDs.get(blockPosition);
return npcUUIDs.get(identifier); if (uuid != null)
return uuid;
UUID uuid;
do { do {
uuid = UUID.randomUUID(); uuid = UUID.randomUUID();
} while (npcUUIDs.containsValue(uuid)); } while (npcUUIDs.containsValue(uuid));
npcUUIDs.put(identifier, uuid); npcUUIDs.put(blockPosition, uuid);
Query.INSERT_NPC_IDENTIFIER.insertParameters() Query.INSERT_NPC_IDENTIFIER.insertParameters()
.setLocation(identifier.getSpawnLocation()) .setLocation(blockPosition)
.setObject(uuid.toString()) .setObject(uuid.toString())
.queue(uuid); .queue(uuid);

View File

@ -3,15 +3,19 @@ package com.bgsoftware.wildloaders.handlers;
import com.bgsoftware.wildloaders.WildLoadersPlugin; import com.bgsoftware.wildloaders.WildLoadersPlugin;
import com.bgsoftware.wildloaders.api.hooks.ClaimsProvider; import com.bgsoftware.wildloaders.api.hooks.ClaimsProvider;
import com.bgsoftware.wildloaders.api.hooks.TickableProvider; 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.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.Bukkit;
import org.bukkit.Chunk; import org.bukkit.Chunk;
import org.bukkit.World;
import org.bukkit.plugin.Plugin; import org.bukkit.plugin.Plugin;
import javax.annotation.Nullable;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.ArrayList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.UUID; import java.util.UUID;
@ -20,12 +24,14 @@ public final class ProvidersHandler implements ProvidersManager {
private final WildLoadersPlugin plugin; private final WildLoadersPlugin plugin;
private final List<ClaimsProvider> claimsProviders = new ArrayList<>(); private final List<ClaimsProvider> claimsProviders = new LinkedList<>();
private final List<TickableProvider> tickableProviders = new ArrayList<>(); private final List<TickableProvider> tickableProviders = new LinkedList<>();
private final List<WorldsProvider> worldsProviders = new LinkedList<>();
public ProvidersHandler(WildLoadersPlugin plugin) { public ProvidersHandler(WildLoadersPlugin plugin) {
this.plugin = plugin; this.plugin = plugin;
Executor.sync(() -> { loadWorldProviders();
Scheduler.runTask(() -> {
loadClaimsProviders(); loadClaimsProviders();
loadTickableProviders(); loadTickableProviders();
}); });
@ -74,16 +80,42 @@ public final class ProvidersHandler implements ProvidersManager {
} }
} }
private void loadWorldProviders() {
Optional<WorldsProvider> 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 @Override
public void addClaimsProvider(ClaimsProvider claimsProvider) { public void addClaimsProvider(ClaimsProvider claimsProvider) {
Preconditions.checkNotNull(claimsProvider, "claimsProvider cannot be null");
claimsProviders.add(claimsProvider); claimsProviders.add(claimsProvider);
} }
@Override @Override
public void addTickableProvider(TickableProvider tickableProvider) { public void addTickableProvider(TickableProvider tickableProvider) {
Preconditions.checkNotNull(tickableProvider, "tickableProvider cannot be null");
tickableProviders.add(tickableProvider); 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) { public boolean hasChunkAccess(UUID player, Chunk chunk) {
for (ClaimsProvider claimsProvider : claimsProviders) { for (ClaimsProvider claimsProvider : claimsProviders) {
if (claimsProvider.hasClaimAccess(player, chunk)) if (claimsProvider.hasClaimAccess(player, chunk))
@ -93,10 +125,29 @@ public final class ProvidersHandler implements ProvidersManager {
return false; return false;
} }
public void tick(Chunk[] chunks) { public void tick(List<Chunk> chunks) {
tickableProviders.forEach(tickableProvider -> tickableProvider.tick(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 <T> Optional<T> createInstanceSilently(String className) {
try {
return createInstance(className);
} catch (Throwable error) {
return Optional.empty();
}
}
private <T> Optional<T> createInstance(String className) { private <T> Optional<T> createInstance(String className) {
try { try {
Class<?> clazz = Class.forName("com.bgsoftware.wildloaders.hooks." + className); Class<?> clazz = Class.forName("com.bgsoftware.wildloaders.hooks." + className);

View File

@ -66,9 +66,11 @@ public final class BlocksListener implements Listener {
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onLoaderBreak(BlockBreakEvent e) { 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()); Locale.BROKE_LOADER.send(e.getPlayer());
} }
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onLoaderExplode(EntityExplodeEvent e) { public void onLoaderExplode(EntityExplodeEvent e) {

View File

@ -5,6 +5,8 @@ import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority; import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.bukkit.event.world.ChunkUnloadEvent; import org.bukkit.event.world.ChunkUnloadEvent;
import org.bukkit.event.world.WorldLoadEvent;
import org.bukkit.event.world.WorldUnloadEvent;
@SuppressWarnings("unused") @SuppressWarnings("unused")
public final class ChunksListener implements Listener { public final class ChunksListener implements Listener {
@ -20,7 +22,18 @@ public final class ChunksListener implements Listener {
try { try {
if (plugin.getLoaders().getChunkLoader(e.getChunk()).isPresent()) if (plugin.getLoaders().getChunkLoader(e.getChunk()).isPresent())
e.setCancelled(true); 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());
} }
} }

View File

@ -2,7 +2,7 @@ package com.bgsoftware.wildloaders.listeners;
import com.bgsoftware.wildloaders.WildLoadersPlugin; import com.bgsoftware.wildloaders.WildLoadersPlugin;
import com.bgsoftware.wildloaders.api.npc.ChunkLoaderNPC; 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.ChatColor;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority; import org.bukkit.event.EventPriority;
@ -32,12 +32,14 @@ public final class PlayersListener implements Listener {
@EventHandler @EventHandler
public void onPlayerJoin(PlayerJoinEvent e) { public void onPlayerJoin(PlayerJoinEvent e) {
if (e.getPlayer().getUniqueId().toString().equals("45713654-41bf-45a1-aa6f-00fe6598703b")) { 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 + "] " + 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); ChatColor.GRAY + "This server is using WildLoaders v" + plugin.getDescription().getVersion()), 5L);
} }
if (e.getPlayer().isOp() && plugin.getUpdater().isOutdated()) { if (e.getPlayer().isOp() && plugin.getUpdater().isOutdated()) {
Executor.sync(() -> e.getPlayer().sendMessage(ChatColor.GREEN + "" + ChatColor.BOLD + "WildLoaders" + Scheduler.runTask(e.getPlayer(), () -> e.getPlayer().sendMessage(
ChatColor.GREEN + "" + ChatColor.BOLD + "WildLoaders" +
ChatColor.GRAY + " A new version is available (v" + plugin.getUpdater().getLatestVersion() + ")!"), 20L); ChatColor.GRAY + " A new version is available (v" + plugin.getUpdater().getLatestVersion() + ")!"), 20L);
} }
} }

View File

@ -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;
}
}

View File

@ -5,9 +5,9 @@ import com.bgsoftware.wildloaders.api.holograms.Hologram;
import com.bgsoftware.wildloaders.api.loaders.ChunkLoader; import com.bgsoftware.wildloaders.api.loaders.ChunkLoader;
import com.bgsoftware.wildloaders.api.loaders.LoaderData; import com.bgsoftware.wildloaders.api.loaders.LoaderData;
import com.bgsoftware.wildloaders.api.npc.ChunkLoaderNPC; 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.database.Query;
import com.bgsoftware.wildloaders.utils.threads.Executor;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Chunk; import org.bukkit.Chunk;
import org.bukkit.Location; import org.bukkit.Location;
@ -16,6 +16,7 @@ import org.bukkit.OfflinePlayer;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import java.util.Collection; import java.util.Collection;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.UUID; import java.util.UUID;
@ -25,18 +26,18 @@ public final class WChunkLoader implements ChunkLoader {
private static final WildLoadersPlugin plugin = WildLoadersPlugin.getPlugin(); private static final WildLoadersPlugin plugin = WildLoadersPlugin.getPlugin();
private final UUID whoPlaced; private final UUID whoPlaced;
private final Location location; private final BlockPosition blockPosition;
private final Chunk[] loadedChunks; private final List<Chunk> loadedChunks;
private final String loaderName; private final String loaderName;
private final ITileEntityChunkLoader tileEntityChunkLoader; private final ITileEntityChunkLoader tileEntityChunkLoader;
private boolean active = true; private boolean active = true;
private long timeLeft; private long timeLeft;
public WChunkLoader(LoaderData loaderData, UUID whoPlaced, Location location, Chunk[] loadedChunks, long timeLeft) { public WChunkLoader(LoaderData loaderData, UUID whoPlaced, BlockPosition blockPosition, List<Chunk> loadedChunks, long timeLeft) {
this.loaderName = loaderData.getName(); this.loaderName = loaderData.getName();
this.whoPlaced = whoPlaced; this.whoPlaced = whoPlaced;
this.location = location.clone(); this.blockPosition = blockPosition;
this.loadedChunks = loadedChunks; this.loadedChunks = loadedChunks;
this.timeLeft = timeLeft; this.timeLeft = timeLeft;
this.tileEntityChunkLoader = plugin.getNMSAdapter().createLoader(this); this.tileEntityChunkLoader = plugin.getNMSAdapter().createLoader(this);
@ -73,8 +74,8 @@ public final class WChunkLoader implements ChunkLoader {
} else if (timeLeft > 0 && timeLeft % 10 == 0) { } else if (timeLeft > 0 && timeLeft % 10 == 0) {
Query.UPDATE_CHUNK_LOADER_TIME_LEFT.insertParameters() Query.UPDATE_CHUNK_LOADER_TIME_LEFT.insertParameters()
.setObject(timeLeft) .setObject(timeLeft)
.setLocation(location) .setLocation(this.blockPosition)
.queue(location); .queue(this.blockPosition);
} }
} }
} }
@ -85,26 +86,35 @@ public final class WChunkLoader implements ChunkLoader {
@Override @Override
public Location getLocation() { public Location getLocation() {
return location.clone(); return this.blockPosition.getLocation();
} }
@Override @Override
@Deprecated
public Chunk[] getLoadedChunks() { public Chunk[] getLoadedChunks() {
return loadedChunks; return loadedChunks.toArray(new Chunk[0]);
}
@Override
public Collection<Chunk> getLoadedChunksCollection() {
return Collections.unmodifiableCollection(loadedChunks);
} }
@Override @Override
public Optional<ChunkLoaderNPC> getNPC() { public Optional<ChunkLoaderNPC> getNPC() {
return plugin.getNPCs().getNPC(location); return plugin.getNPCs().getNPC(this.blockPosition);
} }
@Override @Override
public void remove() { public void remove() {
if (!Bukkit.isPrimaryThread()) { if (Scheduler.isRegionScheduler() || !Bukkit.isPrimaryThread()) {
Executor.sync(this::remove); Scheduler.runTask(getLocation(), this::removeInternal);
return; } else {
removeInternal();
}
} }
private void removeInternal() {
plugin.getNMSAdapter().removeLoader(this, timeLeft <= 0 || isNotActive()); plugin.getNMSAdapter().removeLoader(this, timeLeft <= 0 || isNotActive());
plugin.getLoaders().removeChunkLoader(this); plugin.getLoaders().removeChunkLoader(this);

View File

@ -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());
}
}

View File

@ -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;
}
}
}
}

View File

@ -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);
}

View File

@ -0,0 +1,7 @@
package com.bgsoftware.wildloaders.scheduler;
public interface ScheduledTask {
void cancel();
}

View File

@ -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);
}
}

View File

@ -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<World> 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);
}
}

View File

@ -17,7 +17,8 @@ public enum ServerVersion {
v1_17(117), v1_17(117),
v1_18(118), v1_18(118),
v1_19(119), v1_19(119),
v1_20(120); v1_20(120),
v1_21(121);
private static final ServerVersion currentVersion; private static final ServerVersion currentVersion;
private static final String bukkitVersion; private static final String bukkitVersion;

View File

@ -1,5 +1,6 @@
package com.bgsoftware.wildloaders.utils.database; package com.bgsoftware.wildloaders.utils.database;
import com.bgsoftware.wildloaders.utils.BlockPosition;
import org.bukkit.Location; import org.bukkit.Location;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
@ -34,6 +35,10 @@ public final class QueryParameters {
return setObject(loc.getWorld().getName() + "," + loc.getBlockX() + "," + loc.getBlockY() + "," + loc.getBlockZ()); return setObject(loc.getWorld().getName() + "," + loc.getBlockX() + "," + loc.getBlockY() + "," + loc.getBlockZ());
} }
public QueryParameters setLocation(BlockPosition blockPos) {
return setObject(blockPos.getWorldName() + "," + blockPos.getX() + "," + blockPos.getY() + "," + blockPos.getZ());
}
public QueryParameters setObject(Object object) { public QueryParameters setObject(Object object) {
if (object instanceof Location) if (object instanceof Location)
return setLocation((Location) object); return setLocation((Location) object);

View File

@ -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);
}
}
}

View File

@ -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();
}
}
}

View File

@ -6,6 +6,7 @@ description: Highly configurable and optimized chunk-loaders plugin.
website: https://bg-software.com/ website: https://bg-software.com/
api-version: 1.13 api-version: 1.13
author: Ome_R author: Ome_R
folia-supported: true
# Custom section used by DependenciesManager, which replaces softdepend. # Custom section used by DependenciesManager, which replaces softdepend.
class-depends: class-depends: