9
0
mirror of https://github.com/Xiao-MoMi/Custom-Crops.git synced 2025-12-26 18:39:17 +00:00

slime world support

This commit is contained in:
XiaoMoMi
2024-03-11 04:59:46 +08:00
parent 4193d491b6
commit 1c64f84ec9
6 changed files with 210 additions and 24 deletions

View File

@@ -146,12 +146,12 @@ public class HologramManager implements Listener, Reloadable {
this.tuples = tupleList.toArray(new Tuple[0]);
if (VersionManager.isHigherThan1_20_R2()) {
PacketManager.getInstance().send(player,
FakeEntityUtils.getSpawnPacket(random, location.clone().add(0,1.1,0), EntityType.TEXT_DISPLAY),
FakeEntityUtils.getSpawnPacket(random, location.clone().add(0,1.25,0), EntityType.TEXT_DISPLAY),
FakeEntityUtils.get1_20_2TextDisplayMetaPacket(random, component)
);
} else if (VersionManager.isHigherThan1_19_R3()) {
PacketManager.getInstance().send(player,
FakeEntityUtils.getSpawnPacket(random, location.clone().add(0,1.1,0), EntityType.TEXT_DISPLAY),
FakeEntityUtils.getSpawnPacket(random, location.clone().add(0,1.25,0), EntityType.TEXT_DISPLAY),
FakeEntityUtils.get1_19_4TextDisplayMetaPacket(random, component)
);
} else {
@@ -168,7 +168,6 @@ public class HologramManager implements Listener, Reloadable {
} else {
PacketManager.getInstance().send(player, FakeEntityUtils.getVanishArmorStandMetaPacket(entity_id, component));
}
}
}

View File

