Compare commits

..

3 Commits

Author SHA1 Message Date
MrHua269
d2fc625ce9 Fix off region thrown egg new entity creating
should set pos before so that we could correctly modify the entity's other attribute on-region without triggering the async catchers
2025-06-05 21:42:38 +08:00
Helvetica Volubi
70efb6748b fix: introduced two patches from leaves to fix some bugs
update [Fix Incorrect Collision Behavior for Block Shape] to [Configurable collision behavior]

fix chunk reload detector

20250604 23:22:57 UTC+8: use BLOCK_SHAPE_VANILLA as default instead of PAPER
2025-06-04 23:35:31 +08:00
Helvetica Volubi
4ea7b2833b feat: add config query, set and reset support 2025-06-03 23:42:29 +08:00
35 changed files with 260 additions and 95 deletions

View File

@@ -19,8 +19,8 @@ jobs:
- name: Set up JDK
uses: actions/setup-java@v4
with:
distribution: 'zulu'
java-version: '22'
distribution: zulu
java-version: 22
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v4
@@ -28,17 +28,16 @@ jobs:
- name: Configure Git User Details
run: git config --global user.email "ci@luminolmc.com" && git config --global user.name "LuminolMC CI"
- name: Apply Patches
- name: Apply All Patches
run: ./gradlew applyAllPatches
- name: CreateJar
- name: CreateMojmapPaperclipJar
run: ./gradlew createMojmapPaperclipJar
- name: Publish to repo
if: github.event_name != 'pull_request'
continue-on-error: true
run: |
./gradlew generateDevelopmentBundle publish -PpublishDevBundle=true
run: ./gradlew generateDevelopmentBundle publish -PpublishDevBundle=true
env:
PRIVATE_MAVEN_REPO_PASSWORD: ${{ secrets.PRIVATE_MAVEN_REPO_PASSWORD }}
PRIVATE_MAVEN_REPO_USERNAME: ${{ secrets.PRIVATE_MAVEN_REPO_USERNAME }}
@@ -46,8 +45,8 @@ jobs:
- name: Upload Artifact
uses: actions/upload-artifact@v4
with:
name: "${{ env.project_id_b }} CI Artifacts"
path: "luminol-server/build/libs/*-paperclip-*-mojmap.jar"
name: ${{ env.project_id_b }} CI Artifacts
path: luminol-server/build/libs/*-paperclip-*-mojmap.jar
- name: SetENV
if: github.event_name != 'pull_request'
@@ -64,9 +63,8 @@ jobs:
This release is automatically compiled by GitHub Actions
### Commit Message
${{ env.commit_msg }}
artifacts: |
${{ env.jar_dir }}
artifacts: ${{ env.jar_dir }}
generateReleaseNotes: true
prerelease: false
prerelease: ${{ env.pre }}
makeLatest: ${{ env.make_latest }}
token: "${{ secrets.GITHUB_TOKEN }}"
token: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -0,0 +1,56 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Wed, 4 Jun 2025 12:51:07 +0800
Subject: [PATCH] Leaves: Configurable collision behavior
Co-authored by: Fortern <blueten.ki@gmail.com>
As part of: Leaves (https://github.com/LeavesMC/Leaves/blob/c5f18b7864206cea4411211b51787f10affbcb9c/leaves-server/minecraft-patches/features/0111-Configurable-collision-behavior.patch)
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/ca/spottedleaf/moonrise/patches/collisions/CollisionUtil.java b/ca/spottedleaf/moonrise/patches/collisions/CollisionUtil.java
index e1bf7bc3cca63101b3c0550b5b4c0d28d0f3776e..d753d550b1df88ad9f2315ec3fc8f342be183c6d 100644
--- a/ca/spottedleaf/moonrise/patches/collisions/CollisionUtil.java
+++ b/ca/spottedleaf/moonrise/patches/collisions/CollisionUtil.java
@@ -101,6 +101,14 @@ public final class CollisionUtil {
(box1.minZ - box2.maxZ) < -COLLISION_EPSILON && (box1.maxZ - box2.minZ) > COLLISION_EPSILON;
}
+ // Leaves start - Configurable collision behavior
+ public static boolean voxelShapeIntersectVanilla(final AABB box1, final AABB box2) {
+ return box1.minX < box2.maxX && box1.maxX > box2.minX &&
+ box1.minY < box2.maxY && box1.maxY > box2.minY &&
+ box1.minZ < box2.maxZ && box1.maxZ > box2.minZ;
+ }
+ // Leaves end - Configurable collision behavior
+
// assume !isEmpty(target) && abs(source_move) >= COLLISION_EPSILON
public static double collideX(final AABB target, final AABB source, final double source_move) {
if ((source.minY - target.maxY) < -COLLISION_EPSILON && (source.maxY - target.minY) > COLLISION_EPSILON &&
@@ -2025,7 +2033,7 @@ public final class CollisionUtil {
AABB singleAABB = ((CollisionVoxelShape)blockCollision).moonrise$getSingleAABBRepresentation();
if (singleAABB != null) {
singleAABB = singleAABB.move((double)blockX, (double)blockY, (double)blockZ);
- if (!voxelShapeIntersect(aabb, singleAABB)) {
+ if (shouldSkip(aabb, blockCollision, singleAABB)) { // Leaves - Configurable collision behavior
continue;
}
@@ -2078,6 +2086,18 @@ public final class CollisionUtil {
return ret;
}
+ // Leaves start - Configurable collision behavior
+ private static boolean shouldSkip(AABB aabb, VoxelShape blockCollision, AABB singleAABB) {
+ boolean isBlockShape = blockCollision == Shapes.block();
+ return switch (me.earthme.luminol.config.modules.misc.CollisionBehaviorConfig.behaviorMode) {
+ case "VANILLA" -> !voxelShapeIntersectVanilla(aabb, singleAABB);
+ case "PAPER" -> !voxelShapeIntersect(aabb, singleAABB);
+ default -> isBlockShape && !voxelShapeIntersectVanilla(aabb, singleAABB) || !isBlockShape && !voxelShapeIntersect(aabb, singleAABB);
+ // All other value as BLOCK_SHAPE_VANILLA to process
+ };
+ }
+ // Leaves end - Configurable collision behavior
+
public static boolean getEntityHardCollisions(final Level world, final Entity entity, AABB aabb,
final List<AABB> into, final int collisionFlags, final Predicate<Entity> predicate) {
final boolean checkOnly = (collisionFlags & COLLISION_FLAG_CHECK_ONLY) != 0;

View File

@@ -1,40 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MrHua269 <wangxyper@163.com>
Date: Sat, 8 Feb 2025 14:25:16 +0800
Subject: [PATCH] Leaves: Fix Incorrect Collision Behavior for Block Shape
Co-authored by: Fortern <blueten.ki@gmail.com>
As part of: Leaves (https://github.com/LeavesMC/Leaves/blob/f553c53e4230aa032e54a69b6479f1959ed24a60/leaves-server/minecraft-patches/features/0110-Fix-Incorrect-Collision-Behavior-for-Block-Shape.patch)
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/ca/spottedleaf/moonrise/patches/collisions/CollisionUtil.java b/ca/spottedleaf/moonrise/patches/collisions/CollisionUtil.java
index e1bf7bc3cca63101b3c0550b5b4c0d28d0f3776e..ea01087967dd9ff32b23661079e97ea468d31163 100644
--- a/ca/spottedleaf/moonrise/patches/collisions/CollisionUtil.java
+++ b/ca/spottedleaf/moonrise/patches/collisions/CollisionUtil.java
@@ -101,6 +101,14 @@ public final class CollisionUtil {
(box1.minZ - box2.maxZ) < -COLLISION_EPSILON && (box1.maxZ - box2.minZ) > COLLISION_EPSILON;
}
+ // Leaves start
+ public static boolean voxelShapeIntersectVanilla(final net.minecraft.world.phys.AABB box1, final net.minecraft.world.phys.AABB box2) {
+ return box1.minX < box2.maxX && box1.maxX > box2.minX &&
+ box1.minY < box2.maxY && box1.maxY > box2.minY &&
+ box1.minZ < box2.maxZ && box1.maxZ > box2.minZ;
+ }
+ // Leaves end
+
// assume !isEmpty(target) && abs(source_move) >= COLLISION_EPSILON
public static double collideX(final AABB target, final AABB source, final double source_move) {
if ((source.minY - target.maxY) < -COLLISION_EPSILON && (source.maxY - target.minY) > COLLISION_EPSILON &&
@@ -2025,7 +2033,10 @@ public final class CollisionUtil {
AABB singleAABB = ((CollisionVoxelShape)blockCollision).moonrise$getSingleAABBRepresentation();
if (singleAABB != null) {
singleAABB = singleAABB.move((double)blockX, (double)blockY, (double)blockZ);
- if (!voxelShapeIntersect(aabb, singleAABB)) {
+ // Leaves start - Fix incorrect collision behavior for block shape
+ boolean isBlockShape = blockCollision == net.minecraft.world.phys.shapes.Shapes.block();
+ if (isBlockShape && !voxelShapeIntersectVanilla(aabb, singleAABB) || !isBlockShape && !voxelShapeIntersect(aabb, singleAABB)) {
+ // Leaves end - Fix incorrect collision behavior for block shape
continue;
}

View File

@@ -0,0 +1,22 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Wed, 4 Jun 2025 12:54:22 +0800
Subject: [PATCH] Leaves: Fix chunk reload detector
Co-authored by: Fortern <blueten.ki@gmail.com>
As part of: Leaves (https://github.com/LeavesMC/Leaves/blob/c5f18b7864206cea4411211b51787f10affbcb9c/leaves-server/minecraft-patches/features/0123-Fix-chunk-reload-detector.patch)
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/net/minecraft/server/level/ServerEntity.java b/net/minecraft/server/level/ServerEntity.java
index b118e91f1e0b5a8b8c0b2a4a32faabc5a34a5954..663bd286426537daf97ae09dc7e076a9ec6d4c9c 100644
--- a/net/minecraft/server/level/ServerEntity.java
+++ b/net/minecraft/server/level/ServerEntity.java
@@ -376,7 +376,7 @@ public class ServerEntity {
if (!list.isEmpty()) {
consumer.accept(new ClientboundSetEquipmentPacket(this.entity.getId(), list, true)); // Paper - data sanitization
}
- ((LivingEntity) this.entity).detectEquipmentUpdates(); // CraftBukkit - SPIGOT-3789: sync again immediately after sending
+ if (this.entity.totalEntityAge == 0) ((LivingEntity) this.entity).detectEquipmentUpdates(); // CraftBukkit - SPIGOT-3789: sync again immediately after sending // Leaves - fix chunk reload detector (#492)
}
if (!this.entity.getPassengers().isEmpty()) {

View File

@@ -8,7 +8,7 @@ As part of: Leaves (https://github.com/LeavesMC/Leaves/blob/f553c53e4230aa032e54
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
index 5564bba66959a2a280f700f6c6a05d292faced88..4492f3ab470c0bf735b6fdc69115c1ebbcd727ef 100644
index bcc0c3cfa5be4daeec6e95a1b63a6cd38890f04d..e83c6a81e318a05580f5c811cb2543a83435f04c 100644
--- a/net/minecraft/server/level/ServerPlayer.java
+++ b/net/minecraft/server/level/ServerPlayer.java
@@ -1285,7 +1285,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc

View File

@@ -8,7 +8,7 @@ As part of: Pufferfish (https://github.com/pufferfish-gg/Pufferfish/blob/04bc249
Licensed under: GPL-3.0 (https://github.com/pufferfish-gg/Pufferfish/blob/04bc249f9eee6157338b6884113b6fa3192bf59b/PATCH-LICENSE)
diff --git a/net/minecraft/world/entity/monster/EnderMan.java b/net/minecraft/world/entity/monster/EnderMan.java
index ab7f7846d3fc0252c6f71277b3e67d7a785a96b5..0f496f0e1c63bc3d8b17a8f0cb065138cb079334 100644
index 5ae08be75ca01924fc78bdd8d6bb6747ddc21aea..6e0b6304205210cc60293329fe30bd6c99cd263a 100644
--- a/net/minecraft/world/entity/monster/EnderMan.java
+++ b/net/minecraft/world/entity/monster/EnderMan.java
@@ -300,11 +300,18 @@ public class EnderMan extends Monster implements NeutralMob {

View File

@@ -8,7 +8,7 @@ Co-authored by: MrPowerGamerBR <git@mrpowergamerbr.com>
As part of: SparklyPaper (https://github.com/SparklyPower/SparklyPaper/blob/a69d3690472c9967772ffd4d4bd1f41403b7ea6f/sparklypaper-server/minecraft-patches/features/0002-Skip-distanceToSqr-call-in-ServerEntity-sendChanges-.patch)
diff --git a/net/minecraft/server/level/ServerEntity.java b/net/minecraft/server/level/ServerEntity.java
index b118e91f1e0b5a8b8c0b2a4a32faabc5a34a5954..8c232ae73a8c6500723994af3a28b36814cccae0 100644
index 663bd286426537daf97ae09dc7e076a9ec6d4c9c..8739b4e806878cf3a4af9ad1aef7f2a55880d503 100644
--- a/net/minecraft/server/level/ServerEntity.java
+++ b/net/minecraft/server/level/ServerEntity.java
@@ -205,6 +205,8 @@ public class ServerEntity {

View File

@@ -5,7 +5,7 @@ Subject: [PATCH] Correct player respawn place
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
index 4492f3ab470c0bf735b6fdc69115c1ebbcd727ef..8b9c823deed1844fa69d1456a91ac65487b8ae69 100644
index e83c6a81e318a05580f5c811cb2543a83435f04c..2f2726ed97658732751032b21752840702da233e 100644
--- a/net/minecraft/server/level/ServerPlayer.java
+++ b/net/minecraft/server/level/ServerPlayer.java
@@ -492,8 +492,10 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc

View File

@@ -0,0 +1,33 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MrHua269 <mrhua269@gmail.com>
Date: Thu, 5 Jun 2025 21:11:31 +0800
Subject: [PATCH] Fix off region thrown egg new entity creating
should set pos before so that we could correctly modify the entity's other attribute on-region without triggering the async catchers
diff --git a/net/minecraft/world/entity/projectile/ThrownEgg.java b/net/minecraft/world/entity/projectile/ThrownEgg.java
index 73ec34b43f3fb2aa3edc3f1cb48a923d1fa32036..5d2f80c4dd8cb6726b0f42891d4ddbc85bf153a7 100644
--- a/net/minecraft/world/entity/projectile/ThrownEgg.java
+++ b/net/minecraft/world/entity/projectile/ThrownEgg.java
@@ -97,17 +97,18 @@ public class ThrownEgg extends ThrowableItemProjectile {
for (int i1 = 0; i1 < i; i1++) {
net.minecraft.world.entity.Entity chicken = newEntityType.create(this.level(), net.minecraft.world.entity.EntitySpawnReason.TRIGGERED); // CraftBukkit
if (chicken != null) {
+ chicken.snapTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), 0.0F); // Luminol - Fix off region thrown egg - move up
// CraftBukkit start
if (chicken.getBukkitEntity() instanceof org.bukkit.entity.Ageable ageable) {
ageable.setBaby();
}
// CraftBukkit end
- chicken.snapTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), 0.0F);
+ // chicken.snapTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), 0.0F); // Luminol - Fix off region thrown egg - move up
// CraftBukkit start
if (chicken instanceof Chicken realChicken) {
Optional.ofNullable(this.getItem().get(DataComponents.CHICKEN_VARIANT))
- .flatMap(eitherHolder -> eitherHolder.unwrap(this.registryAccess()))
- .ifPresent(realChicken::setVariant);
+ .flatMap(eitherHolder -> eitherHolder.unwrap(this.registryAccess()))
+ .ifPresent(realChicken::setVariant);
}
// CraftBukkit end
if (!chicken.fudgePositionAfterSizeChange(ZERO_SIZED_DIMENSIONS)) {

View File

@@ -1,6 +1,6 @@
--- /dev/null
+++ b/src/main/java/me/earthme/luminol/commands/LuminolConfigCommand.java
@@ -1,0 +_,80 @@
@@ -1,0 +_,121 @@
+package me.earthme.luminol.commands;
+
+import me.earthme.luminol.config.LuminolConfig;
@@ -23,16 +23,26 @@
+ this.setUsage("/luminolconfig");
+ }
+
+ public void wrongUse(CommandSender sender) {
+ sender.sendMessage(
+ Component
+ .text("Wrong use!")
+ .color(TextColor.color(255, 0, 0))
+ );
+ }
+
+ @Override
+ public @NotNull List<String> tabComplete(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args, @Nullable Location location) throws IllegalArgumentException {
+ final List<String> result = new ArrayList<>();
+
+ if (args.length == 1) {
+ result.add("query");
+ // result.add("set"); // TODO Later
+ // result.add("reload"); // TODO Later
+ result.add("set");
+ result.add("reset");
+ result.add("reload");
+ } else if (args.length == 2 && args[0] != "reload") {
+ result.addAll(LuminolConfig.getAllConfigPaths(args[1]));
+ }
+
+ return result;
+ }
+
@@ -46,11 +56,7 @@
+ }
+
+ if (args.length < 1) {
+ sender.sendMessage(
+ Component
+ .text("Wrong use!\n")
+ .color(TextColor.color(255, 0, 0))
+ );
+ wrongUse(sender);
+ return true;
+ }
+
@@ -62,18 +68,53 @@
+ .color(TextColor.color(0, 255, 0))
+ ));
+ }
+
+ case "set" -> {
+ // TODO Later
+ if (args.length == 2 || args.length > 3) {
+ wrongUse(sender);
+ return true;
+ } else if (LuminolConfig.setConfig(args[1], args[2])) {
+ LuminolConfig.reloadAsync().thenAccept(nullValue -> sender.sendMessage(
+ Component
+ .text("Set Config " + args[1] + " to " + args[2] + " successfully!")
+ .color(TextColor.color(0, 255, 0))
+ ));
+ } else {
+ sender.sendMessage(
+ Component
+ .text("Failed to set config " + args[1] + " to " + args[2] + "!")
+ .color(TextColor.color(255, 0, 0))
+ );
+ }
+ }
+ case "reset" -> {
+ if (args.length != 2) {
+ wrongUse(sender);
+ return true;
+ } else {
+ LuminolConfig.resetConfig(args[1]);
+ LuminolConfig.reloadAsync().thenAccept(nullValue -> sender.sendMessage(
+ Component
+ .text("Reset Config " + args[1] + " to " + LuminolConfig.getConfig(args[1]) + " successfully!")
+ .color(TextColor.color(0, 255, 0))
+ ));
+ }
+ }
+
+ case "query" -> {
+ // TODO Later
+ if (args.length != 2) {
+ wrongUse(sender);
+ return true;
+ } else {
+ sender.sendMessage(
+ Component
+ .text("Config " + args[1] + " is " + LuminolConfig.getConfig(args[1]) + "!")
+ .color(TextColor.color(0, 255, 0))
+ );
+ }
+ }
+
+ default -> sender.sendMessage(
+ Component
+ .text("Unknown action!\n")
+ .text("Unknown action!")
+ .color(TextColor.color(255, 0, 0))
+ );
+ }

View File

@@ -1,6 +1,6 @@
--- /dev/null
+++ b/src/main/java/me/earthme/luminol/config/LuminolConfig.java
@@ -1,0 +_,351 @@
@@ -1,0 +_,378 @@
+package me.earthme.luminol.config;
+
+import com.electronwill.nightconfig.core.CommentedConfig;
@@ -37,12 +37,14 @@
+ private static final File baseConfigFolder = new File("luminol_config");
+ private static final File baseConfigFile = new File(baseConfigFolder, "luminol_global_config.toml");
+ private static final Set<IConfigModule> allInstanced = new HashSet<>();
+ public static boolean alreadyInited = false;
+ private static final Map<String, Object> stagedConfigMap = new HashMap<>();
+ private static final Map<String, Object> defaultvalueMap = new HashMap<>();
+ public static boolean alreadyInit = false;
+ private static CommentedFileConfig configFileInstance;
+
+ public static void setupLatch() {
+ Bukkit.getCommandMap().register("luminolconfig", "luminol", new LuminolConfigCommand());
+ alreadyInited = true;
+ alreadyInit = true;
+ }
+
+ public static void reload() {
@@ -97,7 +99,7 @@
+ throw new RuntimeException(e);
+ }
+
+ configFileInstance.save();
+ saveConfigs();
+ }
+
+ private static void loadAllModules() throws IllegalAccessException {
@@ -122,7 +124,7 @@
+ for (Field field : fields) {
+ int modifiers = field.getModifiers();
+ if (Modifier.isStatic(modifiers) && !Modifier.isFinal(modifiers)) {
+ boolean skipLoad = field.getAnnotation(DoNotLoad.class) != null || (alreadyInited && field.getAnnotation(HotReloadUnsupported.class) != null);
+ boolean skipLoad = field.getAnnotation(DoNotLoad.class) != null || (alreadyInit && field.getAnnotation(HotReloadUnsupported.class) != null);
+ ConfigInfo configInfo = field.getAnnotation(ConfigInfo.class);
+
+ if (skipLoad || configInfo == null) {
@@ -133,6 +135,7 @@
+
+ field.setAccessible(true);
+ final Object currentValue = field.get(null);
+ if (!alreadyInit) defaultvalueMap.put(fullConfigKeyName, currentValue);
+ boolean removed = fullConfigKeyName.equals("removed.removed_config.removed");
+
+ if (!configFileInstance.contains(fullConfigKeyName) || removed) {
@@ -180,7 +183,21 @@
+ continue;
+ }
+
+ final Object actuallyValue = configFileInstance.get(fullConfigKeyName);
+ Object actuallyValue;
+ if (stagedConfigMap.containsKey(fullConfigKeyName)) {
+ actuallyValue = stagedConfigMap.get(fullConfigKeyName);
+ if (actuallyValue == null) actuallyValue = defaultvalueMap.get(fullConfigKeyName);
+ stagedConfigMap.remove(fullConfigKeyName);
+ } else {
+ actuallyValue = configFileInstance.get(fullConfigKeyName);
+ }
+ try {
+ actuallyValue = tryTransform(field.get(null).getClass(), actuallyValue);
+ configFileInstance.set(fullConfigKeyName, actuallyValue);
+ } catch (IllegalFormatConversionException e) {
+ resetConfig(fullConfigKeyName);
+ logger.error("Failed to transform config {}, reset to default!", fullConfigKeyName);
+ }
+ field.set(null, actuallyValue);
+ }
+ }
@@ -202,31 +219,43 @@
+ }
+ }
+
+ public static boolean setConfigAndSave(String[] keys, Object value) {
+ return setConfigAndSave(String.join(".", keys), value);
+ }
+
+ public static boolean setConfigAndSave(String key, Object value) {
+ if (setConfig(key, value)) {
+ saveConfig();
+ return true;
+ }
+ return false;
+ }
+
+ public static boolean setConfig(String[] keys, Object value) {
+ return setConfig(String.join(".", keys), value);
+ }
+
+ public static boolean setConfig(String key, Object value) {
+ if (configFileInstance.contains(key) && configFileInstance.get(key) != null) {
+ configFileInstance.set(key, value);
+ stagedConfigMap.put(key, value);
+ return true;
+ }
+ return false;
+ }
+
+ public static void saveConfig() {
+ private static Object tryTransform(Class<?> targetType, Object value) {
+ if (!targetType.isAssignableFrom(value.getClass())) {
+ try {
+ if (targetType == Integer.class) {
+ value = Integer.parseInt(value.toString());
+ } else if (targetType == Double.class) {
+ value = Double.parseDouble(value.toString());
+ } else if (targetType == Boolean.class) {
+ value = Boolean.parseBoolean(value.toString());
+ } else if (targetType == Long.class) {
+ value = Long.parseLong(value.toString());
+ } else if (targetType == Float.class) {
+ value = Float.parseFloat(value.toString());
+ } else if (targetType == String.class) {
+ value = value.toString();
+ }
+ } catch (Exception e) {
+ logger.error("Failed to transform value {}!", value);
+ throw new IllegalFormatConversionException((char) 0, targetType);
+ }
+ }
+ return value;
+ }
+
+ public static void saveConfigs() {
+ configFileInstance.save();
+ }
+
@@ -235,9 +264,7 @@
+ }
+
+ public static void resetConfig(String key) {
+ configFileInstance.remove(key);
+ configFileInstance.save();
+ reload();
+ stagedConfigMap.put(key, null);
+ }
+
+ public static String getConfig(String[] keys) {
@@ -245,10 +272,10 @@
+ }
+
+ public static String getConfig(String key) {
+ return configFileInstance.get(key);
+ return configFileInstance.get(key).toString();
+ }
+
+ public List<String> getAllConfigPaths(String prefix) {
+ public static List<String> getAllConfigPaths(String prefix) {
+ List<String> configPaths = getAllConfigPaths();
+ return configPaths.stream().filter(path -> path.startsWith(prefix)).toList();
+ }

View File

@@ -0,0 +1,28 @@
--- /dev/null
+++ b/src/main/java/me/earthme/luminol/config/modules/misc/CollisionBehaviorConfig.java
@@ -1,0 +_,25 @@
+package me.earthme.luminol.config.modules.misc;
+
+import me.earthme.luminol.config.EnumConfigCategory;
+import me.earthme.luminol.config.IConfigModule;
+import me.earthme.luminol.config.flags.ConfigInfo;
+
+public class CollisionBehaviorConfig implements IConfigModule {
+ @ConfigInfo(baseName = "mode", comments =
+ """
+ Available Value:
+ VANILLA
+ BLOCK_SHAPE_VANILLA
+ PAPER""")
+ public static String behaviorMode = "BLOCK_SHAPE_VANILLA";
+
+ @Override
+ public EnumConfigCategory getCategory() {
+ return EnumConfigCategory.MISC;
+ }
+
+ @Override
+ public String getBaseName() {
+ return "collision_behavior";
+ }
+}