Skip to content

Commit bff0258

Browse files
committed
Add config option for disabled world physics (#372)
1 parent 93edacb commit bff0258

File tree

19 files changed

+165
-65
lines changed

19 files changed

+165
-65
lines changed

buildsystem-api/src/main/java/de/eintosti/buildsystem/api/world/display/Folder.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,14 @@ public interface Folder extends Displayable {
8989
*/
9090
boolean containsWorld(BuildWorld buildWorld);
9191

92+
/**
93+
* Checks if this folder contains the {@link BuildWorld} with the specified UUID.
94+
*
95+
* @param uuid The unique identifier of the {@link BuildWorld} to check for
96+
* @return {@code true} if the folder contains the world, {@code false} otherwise
97+
*/
98+
boolean containsWorld(UUID uuid);
99+
92100
/**
93101
* Adds a {@link BuildWorld} to this folder.
94102
*
@@ -103,6 +111,13 @@ public interface Folder extends Displayable {
103111
*/
104112
void removeWorld(BuildWorld buildWorld);
105113

114+
/**
115+
* Removes a {@link BuildWorld} with the specified UUID from this folder.
116+
*
117+
* @param uuid The unique identifier of the {@link BuildWorld} to remove
118+
*/
119+
void removeWorld(UUID uuid);
120+
106121
/**
107122
* Returns an unmodifiable list of all immediate subfolders contained within this folder.
108123
* <p>

buildsystem-core/src/main/java/de/eintosti/buildsystem/BuildSystemPlugin.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,8 @@ public class BuildSystemPlugin extends JavaPlugin {
114114
public static final int METRICS_ID = 7427;
115115
public static final String ADMIN_PERMISSION = "buildsystem.admin";
116116

117+
private static BuildSystemPlugin instance;
118+
117119
private ArmorStandManager armorStandManager;
118120
private CustomBlockManager customBlockManager;
119121
private InventoryManager inventoryManager;
@@ -132,6 +134,8 @@ public class BuildSystemPlugin extends JavaPlugin {
132134

133135
@Override
134136
public void onLoad() {
137+
instance = this;
138+
135139
new ConfigMigrationManager(this).migrate();
136140
this.getConfig().options().copyDefaults(true);
137141
this.saveConfig();
@@ -196,6 +200,15 @@ public void onDisable() {
196200
Bukkit.getConsoleSender().sendMessage(
197201
"%sBuildSystem » Plugin %sdisabled%s!".formatted(ChatColor.RESET, ChatColor.RED, ChatColor.RESET)
198202
);
203+
204+
instance = null;
205+
}
206+
207+
public static BuildSystemPlugin get() {
208+
if (instance == null) {
209+
throw new IllegalStateException("BuildSystemPlugin instance is not initialized. Make sure the plugin is enabled.");
210+
}
211+
return instance;
199212
}
200213

201214
private void initClasses() {

buildsystem-core/src/main/java/de/eintosti/buildsystem/Messages.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,15 +43,14 @@
4343
import org.bukkit.configuration.ConfigurationSection;
4444
import org.bukkit.configuration.file.YamlConfiguration;
4545
import org.bukkit.entity.Player;
46-
import org.bukkit.plugin.java.JavaPlugin;
4746
import org.jetbrains.annotations.Unmodifiable;
4847
import org.jspecify.annotations.NullMarked;
4948
import org.jspecify.annotations.Nullable;
5049

5150
@NullMarked
5251
public class Messages {
5352

54-
private static final BuildSystemPlugin PLUGIN = JavaPlugin.getPlugin(BuildSystemPlugin.class);
53+
private static final BuildSystemPlugin PLUGIN = BuildSystemPlugin.get();
5554
private static final Map<String, String> MESSAGES = new HashMap<>();
5655
private static final boolean PLACEHOLDER_API_ENABLED = Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null;
5756

buildsystem-core/src/main/java/de/eintosti/buildsystem/command/ExplosionsCommand.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ public boolean onCommand(CommandSender sender, Command cmd, String label, String
5454

5555
String worldName = args.length == 0 ? player.getWorld().getName() : args[0];
5656
BuildWorld buildWorld = worldStorage.getBuildWorld(worldName);
57-
if (WorldPermissionsImpl.of(buildWorld).canPerformCommand(player, "buildsystem.explosions")) {
57+
if (!WorldPermissionsImpl.of(buildWorld).canPerformCommand(player, "buildsystem.explosions")) {
5858
Messages.sendPermissionError(player);
5959
return true;
6060
}

buildsystem-core/src/main/java/de/eintosti/buildsystem/command/NoAICommand.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ public boolean onCommand(CommandSender sender, Command cmd, String label, String
5454

5555
String worldName = args.length == 0 ? player.getWorld().getName() : args[0];
5656
BuildWorld buildWorld = worldStorage.getBuildWorld(worldName);
57-
if (WorldPermissionsImpl.of(buildWorld).canPerformCommand(player, "buildsystem.noai")) {
57+
if (!WorldPermissionsImpl.of(buildWorld).canPerformCommand(player, "buildsystem.noai")) {
5858
Messages.sendPermissionError(player);
5959
return true;
6060
}

buildsystem-core/src/main/java/de/eintosti/buildsystem/command/PhysicsCommand.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ public boolean onCommand(CommandSender sender, Command cmd, String label, String
5454

5555
String worldName = args.length == 0 ? player.getWorld().getName() : args[0];
5656
BuildWorld buildWorld = worldStorage.getBuildWorld(worldName);
57-
if (WorldPermissionsImpl.of(buildWorld).canPerformCommand(player, "buildsystem.physics")) {
57+
if (!WorldPermissionsImpl.of(buildWorld).canPerformCommand(player, "buildsystem.physics")) {
5858
Messages.sendPermissionError(player);
5959
return true;
6060
}

buildsystem-core/src/main/java/de/eintosti/buildsystem/config/Config.java

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import de.eintosti.buildsystem.config.Config.Settings.Archive;
2424
import de.eintosti.buildsystem.config.Config.Settings.BuildMode;
2525
import de.eintosti.buildsystem.config.Config.Settings.Builder;
26+
import de.eintosti.buildsystem.config.Config.Settings.DisabledPhysics;
2627
import de.eintosti.buildsystem.config.Config.Settings.Navigator;
2728
import de.eintosti.buildsystem.config.Config.Settings.SaveFromDeath;
2829
import de.eintosti.buildsystem.config.Config.World.Backup;
@@ -53,21 +54,18 @@
5354
import org.bukkit.configuration.ConfigurationSection;
5455
import org.bukkit.configuration.file.FileConfiguration;
5556
import org.bukkit.configuration.file.YamlConfiguration;
56-
import org.bukkit.plugin.java.JavaPlugin;
5757
import org.jetbrains.annotations.Contract;
5858
import org.jspecify.annotations.NullMarked;
5959
import org.jspecify.annotations.Nullable;
60-
import org.slf4j.LoggerFactory;
6160

6261
/**
6362
* Manages the plugin's configuration, loading and providing access to various settings.
6463
*/
6564
@NullMarked
6665
public class Config {
6766

68-
private static final BuildSystemPlugin PLUGIN = JavaPlugin.getPlugin(BuildSystemPlugin.class);
67+
private static final BuildSystemPlugin PLUGIN = BuildSystemPlugin.get();
6968
private static final FileConfiguration CONFIG = PLUGIN.getConfig();
70-
private static final org.slf4j.Logger log = LoggerFactory.getLogger(Config.class);
7169

7270
/**
7371
* Gets the plugin's configuration.
@@ -151,6 +149,25 @@ public static class Archive {
151149
public static GameMode worldGameMode = GameMode.ADVENTURE;
152150
}
153151

152+
/**
153+
* Stores settings related to worlds with disabled physics.
154+
*/
155+
public static class DisabledPhysics {
156+
157+
/**
158+
* Whether connections should be prevented in worlds with disabled physics.
159+
*/
160+
public static boolean preventConnections = true;
161+
/**
162+
* Whether fluid flow should be prevented in worlds with disabled physics.
163+
*/
164+
public static boolean preventFluidFlow = true;
165+
/**
166+
* Whether falling blocks should be prevented in worlds with disabled physics.
167+
*/
168+
public static boolean preventFallingBlocks = true;
169+
}
170+
154171
/**
155172
* Stores settings related to saving players from death.
156173
*/
@@ -437,6 +454,10 @@ public static void load() {
437454
Archive.vanish = CONFIG.getBoolean("settings.archive.vanish", true);
438455
Archive.changeGamemode = CONFIG.getBoolean("settings.archive.change-gamemode", true);
439456
Archive.worldGameMode = parseGameMode(CONFIG.getString("settings.archive.world-gamemode"));
457+
// Settings - Disabled physics
458+
DisabledPhysics.preventConnections = CONFIG.getBoolean("settings.disabled-physics.prevent-connections", true);
459+
DisabledPhysics.preventFluidFlow = CONFIG.getBoolean("settings.disabled-physics.prevent-fluid-flow", true);
460+
DisabledPhysics.preventFallingBlocks = CONFIG.getBoolean("settings.disabled-physics.prevent-falling-blocks", true);
440461
// Settings - Save from death
441462
SaveFromDeath.enabled = CONFIG.getBoolean("settings.save-from-death.enabled", true);
442463
SaveFromDeath.teleportToMapSpawn = CONFIG.getBoolean("settings.save-from-death.teleport-to-map-spawn", true);

buildsystem-core/src/main/java/de/eintosti/buildsystem/listener/BlockPhysicsListener.java

Lines changed: 53 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,18 @@
2020
import com.cryptomorin.xseries.XMaterial;
2121
import de.eintosti.buildsystem.BuildSystemPlugin;
2222
import de.eintosti.buildsystem.api.world.BuildWorld;
23+
import de.eintosti.buildsystem.config.Config.Settings.DisabledPhysics;
2324
import de.eintosti.buildsystem.storage.WorldStorageImpl;
2425
import de.eintosti.buildsystem.util.DirectionUtil;
2526
import java.util.List;
2627
import org.bukkit.World;
2728
import org.bukkit.block.Block;
2829
import org.bukkit.block.BlockFace;
30+
import org.bukkit.block.data.type.Fence;
31+
import org.bukkit.block.data.type.Gate;
32+
import org.bukkit.block.data.type.GlassPane;
33+
import org.bukkit.block.data.type.Stairs;
34+
import org.bukkit.block.data.type.Wall;
2935
import org.bukkit.entity.EntityType;
3036
import org.bukkit.event.EventHandler;
3137
import org.bukkit.event.EventPriority;
@@ -62,6 +68,21 @@ public void onBlockPhysics(BlockPhysicsEvent event) {
6268
return;
6369
}
6470

71+
if (!DisabledPhysics.preventConnections) {
72+
boolean canConnect = switch (block.getBlockData()) {
73+
case Fence fence -> true;
74+
case Gate gate -> true;
75+
case GlassPane glassPane -> true;
76+
case Stairs stairs -> true;
77+
case Wall wall -> true;
78+
default -> false;
79+
};
80+
if (canConnect) {
81+
event.setCancelled(false);
82+
return;
83+
}
84+
}
85+
6586
switch (XMaterial.matchXMaterial(block.getType())) {
6687
case REDSTONE_BLOCK -> {
6788
for (BlockFace blockFace : DirectionUtil.BLOCK_SIDES) {
@@ -87,49 +108,61 @@ public void onBlockPhysics(BlockPhysicsEvent event) {
87108
@EventHandler
88109
public void onLeavesDecay(LeavesDecayEvent event) {
89110
BuildWorld buildWorld = worldStorage.getBuildWorld(event.getBlock().getWorld());
90-
if (buildWorld != null && !buildWorld.getData().physics().get()) {
91-
event.setCancelled(true);
111+
if (buildWorld == null || buildWorld.getData().physics().get()) {
112+
return;
92113
}
114+
event.setCancelled(true);
93115
}
94116

95117
@EventHandler
96118
public void onBlockFade(BlockFadeEvent event) {
97119
BuildWorld buildWorld = worldStorage.getBuildWorld(event.getBlock().getWorld());
98-
if (buildWorld != null && !buildWorld.getData().physics().get()) {
99-
event.setCancelled(true);
120+
if (buildWorld == null || buildWorld.getData().physics().get()) {
121+
return;
100122
}
123+
event.setCancelled(true);
101124
}
102125

103126
@EventHandler
104127
public void onBlockForm(BlockFormEvent event) {
105128
BuildWorld buildWorld = worldStorage.getBuildWorld(event.getBlock().getWorld());
106-
if (buildWorld != null && !buildWorld.getData().physics().get()) {
107-
event.setCancelled(true);
129+
if (buildWorld == null || buildWorld.getData().physics().get()) {
130+
return;
108131
}
132+
event.setCancelled(true);
109133
}
110134

111135
@EventHandler
112136
public void onBlockFromTo(BlockFromToEvent event) {
113137
BuildWorld buildWorld = worldStorage.getBuildWorld(event.getBlock().getWorld());
114-
if (buildWorld != null && !buildWorld.getData().physics().get()) {
115-
event.setCancelled(true);
138+
if (buildWorld == null || buildWorld.getData().physics().get()) {
139+
return;
140+
}
141+
142+
if (event.getBlock().isLiquid() && !DisabledPhysics.preventFluidFlow) {
143+
event.setCancelled(false);
144+
return;
116145
}
146+
147+
event.setCancelled(true);
117148
}
118149

119150
@EventHandler
120151
public void onBlockGrow(BlockGrowEvent event) {
121152
BuildWorld buildWorld = worldStorage.getBuildWorld(event.getBlock().getWorld());
122-
if (buildWorld != null && !buildWorld.getData().physics().get()) {
123-
event.setCancelled(true);
153+
if (buildWorld == null || buildWorld.getData().physics().get()) {
154+
return;
124155
}
156+
event.setCancelled(true);
125157
}
126158

127159
@EventHandler
128160
public void onBlockSpread(BlockSpreadEvent event) {
129161
BuildWorld buildWorld = worldStorage.getBuildWorld(event.getBlock().getWorld());
130-
if (buildWorld != null && !buildWorld.getData().physics().get()) {
131-
event.setCancelled(true);
162+
if (buildWorld == null || buildWorld.getData().physics().get()) {
163+
return;
132164
}
165+
event.setCancelled(true);
133166
}
134167

135168
@EventHandler
@@ -139,7 +172,7 @@ public void onEntityChangeBlock(EntityChangeBlockEvent event) {
139172
return;
140173
}
141174

142-
if (event.getEntityType() == EntityType.FALLING_BLOCK) {
175+
if (event.getEntityType() == EntityType.FALLING_BLOCK && DisabledPhysics.preventFallingBlocks) {
143176
event.setCancelled(true);
144177
event.getBlock().getState().update(false, false);
145178
}
@@ -167,9 +200,10 @@ public void onBlockRedstone(BlockRedstoneEvent event) {
167200
@EventHandler
168201
public void onBlockExplode(BlockExplodeEvent event) {
169202
BuildWorld buildWorld = worldStorage.getBuildWorld(event.getBlock().getWorld());
170-
if (buildWorld != null && !buildWorld.getData().explosions().get()) {
171-
event.setCancelled(true);
203+
if (buildWorld == null || buildWorld.getData().physics().get()) {
204+
return;
172205
}
206+
event.setCancelled(true);
173207
}
174208

175209
@EventHandler
@@ -180,9 +214,11 @@ public void onEntityExplode(EntityExplodeEvent event) {
180214
}
181215

182216
BuildWorld buildWorld = worldStorage.getBuildWorld(world);
183-
if (buildWorld != null && !buildWorld.getData().explosions().get()) {
184-
event.setCancelled(true);
217+
if (buildWorld == null || buildWorld.getData().physics().get()) {
218+
return;
185219
}
220+
221+
event.setCancelled(true);
186222
}
187223

188224
private boolean isCustomRedstoneLamp(Block block) {

buildsystem-core/src/main/java/de/eintosti/buildsystem/player/customblock/CustomBlock.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
import org.bukkit.inventory.meta.ItemMeta;
2525
import org.bukkit.persistence.PersistentDataContainer;
2626
import org.bukkit.persistence.PersistentDataType;
27-
import org.bukkit.plugin.java.JavaPlugin;
2827
import org.jetbrains.annotations.Contract;
2928
import org.jspecify.annotations.NullMarked;
3029
import org.jspecify.annotations.Nullable;
@@ -59,7 +58,7 @@ public enum CustomBlock {
5958
SMOOTH_STONE("blocks_smooth_stone", "8dd0cd158c2bb6618650e3954b2d29237f5b4c0ddc7d258e17380ab6979f071"),
6059
DEBUG_STICK("blocks_debug_stick", "badc048a7ce78f7dad72a07da27d85c0916881e5522eeed1e3daf217a38c1a");
6160

62-
public static final NamespacedKey CUSTOM_BLOCK_KEY = new NamespacedKey(JavaPlugin.getPlugin(BuildSystemPlugin.class), "custom-block");
61+
public static final NamespacedKey CUSTOM_BLOCK_KEY = new NamespacedKey(BuildSystemPlugin.get(), "custom-block");
6362

6463
private final String messageKey;
6564
private final String skullUrl;

buildsystem-core/src/main/java/de/eintosti/buildsystem/storage/WorldStorageImpl.java

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -198,17 +198,21 @@ public void loadWorlds() {
198198
* Must be called after all folders and worlds have been loaded.
199199
*/
200200
private void assignWorldsToFolders() {
201-
worldService.getFolderStorage().getFolders().forEach(folder ->
202-
folder.getWorldUUIDs().stream()
203-
.map(worldUUID -> {
204-
BuildWorld buildWorld = getBuildWorld(worldUUID);
205-
if (buildWorld == null) {
206-
logger.warning("World with UUID " + worldUUID + " does not exist.");
207-
}
208-
return buildWorld;
209-
})
210-
.filter(Objects::nonNull)
211-
.forEach(buildWorld -> buildWorld.setFolder(folder))
201+
worldService.getFolderStorage().getFolders().forEach(folder -> {
202+
List<UUID> invalidWorlds = new ArrayList<>();
203+
folder.getWorldUUIDs().stream()
204+
.map(worldUUID -> {
205+
BuildWorld buildWorld = getBuildWorld(worldUUID);
206+
if (buildWorld == null) {
207+
invalidWorlds.add(worldUUID);
208+
logger.warning("World with UUID " + worldUUID + " does not exist. Removing from folder: " + folder.getName());
209+
}
210+
return buildWorld;
211+
})
212+
.filter(Objects::nonNull)
213+
.forEach(buildWorld -> buildWorld.setFolder(folder));
214+
invalidWorlds.forEach(folder::removeWorld);
215+
}
212216
);
213217
}
214218

0 commit comments

Comments
 (0)