@@ -461,11 +461,14 @@ public class WorldManagerImpl implements WorldManager, Listener {
Optional<CustomCropsWorld> optional = getCustomCropsWorld(bukkitChunk.getWorld());
if (optional.isEmpty())
return;
CustomCropsWorld customCropsWorld = optional.get();
ChunkCoordinate chunkCoordinate = ChunkCoordinate.getByBukkitChunk(bukkitChunk);
if (customCropsWorld.isChunkLoaded(chunkCoordinate)) {
return;
}
// load chunks
this.worldAdaptor.loadDynamicData(customCropsWorld, chunkCoordinate);
@@ -491,6 +494,7 @@ public class WorldManagerImpl implements WorldManager, Listener {
CustomCropsWorld customCropsWorld = optional.get();
ChunkCoordinate chunkCoordinate = ChunkCoordinate.getByBukkitChunk(bukkitChunk);
this.worldAdaptor.unloadDynamicData(customCropsWorld, chunkCoordinate);
}

View File

@@ -59,7 +59,7 @@ import java.util.concurrent.ConcurrentHashMap;
public class BukkitWorldAdaptor extends AbstractWorldAdaptor {
private static final NamespacedKey key = new NamespacedKey(CustomCropsPlugin.get(), "data");
private final Gson gson;
protected final Gson gson;
private String worldFolder;
public BukkitWorldAdaptor(WorldManager worldManager) {

View File

@@ -17,19 +17,35 @@
package net.momirealms.customcrops.mechanic.world.adaptor;
import com.flowpowered.nbt.*;
import com.infernalsuite.aswm.api.SlimePlugin;
import com.infernalsuite.aswm.api.events.LoadSlimeWorldEvent;
import com.infernalsuite.aswm.api.world.SlimeWorld;
import net.momirealms.customcrops.api.CustomCropsPlugin;
import net.momirealms.customcrops.api.manager.WorldManager;
import net.momirealms.customcrops.api.mechanic.world.AbstractWorldAdaptor;
import net.momirealms.customcrops.api.mechanic.world.ChunkCoordinate;
import net.momirealms.customcrops.api.mechanic.world.ChunkPos;
import net.momirealms.customcrops.api.mechanic.world.CustomCropsBlock;
import net.momirealms.customcrops.api.mechanic.world.level.CustomCropsChunk;
import net.momirealms.customcrops.api.mechanic.world.level.CustomCropsWorld;
import net.momirealms.customcrops.api.mechanic.world.level.WorldInfoData;
import net.momirealms.customcrops.api.util.LogUtils;
import net.momirealms.customcrops.mechanic.world.*;
import net.momirealms.customcrops.mechanic.world.block.*;
import net.momirealms.customcrops.scheduler.task.TickTask;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.event.EventHandler;
import org.bukkit.event.world.WorldLoadEvent;
import org.bukkit.event.world.WorldUnloadEvent;
import org.bukkit.persistence.PersistentDataType;
public class SlimeWorldAdaptor extends AbstractWorldAdaptor {
import java.io.*;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
public class SlimeWorldAdaptor extends BukkitWorldAdaptor {
private final SlimePlugin slimePlugin;
@@ -40,46 +56,211 @@ public class SlimeWorldAdaptor extends AbstractWorldAdaptor {
@EventHandler (ignoreCancelled = true)
public void onSlimeWorldLoad(LoadSlimeWorldEvent event) {
}
@EventHandler(ignoreCancelled = true)
public void onWorldLoad(WorldLoadEvent event) {
if (worldManager.isMechanicEnabled(event.getWorld())) {
worldManager.loadWorld(event.getWorld());
World world = Bukkit.getWorld(event.getSlimeWorld().getName());
if (world == null) {
LogUtils.warn("Failed to load slime world because the bukkit world not loaded");
return;
}
if (worldManager.isMechanicEnabled(world)) {
worldManager.loadWorld(world);
}
}
@EventHandler (ignoreCancelled = true)
public void onWorldUnload(WorldUnloadEvent event) {
}
@Override
public void unload(CustomCropsWorld customCropsWorld) {
SlimeWorld slimeWorld = slimePlugin.getWorld(customCropsWorld.getWorldName());
if (slimeWorld == null) {
super.unload(customCropsWorld);
return;
}
CWorld cWorld = (CWorld) customCropsWorld;
Optional<CompoundTag> optionalCompoundTag = slimeWorld.getExtraData().getAsCompoundTag("customcrops");
if (optionalCompoundTag.isEmpty()) {
LogUtils.warn("Failed to unload data for world " + customCropsWorld.getWorldName() + " because slime world format is incorrect.");
return;
}
CompoundMap ccDataMap = optionalCompoundTag.get().getValue();
ccDataMap.put(new StringTag("world-info", gson.toJson(customCropsWorld.getInfoData())));
for (CChunk chunk : cWorld.getAllChunksToSave()) {
ccDataMap.put(chunkToTag(chunk));
}
}
@Override
public void init(CustomCropsWorld customCropsWorld) {
SlimeWorld slimeWorld = slimePlugin.getWorld(customCropsWorld.getWorldName());
if (slimeWorld == null) {
super.init(customCropsWorld);
return;
}
Optional<CompoundTag> optionalCompoundTag = slimeWorld.getExtraData().getAsCompoundTag("customcrops");
CompoundMap ccDataMap;
if (optionalCompoundTag.isEmpty()) {
ccDataMap = new CompoundMap();
slimeWorld.getExtraData().getValue().put(new CompoundTag("customcrops", ccDataMap));
} else {
ccDataMap = optionalCompoundTag.get().getValue();
}
String json = Optional.ofNullable(ccDataMap.get("world-info")).map(tag -> tag.getAsStringTag().get().getValue()).orElse(null);
WorldInfoData data = (json == null || json.equals("null")) ? WorldInfoData.empty() : gson.fromJson(json, WorldInfoData.class);
customCropsWorld.setInfoData(data);
}
@Override
public void loadDynamicData(CustomCropsWorld customCropsWorld, ChunkCoordinate chunkCoordinate) {
SlimeWorld slimeWorld = slimePlugin.getWorld(customCropsWorld.getWorldName());
if (slimeWorld == null) {
super.loadDynamicData(customCropsWorld, chunkCoordinate);
return;
}
CWorld cWorld = (CWorld) customCropsWorld;
// load lazy chunks firstly
CustomCropsChunk lazyChunk = customCropsWorld.removeLazyChunkAt(chunkCoordinate);
if (lazyChunk != null) {
CChunk cChunk = (CChunk) lazyChunk;
cChunk.setUnloadedSeconds(0);
cWorld.loadChunk(cChunk);
return;
}
Optional<CompoundTag> optionalCompoundTag = slimeWorld.getExtraData().getAsCompoundTag("customcrops");
if (optionalCompoundTag.isEmpty()) {
LogUtils.warn("Failed to load data for " + chunkCoordinate + " in world " + customCropsWorld.getWorldName() + " because slime world format is incorrect.");
return;
}
Tag<?> chunkTag = optionalCompoundTag.get().getValue().get(chunkCoordinate.toString());
if (chunkTag == null) return;
Optional<CompoundTag> chunkCompoundTag = chunkTag.getAsCompoundTag();
if (chunkCompoundTag.isEmpty()) return;
// load chunk from local files
long time1 = System.currentTimeMillis();
cWorld.loadChunk(tagToChunk(cWorld, chunkCompoundTag.get()));
long time2 = System.currentTimeMillis();
CustomCropsPlugin.get().debug("Took " + (time2-time1) + "ms to load chunk " + chunkCoordinate);
}
@Override
public void unloadDynamicData(CustomCropsWorld customCropsWorld, ChunkCoordinate chunkCoordinate) {
public void saveDynamicData(CustomCropsWorld customCropsWorld, CustomCropsChunk chunk) {
SlimeWorld slimeWorld = getSlimeWorld(customCropsWorld.getWorldName());
if (slimeWorld == null) {
super.saveDynamicData(customCropsWorld, chunk);
return;
}
Optional<CompoundTag> optionalCompoundTag = slimeWorld.getExtraData().getAsCompoundTag("customcrops");
if (optionalCompoundTag.isEmpty()) {
LogUtils.warn("Failed to save data for " + chunk + " in world " + customCropsWorld.getWorldName() + " because slime world format is incorrect.");
return;
}
CustomCropsPlugin.get().getScheduler().runTaskSync(() -> optionalCompoundTag.get().getValue().put(chunkToTag((CChunk) chunk)), null);
}
@Override
public void saveDynamicData(CustomCropsWorld ccWorld, CustomCropsChunk chunk) {
private SlimeWorld getSlimeWorld(String name) {
return slimePlugin.getWorld(name);
}
private boolean isSlimeWorld(String name) {
return slimePlugin.getWorld(name) != null;
private CompoundTag chunkToTag(CChunk chunk) {
SerializableChunk serializableChunk = toSerializableChunk(chunk);
CompoundMap map = new CompoundMap();
map.put(new IntTag("x", serializableChunk.getX()));
map.put(new IntTag("z", serializableChunk.getZ()));
map.put(new IntTag("loadedSeconds", serializableChunk.getLoadedSeconds()));
map.put(new LongTag("lastLoadedTime", serializableChunk.getLastLoadedTime()));
map.put(new IntArrayTag("queued", serializableChunk.getTicked()));
map.put(new IntArrayTag("ticked", serializableChunk.getTicked()));
CompoundMap sectionMap = new CompoundMap();
for (SerializableSection section : serializableChunk.getSections()) {
sectionMap.put(new ListTag<>(String.valueOf(section.getSectionID()), TagType.TAG_COMPOUND, section.getBlocks()));
}
map.put(new CompoundTag("sections", sectionMap));
return new CompoundTag(chunk.getChunkCoordinate().toString(), map);
}
private CChunk tagToChunk(CWorld cWorld, CompoundTag tag) {
String world = cWorld.getWorldName();
CompoundMap map = tag.getValue();
int x = map.get("x").getAsIntTag().get().getValue();
int z = map.get("z").getAsIntTag().get().getValue();
ChunkCoordinate coordinate = new ChunkCoordinate(x, z);
int loadedSeconds = map.get("loadedSeconds").getAsIntTag().get().getValue();
long lastLoadedTime = map.get("lastLoadedTime").getAsLongTag().get().getValue();
int[] queued = map.get("queued").getAsIntArrayTag().get().getValue();
int[] ticked = map.get("ticked").getAsIntArrayTag().get().getValue();
PriorityQueue<TickTask> queue = new PriorityQueue<>(Math.max(11, queued.length / 2));
for (int i = 0, size = queued.length / 2; i < size; i++) {
ChunkPos pos = new ChunkPos(queued[2*i+1]);
queue.add(new TickTask(queued[2*i], pos));
}
HashSet<ChunkPos> tickedSet = new HashSet<>(Math.max(11, ticked.length));
for (int tick : ticked) {
tickedSet.add(new ChunkPos(tick));
}
ConcurrentHashMap<Integer, CSection> sectionMap = new ConcurrentHashMap<>();
CompoundMap sectionCompoundMap = map.get("sections").getAsCompoundTag().get().getValue();
for (Map.Entry<String, Tag<?>> entry : sectionCompoundMap.entrySet()) {
if (entry.getValue() instanceof ListTag<?> listTag) {
int id = Integer.parseInt(entry.getKey());
ConcurrentHashMap<ChunkPos, CustomCropsBlock> blockMap = new ConcurrentHashMap<>();
ListTag<CompoundTag> blocks = (ListTag<CompoundTag>) listTag;
for (CompoundTag blockTag : blocks.getValue()) {
CompoundMap block = blockTag.getValue();
String type = (String) block.get("type").getValue();
CompoundMap data = (CompoundMap) block.get("data").getValue();
switch (type) {
case "CROP" -> {
for (int pos : (int[]) block.get("pos").getValue()) {
ChunkPos chunkPos = new ChunkPos(pos);
blockMap.put(chunkPos, new MemoryCrop(chunkPos.getLocation(world, coordinate), new CompoundMap(data)));
}
}
case "POT" -> {
for (int pos : (int[]) block.get("pos").getValue()) {
ChunkPos chunkPos = new ChunkPos(pos);
blockMap.put(chunkPos, new MemoryPot(chunkPos.getLocation(world, coordinate), new CompoundMap(data)));
}
}
case "SPRINKLER" -> {
for (int pos : (int[]) block.get("pos").getValue()) {
ChunkPos chunkPos = new ChunkPos(pos);
blockMap.put(chunkPos, new MemorySprinkler(chunkPos.getLocation(world, coordinate), new CompoundMap(data)));
}
}
case "SCARECROW" -> {
for (int pos : (int[]) block.get("pos").getValue()) {
ChunkPos chunkPos = new ChunkPos(pos);
blockMap.put(chunkPos, new MemoryScarecrow(chunkPos.getLocation(world, coordinate), new CompoundMap(data)));
}
}
case "GLASS" -> {
for (int pos : (int[]) block.get("pos").getValue()) {
ChunkPos chunkPos = new ChunkPos(pos);
blockMap.put(chunkPos, new MemoryGlass(chunkPos.getLocation(world, coordinate), new CompoundMap(data)));
}
}
}
}
sectionMap.put(id, new CSection(id, blockMap));
}
}
return new CChunk(
cWorld,
coordinate,
loadedSeconds,
lastLoadedTime,
sectionMap,
queue,
tickedSet
);
}
}

View File

@@ -4,6 +4,7 @@ main: net.momirealms.customcrops.CustomCropsPluginImpl
api-version: 1.17
load: POSTWORLD
authors: [ XiaoMoMi ]
folia-supported: true
depend:
- ProtocolLib
softdepend:
@@ -22,4 +23,5 @@ softdepend:
- EcoSkills
- Jobs
- RealisticSeasons
- AdvancedSeasons
- AdvancedSeasons
- SlimeWorldManager