9
0
mirror of https://github.com/Samsuik/Sakura.git synced 2025-12-22 16:29:16 +00:00
Files
SakuraMC/patches/server/0004-Local-Config-and-Value-Storage-API.patch
Samsuik 64bf46cba3 Updated Upstream (Paper)
Upstream has released updates that appear to apply and compile correctly

Paper Changes:
PaperMC/Paper@1cecc24 Fix tag key generator output inconsistencies (#11218)
PaperMC/Paper@7d7f123 Fix wrong spawn reason for trial spawners (#11229)
PaperMC/Paper@1c3c47a Correctly check enchants for ItemStack#damage (#11240)
PaperMC/Paper@1187544 Fix teleport event getTo returning null (#11239)
PaperMC/Paper@dd941cc Re-add patches for can-place/can-destroy API (#11238)
PaperMC/Paper@ab0d24a Configuration for horizontal-only item merging (#11219)
PaperMC/Paper@098bd39 Remove arbitrary book page limit (#11228)
PaperMC/Paper@f97aff7 [ci skip] Fix Effect javadocs (#11182)
PaperMC/Paper@4a97ba3 Fix `setSendViewDistance`'s return (#11247)
PaperMC/Paper@1798e94 Fix BasicCommand suggestion arg count (#11241)
PaperMC/Paper@7c9240f Improve standard messenger logging
PaperMC/Paper@9ab644e Fix `TooltipContext.create` being wrong(#11254)
PaperMC/Paper@11b4ac7 Fix disableEndCredits world config (#11261)
PaperMC/Paper@bf5852a Fix NPE for PlayerPostRespawnEvent#getRespawnedLocation (#11268)
PaperMC/Paper@fb53074 Apply optimise collision checking in move packet handling patch
PaperMC/Paper@81bfda8 [ci skip] Specify rebase location in CONTRIBUTING (#11255)
PaperMC/Paper@9571983 Fix scanForLegacyEnderDragon world config (#11262)
PaperMC/Paper@ec55c11 Fix indestructable light blocks (#11275)
PaperMC/Paper@1b8ab11 Add Configuration for vertical Despawn Ranges (#10440)
PaperMC/Paper@534ab86 [ci-skip] Revert "Add Configuration for vertical Despawn Ranges (#10440)" (#11278)
PaperMC/Paper@e619744 Allow skipping of world symlink validation (#11250)
PaperMC/Paper@78216fe Re-implement portalCreateRadius world config (#11267)
PaperMC/Paper@4829fbf Handle custom registry elements properly (#11230)
PaperMC/Paper@d5ffc57 Implement more methods for horse inventories (#11147)
PaperMC/Paper@52ae4ad Migrate ArmorStand meta to using entity tag (#11107)
PaperMC/Paper@75655ec Add Configuration for vertical Despawn Ranges (#11279)
PaperMC/Paper@0e73617 Updated Upstream (Bukkit/CraftBukkit/Spigot) (#11284)
PaperMC/Paper@66a97cc Update item data sanitization (#11227)
PaperMC/Paper@2e82fd2 Add even more Enchantment API (#11115)
PaperMC/Paper@57dd822 Leashable API (#10961)
PaperMC/Paper@8c3018a Fix Selector Arguments not working with permission (#11286)
PaperMC/Paper@4401748 Fix CraftBukkit drag system (#10703)
PaperMC/Paper@64c9ee6 Allow getting/setting the sign's editor uuid (#10637)
PaperMC/Paper@b4bc512 Fix entity limit patch deleting unnecessary entities
PaperMC/Paper@be1078f Use player file, not directory, when checking for offline player data
PaperMC/Paper@8fd3a67 [ci skip] Clean up book limits patch (#11297)
PaperMC/Paper@dae906b Add getWorld method that uses adventure Key (#11199)
PaperMC/Paper@ba1b016 Allow server administrators to disable book size checks (#10457)
PaperMC/Paper@a8cb8e6 [ci skip] Fix JavaDocs for HeightMap#MOTION_BLOCKING_NO_LEAVES (#11291)
PaperMC/Paper@e4b38b4 Fixup config parsing
PaperMC/Paper@3271119 Fix SculkBloomEvent firing for block entity loading (#11306)
PaperMC/Paper@2fdb2e9 Fix structure check API (#11307)
2024-08-22 20:17:51 +01:00

280 lines
11 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Samsuik <40902469+Samsuik@users.noreply.github.com>
Date: Tue, 21 Nov 2023 23:24:24 +0000
Subject: [PATCH] Local Config and Value Storage API
diff --git a/src/main/java/me/samsuik/sakura/local/config/LocalConfigManager.java b/src/main/java/me/samsuik/sakura/local/config/LocalConfigManager.java
new file mode 100644
index 0000000000000000000000000000000000000000..a3a09b8d58589883c7c465597bc64502bbfa0d88
--- /dev/null
+++ b/src/main/java/me/samsuik/sakura/local/config/LocalConfigManager.java
@@ -0,0 +1,143 @@
+package me.samsuik.sakura.local.config;
+
+import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
+import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
+import it.unimi.dsi.fastutil.longs.Long2ObjectRBTreeMap;
+import it.unimi.dsi.fastutil.longs.Long2ObjectSortedMap;
+import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
+import me.samsuik.sakura.local.LocalRegion;
+import me.samsuik.sakura.local.storage.LocalStorageHandler;
+import me.samsuik.sakura.local.storage.LocalValueStorage;
+import me.samsuik.sakura.utils.objects.Expiry;
+import net.minecraft.core.BlockPos;
+import net.minecraft.server.MinecraftServer;
+import net.minecraft.world.level.ChunkPos;
+import net.minecraft.world.level.Level;
+import org.bukkit.Location;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+public final class LocalConfigManager implements LocalStorageHandler {
+
+ private final Map<LocalRegion, LocalValueStorage> storageMap = new Object2ObjectOpenHashMap<>();
+ // tree is a tree. it may not be correct but it works.
+ private final Long2ObjectRBTreeMap<LocalRegion> regionTree = new Long2ObjectRBTreeMap<>();
+ private final Long2ObjectMap<LocalValueConfig> configMap = new Long2ObjectOpenHashMap<>();
+ private final Level level;
+
+ public LocalConfigManager(Level level) {
+ this.level = level;
+ }
+
+ @Override
+ public LocalRegion locate(Location location, int searchDistance) {
+ return this.locate(location.getBlockX(), location.getBlockZ(), searchDistance);
+ }
+
+ @Override
+ public synchronized LocalRegion locate(int x, int z, int searchDistance) {
+ long search = (long) searchDistance << 32;
+ long coordinate = ChunkPos.asLong(x, z);
+
+ // all regions below the coordinate (they're stored with the minX, minZ)
+ Long2ObjectSortedMap<LocalRegion> head = this.regionTree.headMap(coordinate);
+
+ if (head.isEmpty()) return null;
+
+ for (Long2ObjectMap.Entry<LocalRegion> entry : head.long2ObjectEntrySet()) {
+ // this has no respect for the x coordinate, but it works
+ if (coordinate - entry.getLongKey() > search) {
+ break;
+ }
+
+ // check if the region we found contains the position
+ if (entry.getValue().contains(x, z)) {
+ return entry.getValue();
+ }
+ }
+
+ return null;
+ }
+
+ @Override
+ public synchronized LocalValueStorage get(LocalRegion region) {
+ return this.storageMap.get(region);
+ }
+
+ @Override
+ public synchronized boolean has(LocalRegion region) {
+ return this.storageMap.containsKey(region);
+ }
+
+ @Override
+ public synchronized void put(LocalRegion region, LocalValueStorage storage) {
+ assert region != null : "region cannot be null";
+ assert storage != null : "storage cannot be null";
+
+ long base = ChunkPos.asLong(region.minX(), region.minZ());
+ this.ensureNotOverlapping(region);
+
+ this.storageMap.put(region, storage);
+ this.regionTree.put(base, region);
+ }
+
+ @Override
+ public synchronized void remove(LocalRegion region) {
+ assert region != null : "region cannot be null";
+
+ long base = ChunkPos.asLong(region.minX(), region.minZ());
+
+ this.storageMap.remove(region);
+ this.regionTree.remove(base);
+ }
+
+ @Override
+ public synchronized List<LocalRegion> regions() {
+ return new ArrayList<>(this.storageMap.keySet());
+ }
+
+ public synchronized LocalValueConfig config(BlockPos position) {
+ long chunkKey = ChunkPos.asLong(position.getX() >> 4, position.getZ() >> 4);
+
+ LocalValueConfig local = this.configMap.computeIfAbsent(chunkKey, (key) -> {
+ LocalValueConfig config = new LocalValueConfig(new Expiry(MinecraftServer.currentTickLong, 600));
+
+ // defaults from sakura config
+ config.init(level);
+
+ // search the entire map if we have to for a region
+ LocalRegion region = this.locate(position.getX(), position.getZ(), Integer.MAX_VALUE);
+
+ if (region != null) {
+ // load local values
+ config.load(this.storageMap.get(region));
+ }
+
+ return config;
+ });
+
+ local.expiry().refresh(MinecraftServer.currentTickLong);
+ return local;
+ }
+
+ public synchronized void expire(long tick) {
+ if (tick % 200 != 0) return;
+
+ // remove expired
+ this.configMap.values().removeIf(obj -> obj.expiry().isExpired(tick));
+ }
+
+ private void ensureNotOverlapping(LocalRegion region) {
+ long top = ChunkPos.asLong(region.maxX(), region.maxZ());
+ Long2ObjectSortedMap<LocalRegion> head = this.regionTree.headMap(top);
+
+ for (LocalRegion present : head.values()) {
+ if (present != region && present.intersects(region)) {
+ throw new UnsupportedOperationException("overlapping regions");
+ }
+ }
+ }
+
+}
diff --git a/src/main/java/me/samsuik/sakura/local/config/LocalValueConfig.java b/src/main/java/me/samsuik/sakura/local/config/LocalValueConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..3f518f3f1241d3dc1f76fab42e9fd789fab4d53e
--- /dev/null
+++ b/src/main/java/me/samsuik/sakura/local/config/LocalValueConfig.java
@@ -0,0 +1,71 @@
+package me.samsuik.sakura.local.config;
+
+import io.papermc.paper.configuration.WorldConfiguration.Misc.RedstoneImplementation;
+import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap;
+import me.samsuik.sakura.explosion.durable.DurableMaterial;
+import me.samsuik.sakura.local.LocalValueKey;
+import me.samsuik.sakura.local.storage.LocalValueStorage;
+import me.samsuik.sakura.physics.PhysicsVersion;
+import me.samsuik.sakura.utils.objects.Expiry;
+import net.minecraft.world.level.Level;
+import net.minecraft.world.level.block.Block;
+import org.bukkit.craftbukkit.util.CraftMagicNumbers;
+
+import java.util.Map;
+
+public final class LocalValueConfig {
+
+ private final Expiry expiry;
+ public Map<Block, DurableMaterial> durableMaterials;
+ public PhysicsVersion physicsVersion;
+ public RedstoneImplementation redstoneImplementation;
+ public boolean consistentRadius;
+ public boolean redstoneCache;
+
+ LocalValueConfig(Expiry expiry) {
+ this.expiry = expiry;
+ }
+
+ void init(Level level) {
+ // default materials
+ this.durableMaterials = new Reference2ObjectOpenHashMap<>(level.sakuraConfig().cannons.explosion.durableMaterials);
+
+ // physics version
+ this.physicsVersion = level.sakuraConfig().cannons.mechanics.physicsVersion;
+
+ // redstone implementation
+ this.redstoneImplementation = level.paperConfig().misc.redstoneImplementation;
+
+ // consistent explosion radius
+ this.consistentRadius = level.sakuraConfig().cannons.explosion.consistentRadius;
+
+ // redstone cache
+ this.redstoneCache = level.sakuraConfig().technical.redstone.redstoneCache;
+ }
+
+ void load(LocalValueStorage storage) {
+ // local materials
+ storage.value(LocalValueKey.DURABLE_MATERIALS, true).forEach(((material, entry) -> {
+ this.durableMaterials.put(CraftMagicNumbers.getBlock(material), new DurableMaterial(entry.getKey(), entry.getValue()));
+ }));
+
+ // physics version
+ this.physicsVersion = storage.getOrDefault(LocalValueKey.PHYSICS_VERSION, this.physicsVersion);
+
+ // redstone implementation
+ if (storage.exists(LocalValueKey.REDSTONE_IMPLEMENTATION)) {
+ this.redstoneImplementation = RedstoneImplementation.values()[storage.value(LocalValueKey.REDSTONE_IMPLEMENTATION).ordinal()];
+ }
+
+ // consistent explosion radius
+ this.consistentRadius = storage.getOrDefault(LocalValueKey.CONSISTENT_EXPLOSION_RADIUS, this.consistentRadius);
+
+ // redstone cache
+ this.redstoneCache = storage.getOrDefault(LocalValueKey.REDSTONE_CACHE, this.redstoneCache);
+ }
+
+ Expiry expiry() {
+ return expiry;
+ }
+
+}
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index 741ca90ca91c77f3cc58a7020169165b20250225..39cc9aba054696c063133d529e79594a5ce2c0cd 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -1820,6 +1820,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
this.profiler.pop();
this.profiler.pop();
worldserver.explosionDensityCache.clear(); // Paper - Optimize explosions
+ worldserver.localConfig().expire(currentTickLong); // Sakura - add local config
}
this.isIteratingOverLevels = false; // Paper - Throw exception on world create while being ticked
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
index 7da2fc17f6e7bf888ef0c2a8eba0fc3b4c10436e..c811bc64d0686fdec58defb707d57e539c261b48 100644
--- a/src/main/java/net/minecraft/world/level/Level.java
+++ b/src/main/java/net/minecraft/world/level/Level.java
@@ -177,6 +177,12 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl
return this.sakuraConfig;
}
// Sakura end - sakura configuration files
+ // Sakura start - add local config
+ private final me.samsuik.sakura.local.config.LocalConfigManager localConfig = new me.samsuik.sakura.local.config.LocalConfigManager(this);
+ public final me.samsuik.sakura.local.config.LocalConfigManager localConfig() {
+ return this.localConfig;
+ }
+ // Sakura end - add local config
public final com.destroystokyo.paper.antixray.ChunkPacketBlockController chunkPacketBlockController; // Paper - Anti-Xray
public final co.aikar.timings.WorldTimingsHandler timings; // Paper
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
index ffd284f0e25c6f20672f7225aafd37e6c87ccf03..f07bdac9a26ce669346e87f7faf70d1fcb25c71b 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
@@ -246,6 +246,13 @@ public class CraftWorld extends CraftRegionAccessor implements World {
}
// Paper end
+ // Sakura start - add local config
+ @Override
+ public final me.samsuik.sakura.local.storage.LocalStorageHandler getStorageHandler() {
+ return this.getHandle().localConfig();
+ }
+ // Sakura end - add local config
+
private static final Random rand = new Random();
public CraftWorld(ServerLevel world, ChunkGenerator gen, BiomeProvider biomeProvider, Environment env) {