mirror of
https://github.com/Xiao-MoMi/Custom-Crops.git
synced 2025-12-22 16:39:36 +00:00
region file
This commit is contained in:
@@ -133,7 +133,9 @@ public interface WorldManager extends Reloadable {
|
||||
|
||||
void handleChunkUnload(Chunk bukkitChunk);
|
||||
|
||||
void saveChunkToFile(CustomCropsChunk chunk);
|
||||
void saveChunkToCachedRegion(CustomCropsChunk chunk);
|
||||
|
||||
void saveRegionToFile(CustomCropsRegion region);
|
||||
|
||||
void removeGlassAt(@NotNull SimpleLocation location);
|
||||
|
||||
@@ -142,4 +144,6 @@ public interface WorldManager extends Reloadable {
|
||||
CustomCropsBlock removeAnythingAt(SimpleLocation location);
|
||||
|
||||
AbstractWorldAdaptor getWorldAdaptor();
|
||||
|
||||
void saveInfoData(CustomCropsWorld customCropsWorld);
|
||||
}
|
||||
|
||||
@@ -56,4 +56,6 @@ public interface Pot extends KeyItem {
|
||||
String getBlockState(boolean water, FertilizerType type);
|
||||
|
||||
boolean isVanillaBlock();
|
||||
|
||||
boolean isWetPot(String id);
|
||||
}
|
||||
|
||||
@@ -19,12 +19,14 @@ package net.momirealms.customcrops.api.mechanic.world;
|
||||
|
||||
import net.momirealms.customcrops.api.manager.WorldManager;
|
||||
import net.momirealms.customcrops.api.mechanic.world.level.CustomCropsChunk;
|
||||
import net.momirealms.customcrops.api.mechanic.world.level.CustomCropsRegion;
|
||||
import net.momirealms.customcrops.api.mechanic.world.level.CustomCropsWorld;
|
||||
import org.bukkit.event.Listener;
|
||||
|
||||
public abstract class AbstractWorldAdaptor implements Listener {
|
||||
|
||||
public static final int version = 1;
|
||||
public static final int chunkVersion = 1;
|
||||
public static final int regionVersion = 1;
|
||||
protected WorldManager worldManager;
|
||||
|
||||
public AbstractWorldAdaptor(WorldManager worldManager) {
|
||||
@@ -35,9 +37,13 @@ public abstract class AbstractWorldAdaptor implements Listener {
|
||||
|
||||
public abstract void init(CustomCropsWorld customCropsWorld);
|
||||
|
||||
public abstract void loadDynamicData(CustomCropsWorld customCropsWorld, ChunkCoordinate chunkCoordinate);
|
||||
public abstract void loadChunkData(CustomCropsWorld customCropsWorld, ChunkPos chunkPos);
|
||||
|
||||
public abstract void unloadDynamicData(CustomCropsWorld customCropsWorld, ChunkCoordinate chunkCoordinate);
|
||||
public abstract void unloadChunkData(CustomCropsWorld customCropsWorld, ChunkPos chunkPos);
|
||||
|
||||
public abstract void saveDynamicData(CustomCropsWorld ccWorld, CustomCropsChunk chunk);
|
||||
public abstract void saveChunkToCachedRegion(CustomCropsChunk customCropsChunk);
|
||||
|
||||
public abstract void saveRegion(CustomCropsRegion customCropsRegion);
|
||||
|
||||
public abstract void saveInfoData(CustomCropsWorld customCropsWorld);
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ public class BlockPos {
|
||||
return new BlockPos(location.getX() % 16, location.getY(), location.getZ() % 16);
|
||||
}
|
||||
|
||||
public SimpleLocation getLocation(String world, ChunkCoordinate coordinate) {
|
||||
public SimpleLocation getLocation(String world, ChunkPos coordinate) {
|
||||
return new SimpleLocation(world, coordinate.x() * 16 + getX(), getY(), coordinate.z() * 16 + getZ());
|
||||
}
|
||||
|
||||
|
||||
@@ -20,20 +20,18 @@ package net.momirealms.customcrops.api.mechanic.world;
|
||||
import org.bukkit.Chunk;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public record ChunkCoordinate(int x, int z) {
|
||||
public record ChunkPos(int x, int z) {
|
||||
|
||||
private static final ChunkCoordinate empty = new ChunkCoordinate(0, 0);
|
||||
|
||||
public static ChunkCoordinate of(int x, int z) {
|
||||
return new ChunkCoordinate(x, z);
|
||||
public static ChunkPos of(int x, int z) {
|
||||
return new ChunkPos(x, z);
|
||||
}
|
||||
|
||||
public static ChunkCoordinate getByString(String coordinate) {
|
||||
public static ChunkPos getByString(String coordinate) {
|
||||
String[] split = coordinate.split(",", 2);
|
||||
try {
|
||||
int x = Integer.parseInt(split[0]);
|
||||
int z = Integer.parseInt(split[1]);
|
||||
return new ChunkCoordinate(x, z);
|
||||
return new ChunkPos(x, z);
|
||||
}
|
||||
catch (NumberFormatException e) {
|
||||
e.printStackTrace();
|
||||
@@ -55,7 +53,7 @@ public record ChunkCoordinate(int x, int z) {
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
final ChunkCoordinate other = (ChunkCoordinate) obj;
|
||||
final ChunkPos other = (ChunkPos) obj;
|
||||
if (this.x != other.x) {
|
||||
return false;
|
||||
}
|
||||
@@ -66,13 +64,22 @@ public record ChunkCoordinate(int x, int z) {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static ChunkCoordinate getByBukkitChunk(@NotNull Chunk chunk) {
|
||||
return new ChunkCoordinate(chunk.getX(), chunk.getZ());
|
||||
public RegionPos getRegionPos() {
|
||||
return RegionPos.getByChunkPos(this);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static ChunkPos getByBukkitChunk(@NotNull Chunk chunk) {
|
||||
return new ChunkPos(chunk.getX(), chunk.getZ());
|
||||
}
|
||||
|
||||
public String getAsString() {
|
||||
return x + "," + z;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ChunkCoordinate{" +
|
||||
return "ChunkPos{" +
|
||||
"x=" + x +
|
||||
", z=" + z +
|
||||
'}';
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright (C) <2022> <XiaoMoMi>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.momirealms.customcrops.api.mechanic.world;
|
||||
|
||||
import org.bukkit.Chunk;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public record RegionPos(int x, int z) {
|
||||
|
||||
public static RegionPos of(int x, int z) {
|
||||
return new RegionPos(x, z);
|
||||
}
|
||||
|
||||
public static RegionPos getByString(String coordinate) {
|
||||
String[] split = coordinate.split(",", 2);
|
||||
try {
|
||||
int x = Integer.parseInt(split[0]);
|
||||
int z = Integer.parseInt(split[1]);
|
||||
return new RegionPos(x, z);
|
||||
}
|
||||
catch (NumberFormatException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
long combined = (long) x << 32 | z;
|
||||
return Long.hashCode(combined);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
final RegionPos other = (RegionPos) obj;
|
||||
if (this.x != other.x) {
|
||||
return false;
|
||||
}
|
||||
if (this.z != other.z) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static RegionPos getByBukkitChunk(@NotNull Chunk chunk) {
|
||||
int regionX = (int) Math.floor((double) chunk.getX() / 32.0);
|
||||
int regionZ = (int) Math.floor((double) chunk.getZ() / 32.0);
|
||||
return new RegionPos(regionX, regionZ);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static RegionPos getByChunkPos(@NotNull ChunkPos chunk) {
|
||||
int regionX = (int) Math.floor((double) chunk.x() / 32.0);
|
||||
int regionZ = (int) Math.floor((double) chunk.z() / 32.0);
|
||||
return new RegionPos(regionX, regionZ);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RegionPos{" +
|
||||
"x=" + x +
|
||||
", z=" + z +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -57,8 +57,8 @@ public class SimpleLocation {
|
||||
return worldName;
|
||||
}
|
||||
|
||||
public ChunkCoordinate getChunkCoordinate() {
|
||||
return new ChunkCoordinate(x >> 4, z >> 4);
|
||||
public ChunkPos getChunkCoordinate() {
|
||||
return new ChunkPos(x >> 4, z >> 4);
|
||||
}
|
||||
|
||||
public SimpleLocation add(int x, int y, int z) {
|
||||
|
||||
@@ -21,7 +21,7 @@ import net.momirealms.customcrops.api.mechanic.item.Crop;
|
||||
import net.momirealms.customcrops.api.mechanic.item.Fertilizer;
|
||||
import net.momirealms.customcrops.api.mechanic.item.Pot;
|
||||
import net.momirealms.customcrops.api.mechanic.item.Sprinkler;
|
||||
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.SimpleLocation;
|
||||
|
||||
@@ -33,7 +33,9 @@ public interface CustomCropsChunk {
|
||||
|
||||
CustomCropsWorld getCustomCropsWorld();
|
||||
|
||||
ChunkCoordinate getChunkCoordinate();
|
||||
CustomCropsRegion getCustomCropsRegion();
|
||||
|
||||
ChunkPos getChunkPos();
|
||||
|
||||
void secondTimer();
|
||||
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (C) <2022> <XiaoMoMi>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.momirealms.customcrops.api.mechanic.world.level;
|
||||
|
||||
import net.momirealms.customcrops.api.mechanic.world.ChunkPos;
|
||||
import net.momirealms.customcrops.api.mechanic.world.RegionPos;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public interface CustomCropsRegion {
|
||||
|
||||
CustomCropsWorld getCustomCropsWorld();
|
||||
|
||||
byte @Nullable [] getChunkBytes(ChunkPos pos);
|
||||
|
||||
RegionPos getRegionPos();
|
||||
|
||||
void removeChunk(ChunkPos pos);
|
||||
|
||||
void saveChunk(ChunkPos pos, byte[] data);
|
||||
|
||||
Map<ChunkPos, byte[]> getRegionDataToSave();
|
||||
|
||||
boolean canPrune();
|
||||
}
|
||||
@@ -21,8 +21,9 @@ import net.momirealms.customcrops.api.mechanic.item.Crop;
|
||||
import net.momirealms.customcrops.api.mechanic.item.Fertilizer;
|
||||
import net.momirealms.customcrops.api.mechanic.item.Pot;
|
||||
import net.momirealms.customcrops.api.mechanic.item.Sprinkler;
|
||||
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.RegionPos;
|
||||
import net.momirealms.customcrops.api.mechanic.world.SimpleLocation;
|
||||
import net.momirealms.customcrops.api.mechanic.world.season.Season;
|
||||
import org.bukkit.World;
|
||||
@@ -33,11 +34,15 @@ import java.util.Optional;
|
||||
|
||||
public interface CustomCropsWorld {
|
||||
|
||||
void save();
|
||||
|
||||
void startTick();
|
||||
|
||||
void cancelTick();
|
||||
|
||||
CustomCropsChunk removeLazyChunkAt(ChunkCoordinate chunkCoordinate);
|
||||
boolean isRegionLoaded(RegionPos regionPos);
|
||||
|
||||
CustomCropsChunk removeLazyChunkAt(ChunkPos chunkPos);
|
||||
|
||||
WorldSetting getWorldSetting();
|
||||
|
||||
@@ -49,13 +54,17 @@ public interface CustomCropsWorld {
|
||||
|
||||
String getWorldName();
|
||||
|
||||
boolean isChunkLoaded(ChunkCoordinate chunkCoordinate);
|
||||
boolean isChunkLoaded(ChunkPos chunkPos);
|
||||
|
||||
Optional<CustomCropsChunk> getChunkAt(ChunkCoordinate chunkCoordinate);
|
||||
Optional<CustomCropsChunk> getLoadedChunkAt(ChunkPos chunkPos);
|
||||
|
||||
Optional<CustomCropsRegion> getLoadedRegionAt(RegionPos regionPos);
|
||||
|
||||
void loadRegion(CustomCropsRegion region);
|
||||
|
||||
void loadChunk(CustomCropsChunk chunk);
|
||||
|
||||
void unloadChunk(ChunkCoordinate chunkCoordinate);
|
||||
void unloadChunk(ChunkPos chunkPos);
|
||||
|
||||
void setInfoData(WorldInfoData infoData);
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ plugins {
|
||||
allprojects {
|
||||
|
||||
project.group = "net.momirealms"
|
||||
project.version = "3.4.2.3"
|
||||
project.version = "3.4.3.0"
|
||||
|
||||
apply<JavaPlugin>()
|
||||
apply(plugin = "java")
|
||||
|
||||
@@ -103,7 +103,6 @@ public class CustomCropsPluginImpl extends CustomCropsPlugin {
|
||||
this.disableNBTAPILogs();
|
||||
Migration.tryUpdating();
|
||||
this.reload();
|
||||
this.worldManager.init();
|
||||
if (ConfigManager.metrics()) new Metrics(this, 16593);
|
||||
if (ConfigManager.checkUpdate()) {
|
||||
this.versionManager.checkUpdate().thenAccept(result -> {
|
||||
|
||||
@@ -21,7 +21,6 @@ import dev.jorel.commandapi.*;
|
||||
import dev.jorel.commandapi.arguments.ArgumentSuggestions;
|
||||
import dev.jorel.commandapi.arguments.IntegerArgument;
|
||||
import dev.jorel.commandapi.arguments.StringArgument;
|
||||
import dev.jorel.commandapi.arguments.WorldArgument;
|
||||
import net.momirealms.customcrops.api.CustomCropsPlugin;
|
||||
import net.momirealms.customcrops.api.common.Initable;
|
||||
import net.momirealms.customcrops.api.integration.SeasonInterface;
|
||||
@@ -33,7 +32,9 @@ import net.momirealms.customcrops.api.mechanic.world.level.CustomCropsSection;
|
||||
import net.momirealms.customcrops.api.mechanic.world.level.CustomCropsWorld;
|
||||
import net.momirealms.customcrops.api.mechanic.world.season.Season;
|
||||
import net.momirealms.customcrops.compatibility.season.InBuiltSeason;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.generator.WorldInfo;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.Optional;
|
||||
@@ -91,10 +92,15 @@ public class CommandManager implements Initable {
|
||||
|
||||
private CommandAPICommand getForceTickCommand() {
|
||||
return new CommandAPICommand("force-tick")
|
||||
.withArguments(new WorldArgument("world"))
|
||||
.withArguments(new StringArgument("world").replaceSuggestions(ArgumentSuggestions.strings(commandSenderSuggestionInfo -> Bukkit.getWorlds().stream().map(WorldInfo::getName).toList().toArray(new String[0]))))
|
||||
.withArguments(new StringArgument("type").replaceSuggestions(ArgumentSuggestions.strings("sprinkler", "crop", "pot", "scarecrow", "greenhouse")))
|
||||
.executes((sender, args) -> {
|
||||
World world = (World) args.get("world");
|
||||
String worldName = (String) args.get("world");
|
||||
World world = Bukkit.getWorld(worldName);
|
||||
if (world == null) {
|
||||
plugin.getAdventure().sendMessageWithPrefix(sender, "CustomCrops is not enabled in that world");
|
||||
return;
|
||||
}
|
||||
ItemType itemType = ItemType.valueOf(((String) args.get("type")).toUpperCase(Locale.ENGLISH));
|
||||
Optional<CustomCropsWorld> customCropsWorld = plugin.getWorldManager().getCustomCropsWorld(world);
|
||||
if (customCropsWorld.isEmpty()) {
|
||||
@@ -119,16 +125,26 @@ public class CommandManager implements Initable {
|
||||
return new CommandAPICommand("date")
|
||||
.withSubcommands(
|
||||
new CommandAPICommand("get")
|
||||
.withArguments(new WorldArgument("world"))
|
||||
.withArguments(new StringArgument("world").replaceSuggestions(ArgumentSuggestions.strings(commandSenderSuggestionInfo -> Bukkit.getWorlds().stream().map(WorldInfo::getName).toList().toArray(new String[0]))))
|
||||
.executes((sender, args) -> {
|
||||
World world = (World) args.get("world");
|
||||
String worldName = (String) args.get("world");
|
||||
World world = Bukkit.getWorld(worldName);
|
||||
if (world == null) {
|
||||
plugin.getAdventure().sendMessageWithPrefix(sender, "CustomCrops is not enabled in that world");
|
||||
return;
|
||||
}
|
||||
plugin.getAdventure().sendMessageWithPrefix(sender, String.valueOf(plugin.getIntegrationManager().getDate(world)));
|
||||
}),
|
||||
new CommandAPICommand("set")
|
||||
.withArguments(new WorldArgument("world"))
|
||||
.withArguments(new StringArgument("world").replaceSuggestions(ArgumentSuggestions.strings(commandSenderSuggestionInfo -> Bukkit.getWorlds().stream().map(WorldInfo::getName).toList().toArray(new String[0]))))
|
||||
.withArguments(new IntegerArgument("date",1))
|
||||
.executes((sender, args) -> {
|
||||
World world = (World) args.get("world");
|
||||
String worldName = (String) args.get("world");
|
||||
World world = Bukkit.getWorld(worldName);
|
||||
if (world == null) {
|
||||
plugin.getAdventure().sendMessageWithPrefix(sender, "CustomCrops is not enabled in that world");
|
||||
return;
|
||||
}
|
||||
int date = (int) args.getOrDefault("date", 1);
|
||||
SeasonInterface seasonInterface = plugin.getIntegrationManager().getSeasonInterface();
|
||||
if (!(seasonInterface instanceof InBuiltSeason inBuiltSeason)) {
|
||||
@@ -159,13 +175,18 @@ public class CommandManager implements Initable {
|
||||
return new CommandAPICommand("season")
|
||||
.withSubcommands(
|
||||
new CommandAPICommand("get")
|
||||
.withArguments(new WorldArgument("world"))
|
||||
.withArguments(new StringArgument("world").replaceSuggestions(ArgumentSuggestions.strings(commandSenderSuggestionInfo -> Bukkit.getWorlds().stream().map(WorldInfo::getName).toList().toArray(new String[0]))))
|
||||
.executes((sender, args) -> {
|
||||
World world = (World) args.get("world");
|
||||
String worldName = (String) args.get("world");
|
||||
World world = Bukkit.getWorld(worldName);
|
||||
if (world == null) {
|
||||
plugin.getAdventure().sendMessageWithPrefix(sender, "CustomCrops is not enabled in that world");
|
||||
return;
|
||||
}
|
||||
plugin.getAdventure().sendMessageWithPrefix(sender, MessageManager.seasonTranslation(plugin.getIntegrationManager().getSeason(world)));
|
||||
}),
|
||||
new CommandAPICommand("set")
|
||||
.withArguments(new WorldArgument("world"))
|
||||
.withArguments(new StringArgument("world").replaceSuggestions(ArgumentSuggestions.strings(commandSenderSuggestionInfo -> Bukkit.getWorlds().stream().map(WorldInfo::getName).toList().toArray(new String[0]))))
|
||||
.withArguments(new StringArgument("season")
|
||||
.replaceSuggestions(ArgumentSuggestions.stringsWithTooltips(info ->
|
||||
new IStringTooltip[] {
|
||||
@@ -177,7 +198,12 @@ public class CommandManager implements Initable {
|
||||
))
|
||||
)
|
||||
.executes((sender, args) -> {
|
||||
World world = (World) args.get("world");
|
||||
String worldName = (String) args.get("world");
|
||||
World world = Bukkit.getWorld(worldName);
|
||||
if (world == null) {
|
||||
plugin.getAdventure().sendMessageWithPrefix(sender, "CustomCrops is not enabled in that world");
|
||||
return;
|
||||
}
|
||||
String seasonName = (String) args.get("season");
|
||||
|
||||
SeasonInterface seasonInterface = plugin.getIntegrationManager().getSeasonInterface();
|
||||
|
||||
@@ -41,7 +41,7 @@ import net.momirealms.customcrops.api.mechanic.misc.CRotation;
|
||||
import net.momirealms.customcrops.api.mechanic.misc.Reason;
|
||||
import net.momirealms.customcrops.api.mechanic.misc.Value;
|
||||
import net.momirealms.customcrops.api.mechanic.requirement.Requirement;
|
||||
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.SimpleLocation;
|
||||
import net.momirealms.customcrops.api.mechanic.world.level.WorldCrop;
|
||||
@@ -443,7 +443,7 @@ public class ActionManagerImpl implements ActionManager {
|
||||
if (Math.random() > chance) return;
|
||||
Location location = state.getLocation();
|
||||
plugin.getWorldManager().getCustomCropsWorld(location.getWorld())
|
||||
.flatMap(world -> world.getChunkAt(ChunkCoordinate.getByBukkitChunk(location.getChunk())))
|
||||
.flatMap(world -> world.getLoadedChunkAt(ChunkPos.getByBukkitChunk(location.getChunk())))
|
||||
.flatMap(chunk -> chunk.getBlockAt(SimpleLocation.of(location)))
|
||||
.ifPresent(block -> {
|
||||
block.tick(1);
|
||||
|
||||
@@ -2020,6 +2020,9 @@ public class ItemManagerImpl implements ItemManager {
|
||||
if (optionalPot.isEmpty()) {
|
||||
plugin.debug("Found a pot without data interacted by " + player.getName() + " at " + location);
|
||||
WorldPot newPot = new MemoryPot(simpleLocation, pot.getKey());
|
||||
if (pot.isWetPot(potItemID)) {
|
||||
newPot.setWater(1);
|
||||
}
|
||||
plugin.getWorldManager().addPotAt(newPot, simpleLocation);
|
||||
optionalPot = Optional.of(newPot);
|
||||
} else {
|
||||
|
||||
@@ -45,6 +45,7 @@ import org.bukkit.event.entity.EntityExplodeEvent;
|
||||
import org.bukkit.event.entity.ItemSpawnEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.event.player.PlayerItemDamageEvent;
|
||||
import org.bukkit.event.world.WorldSaveEvent;
|
||||
import org.bukkit.inventory.EquipmentSlot;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
@@ -161,4 +161,17 @@ public class PotConfig extends AbstractEventItem implements Pot {
|
||||
public boolean isVanillaBlock() {
|
||||
return isVanillaBlock;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWetPot(String id) {
|
||||
if (id.equals(getWetItem())) {
|
||||
return true;
|
||||
}
|
||||
for (Pair<String, String> pair : fertilizedPotMap.values()) {
|
||||
if (pair.right().equals(id)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,10 +34,26 @@ public class Migration {
|
||||
if (version == null) return;
|
||||
|
||||
int versionNumber = Integer.parseInt(version);
|
||||
if (!(versionNumber >= 25 && versionNumber <= 34)) {
|
||||
if (versionNumber >= 25 && versionNumber <= 34) {
|
||||
doV33Migration(config);
|
||||
return;
|
||||
}
|
||||
if (versionNumber == 35) {
|
||||
doV343Migration();
|
||||
}
|
||||
}
|
||||
|
||||
private static void doV343Migration() {
|
||||
if (CustomCropsPlugin.get().getWorldManager().getWorldAdaptor() instanceof BukkitWorldAdaptor adaptor) {
|
||||
for (World world : Bukkit.getWorlds()) {
|
||||
CWorld temp = new CWorld(CustomCropsPlugin.getInstance().getWorldManager(), world);
|
||||
temp.setWorldSetting(WorldSetting.of(false,300,true, 1,true,2,true,2,false,false,false,28,-1,-1,-1, 0));
|
||||
adaptor.convertWorldFromV342toV343(temp, world);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void doV33Migration(YamlConfiguration config) {
|
||||
// do migration
|
||||
if (config.contains("mechanics.season.sync-season")) {
|
||||
config.set("mechanics.sync-season.enable", config.getBoolean("mechanics.season.sync-season.enable"));
|
||||
@@ -53,7 +69,7 @@ public class Migration {
|
||||
}
|
||||
|
||||
try {
|
||||
config.save(configFile);
|
||||
config.save(new File(CustomCropsPlugin.getInstance().getDataFolder(), "config.yml"));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
@@ -87,7 +103,7 @@ public class Migration {
|
||||
for (World world : Bukkit.getWorlds()) {
|
||||
CWorld temp = new CWorld(CustomCropsPlugin.getInstance().getWorldManager(), world);
|
||||
temp.setWorldSetting(WorldSetting.of(false,300,true, 1,true,2,true,2,false,false,false,28,-1,-1,-1, 0));
|
||||
adaptor.convertWorld(temp, world);
|
||||
adaptor.convertWorldFromV33toV34(temp, world);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,8 +25,8 @@ import net.momirealms.customcrops.api.mechanic.item.Pot;
|
||||
import net.momirealms.customcrops.api.mechanic.item.Sprinkler;
|
||||
import net.momirealms.customcrops.api.mechanic.misc.CRotation;
|
||||
import net.momirealms.customcrops.api.mechanic.requirement.State;
|
||||
import net.momirealms.customcrops.api.mechanic.world.ChunkCoordinate;
|
||||
import net.momirealms.customcrops.api.mechanic.world.BlockPos;
|
||||
import net.momirealms.customcrops.api.mechanic.world.ChunkPos;
|
||||
import net.momirealms.customcrops.api.mechanic.world.CustomCropsBlock;
|
||||
import net.momirealms.customcrops.api.mechanic.world.SimpleLocation;
|
||||
import net.momirealms.customcrops.api.mechanic.world.level.*;
|
||||
@@ -44,7 +44,7 @@ import java.util.concurrent.ThreadLocalRandom;
|
||||
public class CChunk implements CustomCropsChunk {
|
||||
|
||||
private transient CWorld cWorld;
|
||||
private final ChunkCoordinate chunkCoordinate;
|
||||
private final ChunkPos chunkPos;
|
||||
private final ConcurrentHashMap<Integer, CSection> loadedSections;
|
||||
private final PriorityQueue<TickTask> queue;
|
||||
private final Set<BlockPos> tickedBlocks;
|
||||
@@ -52,9 +52,9 @@ public class CChunk implements CustomCropsChunk {
|
||||
private int loadedSeconds;
|
||||
private int unloadedSeconds;
|
||||
|
||||
public CChunk(CWorld cWorld, ChunkCoordinate chunkCoordinate) {
|
||||
public CChunk(CWorld cWorld, ChunkPos chunkPos) {
|
||||
this.cWorld = cWorld;
|
||||
this.chunkCoordinate = chunkCoordinate;
|
||||
this.chunkPos = chunkPos;
|
||||
this.loadedSections = new ConcurrentHashMap<>(64);
|
||||
this.queue = new PriorityQueue<>();
|
||||
this.unloadedSeconds = 0;
|
||||
@@ -64,7 +64,7 @@ public class CChunk implements CustomCropsChunk {
|
||||
|
||||
public CChunk(
|
||||
CWorld cWorld,
|
||||
ChunkCoordinate chunkCoordinate,
|
||||
ChunkPos chunkPos,
|
||||
int loadedSeconds,
|
||||
long lastLoadedTime,
|
||||
ConcurrentHashMap<Integer, CSection> loadedSections,
|
||||
@@ -72,7 +72,7 @@ public class CChunk implements CustomCropsChunk {
|
||||
HashSet<BlockPos> tickedBlocks
|
||||
) {
|
||||
this.cWorld = cWorld;
|
||||
this.chunkCoordinate = chunkCoordinate;
|
||||
this.chunkPos = chunkPos;
|
||||
this.loadedSections = loadedSections;
|
||||
this.lastLoadedTime = lastLoadedTime;
|
||||
this.loadedSeconds = loadedSeconds;
|
||||
@@ -101,8 +101,13 @@ public class CChunk implements CustomCropsChunk {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChunkCoordinate getChunkCoordinate() {
|
||||
return chunkCoordinate;
|
||||
public CustomCropsRegion getCustomCropsRegion() {
|
||||
return cWorld.getLoadedRegionAt(chunkPos.getRegionPos()).orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChunkPos getChunkPos() {
|
||||
return chunkPos;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright (C) <2022> <XiaoMoMi>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.momirealms.customcrops.mechanic.world;
|
||||
|
||||
import net.momirealms.customcrops.api.mechanic.world.ChunkPos;
|
||||
import net.momirealms.customcrops.api.mechanic.world.RegionPos;
|
||||
import net.momirealms.customcrops.api.mechanic.world.level.CustomCropsRegion;
|
||||
import net.momirealms.customcrops.api.mechanic.world.level.CustomCropsWorld;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class CRegion implements CustomCropsRegion {
|
||||
|
||||
private final CWorld cWorld;
|
||||
private final RegionPos regionPos;
|
||||
private final ConcurrentHashMap<ChunkPos, byte[]> cachedChunkBytes;
|
||||
|
||||
public CRegion(CWorld cWorld, RegionPos regionPos) {
|
||||
this.cWorld = cWorld;
|
||||
this.regionPos = regionPos;
|
||||
this.cachedChunkBytes = new ConcurrentHashMap<>();
|
||||
}
|
||||
|
||||
public CRegion(CWorld cWorld, RegionPos regionPos, ConcurrentHashMap<ChunkPos, byte[]> cachedChunkBytes) {
|
||||
this.cWorld = cWorld;
|
||||
this.regionPos = regionPos;
|
||||
this.cachedChunkBytes = cachedChunkBytes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CustomCropsWorld getCustomCropsWorld() {
|
||||
return cWorld;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public byte[] getChunkBytes(ChunkPos pos) {
|
||||
return cachedChunkBytes.get(pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RegionPos getRegionPos() {
|
||||
return regionPos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeChunk(ChunkPos pos) {
|
||||
cachedChunkBytes.remove(pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveChunk(ChunkPos pos, byte[] data) {
|
||||
cachedChunkBytes.put(pos, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<ChunkPos, byte[]> getRegionDataToSave() {
|
||||
return new HashMap<>(cachedChunkBytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canPrune() {
|
||||
return cachedChunkBytes.size() == 0;
|
||||
}
|
||||
}
|
||||
@@ -26,20 +26,23 @@ import net.momirealms.customcrops.api.mechanic.item.Crop;
|
||||
import net.momirealms.customcrops.api.mechanic.item.Fertilizer;
|
||||
import net.momirealms.customcrops.api.mechanic.item.Pot;
|
||||
import net.momirealms.customcrops.api.mechanic.item.Sprinkler;
|
||||
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.RegionPos;
|
||||
import net.momirealms.customcrops.api.mechanic.world.SimpleLocation;
|
||||
import net.momirealms.customcrops.api.mechanic.world.level.*;
|
||||
import net.momirealms.customcrops.api.mechanic.world.season.Season;
|
||||
import net.momirealms.customcrops.api.scheduler.CancellableTask;
|
||||
import net.momirealms.customcrops.api.util.LogUtils;
|
||||
import net.momirealms.customcrops.utils.EventUtils;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.World;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@@ -47,21 +50,42 @@ public class CWorld implements CustomCropsWorld {
|
||||
|
||||
private final WorldManager worldManager;
|
||||
private final WeakReference<World> world;
|
||||
private final ConcurrentHashMap<ChunkCoordinate, CChunk> loadedChunks;
|
||||
private final ConcurrentHashMap<ChunkCoordinate, CChunk> lazyChunks;
|
||||
private final ConcurrentHashMap<ChunkPos, CChunk> loadedChunks;
|
||||
private final ConcurrentHashMap<ChunkPos, CChunk> lazyChunks;
|
||||
private final ConcurrentHashMap<RegionPos, CRegion> loadedRegions;
|
||||
private WorldSetting setting;
|
||||
private WorldInfoData infoData;
|
||||
private final String worldName;
|
||||
private CancellableTask worldTask;
|
||||
private int currentMinecraftDay;
|
||||
private int regionTimer;
|
||||
|
||||
public CWorld(WorldManager worldManager, World world) {
|
||||
this.world = new WeakReference<>(world);
|
||||
this.worldManager = worldManager;
|
||||
this.loadedChunks = new ConcurrentHashMap<>();
|
||||
this.lazyChunks = new ConcurrentHashMap<>();
|
||||
this.loadedRegions = new ConcurrentHashMap<>();
|
||||
this.worldName = world.getName();
|
||||
this.currentMinecraftDay = (int) (world.getFullTime() / 24000);
|
||||
this.regionTimer = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save() {
|
||||
long time1 = System.currentTimeMillis();
|
||||
worldManager.saveInfoData(this);
|
||||
for (CChunk chunk : loadedChunks.values()) {
|
||||
worldManager.saveChunkToCachedRegion(chunk);
|
||||
}
|
||||
for (CChunk chunk : lazyChunks.values()) {
|
||||
worldManager.saveChunkToCachedRegion(chunk);
|
||||
}
|
||||
for (CRegion region : loadedRegions.values()) {
|
||||
worldManager.saveRegionToFile(region);
|
||||
}
|
||||
long time2 = System.currentTimeMillis();
|
||||
CustomCropsPlugin.get().debug("Took " + (time2-time1) + "ms to save world " + worldName + ". Saved " + (lazyChunks.size() + loadedChunks.size()) + " chunks.");
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -77,8 +101,8 @@ public class CWorld implements CustomCropsWorld {
|
||||
}
|
||||
|
||||
private void timer() {
|
||||
ArrayList<Pair<ChunkCoordinate, CChunk>> chunksToSave = new ArrayList<>();
|
||||
for (Map.Entry<ChunkCoordinate, CChunk> lazyEntry : lazyChunks.entrySet()) {
|
||||
ArrayList<Pair<ChunkPos, CChunk>> chunksToSave = new ArrayList<>();
|
||||
for (Map.Entry<ChunkPos, CChunk> lazyEntry : lazyChunks.entrySet()) {
|
||||
CChunk chunk = lazyEntry.getValue();
|
||||
int sec = chunk.getUnloadedSeconds() + 1;
|
||||
if (sec >= 30) {
|
||||
@@ -87,9 +111,9 @@ public class CWorld implements CustomCropsWorld {
|
||||
chunk.setUnloadedSeconds(sec);
|
||||
}
|
||||
}
|
||||
for (Pair<ChunkCoordinate, CChunk> pair : chunksToSave) {
|
||||
for (Pair<ChunkPos, CChunk> pair : chunksToSave) {
|
||||
lazyChunks.remove(pair.left());
|
||||
worldManager.saveChunkToFile(pair.right());
|
||||
worldManager.saveChunkToCachedRegion(pair.right());
|
||||
}
|
||||
if (setting.isAutoSeasonChange()) {
|
||||
this.updateSeasonAndDate();
|
||||
@@ -99,6 +123,22 @@ public class CWorld implements CustomCropsWorld {
|
||||
chunk.secondTimer();
|
||||
}
|
||||
}
|
||||
|
||||
// timer check to unload regions
|
||||
this.regionTimer++;
|
||||
if (this.regionTimer >= 600) {
|
||||
this.regionTimer = 0;
|
||||
ArrayList<RegionPos> removed = new ArrayList<>();
|
||||
for (Map.Entry<RegionPos, CRegion> entry : loadedRegions.entrySet()) {
|
||||
if (isRegionNoLongerLoaded(entry.getKey())) {
|
||||
worldManager.saveRegionToFile(entry.getValue());
|
||||
removed.add(entry.getKey());
|
||||
}
|
||||
}
|
||||
for (RegionPos pos : removed) {
|
||||
loadedRegions.remove(pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateSeasonAndDate() {
|
||||
@@ -130,8 +170,8 @@ public class CWorld implements CustomCropsWorld {
|
||||
}
|
||||
|
||||
@Override
|
||||
public CustomCropsChunk removeLazyChunkAt(ChunkCoordinate chunkCoordinate) {
|
||||
return lazyChunks.remove(chunkCoordinate);
|
||||
public CustomCropsChunk removeLazyChunkAt(ChunkPos chunkPos) {
|
||||
return lazyChunks.remove(chunkPos);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -161,31 +201,51 @@ public class CWorld implements CustomCropsWorld {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isChunkLoaded(ChunkCoordinate chunkCoordinate) {
|
||||
return loadedChunks.containsKey(chunkCoordinate);
|
||||
public boolean isChunkLoaded(ChunkPos chunkPos) {
|
||||
return loadedChunks.containsKey(chunkPos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<CustomCropsChunk> getChunkAt(ChunkCoordinate chunkCoordinate) {
|
||||
return Optional.ofNullable(createOrGetChunk(chunkCoordinate));
|
||||
public boolean isRegionLoaded(RegionPos regionPos) {
|
||||
return loadedRegions.containsKey(regionPos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<CustomCropsChunk> getLoadedChunkAt(ChunkPos chunkPos) {
|
||||
return Optional.ofNullable(createOrGetChunk(chunkPos));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<CustomCropsRegion> getLoadedRegionAt(RegionPos regionPos) {
|
||||
return Optional.ofNullable(loadedRegions.get(regionPos));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadRegion(CustomCropsRegion region) {
|
||||
RegionPos regionPos = region.getRegionPos();
|
||||
if (loadedRegions.containsKey(regionPos)) {
|
||||
LogUtils.warn("Invalid operation: Loaded region is loaded again." + regionPos);
|
||||
return;
|
||||
}
|
||||
loadedRegions.put(regionPos, (CRegion) region);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadChunk(CustomCropsChunk chunk) {
|
||||
ChunkCoordinate chunkCoordinate = chunk.getChunkCoordinate();
|
||||
if (loadedChunks.containsKey(chunkCoordinate)) {
|
||||
LogUtils.warn("Invalid operation: Loaded chunk is loaded again." + chunkCoordinate);
|
||||
ChunkPos chunkPos = chunk.getChunkPos();
|
||||
if (loadedChunks.containsKey(chunkPos)) {
|
||||
LogUtils.warn("Invalid operation: Loaded chunk is loaded again." + chunkPos);
|
||||
return;
|
||||
}
|
||||
loadedChunks.put(chunkCoordinate, (CChunk) chunk);
|
||||
loadedChunks.put(chunkPos, (CChunk) chunk);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unloadChunk(ChunkCoordinate chunkCoordinate) {
|
||||
CChunk chunk = loadedChunks.remove(chunkCoordinate);
|
||||
public void unloadChunk(ChunkPos chunkPos) {
|
||||
CChunk chunk = loadedChunks.remove(chunkPos);
|
||||
if (chunk != null) {
|
||||
chunk.updateLastLoadedTime();
|
||||
lazyChunks.put(chunkCoordinate, chunk);
|
||||
lazyChunks.put(chunkPos, chunk);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -256,7 +316,7 @@ public class CWorld implements CustomCropsWorld {
|
||||
|
||||
@Override
|
||||
public void addWaterToSprinkler(Sprinkler sprinkler, SimpleLocation location, int amount) {
|
||||
Optional<CustomCropsChunk> chunk = getChunkAt(location.getChunkCoordinate());
|
||||
Optional<CustomCropsChunk> chunk = getLoadedChunkAt(location.getChunkCoordinate());
|
||||
if (chunk.isPresent()) {
|
||||
chunk.get().addWaterToSprinkler(sprinkler, location, amount);
|
||||
} else {
|
||||
@@ -266,7 +326,7 @@ public class CWorld implements CustomCropsWorld {
|
||||
|
||||
@Override
|
||||
public void addFertilizerToPot(Pot pot, Fertilizer fertilizer, SimpleLocation location) {
|
||||
Optional<CustomCropsChunk> chunk = getChunkAt(location.getChunkCoordinate());
|
||||
Optional<CustomCropsChunk> chunk = getLoadedChunkAt(location.getChunkCoordinate());
|
||||
if (chunk.isPresent()) {
|
||||
chunk.get().addFertilizerToPot(pot, fertilizer, location);
|
||||
} else {
|
||||
@@ -276,7 +336,7 @@ public class CWorld implements CustomCropsWorld {
|
||||
|
||||
@Override
|
||||
public void addWaterToPot(Pot pot, SimpleLocation location, int amount) {
|
||||
Optional<CustomCropsChunk> chunk = getChunkAt(location.getChunkCoordinate());
|
||||
Optional<CustomCropsChunk> chunk = getLoadedChunkAt(location.getChunkCoordinate());
|
||||
if (chunk.isPresent()) {
|
||||
chunk.get().addWaterToPot(pot, location, amount);
|
||||
} else {
|
||||
@@ -286,7 +346,7 @@ public class CWorld implements CustomCropsWorld {
|
||||
|
||||
@Override
|
||||
public void addPotAt(WorldPot pot, SimpleLocation location) {
|
||||
Optional<CustomCropsChunk> chunk = getChunkAt(location.getChunkCoordinate());
|
||||
Optional<CustomCropsChunk> chunk = getLoadedChunkAt(location.getChunkCoordinate());
|
||||
if (chunk.isPresent()) {
|
||||
chunk.get().addPotAt(pot, location);
|
||||
} else {
|
||||
@@ -296,7 +356,7 @@ public class CWorld implements CustomCropsWorld {
|
||||
|
||||
@Override
|
||||
public void addSprinklerAt(WorldSprinkler sprinkler, SimpleLocation location) {
|
||||
Optional<CustomCropsChunk> chunk = getChunkAt(location.getChunkCoordinate());
|
||||
Optional<CustomCropsChunk> chunk = getLoadedChunkAt(location.getChunkCoordinate());
|
||||
if (chunk.isPresent()) {
|
||||
chunk.get().addSprinklerAt(sprinkler, location);
|
||||
} else {
|
||||
@@ -306,7 +366,7 @@ public class CWorld implements CustomCropsWorld {
|
||||
|
||||
@Override
|
||||
public void addCropAt(WorldCrop crop, SimpleLocation location) {
|
||||
Optional<CustomCropsChunk> chunk = getChunkAt(location.getChunkCoordinate());
|
||||
Optional<CustomCropsChunk> chunk = getLoadedChunkAt(location.getChunkCoordinate());
|
||||
if (chunk.isPresent()) {
|
||||
chunk.get().addCropAt(crop, location);
|
||||
} else {
|
||||
@@ -316,7 +376,7 @@ public class CWorld implements CustomCropsWorld {
|
||||
|
||||
@Override
|
||||
public void addPointToCrop(Crop crop, SimpleLocation location, int points) {
|
||||
Optional<CustomCropsChunk> chunk = getChunkAt(location.getChunkCoordinate());
|
||||
Optional<CustomCropsChunk> chunk = getLoadedChunkAt(location.getChunkCoordinate());
|
||||
if (chunk.isPresent()) {
|
||||
chunk.get().addPointToCrop(crop, location, points);
|
||||
} else {
|
||||
@@ -326,7 +386,7 @@ public class CWorld implements CustomCropsWorld {
|
||||
|
||||
@Override
|
||||
public void addGlassAt(WorldGlass glass, SimpleLocation location) {
|
||||
Optional<CustomCropsChunk> chunk = getChunkAt(location.getChunkCoordinate());
|
||||
Optional<CustomCropsChunk> chunk = getLoadedChunkAt(location.getChunkCoordinate());
|
||||
if (chunk.isPresent()) {
|
||||
chunk.get().addGlassAt(glass, location);
|
||||
} else {
|
||||
@@ -336,7 +396,7 @@ public class CWorld implements CustomCropsWorld {
|
||||
|
||||
@Override
|
||||
public void addScarecrowAt(WorldScarecrow scarecrow, SimpleLocation location) {
|
||||
Optional<CustomCropsChunk> chunk = getChunkAt(location.getChunkCoordinate());
|
||||
Optional<CustomCropsChunk> chunk = getLoadedChunkAt(location.getChunkCoordinate());
|
||||
if (chunk.isPresent()) {
|
||||
chunk.get().addScarecrowAt(scarecrow, location);
|
||||
} else {
|
||||
@@ -346,7 +406,7 @@ public class CWorld implements CustomCropsWorld {
|
||||
|
||||
@Override
|
||||
public void removeSprinklerAt(SimpleLocation location) {
|
||||
Optional<CustomCropsChunk> chunk = getChunkAt(location.getChunkCoordinate());
|
||||
Optional<CustomCropsChunk> chunk = getLoadedChunkAt(location.getChunkCoordinate());
|
||||
if (chunk.isPresent()) {
|
||||
chunk.get().removeSprinklerAt(location);
|
||||
} else {
|
||||
@@ -356,7 +416,7 @@ public class CWorld implements CustomCropsWorld {
|
||||
|
||||
@Override
|
||||
public void removePotAt(SimpleLocation location) {
|
||||
Optional<CustomCropsChunk> chunk = getChunkAt(location.getChunkCoordinate());
|
||||
Optional<CustomCropsChunk> chunk = getLoadedChunkAt(location.getChunkCoordinate());
|
||||
if (chunk.isPresent()) {
|
||||
chunk.get().removePotAt(location);
|
||||
} else {
|
||||
@@ -366,7 +426,7 @@ public class CWorld implements CustomCropsWorld {
|
||||
|
||||
@Override
|
||||
public void removeCropAt(SimpleLocation location) {
|
||||
Optional<CustomCropsChunk> chunk = getChunkAt(location.getChunkCoordinate());
|
||||
Optional<CustomCropsChunk> chunk = getLoadedChunkAt(location.getChunkCoordinate());
|
||||
if (chunk.isPresent()) {
|
||||
chunk.get().removeCropAt(location);
|
||||
} else {
|
||||
@@ -376,7 +436,7 @@ public class CWorld implements CustomCropsWorld {
|
||||
|
||||
@Override
|
||||
public void removeGlassAt(SimpleLocation location) {
|
||||
Optional<CustomCropsChunk> chunk = getChunkAt(location.getChunkCoordinate());
|
||||
Optional<CustomCropsChunk> chunk = getLoadedChunkAt(location.getChunkCoordinate());
|
||||
if (chunk.isPresent()) {
|
||||
chunk.get().removeGlassAt(location);
|
||||
} else {
|
||||
@@ -386,7 +446,7 @@ public class CWorld implements CustomCropsWorld {
|
||||
|
||||
@Override
|
||||
public void removeScarecrowAt(SimpleLocation location) {
|
||||
Optional<CustomCropsChunk> chunk = getChunkAt(location.getChunkCoordinate());
|
||||
Optional<CustomCropsChunk> chunk = getLoadedChunkAt(location.getChunkCoordinate());
|
||||
if (chunk.isPresent()) {
|
||||
chunk.get().removeScarecrowAt(location);
|
||||
} else {
|
||||
@@ -396,7 +456,7 @@ public class CWorld implements CustomCropsWorld {
|
||||
|
||||
@Override
|
||||
public CustomCropsBlock removeAnythingAt(SimpleLocation location) {
|
||||
Optional<CustomCropsChunk> chunk = getChunkAt(location.getChunkCoordinate());
|
||||
Optional<CustomCropsChunk> chunk = getLoadedChunkAt(location.getChunkCoordinate());
|
||||
if (chunk.isPresent()) {
|
||||
return chunk.get().removeBlockAt(location);
|
||||
} else {
|
||||
@@ -406,33 +466,35 @@ public class CWorld implements CustomCropsWorld {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private CustomCropsChunk createOrGetChunk(ChunkCoordinate chunkCoordinate) {
|
||||
private CustomCropsChunk createOrGetChunk(ChunkPos chunkPos) {
|
||||
World bukkitWorld = world.get();
|
||||
if (bukkitWorld == null)
|
||||
return null;
|
||||
CChunk chunk = loadedChunks.get(chunkCoordinate);
|
||||
CChunk chunk = loadedChunks.get(chunkPos);
|
||||
if (chunk != null) {
|
||||
return chunk;
|
||||
}
|
||||
if (bukkitWorld.isChunkLoaded(chunkCoordinate.x(), chunkCoordinate.z())) {
|
||||
chunk = new CChunk(this, chunkCoordinate);
|
||||
// is a loaded chunk, but it doesn't have customcrops data
|
||||
if (bukkitWorld.isChunkLoaded(chunkPos.x(), chunkPos.z())) {
|
||||
chunk = new CChunk(this, chunkPos);
|
||||
loadChunk(chunk);
|
||||
return chunk;
|
||||
} else {
|
||||
if (bukkitWorld.isChunkGenerated(chunkCoordinate.x(), chunkCoordinate.z())) {
|
||||
Chunk bukkitChunk = bukkitWorld.getChunkAt(chunkCoordinate.x(), chunkCoordinate.z());
|
||||
worldManager.handleChunkLoad(bukkitChunk);
|
||||
chunk = loadedChunks.get(chunkCoordinate);
|
||||
return Objects.requireNonNullElseGet(chunk, () -> new CChunk(this, chunkCoordinate));
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
// is an unloaded chunk, but has been generated
|
||||
// if (bukkitWorld.isChunkGenerated(chunkPos.x(), chunkPos.z())) {
|
||||
// Chunk bukkitChunk = bukkitWorld.getChunkAt(chunkPos.x(), chunkPos.z());
|
||||
// worldManager.handleChunkLoad(bukkitChunk);
|
||||
// chunk = loadedChunks.get(chunkPos);
|
||||
// return Objects.requireNonNullElseGet(chunk, () -> new CChunk(this, chunkPos));
|
||||
// } else {
|
||||
return null;
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPotReachLimit(SimpleLocation location) {
|
||||
Optional<CustomCropsChunk> chunk = getChunkAt(location.getChunkCoordinate());
|
||||
Optional<CustomCropsChunk> chunk = getLoadedChunkAt(location.getChunkCoordinate());
|
||||
if (chunk.isEmpty()) {
|
||||
LogUtils.warn("Invalid operation: Querying pot amount from a not generated chunk");
|
||||
return true;
|
||||
@@ -443,7 +505,7 @@ public class CWorld implements CustomCropsWorld {
|
||||
|
||||
@Override
|
||||
public boolean isCropReachLimit(SimpleLocation location) {
|
||||
Optional<CustomCropsChunk> chunk = getChunkAt(location.getChunkCoordinate());
|
||||
Optional<CustomCropsChunk> chunk = getLoadedChunkAt(location.getChunkCoordinate());
|
||||
if (chunk.isEmpty()) {
|
||||
LogUtils.warn("Invalid operation: Querying crop amount from a not generated chunk");
|
||||
return true;
|
||||
@@ -454,7 +516,7 @@ public class CWorld implements CustomCropsWorld {
|
||||
|
||||
@Override
|
||||
public boolean isSprinklerReachLimit(SimpleLocation location) {
|
||||
Optional<CustomCropsChunk> chunk = getChunkAt(location.getChunkCoordinate());
|
||||
Optional<CustomCropsChunk> chunk = getLoadedChunkAt(location.getChunkCoordinate());
|
||||
if (chunk.isEmpty()) {
|
||||
LogUtils.warn("Invalid operation: Querying sprinkler amount from a not generated chunk");
|
||||
return true;
|
||||
@@ -463,10 +525,18 @@ public class CWorld implements CustomCropsWorld {
|
||||
return chunk.get().getSprinklerAmount() >= setting.getSprinklerPerChunk();
|
||||
}
|
||||
|
||||
public Collection<CChunk> getAllChunksToSave() {
|
||||
ArrayList<CChunk> chunks = new ArrayList<>();
|
||||
chunks.addAll(lazyChunks.values());
|
||||
chunks.addAll(loadedChunks.values());
|
||||
return chunks;
|
||||
private boolean isRegionNoLongerLoaded(RegionPos region) {
|
||||
World w = world.get();
|
||||
if (w != null) {
|
||||
for (int chunkX = region.x() * 32; chunkX < region.x() * 32 + 32; chunkX++) {
|
||||
for (int chunkZ = region.z() * 32; chunkZ < region.z() * 32 + 32; chunkZ++) {
|
||||
// if a chunk is unloaded, then it should not be in the loaded chunks map
|
||||
if (w.isChunkLoaded(chunkX, chunkZ) || lazyChunks.containsKey(ChunkPos.of(chunkX, chunkZ))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,4 +66,8 @@ public class SerializableChunk {
|
||||
public int[] getTicked() {
|
||||
return ticked;
|
||||
}
|
||||
|
||||
public boolean canPrune() {
|
||||
return sections.size() == 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ import net.momirealms.customcrops.api.CustomCropsPlugin;
|
||||
import net.momirealms.customcrops.api.manager.WorldManager;
|
||||
import net.momirealms.customcrops.api.mechanic.item.*;
|
||||
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.SimpleLocation;
|
||||
import net.momirealms.customcrops.api.mechanic.world.level.*;
|
||||
@@ -39,6 +39,7 @@ import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.world.ChunkLoadEvent;
|
||||
import org.bukkit.event.world.ChunkUnloadEvent;
|
||||
import org.bukkit.event.world.WorldSaveEvent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.*;
|
||||
@@ -404,7 +405,7 @@ public class WorldManagerImpl implements WorldManager, Listener {
|
||||
public void removeGlassAt(@NotNull SimpleLocation location) {
|
||||
CWorld cWorld = loadedWorlds.get(location.getWorldName());
|
||||
if (cWorld == null) {
|
||||
LogUtils.warn("Unsupported operation: Removing crop from unloaded world " + location);
|
||||
LogUtils.warn("Unsupported operation: Removing glass from unloaded world " + location);
|
||||
return;
|
||||
}
|
||||
cWorld.removeGlassAt(location);
|
||||
@@ -463,20 +464,20 @@ public class WorldManagerImpl implements WorldManager, Listener {
|
||||
return;
|
||||
|
||||
CustomCropsWorld customCropsWorld = optional.get();
|
||||
ChunkCoordinate chunkCoordinate = ChunkCoordinate.getByBukkitChunk(bukkitChunk);
|
||||
ChunkPos chunkPos = ChunkPos.getByBukkitChunk(bukkitChunk);
|
||||
|
||||
if (customCropsWorld.isChunkLoaded(chunkCoordinate)) {
|
||||
if (customCropsWorld.isChunkLoaded(chunkPos)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// load chunks
|
||||
this.worldAdaptor.loadDynamicData(customCropsWorld, chunkCoordinate);
|
||||
this.worldAdaptor.loadChunkData(customCropsWorld, chunkPos);
|
||||
|
||||
// offline grow part
|
||||
if (!customCropsWorld.getWorldSetting().isOfflineGrow()) return;
|
||||
|
||||
// If chunk data not exists, return
|
||||
Optional<CustomCropsChunk> optionalChunk = customCropsWorld.getChunkAt(chunkCoordinate);
|
||||
Optional<CustomCropsChunk> optionalChunk = customCropsWorld.getLoadedChunkAt(chunkPos);
|
||||
if (optionalChunk.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
@@ -493,9 +494,9 @@ public class WorldManagerImpl implements WorldManager, Listener {
|
||||
return;
|
||||
|
||||
CustomCropsWorld customCropsWorld = optional.get();
|
||||
ChunkCoordinate chunkCoordinate = ChunkCoordinate.getByBukkitChunk(bukkitChunk);
|
||||
ChunkPos chunkPos = ChunkPos.getByBukkitChunk(bukkitChunk);
|
||||
|
||||
this.worldAdaptor.unloadDynamicData(customCropsWorld, chunkCoordinate);
|
||||
this.worldAdaptor.unloadChunkData(customCropsWorld, chunkPos);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
@@ -509,12 +510,22 @@ public class WorldManagerImpl implements WorldManager, Listener {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveChunkToFile(CustomCropsChunk chunk) {
|
||||
this.worldAdaptor.saveDynamicData(chunk.getCustomCropsWorld(), chunk);
|
||||
public void saveChunkToCachedRegion(CustomCropsChunk chunk) {
|
||||
this.worldAdaptor.saveChunkToCachedRegion(chunk);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveRegionToFile(CustomCropsRegion region) {
|
||||
this.worldAdaptor.saveRegion(region);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractWorldAdaptor getWorldAdaptor() {
|
||||
return worldAdaptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveInfoData(CustomCropsWorld customCropsWorld) {
|
||||
this.worldAdaptor.saveInfoData(customCropsWorld);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ import net.momirealms.customcrops.api.manager.ConfigManager;
|
||||
import net.momirealms.customcrops.api.manager.WorldManager;
|
||||
import net.momirealms.customcrops.api.mechanic.world.*;
|
||||
import net.momirealms.customcrops.api.mechanic.world.level.CustomCropsChunk;
|
||||
import net.momirealms.customcrops.api.mechanic.world.level.CustomCropsRegion;
|
||||
import net.momirealms.customcrops.api.mechanic.world.level.CustomCropsWorld;
|
||||
import net.momirealms.customcrops.api.mechanic.world.level.WorldInfoData;
|
||||
import net.momirealms.customcrops.api.mechanic.world.season.Season;
|
||||
@@ -47,6 +48,7 @@ import org.bukkit.World;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.world.WorldLoadEvent;
|
||||
import org.bukkit.event.world.WorldSaveEvent;
|
||||
import org.bukkit.event.world.WorldUnloadEvent;
|
||||
import org.bukkit.persistence.PersistentDataType;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -70,6 +72,15 @@ public class BukkitWorldAdaptor extends AbstractWorldAdaptor {
|
||||
|
||||
@Override
|
||||
public void unload(CustomCropsWorld customCropsWorld) {
|
||||
World world = customCropsWorld.getWorld();
|
||||
if (world != null) {
|
||||
new File(world.getWorldFolder(), "customcrops").mkdir();
|
||||
customCropsWorld.save();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveInfoData(CustomCropsWorld customCropsWorld) {
|
||||
CWorld cWorld = (CWorld) customCropsWorld;
|
||||
World world = cWorld.getWorld();
|
||||
if (world == null) {
|
||||
@@ -77,15 +88,8 @@ public class BukkitWorldAdaptor extends AbstractWorldAdaptor {
|
||||
return;
|
||||
}
|
||||
|
||||
// save world data into psd
|
||||
world.getPersistentDataContainer().set(key, PersistentDataType.STRING,
|
||||
gson.toJson(cWorld.getInfoData()));
|
||||
|
||||
new File(world.getWorldFolder(), "customcrops").mkdir();
|
||||
|
||||
for (CChunk chunk : cWorld.getAllChunksToSave()) {
|
||||
saveDynamicData(cWorld, chunk);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -102,7 +106,7 @@ public class BukkitWorldAdaptor extends AbstractWorldAdaptor {
|
||||
|
||||
// try converting legacy worlds
|
||||
if (ConfigManager.convertWorldOnLoad()) {
|
||||
convertWorld(cWorld, world);
|
||||
convertWorldFromV33toV34(cWorld, world);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -113,7 +117,7 @@ public class BukkitWorldAdaptor extends AbstractWorldAdaptor {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadDynamicData(CustomCropsWorld customCropsWorld, ChunkCoordinate chunkCoordinate) {
|
||||
public void loadChunkData(CustomCropsWorld customCropsWorld, ChunkPos chunkPos) {
|
||||
CWorld cWorld = (CWorld) customCropsWorld;
|
||||
World world = cWorld.getWorld();
|
||||
if (world == null) {
|
||||
@@ -121,35 +125,81 @@ public class BukkitWorldAdaptor extends AbstractWorldAdaptor {
|
||||
return;
|
||||
}
|
||||
|
||||
long time1 = System.currentTimeMillis();
|
||||
// load lazy chunks firstly
|
||||
CustomCropsChunk lazyChunk = customCropsWorld.removeLazyChunkAt(chunkCoordinate);
|
||||
CustomCropsChunk lazyChunk = cWorld.removeLazyChunkAt(chunkPos);
|
||||
if (lazyChunk != null) {
|
||||
CChunk cChunk = (CChunk) lazyChunk;
|
||||
cChunk.setUnloadedSeconds(0);
|
||||
cWorld.loadChunk(cChunk);
|
||||
long time2 = System.currentTimeMillis();
|
||||
CustomCropsPlugin.get().debug("Took " + (time2-time1) + "ms to load chunk " + chunkPos + " from lazy chunks");
|
||||
return;
|
||||
}
|
||||
// create or get chunk files
|
||||
File data = getChunkDataFilePath(world, chunkCoordinate);
|
||||
if (!data.exists())
|
||||
|
||||
// check if region is loaded, load if not loaded
|
||||
RegionPos regionPos = RegionPos.getByChunkPos(chunkPos);
|
||||
Optional<CustomCropsRegion> optionalRegion = cWorld.getLoadedRegionAt(regionPos);
|
||||
if (optionalRegion.isPresent()) {
|
||||
CustomCropsRegion region = optionalRegion.get();
|
||||
byte[] bytes = region.getChunkBytes(chunkPos);
|
||||
if (bytes != null) {
|
||||
try {
|
||||
DataInputStream dataStream = new DataInputStream(new ByteArrayInputStream(bytes));
|
||||
CChunk chunk = deserializeChunk(cWorld, dataStream);
|
||||
dataStream.close();
|
||||
cWorld.loadChunk(chunk);
|
||||
long time2 = System.currentTimeMillis();
|
||||
CustomCropsPlugin.get().debug("Took " + (time2-time1) + "ms to load chunk " + chunkPos + " from cached region");
|
||||
} catch (IOException e) {
|
||||
LogUtils.severe("Failed to load CustomCrops data at " + chunkPos);
|
||||
e.printStackTrace();
|
||||
region.removeChunk(chunkPos);
|
||||
}
|
||||
}
|
||||
return;
|
||||
// load chunk from local files
|
||||
long time1 = System.currentTimeMillis();
|
||||
try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(getChunkDataFilePath(world, chunkCoordinate)))) {
|
||||
}
|
||||
|
||||
// if region file not exist, create one
|
||||
File data = getRegionDataFilePath(world, regionPos);
|
||||
if (!data.exists()) {
|
||||
cWorld.loadRegion(new CRegion(cWorld, regionPos));
|
||||
return;
|
||||
}
|
||||
|
||||
// load region from local files
|
||||
try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(data))) {
|
||||
DataInputStream dataStream = new DataInputStream(bis);
|
||||
CChunk chunk = deserialize(cWorld, dataStream);
|
||||
CRegion region = deserializeRegion(cWorld, dataStream);
|
||||
dataStream.close();
|
||||
cWorld.loadChunk(chunk);
|
||||
long time2 = System.currentTimeMillis();
|
||||
CustomCropsPlugin.get().debug("Took " + (time2-time1) + "ms to load chunk " + chunkCoordinate);
|
||||
cWorld.loadRegion(region);
|
||||
byte[] bytes = region.getChunkBytes(chunkPos);
|
||||
if (bytes != null) {
|
||||
try {
|
||||
DataInputStream chunkStream = new DataInputStream(new ByteArrayInputStream(bytes));
|
||||
CChunk chunk = deserializeChunk(cWorld, chunkStream);
|
||||
chunkStream.close();
|
||||
cWorld.loadChunk(chunk);
|
||||
long time2 = System.currentTimeMillis();
|
||||
CustomCropsPlugin.get().debug("Took " + (time2-time1) + "ms to load chunk " + chunkPos);
|
||||
} catch (IOException e) {
|
||||
LogUtils.severe("Failed to load CustomCrops data at " + chunkPos + ". Deleting corrupted chunk.");
|
||||
e.printStackTrace();
|
||||
region.removeChunk(chunkPos);
|
||||
}
|
||||
} else {
|
||||
long time2 = System.currentTimeMillis();
|
||||
CustomCropsPlugin.get().debug("Took " + (time2-time1) + "ms to load region " + regionPos);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
LogUtils.severe("Failed to load CustomCrops data at " + chunkCoordinate);
|
||||
LogUtils.severe("Failed to load CustomCrops region data at " + chunkPos + ". Deleting corrupted region.");
|
||||
e.printStackTrace();
|
||||
data.delete();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unloadDynamicData(CustomCropsWorld ccWorld, ChunkCoordinate chunkCoordinate) {
|
||||
public void unloadChunkData(CustomCropsWorld ccWorld, ChunkPos chunkPos) {
|
||||
CWorld cWorld = (CWorld) ccWorld;
|
||||
World world = cWorld.getWorld();
|
||||
if (world == null) {
|
||||
@@ -157,18 +207,35 @@ public class BukkitWorldAdaptor extends AbstractWorldAdaptor {
|
||||
return;
|
||||
}
|
||||
|
||||
cWorld.unloadChunk(chunkCoordinate);
|
||||
cWorld.unloadChunk(chunkPos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveDynamicData(CustomCropsWorld ccWorld, CustomCropsChunk chunk) {
|
||||
public void saveChunkToCachedRegion(CustomCropsChunk customCropsChunk) {
|
||||
CustomCropsRegion customCropsRegion = customCropsChunk.getCustomCropsRegion();
|
||||
SerializableChunk serializableChunk = toSerializableChunk((CChunk) customCropsChunk);
|
||||
if (serializableChunk.canPrune()) {
|
||||
customCropsRegion.removeChunk(customCropsChunk.getChunkPos());
|
||||
} else {
|
||||
customCropsRegion.saveChunk(customCropsChunk.getChunkPos(), serialize(serializableChunk));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveRegion(CustomCropsRegion customCropsRegion) {
|
||||
File file = getRegionDataFilePath(customCropsRegion.getCustomCropsWorld().getWorld(), customCropsRegion.getRegionPos());
|
||||
if (customCropsRegion.canPrune()) {
|
||||
file.delete();
|
||||
return;
|
||||
}
|
||||
|
||||
long time1 = System.currentTimeMillis();
|
||||
try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(getChunkDataFilePath(ccWorld.getWorld(), chunk.getChunkCoordinate())))) {
|
||||
bos.write(serialize((CChunk) chunk));
|
||||
try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file))) {
|
||||
bos.write(serialize(customCropsRegion));
|
||||
long time2 = System.currentTimeMillis();
|
||||
CustomCropsPlugin.get().debug("Took " + (time2-time1) + "ms to save chunk " + chunk.getChunkCoordinate());
|
||||
CustomCropsPlugin.get().debug("Took " + (time2-time1) + "ms to save region " + customCropsRegion.getRegionPos());
|
||||
} catch (IOException e) {
|
||||
LogUtils.severe("Failed to save CustomCrops data.");
|
||||
LogUtils.severe("Failed to save CustomCrops region data." + customCropsRegion.getRegionPos());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
@@ -186,15 +253,35 @@ public class BukkitWorldAdaptor extends AbstractWorldAdaptor {
|
||||
worldManager.unloadWorld(event.getWorld());
|
||||
}
|
||||
|
||||
private String getChunkDataFile(ChunkCoordinate chunkCoordinate) {
|
||||
return chunkCoordinate.x() + "," + chunkCoordinate.z() + ".ccd";
|
||||
@EventHandler (ignoreCancelled = true)
|
||||
public void onWorldSave(WorldSaveEvent event) {
|
||||
World world = event.getWorld();
|
||||
worldManager.getCustomCropsWorld(world).ifPresent(CustomCropsWorld::save);
|
||||
}
|
||||
|
||||
private File getChunkDataFilePath(World world, ChunkCoordinate chunkCoordinate) {
|
||||
@Deprecated
|
||||
private String getChunkDataFile(ChunkPos chunkPos) {
|
||||
return chunkPos.x() + "," + chunkPos.z() + ".ccd";
|
||||
}
|
||||
|
||||
private String getRegionDataFile(RegionPos regionPos) {
|
||||
return "r." + regionPos.x() + "." + regionPos.z() + ".mcc";
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
private File getChunkDataFilePath(World world, ChunkPos chunkPos) {
|
||||
if (worldFolder.isEmpty()) {
|
||||
return new File(world.getWorldFolder(), "customcrops" + File.separator + getChunkDataFile(chunkCoordinate));
|
||||
return new File(world.getWorldFolder(), "customcrops" + File.separator + getChunkDataFile(chunkPos));
|
||||
} else {
|
||||
return new File(worldFolder, world.getName() + File.separator + "customcrops" + File.separator + getChunkDataFile(chunkCoordinate));
|
||||
return new File(worldFolder, world.getName() + File.separator + "customcrops" + File.separator + getChunkDataFile(chunkPos));
|
||||
}
|
||||
}
|
||||
|
||||
private File getRegionDataFilePath(World world, RegionPos regionPos) {
|
||||
if (worldFolder.isEmpty()) {
|
||||
return new File(world.getWorldFolder(), "customcrops" + File.separator + getRegionDataFile(regionPos));
|
||||
} else {
|
||||
return new File(worldFolder, world.getName() + File.separator + "customcrops" + File.separator + getRegionDataFile(regionPos));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -202,12 +289,51 @@ public class BukkitWorldAdaptor extends AbstractWorldAdaptor {
|
||||
this.worldFolder = folder;
|
||||
}
|
||||
|
||||
public byte[] serialize(CChunk chunk) {
|
||||
public byte[] serialize(CustomCropsRegion region) {
|
||||
ByteArrayOutputStream outByteStream = new ByteArrayOutputStream();
|
||||
DataOutputStream outStream = new DataOutputStream(outByteStream);
|
||||
SerializableChunk serializableChunk = toSerializableChunk(chunk);
|
||||
try {
|
||||
outStream.writeByte(version);
|
||||
outStream.writeByte(regionVersion);
|
||||
outStream.writeInt(region.getRegionPos().x());
|
||||
outStream.writeInt(region.getRegionPos().z());
|
||||
Map<ChunkPos, byte[]> map = region.getRegionDataToSave();
|
||||
outStream.writeInt(map.size());
|
||||
for (Map.Entry<ChunkPos, byte[]> entry : map.entrySet()) {
|
||||
outStream.writeInt(entry.getKey().x());
|
||||
outStream.writeInt(entry.getKey().z());
|
||||
byte[] dataArray = entry.getValue();
|
||||
outStream.writeInt(dataArray.length);
|
||||
outStream.write(dataArray);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return outByteStream.toByteArray();
|
||||
}
|
||||
|
||||
public CRegion deserializeRegion(CWorld world, DataInputStream dataStream) throws IOException {
|
||||
int regionVersion = dataStream.readByte();
|
||||
int regionX = dataStream.readInt();
|
||||
int regionZ = dataStream.readInt();
|
||||
RegionPos regionPos = RegionPos.of(regionX, regionZ);
|
||||
ConcurrentHashMap<ChunkPos, byte[]> map = new ConcurrentHashMap<>();
|
||||
int chunkAmount = dataStream.readInt();
|
||||
for (int i = 0; i < chunkAmount; i++) {
|
||||
int chunkX = dataStream.readInt();
|
||||
int chunkZ = dataStream.readInt();
|
||||
ChunkPos chunkPos = ChunkPos.of(chunkX, chunkZ);
|
||||
byte[] chunkData = new byte[dataStream.readInt()];
|
||||
dataStream.read(chunkData);
|
||||
map.put(chunkPos, chunkData);
|
||||
}
|
||||
return new CRegion(world, regionPos, map);
|
||||
}
|
||||
|
||||
public byte[] serialize(SerializableChunk serializableChunk) {
|
||||
ByteArrayOutputStream outByteStream = new ByteArrayOutputStream();
|
||||
DataOutputStream outStream = new DataOutputStream(outByteStream);
|
||||
try {
|
||||
outStream.writeByte(chunkVersion);
|
||||
byte[] serializedSections = serializeChunk(serializableChunk);
|
||||
byte[] compressed = Zstd.compress(serializedSections);
|
||||
outStream.writeInt(compressed.length);
|
||||
@@ -219,8 +345,8 @@ public class BukkitWorldAdaptor extends AbstractWorldAdaptor {
|
||||
return outByteStream.toByteArray();
|
||||
}
|
||||
|
||||
public CChunk deserialize(CWorld world, DataInputStream dataStream) throws IOException {
|
||||
int worldVersion = dataStream.readByte();
|
||||
public CChunk deserializeChunk(CWorld world, DataInputStream dataStream) throws IOException {
|
||||
int chunkVersion = dataStream.readByte();
|
||||
byte[] blockData = readCompressedBytes(dataStream);
|
||||
return deserializeChunk(world, blockData);
|
||||
}
|
||||
@@ -231,7 +357,7 @@ public class BukkitWorldAdaptor extends AbstractWorldAdaptor {
|
||||
// read coordinate
|
||||
int x = chunkData.readInt();
|
||||
int z = chunkData.readInt();
|
||||
ChunkCoordinate coordinate = new ChunkCoordinate(x, z);
|
||||
ChunkPos coordinate = new ChunkPos(x, z);
|
||||
// read loading info
|
||||
int loadedSeconds = chunkData.readInt();
|
||||
long lastLoadedTime = chunkData.readLong();
|
||||
@@ -362,10 +488,10 @@ public class BukkitWorldAdaptor extends AbstractWorldAdaptor {
|
||||
}
|
||||
|
||||
public SerializableChunk toSerializableChunk(CChunk chunk) {
|
||||
ChunkCoordinate chunkCoordinate = chunk.getChunkCoordinate();
|
||||
ChunkPos chunkPos = chunk.getChunkPos();
|
||||
return new SerializableChunk(
|
||||
chunkCoordinate.x(),
|
||||
chunkCoordinate.z(),
|
||||
chunkPos.x(),
|
||||
chunkPos.z(),
|
||||
chunk.getLoadedSeconds(),
|
||||
chunk.getLastLoadedTime(),
|
||||
Arrays.stream(chunk.getSectionsForSerialization()).map(this::toSerializableSection).toList(),
|
||||
@@ -451,7 +577,7 @@ public class BukkitWorldAdaptor extends AbstractWorldAdaptor {
|
||||
return outByteStream.toByteArray();
|
||||
}
|
||||
|
||||
public void convertWorld(@Nullable CWorld cWorld, World world) {
|
||||
public void convertWorldFromV33toV34(@Nullable CWorld cWorld, World world) {
|
||||
// handle legacy files
|
||||
File leagcyFile = new File(world.getWorldFolder(), "customcrops" + File.separator + "data.yml");
|
||||
if (leagcyFile.exists()) {
|
||||
@@ -477,11 +603,14 @@ public class BukkitWorldAdaptor extends AbstractWorldAdaptor {
|
||||
LogUtils.warn("Converting chunks for world " + world.getName() + " from 3.3 to 3.4... This might take some time.");
|
||||
File[] data_files = folder.listFiles();
|
||||
if (data_files == null) return;
|
||||
|
||||
HashMap<RegionPos, CustomCropsRegion> regionHashMap = new HashMap<>();
|
||||
|
||||
for (File file : data_files) {
|
||||
ChunkCoordinate chunkCoordinate = ChunkCoordinate.getByString(file.getName().substring(0, file.getName().length() - 7));
|
||||
ChunkPos chunkPos = ChunkPos.getByString(file.getName().substring(0, file.getName().length() - 7));
|
||||
try (FileInputStream fis = new FileInputStream(file); ObjectInputStream ois = new ObjectInputStream(fis)) {
|
||||
CCChunk chunk = (CCChunk) ois.readObject();
|
||||
CChunk cChunk = new CChunk(cWorld, chunkCoordinate);
|
||||
CChunk cChunk = new CChunk(cWorld, chunkPos);
|
||||
for (net.momirealms.customcrops.api.object.world.SimpleLocation legacyLocation : chunk.getGreenhouseSet()) {
|
||||
SimpleLocation simpleLocation = new SimpleLocation(legacyLocation.getWorldName(), legacyLocation.getX(), legacyLocation.getY(), legacyLocation.getZ());
|
||||
cChunk.addGlassAt(new MemoryGlass(simpleLocation), simpleLocation);
|
||||
@@ -506,19 +635,56 @@ public class BukkitWorldAdaptor extends AbstractWorldAdaptor {
|
||||
Fertilizer fertilizer = entry.getValue().getFertilizer();
|
||||
cChunk.addPotAt(new MemoryPot(simpleLocation, entry.getValue().getKey(), entry.getValue().getWater(), fertilizer == null ? "" : fertilizer.getKey(), fertilizer == null ? 0 : fertilizer.getTimes()), simpleLocation);
|
||||
}
|
||||
try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(getChunkDataFilePath(world, cChunk.getChunkCoordinate())))) {
|
||||
bos.write(serialize(cChunk));
|
||||
} catch (IOException e) {
|
||||
LogUtils.severe("Failed to save CustomCrops data.");
|
||||
e.printStackTrace();
|
||||
CustomCropsRegion region = regionHashMap.get(chunkPos.getRegionPos());
|
||||
if (region == null) {
|
||||
region = new CRegion(cWorld, chunkPos.getRegionPos());
|
||||
regionHashMap.put(chunkPos.getRegionPos(), region);
|
||||
}
|
||||
region.saveChunk(chunkPos, serialize(toSerializableChunk(cChunk)));
|
||||
} catch (IOException | ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
LogUtils.info("Error at " + file.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
|
||||
LogUtils.info("Successfully converted chunks for world: " + world);
|
||||
for (CustomCropsRegion region : regionHashMap.values()) {
|
||||
saveRegion(region);
|
||||
}
|
||||
LogUtils.info("Successfully converted chunks for world: " + world.getName());
|
||||
}
|
||||
}
|
||||
|
||||
public void convertWorldFromV342toV343(@Nullable CWorld cWorld, World world) {
|
||||
File folder = new File(world.getWorldFolder(), "customcrops");
|
||||
if (!folder.exists()) return;
|
||||
LogUtils.warn("Converting chunks for world " + world.getName() + " from 3.4.2 to 3.4.3... This might take some time.");
|
||||
File[] data_files = folder.listFiles();
|
||||
if (data_files == null) return;
|
||||
HashMap<RegionPos, CustomCropsRegion> regionHashMap = new HashMap<>();
|
||||
for (File file : data_files) {
|
||||
String fileName = file.getName();
|
||||
if (fileName.endsWith(".ccd")) {
|
||||
String chunkStr = file.getName().substring(0, fileName.length()-4);
|
||||
ChunkPos chunkPos = ChunkPos.getByString(chunkStr);
|
||||
try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file))) {
|
||||
DataInputStream dataStream = new DataInputStream(bis);
|
||||
byte[] chunkData = dataStream.readAllBytes();
|
||||
dataStream.close();
|
||||
CustomCropsRegion region = regionHashMap.get(chunkPos.getRegionPos());
|
||||
if (region == null) {
|
||||
region = new CRegion(cWorld, chunkPos.getRegionPos());
|
||||
regionHashMap.put(chunkPos.getRegionPos(), region);
|
||||
}
|
||||
region.saveChunk(chunkPos, chunkData);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
file.delete();
|
||||
}
|
||||
}
|
||||
for (CustomCropsRegion region : regionHashMap.values()) {
|
||||
saveRegion(region);
|
||||
}
|
||||
LogUtils.info("Successfully converted chunks for world: " + world.getName());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,10 +23,11 @@ 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.ChunkCoordinate;
|
||||
import net.momirealms.customcrops.api.mechanic.world.BlockPos;
|
||||
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.CustomCropsRegion;
|
||||
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;
|
||||
@@ -65,13 +66,13 @@ public class SlimeWorldAdaptor extends BukkitWorldAdaptor {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unload(CustomCropsWorld customCropsWorld) {
|
||||
public void saveInfoData(CustomCropsWorld customCropsWorld) {
|
||||
SlimeWorld slimeWorld = slimePlugin.getWorld(customCropsWorld.getWorldName());
|
||||
if (slimeWorld == null) {
|
||||
super.unload(customCropsWorld);
|
||||
super.saveInfoData(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.");
|
||||
@@ -80,9 +81,16 @@ public class SlimeWorldAdaptor extends BukkitWorldAdaptor {
|
||||
|
||||
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 unload(CustomCropsWorld customCropsWorld) {
|
||||
SlimeWorld slimeWorld = slimePlugin.getWorld(customCropsWorld.getWorldName());
|
||||
if (slimeWorld == null) {
|
||||
super.unload(customCropsWorld);
|
||||
return;
|
||||
}
|
||||
customCropsWorld.save();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -108,64 +116,97 @@ public class SlimeWorldAdaptor extends BukkitWorldAdaptor {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadDynamicData(CustomCropsWorld customCropsWorld, ChunkCoordinate chunkCoordinate) {
|
||||
public void loadChunkData(CustomCropsWorld customCropsWorld, ChunkPos chunkPos) {
|
||||
SlimeWorld slimeWorld = slimePlugin.getWorld(customCropsWorld.getWorldName());
|
||||
if (slimeWorld == null) {
|
||||
super.loadDynamicData(customCropsWorld, chunkCoordinate);
|
||||
super.loadChunkData(customCropsWorld, chunkPos);
|
||||
return;
|
||||
}
|
||||
|
||||
long time1 = System.currentTimeMillis();
|
||||
CWorld cWorld = (CWorld) customCropsWorld;
|
||||
// load lazy chunks firstly
|
||||
CustomCropsChunk lazyChunk = customCropsWorld.removeLazyChunkAt(chunkCoordinate);
|
||||
CustomCropsChunk lazyChunk = customCropsWorld.removeLazyChunkAt(chunkPos);
|
||||
if (lazyChunk != null) {
|
||||
CChunk cChunk = (CChunk) lazyChunk;
|
||||
cChunk.setUnloadedSeconds(0);
|
||||
cWorld.loadChunk(cChunk);
|
||||
long time2 = System.currentTimeMillis();
|
||||
CustomCropsPlugin.get().debug("Took " + (time2-time1) + "ms to load chunk " + chunkPos + " from lazy chunks");
|
||||
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.");
|
||||
LogUtils.warn("Failed to load data for " + chunkPos + " in world " + customCropsWorld.getWorldName() + " because slime world format is incorrect.");
|
||||
return;
|
||||
}
|
||||
|
||||
Tag<?> chunkTag = optionalCompoundTag.get().getValue().get(chunkCoordinate.toString());
|
||||
if (chunkTag == null) return;
|
||||
Tag<?> chunkTag = optionalCompoundTag.get().getValue().get(chunkPos.getAsString());
|
||||
if (chunkTag == null) {
|
||||
return;
|
||||
}
|
||||
Optional<CompoundTag> chunkCompoundTag = chunkTag.getAsCompoundTag();
|
||||
if (chunkCompoundTag.isEmpty()) return;
|
||||
if (chunkCompoundTag.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// load chunk from local files
|
||||
long time1 = System.currentTimeMillis();
|
||||
// load chunk from slime world
|
||||
cWorld.loadChunk(tagToChunk(cWorld, chunkCompoundTag.get()));
|
||||
long time2 = System.currentTimeMillis();
|
||||
CustomCropsPlugin.get().debug("Took " + (time2-time1) + "ms to load chunk " + chunkCoordinate);
|
||||
CustomCropsPlugin.get().debug("Took " + (time2-time1) + "ms to load chunk " + chunkPos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveDynamicData(CustomCropsWorld customCropsWorld, CustomCropsChunk chunk) {
|
||||
SlimeWorld slimeWorld = getSlimeWorld(customCropsWorld.getWorldName());
|
||||
public void saveChunkToCachedRegion(CustomCropsChunk customCropsChunk) {
|
||||
CustomCropsWorld customCropsWorld = customCropsChunk.getCustomCropsWorld();
|
||||
SlimeWorld slimeWorld = getSlimeWorld(customCropsChunk.getCustomCropsWorld().getWorldName());
|
||||
if (slimeWorld == null) {
|
||||
super.saveDynamicData(customCropsWorld, chunk);
|
||||
super.saveChunkToCachedRegion(customCropsChunk);
|
||||
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.");
|
||||
LogUtils.warn("Failed to save data for " + customCropsChunk.getChunkPos() + " in world " + customCropsWorld.getWorldName() + " because slime world format is incorrect.");
|
||||
return;
|
||||
}
|
||||
|
||||
CustomCropsPlugin.get().getScheduler().runTaskSync(() -> optionalCompoundTag.get().getValue().put(chunkToTag((CChunk) chunk)), null);
|
||||
SerializableChunk serializableChunk = toSerializableChunk((CChunk) customCropsChunk);
|
||||
if (Bukkit.isPrimaryThread()) {
|
||||
if (serializableChunk.canPrune()) {
|
||||
optionalCompoundTag.get().getValue().remove(customCropsChunk.getChunkPos().getAsString());
|
||||
} else {
|
||||
optionalCompoundTag.get().getValue().put(chunkToTag(serializableChunk));
|
||||
}
|
||||
} else {
|
||||
CustomCropsPlugin.get().getScheduler().runTaskSync(() -> {
|
||||
if (serializableChunk.canPrune()) {
|
||||
optionalCompoundTag.get().getValue().remove(customCropsChunk.getChunkPos().getAsString());
|
||||
} else {
|
||||
optionalCompoundTag.get().getValue().put(chunkToTag(serializableChunk));
|
||||
}
|
||||
}, null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveRegion(CustomCropsRegion customCropsRegion) {
|
||||
CustomCropsWorld customCropsWorld = customCropsRegion.getCustomCropsWorld();
|
||||
SlimeWorld slimeWorld = getSlimeWorld(customCropsWorld.getWorldName());
|
||||
if (slimeWorld == null) {
|
||||
super.saveRegion(customCropsRegion);
|
||||
return;
|
||||
}
|
||||
|
||||
// don't need to save region to slime world
|
||||
}
|
||||
|
||||
private SlimeWorld getSlimeWorld(String name) {
|
||||
return slimePlugin.getWorld(name);
|
||||
}
|
||||
|
||||
private CompoundTag chunkToTag(CChunk chunk) {
|
||||
SerializableChunk serializableChunk = toSerializableChunk(chunk);
|
||||
private CompoundTag chunkToTag(SerializableChunk serializableChunk) {
|
||||
CompoundMap map = new CompoundMap();
|
||||
map.put(new IntTag("x", serializableChunk.getX()));
|
||||
map.put(new IntTag("z", serializableChunk.getZ()));
|
||||
@@ -178,7 +219,7 @@ public class SlimeWorldAdaptor extends BukkitWorldAdaptor {
|
||||
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);
|
||||
return new CompoundTag(serializableChunk.getX() + "," + serializableChunk.getZ(), map);
|
||||
}
|
||||
|
||||
private CChunk tagToChunk(CWorld cWorld, CompoundTag tag) {
|
||||
@@ -186,7 +227,7 @@ public class SlimeWorldAdaptor extends BukkitWorldAdaptor {
|
||||
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);
|
||||
ChunkPos coordinate = new ChunkPos(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();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Don't change
|
||||
config-version: '35'
|
||||
config-version: '36'
|
||||
|
||||
# Debug
|
||||
debug: false
|
||||
|
||||
Reference in New Issue
Block a user