diff --git a/gradle.properties b/gradle.properties index 976bc00..4c0ac57 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,7 +4,7 @@ mcVersion=1.21.8 release=2 # 0 for skip release, 1 for pre-release, 2 for release -luminolRef=339614a31138427888df80ea45295d1452ac44b6 +luminolRef=83e11abcac527fcbb589f72ffb3910418a0984d2 org.gradle.configuration-cache=true org.gradle.caching=true diff --git a/lophine-server/luminol-patches/features/0001-Rebrand-to-Lophine.patch b/lophine-server/luminol-patches/features/0001-Rebrand-to-Lophine.patch index 39464d9..3e77082 100644 --- a/lophine-server/luminol-patches/features/0001-Rebrand-to-Lophine.patch +++ b/lophine-server/luminol-patches/features/0001-Rebrand-to-Lophine.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Rebrand to Lophine diff --git a/src/main/java/me/earthme/luminol/config/ConfigManager.java b/src/main/java/me/earthme/luminol/config/ConfigManager.java -index a67fc80eb3182415557b4bdf7f146aefb43103da..52fec4c88fee3c027c954365538516aaa8335c7f 100644 +index 136b9e9c3bcb43698c653060665dc82444e09768..cc2b7b8f897570e5d079f80375c93cf2550df6af 100644 --- a/src/main/java/me/earthme/luminol/config/ConfigManager.java +++ b/src/main/java/me/earthme/luminol/config/ConfigManager.java @@ -21,6 +21,7 @@ public class ConfigManager { @@ -17,11 +17,11 @@ index a67fc80eb3182415557b4bdf7f146aefb43103da..52fec4c88fee3c027c954365538516aa } diff --git a/src/main/java/me/earthme/luminol/config/modules/misc/ServerModNameConfig.java b/src/main/java/me/earthme/luminol/config/modules/misc/ServerModNameConfig.java -index ded1f0667327a70a923ebda55c41b1c9094d3e37..57ddc0832b919b115b85c81ac30f136e32f1e77e 100644 +index 997bc00dffbf5c15fde610c95527e8013ae57660..d94e11eb9f10c9622052c7b327ccfdf24de6ae73 100644 --- a/src/main/java/me/earthme/luminol/config/modules/misc/ServerModNameConfig.java +++ b/src/main/java/me/earthme/luminol/config/modules/misc/ServerModNameConfig.java -@@ -6,7 +6,7 @@ import me.earthme.luminol.config.flags.ConfigInfo; - +@@ -8,7 +8,7 @@ import me.earthme.luminol.config.flags.ConfigInfo; + @ConfigClassInfo(configAttribution = EnumConfigCategory.MISC, mainName = "server_mod_name") public class ServerModNameConfig implements IConfigModule { @ConfigInfo(baseName = "name") - public static String serverModName = "Luminol"; diff --git a/lophine-server/luminol-patches/features/0002-Transformed-Configs.patch b/lophine-server/luminol-patches/features/0002-Transformed-Configs.patch index 4376c77..adbc189 100644 --- a/lophine-server/luminol-patches/features/0002-Transformed-Configs.patch +++ b/lophine-server/luminol-patches/features/0002-Transformed-Configs.patch @@ -5,26 +5,26 @@ Subject: [PATCH] Transformed Configs diff --git a/src/main/java/me/earthme/luminol/config/modules/experiment/CommandBlockExecutionConfig.java b/src/main/java/me/earthme/luminol/config/modules/experiment/CommandBlockExecutionConfig.java -index 531214d7ab28ece4bf84e82b39d1c9f983f0fb0c..b68fa0427bb975e91e76f73ab4cc089a424937a3 100644 +index 83d803d7d7f3cecdbcb593da70234aa9dd81a1ff..00ad1597bdb20118d756d9371c0d50890d0a5e8c 100644 --- a/src/main/java/me/earthme/luminol/config/modules/experiment/CommandBlockExecutionConfig.java +++ b/src/main/java/me/earthme/luminol/config/modules/experiment/CommandBlockExecutionConfig.java -@@ -5,6 +5,7 @@ import me.earthme.luminol.config.IConfigModule; - import me.earthme.luminol.config.flags.ConfigInfo; +@@ -7,6 +7,7 @@ import me.earthme.luminol.config.flags.ConfigInfo; + @ConfigClassInfo(configAttribution = EnumConfigCategory.EXPERIMENT, mainName = "force_enable_command_block_command_execution") public class CommandBlockExecutionConfig implements IConfigModule { + @me.earthme.luminol.config.flags.TransformedConfig(name = "command_block_enabled", category = {"experiment", "command"}, originInstance = "lophine") @ConfigInfo(baseName = "enabled") public static boolean enabled = false; - + } diff --git a/src/main/java/me/earthme/luminol/config/modules/misc/PaperPacketLimiterConfig.java b/src/main/java/me/earthme/luminol/config/modules/misc/PaperPacketLimiterConfig.java -index c269446dda05cfc848407f80f53820c8fcd0c7b4..e69ffae53aa24496a29a4c4890cdcb366d2bec12 100644 +index 385612dd2e3bd2b4651ccfda41986ff7047067e4..4450ba56a491c15aea6ea9e1fed0e379660fbec5 100644 --- a/src/main/java/me/earthme/luminol/config/modules/misc/PaperPacketLimiterConfig.java +++ b/src/main/java/me/earthme/luminol/config/modules/misc/PaperPacketLimiterConfig.java -@@ -5,6 +5,7 @@ import me.earthme.luminol.config.IConfigModule; - import me.earthme.luminol.config.flags.ConfigInfo; +@@ -7,6 +7,7 @@ import me.earthme.luminol.config.flags.ConfigInfo; + @ConfigClassInfo(configAttribution = EnumConfigCategory.MISC, mainName = "force_disable_packet_limiter_of_paper") public class PaperPacketLimiterConfig implements IConfigModule { + @me.earthme.luminol.config.flags.TransformedConfig(name = "unlimit-packet", category = {"misc", "network"}, originInstance = "lophine") @ConfigInfo(baseName = "force_disable") public static boolean forceDisable = false; - + } diff --git a/lophine-server/minecraft-patches/features/0004-Add-config-to-enable-raytracing-tracker.patch b/lophine-server/minecraft-patches/features/0004-Add-config-to-enable-raytracing-tracker.patch index 3c3babf..7c3e139 100644 --- a/lophine-server/minecraft-patches/features/0004-Add-config-to-enable-raytracing-tracker.patch +++ b/lophine-server/minecraft-patches/features/0004-Add-config-to-enable-raytracing-tracker.patch @@ -18,7 +18,7 @@ index 6868b915bf3deb85783a638d4441a15fea6da2dc..70740381c6501c1a518c52b24381edd1 double rangeY = level.paperConfig().entities.trackingRangeY.get(this.entity, -1); if (rangeY != -1) { diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java -index 75f327fff68097c1c9f65767552f686421e1e397..ed7421895311d89ad9726804893eff423868d375 100644 +index 125412d16d1a66dadfe4bbf64629c4052e0c7647..ccb05b6e328a29eea4761721b496ab36ba362361 100644 --- a/net/minecraft/world/entity/Entity.java +++ b/net/minecraft/world/entity/Entity.java @@ -147,7 +147,7 @@ import net.minecraft.world.waypoints.WaypointTransmitter; @@ -30,7 +30,7 @@ index 75f327fff68097c1c9f65767552f686421e1e397..ed7421895311d89ad9726804893eff42 // CraftBukkit start private static final int CURRENT_LEVEL = 2; public boolean preserveMotion = true; // Paper - Fix Entity Teleportation and cancel velocity if teleported; keep initial motion on first snapTo -@@ -6467,4 +6467,46 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -6472,4 +6472,46 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess // Paper end - Expose entity id counter public boolean shouldTickHot() { return this.tickCount > 20 * 10 && this.isAlive(); } // KioCG diff --git a/lophine-server/src/main/java/com/logisticscraft/occlusionculling/DataProvider.java b/lophine-server/src/main/java/com/logisticscraft/occlusionculling/DataProvider.java new file mode 100644 index 0000000..ab2cd35 --- /dev/null +++ b/lophine-server/src/main/java/com/logisticscraft/occlusionculling/DataProvider.java @@ -0,0 +1,34 @@ +package com.logisticscraft.occlusionculling; + +import com.logisticscraft.occlusionculling.util.Vec3d; + +public interface DataProvider { + + /** + * Prepares the requested chunk. Returns true if the chunk is ready, false when + * not loaded. Should not reload the chunk when the x and y are the same as the + * last request! + * + * @param chunkX + * @param chunkZ + * @return + */ + boolean prepareChunk(int chunkX, int chunkZ); + + /** + * Location is inside the chunk. + * + * @param x + * @param y + * @param z + * @return + */ + boolean isOpaqueFullCube(int x, int y, int z); + + default void cleanup() { + } + + default void checkingPosition(Vec3d[] targetPoints, int size, Vec3d viewerPosition) { + } + +} \ No newline at end of file diff --git a/lophine-server/src/main/java/com/logisticscraft/occlusionculling/OcclusionCullingInstance.java b/lophine-server/src/main/java/com/logisticscraft/occlusionculling/OcclusionCullingInstance.java new file mode 100644 index 0000000..6131431 --- /dev/null +++ b/lophine-server/src/main/java/com/logisticscraft/occlusionculling/OcclusionCullingInstance.java @@ -0,0 +1,515 @@ +package com.logisticscraft.occlusionculling; + +import com.logisticscraft.occlusionculling.cache.ArrayOcclusionCache; +import com.logisticscraft.occlusionculling.cache.OcclusionCache; +import com.logisticscraft.occlusionculling.util.MathUtilities; +import com.logisticscraft.occlusionculling.util.Vec3d; + +import java.util.Arrays; +import java.util.BitSet; + +public class OcclusionCullingInstance { + + private static final int ON_MIN_X = 0x01; + private static final int ON_MAX_X = 0x02; + private static final int ON_MIN_Y = 0x04; + private static final int ON_MAX_Y = 0x08; + private static final int ON_MIN_Z = 0x10; + private static final int ON_MAX_Z = 0x20; + + private final int reach; + private final double aabbExpansion; + private final DataProvider provider; + private final OcclusionCache cache; + + // Reused allocated data structures + private final BitSet skipList = new BitSet(); // Grows bigger in case some mod introduces giant hitboxes + private final Vec3d[] targetPoints = new Vec3d[15]; + private final Vec3d targetPos = new Vec3d(0, 0, 0); + private final int[] cameraPos = new int[3]; + private final boolean[] dotselectors = new boolean[14]; + private boolean allowRayChecks = false; + private final int[] lastHitBlock = new int[3]; + private boolean allowWallClipping = false; + + + public OcclusionCullingInstance(int maxDistance, DataProvider provider) { + this(maxDistance, provider, new ArrayOcclusionCache(maxDistance), 0.5); + } + + public OcclusionCullingInstance(int maxDistance, DataProvider provider, OcclusionCache cache, double aabbExpansion) { + this.reach = maxDistance; + this.provider = provider; + this.cache = cache; + this.aabbExpansion = aabbExpansion; + for (int i = 0; i < targetPoints.length; i++) { + targetPoints[i] = new Vec3d(0, 0, 0); + } + } + + public boolean isAABBVisible(Vec3d aabbMin, Vec3d aabbMax, Vec3d viewerPosition) { + try { + int maxX = MathUtilities.floor(aabbMax.x + + aabbExpansion); + int maxY = MathUtilities.floor(aabbMax.y + + aabbExpansion); + int maxZ = MathUtilities.floor(aabbMax.z + + aabbExpansion); + int minX = MathUtilities.floor(aabbMin.x + - aabbExpansion); + int minY = MathUtilities.floor(aabbMin.y + - aabbExpansion); + int minZ = MathUtilities.floor(aabbMin.z + - aabbExpansion); + + cameraPos[0] = MathUtilities.floor(viewerPosition.x); + cameraPos[1] = MathUtilities.floor(viewerPosition.y); + cameraPos[2] = MathUtilities.floor(viewerPosition.z); + + Relative relX = Relative.from(minX, maxX, cameraPos[0]); + Relative relY = Relative.from(minY, maxY, cameraPos[1]); + Relative relZ = Relative.from(minZ, maxZ, cameraPos[2]); + + if (relX == Relative.INSIDE && relY == Relative.INSIDE && relZ == Relative.INSIDE) { + return true; // We are inside of the AABB, don't cull + } + + skipList.clear(); + + // Just check the cache first + int id = 0; + for (int x = minX; x <= maxX; x++) { + for (int y = minY; y <= maxY; y++) { + for (int z = minZ; z <= maxZ; z++) { + int cachedValue = getCacheValue(x, y, z); + + if (cachedValue == 1) { + // non-occluding + return true; + } + + if (cachedValue != 0) { + // was checked and it wasn't visible + skipList.set(id); + } + id++; + } + } + } + + // only after the first hit wall the cache becomes valid. + allowRayChecks = false; + + // since the cache wasn't helpfull + id = 0; + for (int x = minX; x <= maxX; x++) { + byte visibleOnFaceX = 0; + byte faceEdgeDataX = 0; + faceEdgeDataX |= (x == minX) ? ON_MIN_X : 0; + faceEdgeDataX |= (x == maxX) ? ON_MAX_X : 0; + visibleOnFaceX |= (x == minX && relX == Relative.POSITIVE) ? ON_MIN_X : 0; + visibleOnFaceX |= (x == maxX && relX == Relative.NEGATIVE) ? ON_MAX_X : 0; + for (int y = minY; y <= maxY; y++) { + byte faceEdgeDataY = faceEdgeDataX; + byte visibleOnFaceY = visibleOnFaceX; + faceEdgeDataY |= (y == minY) ? ON_MIN_Y : 0; + faceEdgeDataY |= (y == maxY) ? ON_MAX_Y : 0; + visibleOnFaceY |= (y == minY && relY == Relative.POSITIVE) ? ON_MIN_Y : 0; + visibleOnFaceY |= (y == maxY && relY == Relative.NEGATIVE) ? ON_MAX_Y : 0; + for (int z = minZ; z <= maxZ; z++) { + byte faceEdgeData = faceEdgeDataY; + byte visibleOnFace = visibleOnFaceY; + faceEdgeData |= (z == minZ) ? ON_MIN_Z : 0; + faceEdgeData |= (z == maxZ) ? ON_MAX_Z : 0; + visibleOnFace |= (z == minZ && relZ == Relative.POSITIVE) ? ON_MIN_Z : 0; + visibleOnFace |= (z == maxZ && relZ == Relative.NEGATIVE) ? ON_MAX_Z : 0; + if (skipList.get(id)) { // was checked and it wasn't visible + id++; + continue; + } + + if (visibleOnFace != 0) { + targetPos.set(x, y, z); + if (isVoxelVisible(viewerPosition, targetPos, faceEdgeData, visibleOnFace)) { + return true; + } + } + id++; + } + } + } + + return false; + } catch (Throwable t) { + // Failsafe + t.printStackTrace(); + } + return true; + } + + /** + * @param viewerPosition + * @param position + * @param faceData contains rather this Block is on the outside for a given face + * @param visibleOnFace contains rather a face should be concidered + * @return + */ + private boolean isVoxelVisible(Vec3d viewerPosition, Vec3d position, byte faceData, byte visibleOnFace) { + int targetSize = 0; + Arrays.fill(dotselectors, false); + if ((visibleOnFace & ON_MIN_X) == ON_MIN_X) { + dotselectors[0] = true; + if ((faceData & ~ON_MIN_X) != 0) { + dotselectors[1] = true; + dotselectors[4] = true; + dotselectors[5] = true; + } + dotselectors[8] = true; + } + if ((visibleOnFace & ON_MIN_Y) == ON_MIN_Y) { + dotselectors[0] = true; + if ((faceData & ~ON_MIN_Y) != 0) { + dotselectors[3] = true; + dotselectors[4] = true; + dotselectors[7] = true; + } + dotselectors[9] = true; + } + if ((visibleOnFace & ON_MIN_Z) == ON_MIN_Z) { + dotselectors[0] = true; + if ((faceData & ~ON_MIN_Z) != 0) { + dotselectors[1] = true; + dotselectors[4] = true; + dotselectors[5] = true; + } + dotselectors[10] = true; + } + if ((visibleOnFace & ON_MAX_X) == ON_MAX_X) { + dotselectors[4] = true; + if ((faceData & ~ON_MAX_X) != 0) { + dotselectors[5] = true; + dotselectors[6] = true; + dotselectors[7] = true; + } + dotselectors[11] = true; + } + if ((visibleOnFace & ON_MAX_Y) == ON_MAX_Y) { + dotselectors[1] = true; + if ((faceData & ~ON_MAX_Y) != 0) { + dotselectors[2] = true; + dotselectors[5] = true; + dotselectors[6] = true; + } + dotselectors[12] = true; + } + if ((visibleOnFace & ON_MAX_Z) == ON_MAX_Z) { + dotselectors[2] = true; + if ((faceData & ~ON_MAX_Z) != 0) { + dotselectors[3] = true; + dotselectors[6] = true; + dotselectors[7] = true; + } + dotselectors[13] = true; + } + + if (dotselectors[0]) targetPoints[targetSize++].setAdd(position, 0.05, 0.05, 0.05); + if (dotselectors[1]) targetPoints[targetSize++].setAdd(position, 0.05, 0.95, 0.05); + if (dotselectors[2]) targetPoints[targetSize++].setAdd(position, 0.05, 0.95, 0.95); + if (dotselectors[3]) targetPoints[targetSize++].setAdd(position, 0.05, 0.05, 0.95); + if (dotselectors[4]) targetPoints[targetSize++].setAdd(position, 0.95, 0.05, 0.05); + if (dotselectors[5]) targetPoints[targetSize++].setAdd(position, 0.95, 0.95, 0.05); + if (dotselectors[6]) targetPoints[targetSize++].setAdd(position, 0.95, 0.95, 0.95); + if (dotselectors[7]) targetPoints[targetSize++].setAdd(position, 0.95, 0.05, 0.95); + // middle points + if (dotselectors[8]) targetPoints[targetSize++].setAdd(position, 0.05, 0.5, 0.5); + if (dotselectors[9]) targetPoints[targetSize++].setAdd(position, 0.5, 0.05, 0.5); + if (dotselectors[10]) targetPoints[targetSize++].setAdd(position, 0.5, 0.5, 0.05); + if (dotselectors[11]) targetPoints[targetSize++].setAdd(position, 0.95, 0.5, 0.5); + if (dotselectors[12]) targetPoints[targetSize++].setAdd(position, 0.5, 0.95, 0.5); + if (dotselectors[13]) targetPoints[targetSize++].setAdd(position, 0.5, 0.5, 0.95); + + return isVisible(viewerPosition, targetPoints, targetSize); + } + + private boolean rayIntersection(int[] b, Vec3d rayOrigin, Vec3d rayDir) { + Vec3d rInv = new Vec3d(1, 1, 1).div(rayDir); + + double t1 = (b[0] - rayOrigin.x) * rInv.x; + double t2 = (b[0] + 1 - rayOrigin.x) * rInv.x; + double t3 = (b[1] - rayOrigin.y) * rInv.y; + double t4 = (b[1] + 1 - rayOrigin.y) * rInv.y; + double t5 = (b[2] - rayOrigin.z) * rInv.z; + double t6 = (b[2] + 1 - rayOrigin.z) * rInv.z; + + double tmin = Math.max(Math.max(Math.min(t1, t2), Math.min(t3, t4)), Math.min(t5, t6)); + double tmax = Math.min(Math.min(Math.max(t1, t2), Math.max(t3, t4)), Math.max(t5, t6)); + + // if tmax > 0, ray (line) is intersecting AABB, but the whole AABB is behind us + if (tmax > 0) { + return false; + } + + // if tmin > tmax, ray doesn't intersect AABB + if (tmin > tmax) { + return false; + } + + return true; + } + + /** + * returns the grid cells that intersect with this Vec3d
+ * http://playtechs.blogspot.de/2007/03/raytracing-on-grid.html + *

+ * Caching assumes that all Vec3d's are inside the same block + */ + private boolean isVisible(Vec3d start, Vec3d[] targets, int size) { + // start cell coordinate + int x = cameraPos[0]; + int y = cameraPos[1]; + int z = cameraPos[2]; + + for (int v = 0; v < size; v++) { + // ray-casting target + Vec3d target = targets[v]; + + double relativeX = start.x - target.getX(); + double relativeY = start.y - target.getY(); + double relativeZ = start.z - target.getZ(); + + if (allowRayChecks && rayIntersection(lastHitBlock, start, new Vec3d(relativeX, relativeY, relativeZ).normalize())) { + continue; + } + + // horizontal and vertical cell amount spanned + double dimensionX = Math.abs(relativeX); + double dimensionY = Math.abs(relativeY); + double dimensionZ = Math.abs(relativeZ); + + // distance between horizontal intersection points with cell border as a + // fraction of the total Vec3d length + double dimFracX = 1f / dimensionX; + // distance between vertical intersection points with cell border as a fraction + // of the total Vec3d length + double dimFracY = 1f / dimensionY; + double dimFracZ = 1f / dimensionZ; + + // total amount of intersected cells + int intersectCount = 1; + + // 1, 0 or -1 + // determines the direction of the next cell (horizontally / vertically) + int x_inc, y_inc, z_inc; + + // the distance to the next horizontal / vertical intersection point with a cell + // border as a fraction of the total Vec3d length + double t_next_y, t_next_x, t_next_z; + + if (dimensionX == 0f) { + x_inc = 0; + t_next_x = dimFracX; // don't increment horizontally because the Vec3d is perfectly vertical + } else if (target.x > start.x) { + x_inc = 1; // target point is horizontally greater than starting point so increment every + // step by 1 + intersectCount += MathUtilities.floor(target.x) - x; // increment total amount of intersecting cells + t_next_x = (float) ((x + 1 - start.x) * dimFracX); // calculate the next horizontal + // intersection + // point based on the position inside + // the first cell + } else { + x_inc = -1; // target point is horizontally smaller than starting point so reduce every step + // by 1 + intersectCount += x - MathUtilities.floor(target.x); // increment total amount of intersecting cells + t_next_x = (float) ((start.x - x) + * dimFracX); // calculate the next horizontal + // intersection point + // based on the position inside + // the first cell + } + + if (dimensionY == 0f) { + y_inc = 0; + t_next_y = dimFracY; // don't increment vertically because the Vec3d is perfectly horizontal + } else if (target.y > start.y) { + y_inc = 1; // target point is vertically greater than starting point so increment every + // step by 1 + intersectCount += MathUtilities.floor(target.y) - y; // increment total amount of intersecting cells + t_next_y = (float) ((y + 1 - start.y) + * dimFracY); // calculate the next vertical + // intersection + // point based on the position inside + // the first cell + } else { + y_inc = -1; // target point is vertically smaller than starting point so reduce every step + // by 1 + intersectCount += y - MathUtilities.floor(target.y); // increment total amount of intersecting cells + t_next_y = (float) ((start.y - y) + * dimFracY); // calculate the next vertical intersection + // point + // based on the position inside + // the first cell + } + + if (dimensionZ == 0f) { + z_inc = 0; + t_next_z = dimFracZ; // don't increment vertically because the Vec3d is perfectly horizontal + } else if (target.z > start.z) { + z_inc = 1; // target point is vertically greater than starting point so increment every + // step by 1 + intersectCount += MathUtilities.floor(target.z) - z; // increment total amount of intersecting cells + t_next_z = (float) ((z + 1 - start.z) + * dimFracZ); // calculate the next vertical + // intersection + // point based on the position inside + // the first cell + } else { + z_inc = -1; // target point is vertically smaller than starting point so reduce every step + // by 1 + intersectCount += z - MathUtilities.floor(target.z); // increment total amount of intersecting cells + t_next_z = (float) ((start.z - z) + * dimFracZ); // calculate the next vertical intersection + // point + // based on the position inside + // the first cell + } + + boolean finished = stepRay(start, x, y, z, + dimFracX, dimFracY, dimFracZ, intersectCount, x_inc, y_inc, + z_inc, t_next_y, t_next_x, t_next_z); + provider.cleanup(); + if (finished) { + cacheResult(targets[0], true); + return true; + } else { + allowRayChecks = true; + } + } + cacheResult(targets[0], false); + return false; + } + + private boolean stepRay(Vec3d start, int currentX, int currentY, + int currentZ, double distInX, double distInY, + double distInZ, int n, int x_inc, int y_inc, + int z_inc, double t_next_y, double t_next_x, + double t_next_z) { + allowWallClipping = true; // initially allow rays to go through walls till they are on the outside + // iterate through all intersecting cells (n times) + for (; n > 1; n--) { // n-1 times because we don't want to check the last block + // towards - where from + + + // get cached value, 0 means uncached (default) + int cVal = getCacheValue(currentX, currentY, currentZ); + + if (cVal == 2 && !allowWallClipping) { + // block cached as occluding, stop ray + lastHitBlock[0] = currentX; + lastHitBlock[1] = currentY; + lastHitBlock[2] = currentZ; + return false; + } + + if (cVal == 0) { + // save current cell + int chunkX = currentX >> 4; + int chunkZ = currentZ >> 4; + + if (!provider.prepareChunk(chunkX, chunkZ)) { // Chunk not ready + return false; + } + + if (provider.isOpaqueFullCube(currentX, currentY, currentZ)) { + if (!allowWallClipping) { + cache.setLastHidden(); + lastHitBlock[0] = currentX; + lastHitBlock[1] = currentY; + lastHitBlock[2] = currentZ; + return false; + } + } else { + // outside of wall, now clipping is not allowed + allowWallClipping = false; + cache.setLastVisible(); + } + } + + if (cVal == 1) { + // outside of wall, now clipping is not allowed + allowWallClipping = false; + } + + + if (t_next_y < t_next_x && t_next_y < t_next_z) { // next cell is upwards/downwards because the distance to + // the next vertical + // intersection point is smaller than to the next horizontal intersection point + currentY += y_inc; // move up/down + t_next_y += distInY; // update next vertical intersection point + } else if (t_next_x < t_next_y && t_next_x < t_next_z) { // next cell is right/left + currentX += x_inc; // move right/left + t_next_x += distInX; // update next horizontal intersection point + } else { + currentZ += z_inc; // move right/left + t_next_z += distInZ; // update next horizontal intersection point + } + + } + return true; + } + + // -1 = invalid location, 0 = not checked yet, 1 = visible, 2 = occluding + private int getCacheValue(int x, int y, int z) { + x -= cameraPos[0]; + y -= cameraPos[1]; + z -= cameraPos[2]; + if (Math.abs(x) > reach - 2 || Math.abs(y) > reach - 2 + || Math.abs(z) > reach - 2) { + return -1; + } + + // check if target is already known + return cache.getState(x + reach, y + reach, z + reach); + } + + + private void cacheResult(int x, int y, int z, boolean result) { + int cx = x - cameraPos[0] + reach; + int cy = y - cameraPos[1] + reach; + int cz = z - cameraPos[2] + reach; + if (result) { + cache.setVisible(cx, cy, cz); + } else { + cache.setHidden(cx, cy, cz); + } + } + + private void cacheResult(Vec3d vector, boolean result) { + int cx = MathUtilities.floor(vector.x) - cameraPos[0] + reach; + int cy = MathUtilities.floor(vector.y) - cameraPos[1] + reach; + int cz = MathUtilities.floor(vector.z) - cameraPos[2] + reach; + if (result) { + cache.setVisible(cx, cy, cz); + } else { + cache.setHidden(cx, cy, cz); + } + } + + public void resetCache() { + this.cache.resetCache(); + } + + private enum Relative { + INSIDE, POSITIVE, NEGATIVE; + + public static Relative from(int min, int max, int pos) { + if (max > pos && min > pos) { + return POSITIVE; + } else if (min < pos && max < pos) { + return NEGATIVE; + } + return INSIDE; + } + } + +} \ No newline at end of file diff --git a/lophine-server/src/main/java/com/logisticscraft/occlusionculling/cache/ArrayOcclusionCache.java b/lophine-server/src/main/java/com/logisticscraft/occlusionculling/cache/ArrayOcclusionCache.java new file mode 100644 index 0000000..595bf54 --- /dev/null +++ b/lophine-server/src/main/java/com/logisticscraft/occlusionculling/cache/ArrayOcclusionCache.java @@ -0,0 +1,57 @@ +package com.logisticscraft.occlusionculling.cache; + +import java.util.Arrays; + +public class ArrayOcclusionCache implements OcclusionCache { + + private final int reachX2; + private final byte[] cache; + private int positionKey; + private int entry; + private int offset; + + public ArrayOcclusionCache(int reach) { + this.reachX2 = reach * 2; + this.cache = new byte[(reachX2 * reachX2 * reachX2) / 4]; + } + + @Override + public void resetCache() { + Arrays.fill(cache, (byte) 0); + } + + @Override + public void setVisible(int x, int y, int z) { + positionKey = x + y * reachX2 + z * reachX2 * reachX2; + entry = positionKey / 4; + offset = (positionKey % 4) * 2; + cache[entry] |= 1 << offset; + } + + @Override + public void setHidden(int x, int y, int z) { + positionKey = x + y * reachX2 + z * reachX2 * reachX2; + entry = positionKey / 4; + offset = (positionKey % 4) * 2; + cache[entry] |= 1 << offset + 1; + } + + @Override + public int getState(int x, int y, int z) { + positionKey = x + y * reachX2 + z * reachX2 * reachX2; + entry = positionKey / 4; + offset = (positionKey % 4) * 2; + return cache[entry] >> offset & 3; + } + + @Override + public void setLastVisible() { + cache[entry] |= 1 << offset; + } + + @Override + public void setLastHidden() { + cache[entry] |= 1 << offset + 1; + } + +} \ No newline at end of file diff --git a/lophine-server/src/main/java/com/logisticscraft/occlusionculling/cache/OcclusionCache.java b/lophine-server/src/main/java/com/logisticscraft/occlusionculling/cache/OcclusionCache.java new file mode 100644 index 0000000..a5af322 --- /dev/null +++ b/lophine-server/src/main/java/com/logisticscraft/occlusionculling/cache/OcclusionCache.java @@ -0,0 +1,17 @@ +package com.logisticscraft.occlusionculling.cache; + +public interface OcclusionCache { + + void resetCache(); + + void setVisible(int x, int y, int z); + + void setHidden(int x, int y, int z); + + int getState(int x, int y, int z); + + void setLastHidden(); + + void setLastVisible(); + +} \ No newline at end of file diff --git a/lophine-server/src/main/java/com/logisticscraft/occlusionculling/util/MathUtilities.java b/lophine-server/src/main/java/com/logisticscraft/occlusionculling/util/MathUtilities.java new file mode 100644 index 0000000..f044e72 --- /dev/null +++ b/lophine-server/src/main/java/com/logisticscraft/occlusionculling/util/MathUtilities.java @@ -0,0 +1,25 @@ +package com.logisticscraft.occlusionculling.util; + +/** + * Contains MathHelper methods + */ +public final class MathUtilities { + + private MathUtilities() { + } + + public static int floor(double d) { + int i = (int) d; + return d < (double) i ? i - 1 : i; + } + + public static int fastFloor(double d) { + return (int) (d + 1024.0) - 1024; + } + + public static int ceil(double d) { + int i = (int) d; + return d > (double) i ? i + 1 : i; + } + +} \ No newline at end of file diff --git a/lophine-server/src/main/java/com/logisticscraft/occlusionculling/util/Vec3d.java b/lophine-server/src/main/java/com/logisticscraft/occlusionculling/util/Vec3d.java new file mode 100644 index 0000000..4875c46 --- /dev/null +++ b/lophine-server/src/main/java/com/logisticscraft/occlusionculling/util/Vec3d.java @@ -0,0 +1,87 @@ +package com.logisticscraft.occlusionculling.util; + +public class Vec3d { + + public double x; + public double y; + public double z; + + public Vec3d(double x, double y, double z) { + this.x = x; + this.y = y; + this.z = z; + } + + public double getX() { + return x; + } + + public double getY() { + return y; + } + + public double getZ() { + return z; + } + + public void set(double x, double y, double z) { + this.x = x; + this.y = y; + this.z = z; + } + + public void setAdd(Vec3d vec, double x, double y, double z) { + this.x = vec.x + x; + this.y = vec.y + y; + this.z = vec.z + z; + } + + public Vec3d div(Vec3d rayDir) { + this.x /= rayDir.x; + this.z /= rayDir.z; + this.y /= rayDir.y; + return this; + } + + public Vec3d normalize() { + double mag = Math.sqrt(x * x + y * y + z * z); + this.x /= mag; + this.y /= mag; + this.z /= mag; + return this; + } + + public boolean equals(Object other) { + if (this == other) { + return true; + } + if (!(other instanceof Vec3d)) { + return false; + } + Vec3d vec3d = (Vec3d) other; + if (Double.compare(vec3d.x, x) != 0) { + return false; + } + if (Double.compare(vec3d.y, y) != 0) { + return false; + } + return Double.compare(vec3d.z, z) == 0; + } + + @Override + public int hashCode() { + long l = Double.doubleToLongBits(x); + int i = (int) (l ^ l >>> 32); + l = Double.doubleToLongBits(y); + i = 31 * i + (int) (l ^ l >>> 32); + l = Double.doubleToLongBits(z); + i = 31 * i + (int) (l ^ l >>> 32); + return i; + } + + @Override + public String toString() { + return "(" + x + ", " + y + ", " + z + ")"; + } + +} \ No newline at end of file diff --git a/lophine-server/src/main/java/fun/bm/lophine/config/modules/experiment/CommandConfig.java b/lophine-server/src/main/java/fun/bm/lophine/config/modules/experiment/CommandConfig.java index a26fd95..f5c95d4 100644 --- a/lophine-server/src/main/java/fun/bm/lophine/config/modules/experiment/CommandConfig.java +++ b/lophine-server/src/main/java/fun/bm/lophine/config/modules/experiment/CommandConfig.java @@ -2,8 +2,10 @@ package fun.bm.lophine.config.modules.experiment; import me.earthme.luminol.config.EnumConfigCategory; import me.earthme.luminol.config.IConfigModule; +import me.earthme.luminol.config.flags.ConfigClassInfo; import me.earthme.luminol.config.flags.ConfigInfo; +@ConfigClassInfo(configAttribution = EnumConfigCategory.EXPERIMENT, mainName = "command") public class CommandConfig implements IConfigModule { @ConfigInfo(baseName = "tick_command_enabled", comments = """ @@ -15,14 +17,4 @@ public class CommandConfig implements IConfigModule { Allow to use datapack command --- datapack hot-update unsupported, please restart server""") public static boolean datapack = false; - - @Override - public EnumConfigCategory getCategory() { - return EnumConfigCategory.EXPERIMENT; - } - - @Override - public String getBaseName() { - return "command"; - } } \ No newline at end of file diff --git a/lophine-server/src/main/java/fun/bm/lophine/config/modules/experiment/EntityDamageSourceTraceConfig.java b/lophine-server/src/main/java/fun/bm/lophine/config/modules/experiment/EntityDamageSourceTraceConfig.java index b8f810c..3cdaf84 100644 --- a/lophine-server/src/main/java/fun/bm/lophine/config/modules/experiment/EntityDamageSourceTraceConfig.java +++ b/lophine-server/src/main/java/fun/bm/lophine/config/modules/experiment/EntityDamageSourceTraceConfig.java @@ -2,21 +2,13 @@ package fun.bm.lophine.config.modules.experiment; import me.earthme.luminol.config.EnumConfigCategory; import me.earthme.luminol.config.IConfigModule; +import me.earthme.luminol.config.flags.ConfigClassInfo; import me.earthme.luminol.config.flags.ConfigInfo; +@ConfigClassInfo(configAttribution = EnumConfigCategory.EXPERIMENT, mainName = "entity_damage_source_trace") public class EntityDamageSourceTraceConfig implements IConfigModule { @ConfigInfo(baseName = "enabled", comments = """ Allow trace damage source cross different Region Scheduler.""") public static boolean enabled = false; - - @Override - public EnumConfigCategory getCategory() { - return EnumConfigCategory.EXPERIMENT; - } - - @Override - public String getBaseName() { - return "entity_damage_source_trace"; - } } \ No newline at end of file diff --git a/lophine-server/src/main/java/fun/bm/lophine/config/modules/experiment/RayTrackingEntityTrackerConfig.java b/lophine-server/src/main/java/fun/bm/lophine/config/modules/experiment/RayTrackingEntityTrackerConfig.java index 356458f..1bba7c6 100644 --- a/lophine-server/src/main/java/fun/bm/lophine/config/modules/experiment/RayTrackingEntityTrackerConfig.java +++ b/lophine-server/src/main/java/fun/bm/lophine/config/modules/experiment/RayTrackingEntityTrackerConfig.java @@ -2,8 +2,10 @@ package fun.bm.lophine.config.modules.experiment; import me.earthme.luminol.config.EnumConfigCategory; import me.earthme.luminol.config.IConfigModule; +import me.earthme.luminol.config.flags.ConfigClassInfo; import me.earthme.luminol.config.flags.ConfigInfo; +@ConfigClassInfo(configAttribution = EnumConfigCategory.EXPERIMENT, mainName = "ray_tracking_entity_tracker") public class RayTrackingEntityTrackerConfig implements IConfigModule { @ConfigInfo(baseName = "enabled") public static boolean enabled = false; @@ -15,14 +17,4 @@ public class RayTrackingEntityTrackerConfig implements IConfigModule { public static int tracingDistance = 48; @ConfigInfo(baseName = "hitbox_limit") public static int hitboxLimit = 50; - - @Override - public EnumConfigCategory getCategory() { - return EnumConfigCategory.EXPERIMENT; - } - - @Override - public String getBaseName() { - return "ray_tracking_entity_tracker"; - } } \ No newline at end of file diff --git a/lophine-server/src/main/java/fun/bm/lophine/config/modules/experiment/WaypointConfig.java b/lophine-server/src/main/java/fun/bm/lophine/config/modules/experiment/WaypointConfig.java index 699f7e1..90d8917 100644 --- a/lophine-server/src/main/java/fun/bm/lophine/config/modules/experiment/WaypointConfig.java +++ b/lophine-server/src/main/java/fun/bm/lophine/config/modules/experiment/WaypointConfig.java @@ -2,23 +2,15 @@ package fun.bm.lophine.config.modules.experiment; import me.earthme.luminol.config.EnumConfigCategory; import me.earthme.luminol.config.IConfigModule; +import me.earthme.luminol.config.flags.ConfigClassInfo; import me.earthme.luminol.config.flags.ConfigInfo; import me.earthme.luminol.config.flags.TransformedConfig; +@ConfigClassInfo(configAttribution = EnumConfigCategory.EXPERIMENT, mainName = "waypoint_bar") public class WaypointConfig implements IConfigModule { @TransformedConfig(name = "enable-waypoint", category = {"experiment", "waypoint bar"}) @ConfigInfo(baseName = "enabled", comments = """ Enable waypoint bar unsafe""") public static boolean forceEnableWaypointUnsafe = false; - - @Override - public EnumConfigCategory getCategory() { - return EnumConfigCategory.EXPERIMENT; - } - - @Override - public String getBaseName() { - return "waypoint_bar"; - } } diff --git a/lophine-server/src/main/java/fun/bm/lophine/config/modules/misc/ContainerExpansionConfig.java b/lophine-server/src/main/java/fun/bm/lophine/config/modules/misc/ContainerExpansionConfig.java index 7b57f4b..b13e714 100644 --- a/lophine-server/src/main/java/fun/bm/lophine/config/modules/misc/ContainerExpansionConfig.java +++ b/lophine-server/src/main/java/fun/bm/lophine/config/modules/misc/ContainerExpansionConfig.java @@ -2,8 +2,10 @@ package fun.bm.lophine.config.modules.misc; import me.earthme.luminol.config.EnumConfigCategory; import me.earthme.luminol.config.IConfigModule; +import me.earthme.luminol.config.flags.ConfigClassInfo; import me.earthme.luminol.config.flags.ConfigInfo; +@ConfigClassInfo(configAttribution = EnumConfigCategory.MISC, mainName = "container_expansion") public class ContainerExpansionConfig implements IConfigModule { @ConfigInfo(baseName = "barrel_rows", comments = """ @@ -22,14 +24,4 @@ public class ContainerExpansionConfig implements IConfigModule { @ConfigInfo(baseName = "same_nbt_shulker_stackable") public static boolean nbtShulkerStackable = false; - - @Override - public EnumConfigCategory getCategory() { - return EnumConfigCategory.MISC; - } - - @Override - public String getBaseName() { - return "container_expansion"; - } } \ No newline at end of file diff --git a/lophine-server/src/main/java/fun/bm/lophine/config/modules/misc/DisableCheckConfig.java b/lophine-server/src/main/java/fun/bm/lophine/config/modules/misc/DisableCheckConfig.java index 50e9c14..d5a67d4 100644 --- a/lophine-server/src/main/java/fun/bm/lophine/config/modules/misc/DisableCheckConfig.java +++ b/lophine-server/src/main/java/fun/bm/lophine/config/modules/misc/DisableCheckConfig.java @@ -2,8 +2,10 @@ package fun.bm.lophine.config.modules.misc; import me.earthme.luminol.config.EnumConfigCategory; import me.earthme.luminol.config.IConfigModule; +import me.earthme.luminol.config.flags.ConfigClassInfo; import me.earthme.luminol.config.flags.ConfigInfo; +@ConfigClassInfo(configAttribution = EnumConfigCategory.MISC, mainName = "disable_check") public class DisableCheckConfig implements IConfigModule { @ConfigInfo(baseName = "disable-op-move-check", comments = """ Disable the check for the operator's move check""") @@ -12,14 +14,4 @@ public class DisableCheckConfig implements IConfigModule { @ConfigInfo(baseName = "disable-op-fly-check", comments = """ Disable the check for the operator's fly check""") public static boolean disableOpFlyCheck = false; - - @Override - public EnumConfigCategory getCategory() { - return EnumConfigCategory.MISC; - } - - @Override - public String getBaseName() { - return "disable-check"; - } } diff --git a/lophine-server/src/main/java/fun/bm/lophine/config/modules/misc/OldFeatureConfig.java b/lophine-server/src/main/java/fun/bm/lophine/config/modules/misc/OldFeatureConfig.java index a0bddbd..033133a 100644 --- a/lophine-server/src/main/java/fun/bm/lophine/config/modules/misc/OldFeatureConfig.java +++ b/lophine-server/src/main/java/fun/bm/lophine/config/modules/misc/OldFeatureConfig.java @@ -2,9 +2,11 @@ package fun.bm.lophine.config.modules.misc; import me.earthme.luminol.config.EnumConfigCategory; import me.earthme.luminol.config.IConfigModule; +import me.earthme.luminol.config.flags.ConfigClassInfo; import me.earthme.luminol.config.flags.ConfigInfo; import me.earthme.luminol.config.flags.TransformedConfig; +@ConfigClassInfo(configAttribution = EnumConfigCategory.MISC, mainName = "old_feature") public class OldFeatureConfig implements IConfigModule { @ConfigInfo(baseName = "spawn_invulnerable_time") public static boolean spawnInvulnerableTime = false; @@ -18,14 +20,4 @@ public class OldFeatureConfig implements IConfigModule { @TransformedConfig(name = "give_bad_omen_when_kill_raid_captain", category = {"misc", "revert_raid_changes"}, transformComments = false) @ConfigInfo(baseName = "old_raid_behavior") public static boolean oldRaidBehavior = false; - - @Override - public EnumConfigCategory getCategory() { - return EnumConfigCategory.MISC; - } - - @Override - public String getBaseName() { - return "old-feature"; - } } \ No newline at end of file diff --git a/lophine-server/src/main/java/fun/bm/lophine/config/modules/misc/RedStoneConfig.java b/lophine-server/src/main/java/fun/bm/lophine/config/modules/misc/RedStoneConfig.java index 3a200fa..2e5c6c7 100644 --- a/lophine-server/src/main/java/fun/bm/lophine/config/modules/misc/RedStoneConfig.java +++ b/lophine-server/src/main/java/fun/bm/lophine/config/modules/misc/RedStoneConfig.java @@ -2,23 +2,15 @@ package fun.bm.lophine.config.modules.misc; import me.earthme.luminol.config.EnumConfigCategory; import me.earthme.luminol.config.IConfigModule; +import me.earthme.luminol.config.flags.ConfigClassInfo; import me.earthme.luminol.config.flags.ConfigInfo; import me.earthme.luminol.config.flags.TransformedConfig; +@ConfigClassInfo(configAttribution = EnumConfigCategory.MISC, mainName = "redstone") public class RedStoneConfig implements IConfigModule { @TransformedConfig(name = "allow_skip_cooldown", category = {"misc", "redstone"}) @ConfigInfo(baseName = "shears_rotate", comments = """ Allows you to use the Shears to right-click to rotate the block.""") public static boolean shears = false; - - @Override - public EnumConfigCategory getCategory() { - return EnumConfigCategory.MISC; - } - - @Override - public String getBaseName() { - return "redstone"; - } } \ No newline at end of file diff --git a/lophine-server/src/main/java/fun/bm/lophine/config/modules/misc/SurvuxProtocolConfig.java b/lophine-server/src/main/java/fun/bm/lophine/config/modules/misc/SurvuxProtocolConfig.java index d2099f9..fd735e2 100644 --- a/lophine-server/src/main/java/fun/bm/lophine/config/modules/misc/SurvuxProtocolConfig.java +++ b/lophine-server/src/main/java/fun/bm/lophine/config/modules/misc/SurvuxProtocolConfig.java @@ -2,10 +2,12 @@ package fun.bm.lophine.config.modules.misc; import me.earthme.luminol.config.EnumConfigCategory; import me.earthme.luminol.config.IConfigModule; +import me.earthme.luminol.config.flags.ConfigClassInfo; import me.earthme.luminol.config.flags.ConfigInfo; import java.util.List; +@ConfigClassInfo(configAttribution = EnumConfigCategory.MISC, mainName = "survux_protocol") public class SurvuxProtocolConfig implements IConfigModule { @ConfigInfo(baseName = "entity-protocol") public static boolean entityProtocol = false; @@ -33,14 +35,4 @@ public class SurvuxProtocolConfig implements IConfigModule { @ConfigInfo(baseName = "litematics-max-nbt-size") public static int litematicsMaxNbtSize = 2097152; - - @Override - public EnumConfigCategory getCategory() { - return EnumConfigCategory.MISC; - } - - @Override - public String getBaseName() { - return "servux-protocol"; - } } diff --git a/lophine-server/src/main/java/fun/bm/lophine/config/modules/misc/VillagerConfig.java b/lophine-server/src/main/java/fun/bm/lophine/config/modules/misc/VillagerConfig.java index 0fd4d76..201fede 100644 --- a/lophine-server/src/main/java/fun/bm/lophine/config/modules/misc/VillagerConfig.java +++ b/lophine-server/src/main/java/fun/bm/lophine/config/modules/misc/VillagerConfig.java @@ -2,22 +2,16 @@ package fun.bm.lophine.config.modules.misc; import me.earthme.luminol.config.EnumConfigCategory; import me.earthme.luminol.config.IConfigModule; +import me.earthme.luminol.config.flags.ConfigClassInfo; import me.earthme.luminol.config.flags.ConfigInfo; +import me.earthme.luminol.config.flags.TransformedConfig; +@ConfigClassInfo(configAttribution = EnumConfigCategory.MISC, mainName = "villager") public class VillagerConfig implements IConfigModule { + @TransformedConfig(name = "villager-infinite-trade", category = {"misc", "villager-config"}) @ConfigInfo(baseName = "villager-infinite-trade", comments = """ Allow villager infinite trade (limit of 524288 times) ---- we won't edit saved data, only edit in send data to client.""") public static boolean villagerInfiniteTrade = false; - - @Override - public EnumConfigCategory getCategory() { - return EnumConfigCategory.MISC; - } - - @Override - public String getBaseName() { - return "villager-config"; - } } diff --git a/lophine-server/src/main/java/fun/bm/lophine/config/modules/optimizations/LanguageConfig.java b/lophine-server/src/main/java/fun/bm/lophine/config/modules/optimizations/LanguageConfig.java index a8c0ad5..6929d20 100644 --- a/lophine-server/src/main/java/fun/bm/lophine/config/modules/optimizations/LanguageConfig.java +++ b/lophine-server/src/main/java/fun/bm/lophine/config/modules/optimizations/LanguageConfig.java @@ -2,21 +2,13 @@ package fun.bm.lophine.config.modules.optimizations; import me.earthme.luminol.config.EnumConfigCategory; import me.earthme.luminol.config.IConfigModule; +import me.earthme.luminol.config.flags.ConfigClassInfo; import me.earthme.luminol.config.flags.ConfigInfo; +@ConfigClassInfo(configAttribution = EnumConfigCategory.OPTIMIZATIONS, mainName = "language") public class LanguageConfig implements IConfigModule { @ConfigInfo(baseName = "lang", comments = """ Please use the key from https://minecraft.wiki/w/Language Sample of format: en_us zh_cn zh_hk zh_tw""") public static String lang = "en_us"; - - @Override - public EnumConfigCategory getCategory() { - return EnumConfigCategory.OPTIMIZATIONS; - } - - @Override - public String getBaseName() { - return "language"; - } } \ No newline at end of file diff --git a/lophine-server/src/main/java/fun/bm/lophine/config/modules/removed/RemovedConfig.java b/lophine-server/src/main/java/fun/bm/lophine/config/modules/removed/RemovedConfig.java index 8d65f9a..3783fde 100644 --- a/lophine-server/src/main/java/fun/bm/lophine/config/modules/removed/RemovedConfig.java +++ b/lophine-server/src/main/java/fun/bm/lophine/config/modules/removed/RemovedConfig.java @@ -2,9 +2,11 @@ package fun.bm.lophine.config.modules.removed; import me.earthme.luminol.config.EnumConfigCategory; import me.earthme.luminol.config.IConfigModule; +import me.earthme.luminol.config.flags.ConfigClassInfo; import me.earthme.luminol.config.flags.ConfigInfo; import me.earthme.luminol.config.flags.TransformedConfig; +@ConfigClassInfo(configAttribution = EnumConfigCategory.REMOVED, mainName = "removed_config") public class RemovedConfig implements IConfigModule { @TransformedConfig(name = "disable_end_crystal_check", category = {"fixes", "end_crystal"}, transform = false) @TransformedConfig(name = "disable_end_crystal_check", category = {"misc", "end_crystal"}, transform = false) @@ -21,14 +23,4 @@ public class RemovedConfig implements IConfigModule { """ RemovedConfig redirect to here, no any function.""") public static boolean enabled = true; - - @Override - public EnumConfigCategory getCategory() { - return EnumConfigCategory.REMOVED; - } - - @Override - public String getBaseName() { - return "removed_config"; - } } \ No newline at end of file