Compare commits

...
73 Commits
Author SHA1 Message Date
Chaoscaot 829d8a6cdf Initial ChaosSchematicReader
Signed-off-by: Chaoscaot <max@maxsp.de>
2026-01-21 23:33:45 +01:00
YoyoNow 361c698323 Check why StaticMessageChannel does not work? 2026-01-09 10:07:26 +01:00
YoyoNow db4ea2d69d Check why StaticMessageChannel does not work? 2026-01-09 10:05:17 +01:00
YoyoNow 3cecc58bce Check why StaticMessageChannel does not work? 2026-01-09 10:03:14 +01:00
YoyoNow ce3d50fcb7 Check why StaticMessageChannel does not work? 2026-01-09 10:01:36 +01:00
YoyoNow 61bd28150b Check why StaticMessageChannel does not work? 2026-01-09 09:59:22 +01:00
YoyoNow bb9caa28a3 Check why StaticMessageChannel does not work? 2026-01-09 09:57:18 +01:00
YoyoNow 4b2970d243 Check why StaticMessageChannel does not work? 2026-01-09 09:53:34 +01:00
Chaoscaot 834767edbe Fix API
Signed-off-by: Chaoscaot <max@maxsp.de>
2026-01-04 12:35:11 +01:00
Chaoscaot 4bea077d36 Fix Kits
Signed-off-by: Chaoscaot <max@maxsp.de>
2026-01-03 02:25:52 +01:00
Chaoscaot 74d6ccc24f Fix Kits
Signed-off-by: Chaoscaot <max@maxsp.de>
2026-01-03 02:22:55 +01:00
Chaoscaot d9f905d957 Fix Kits
Signed-off-by: Chaoscaot <max@maxsp.de>
2026-01-02 14:24:49 +01:00
Chaoscaot 663a745d8f Fix Kits
Signed-off-by: Chaoscaot <max@maxsp.de>
2026-01-02 14:08:49 +01:00
Chaoscaot 1f64c3383d Fix HotbarKitListener
Signed-off-by: Chaoscaot <max@maxsp.de>
2026-01-01 17:04:09 +01:00
Lixfel e4676d5eba Test hotpatch kit 2026-01-01 15:08:37 +01:00
Chaoscaot ebb2ec817d Fix Windcharge Damage on Arena
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-12-27 19:18:31 +01:00
Chaoscaot b6445ce2e9 Merge pull request 'Change Bug Button to Link' (#263) from update-bug-button into main
Reviewed-on: SteamWar/SteamWar#263
Reviewed-by: YoyoNow <yoyonow@noreply.localhost>
2025-12-25 21:09:37 +01:00
Chaoscaot a454da6da8 Change Bug Button to Link
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-12-25 21:07:53 +01:00
YoyoNow a87cc94700 Pot fix for WinconditionBasePercent 2025-12-23 12:27:48 +01:00
YoyoNow 31dac93698 Remove UnrankCommand 2025-12-23 10:40:53 +01:00
YoyoNow 1f568f3d8b Remove UnrankCommand 2025-12-22 21:25:40 +01:00
YoyoNow b8b8dd1ba0 Update UserPerm.kt 2025-12-21 13:25:30 +01:00
YoyoNow 99f864d889 Hotfix SteamwarUser and ServerStarter 2025-12-21 12:27:55 +01:00
YoyoNow 711a21b634 Merge pull request 'Remove SchemElo and UserElo' (#256) from RemoveElo into main
Reviewed-on: SteamWar/SteamWar#256
2025-12-21 12:04:27 +01:00
YoyoNow 9a85e8b442 Merge branch 'main' into RemoveElo 2025-12-21 12:03:33 +01:00
Chaoscaot 8358203cd4 Fix kits frfrfrfrfrfr
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-12-20 22:15:30 +01:00
Chaoscaot 6a619c2fd1 Fix kits frfrfrfrfr?
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-12-20 22:12:48 +01:00
Chaoscaot d348e4a480 Fix kits frfrfrfr?
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-12-20 22:10:25 +01:00
Chaoscaot 1269e4d971 Fix kits frfrfr
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-12-20 22:03:09 +01:00
Chaoscaot feac17d732 Fix kits frfr
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-12-20 21:58:44 +01:00
Chaoscaot 975b2bb8e6 Fix Kits and Maybe? Locale
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-12-20 21:35:34 +01:00
YoyoNow a1add4f997 Remove SchemElo and UserElo 2025-12-20 21:28:00 +01:00
YoyoNow b517fe3ad0 Remove SchemElo and UserElo 2025-12-20 21:26:42 +01:00
YoyoNow ac5dda58a1 Remove SchemElo and UserElo 2025-12-20 21:19:20 +01:00
YoyoNow 9efe625603 Pot fix for too many open files 2025-12-20 13:14:35 +01:00
YoyoNow 146ed598c8 Improve message on non ManualCheck submitted schematics 2025-12-20 12:20:36 +01:00
YoyoNow 50e86fbf89 Add 1.19 impl for SteamwarGameProfileRepository 2025-12-20 11:53:28 +01:00
YoyoNow 7216806a1c Fix SWPlayer on 1.15 2025-12-20 11:45:36 +01:00
YoyoNow 6cda79f7e1 Fix AbstractLinker 2025-12-20 11:41:36 +01:00
YoyoNow 87cc43a348 Fix FAWE stuff in 1.15 2025-12-20 11:35:08 +01:00
YoyoNow f9509c19d1 Trigger rebuild 2025-12-19 21:20:32 +01:00
YoyoNow e7bd5a9e74 Fix translation 2025-12-19 13:37:29 +01:00
YoyoNow aa74e0b887 Fix SQLWrapperImpl 2025-12-18 18:18:56 +01:00
Chaoscaot fe8d37c966 Maybe? Fix kits
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-12-17 23:29:00 +01:00
YoyoNow ccb79737db Fix Core.setServerName 2025-12-17 21:33:19 +01:00
Chaoscaot 1eea792e23 Synchronize team cache access to ensure thread safety
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-12-17 21:29:14 +01:00
YoyoNow 19c6ad0965 Merge pull request 'Add WorldIdentifier' (#249) from SpigotCore/WorldIdentifier into main
Reviewed-on: SteamWar/SteamWar#249
Reviewed-by: D4rkr34lm <dark@steamwar.de>
2025-12-17 21:28:41 +01:00
YoyoNow 2c5306bfd1 Merge pull request 'Add WaterDestroy feature with command and listener' (#248) from waterblocker into main
Reviewed-on: SteamWar/SteamWar#248
Reviewed-by: YoyoNow <yoyonow@noreply.localhost>
2025-12-17 21:13:45 +01:00
YoyoNow 1982b5e42c Update WaterDestroyCommand 2025-12-17 21:13:31 +01:00
Chaoscaot 3ad4081add Merge pull request 'Add AuditLog to Backend' (#244) from Backend/auditlog into main
Reviewed-on: SteamWar/SteamWar#244
Reviewed-by: YoyoNow <yoyonow@noreply.localhost>
2025-12-17 21:03:04 +01:00
Chaoscaot 33a7961979 Add WaterDestroy feature with command and listener
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-12-17 20:49:23 +01:00
YoyoNow 4e994813eb Add WorldIdentifier 2025-12-17 20:31:21 +01:00
YoyoNow 367a72141a Undo Improve TNTDistributor 2025-12-17 11:32:11 +01:00
YoyoNow c29788f1eb Improve TNTDistributor 2025-12-17 11:15:47 +01:00
YoyoNow 9d32a331ca Improve TNTDistributor 2025-12-16 14:50:56 +01:00
YoyoNow c55494aeba Revert WinconditionPercent for QuickGear 2025-12-16 14:15:04 +01:00
YoyoNow 61dcee6f8e Improve WinconditionPercent for QuickGear 2025-12-16 13:20:55 +01:00
Chaoscaot 8b2b7e011a Add WaterDestroy feature with command and listener
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-12-11 00:34:29 +01:00
YoyoNow 8640d43d4b Merge pull request 'BauSystem/ImproveRegionData' (#234) from BauSystem/ImproveRegionData into main
Reviewed-on: SteamWar/SteamWar#234
Reviewed-by: D4rkr34lm <dark@steamwar.de>
2025-12-03 13:26:10 +01:00
YoyoNow fbdb0cfaf1 Merge pull request 'Fix replay in 1.21 -> RPlayer needs fixing before' (#199) from FightSystem/ReplayFix21 into main
Reviewed-on: SteamWar/SteamWar#199
2025-12-03 10:05:03 +01:00
YoyoNow 9305ab5f91 Merge pull request 'Refactor Authlib integration and adjust entity handling for 1.21 compatibility' (#106) from 1.21.1/rplayer-fix into main
Reviewed-on: SteamWar/SteamWar#106
2025-12-03 10:04:50 +01:00
YoyoNow 34ade1de19 Merge branch 'main' into 1.21.1/rplayer-fix 2025-12-03 09:59:33 +01:00
YoyoNow 87d0df8067 Merge pull request 'Remove Poll-System' (#245) from Refactor/remove-poll-system into main
Reviewed-on: SteamWar/SteamWar#245
Reviewed-by: YoyoNow <yoyonow@noreply.localhost>
2025-12-03 09:56:28 +01:00
Chaoscaot 2f8491c3f6 Fix Team Creation
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-12-02 21:35:14 +01:00
Chaoscaot 4df92f7e5f Remove Poll-System
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-12-02 20:43:37 +01:00
Chaoscaot 9a78b99a75 Remove Poll-System
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-12-02 16:39:16 +01:00
Chaoscaot 1de1bf6571 Fix Leaderboard ID handling
Signed-off-by: Chaoscaot <max@maxsp.de>
2025-12-02 00:47:54 +01:00
YoyoNow eafb469eca Remove FlagStorage and merge into RegionData 2025-11-28 12:04:36 +01:00
YoyoNow 14bd38f471 Improve FlagStorage 2025-11-28 11:59:14 +01:00
YoyoNow febf2c283d Fix REntity.bowDrawnWatcher 2025-11-28 09:56:18 +01:00
YoyoNow 5f53ebf5b3 Fix REntity.getEquipmentPacket
Fix FightSchematic.pasteTeamName
2025-11-28 09:27:04 +01:00
YoyoNow fd4d15ac5a Fix replay in 1.21 -> RPlayer needs fixing before 2025-11-11 17:13:35 +01:00
Chaoscaot fa4d006dd3 Refactor Authlib integration and adjust entity handling for 1.21 compatibility 2025-11-08 20:09:02 +01:00
138 changed files with 1694 additions and 1784 deletions
+1
View File
@@ -21,3 +21,4 @@ lib
/WebsiteBackend/logs /WebsiteBackend/logs
/WebsiteBackend/skins /WebsiteBackend/skins
/WebsiteBackend/config.json /WebsiteBackend/config.json
/WebsiteBackend/sessions
@@ -52,6 +52,9 @@ FLAG_ITEMS=Items
FLAG_NO_GRAVITY = No Gravity FLAG_NO_GRAVITY = No Gravity
FLAG_TESTBLOCK=Testblock FLAG_TESTBLOCK=Testblock
FLAG_CHANGED=Changed FLAG_CHANGED=Changed
FLAG_WATER_DESTROY=Water Destroy
FLAG_WATER_DESTROY_ALLOW=§coff
FLAG_WATER_DESTROY_DENY=§aon
FLAG_FIRE_ALLOW=§con FLAG_FIRE_ALLOW=§con
FLAG_FIRE_DENY=§aoff FLAG_FIRE_DENY=§aoff
FLAG_FREEZE_ACTIVE=§aon FLAG_FREEZE_ACTIVE=§aon
@@ -140,6 +143,7 @@ BAU_INFO_ITEM_LORE_ITEMS=§7Items§8: §e{0}
BAU_INFO_ITEM_LORE_NO_GRAVITY = §7NoGravity§8: §e{0} BAU_INFO_ITEM_LORE_NO_GRAVITY = §7NoGravity§8: §e{0}
BAU_INFO_ITEM_LORE_TESTBLOCK=§7Testblock§8: §e{0} BAU_INFO_ITEM_LORE_TESTBLOCK=§7Testblock§8: §e{0}
BAU_INFO_ITEM_LORE_CHANGED=§7Changed§8: §e{0} BAU_INFO_ITEM_LORE_CHANGED=§7Changed§8: §e{0}
BAU_INFO_ITEM_LORE_WATER_DESTROY=§7Water Destroy§8: §e{0}
BAU_INFO_COMMAND_HELP=§8/§ebauinfo §8- §7Information regarding this build server BAU_INFO_COMMAND_HELP=§8/§ebauinfo §8- §7Information regarding this build server
BAU_INFO_COMMAND_OWNER=§7Owner§8: §e{0} BAU_INFO_COMMAND_OWNER=§7Owner§8: §e{0}
BAU_INFO_COMMAND_MEMBER=§7{0} §8[§7{1}§8]§8: §e{2} BAU_INFO_COMMAND_MEMBER=§7{0} §8[§7{1}§8]§8: §e{2}
@@ -756,6 +760,9 @@ REGION_FIRE_DISABLED=§aFire damage activated in this region
REGION_FREEZE_HELP=§8/§efreeze §8- §7Toggle Freeze REGION_FREEZE_HELP=§8/§efreeze §8- §7Toggle Freeze
REGION_FREEZE_ENABLED=§cRegion frozen REGION_FREEZE_ENABLED=§cRegion frozen
REGION_FREEZE_DISABLED=§aRegion thawed REGION_FREEZE_DISABLED=§aRegion thawed
REGION_WATER_HELP=§8/§ewaterdestroy §8- §7Toggle water damage
REGION_WATER_ENABLED=§aWater damage deactivated in this region
REGION_WATER_DISABLED=§cWater damage activated in this region
REGION_ITEMS_HELP=§8/§eitems §8- §7Toggle Items REGION_ITEMS_HELP=§8/§eitems §8- §7Toggle Items
REGION_ITEMS_ENABLED=§aItems enabled in this region REGION_ITEMS_ENABLED=§aItems enabled in this region
REGION_ITEMS_DISABLED=§cItems disabled in this region REGION_ITEMS_DISABLED=§cItems disabled in this region
@@ -54,6 +54,9 @@ FLAG_FREEZE_ACTIVE=§aan
FLAG_FREEZE_INACTIVE=§caus FLAG_FREEZE_INACTIVE=§caus
FLAG_PROTECT_ACTIVE=§aan FLAG_PROTECT_ACTIVE=§aan
FLAG_PROTECT_INACTIVE=§caus FLAG_PROTECT_INACTIVE=§caus
FLAG_WATER_DESTROY=Wasserschaden
FLAG_WATER_DESTROY_ALLOW=§cerlaubt
FLAG_WATER_DESTROY_DENY=§aaus
FLAG_TNT_ALLOW=§aan FLAG_TNT_ALLOW=§aan
FLAG_TNT_DENY=§caus FLAG_TNT_DENY=§caus
FLAG_TNT_ONLY_TB=§7Kein §eBaurahmen FLAG_TNT_ONLY_TB=§7Kein §eBaurahmen
@@ -122,6 +125,7 @@ BAU_INFO_ITEM_NAME=§eBau-Management
BAU_INFO_ITEM_LORE_FIRE=§7Feuer§8: §e{0} BAU_INFO_ITEM_LORE_FIRE=§7Feuer§8: §e{0}
BAU_INFO_ITEM_LORE_COLOR=§7Farbe§8: §e{0} BAU_INFO_ITEM_LORE_COLOR=§7Farbe§8: §e{0}
BAU_INFO_ITEM_LORE_CHANGED=§7Verändert§8: §e{0} BAU_INFO_ITEM_LORE_CHANGED=§7Verändert§8: §e{0}
BAU_INFO_ITEM_LORE_WATER_DESTROY=§7Wasserschaden§8: §e{0}
BAU_INFO_COMMAND_HELP=§8/§ebauinfo §8- §7Gibt Informationen über den Bau BAU_INFO_COMMAND_HELP=§8/§ebauinfo §8- §7Gibt Informationen über den Bau
BAU_INFO_COMMAND_OWNER=§7Besitzer§8: §e{0} BAU_INFO_COMMAND_OWNER=§7Besitzer§8: §e{0}
BAU_INFO_COMMAND_MEMBER=§7{0} §8[§7{1}§8]§8: §e{2} BAU_INFO_COMMAND_MEMBER=§7{0} §8[§7{1}§8]§8: §e{2}
@@ -704,6 +708,9 @@ REGION_PROTECT_FALSE_REGION=§cDu befindest dich derzeit in keiner (M)WG-Region
REGION_NO_GRAVITY_HELP = §8/§enogravity §8- §7Toggle NoGravity REGION_NO_GRAVITY_HELP = §8/§enogravity §8- §7Toggle NoGravity
REGION_NO_GRAVITY_ENABLED = §aNoGravity aktiviert in dieser Region REGION_NO_GRAVITY_ENABLED = §aNoGravity aktiviert in dieser Region
REGION_NO_GRAVITY_DISABLED = §cNoGravity deaktiviert in dieser Region REGION_NO_GRAVITY_DISABLED = §cNoGravity deaktiviert in dieser Region
REGION_WATER_HELP=§8/§ewaterblock §8- §7Wasserschaden umschalten
REGION_WATER_ENABLED=§aWasserschaden deaktiviert
REGION_WATER_DISABLED=§cWasserschaden aktiviert
REGION_REGION_HELP_UNDO=§8/§eregion undo §8- §7Mache die letzten 20 /testblock oder /reset rückgängig REGION_REGION_HELP_UNDO=§8/§eregion undo §8- §7Mache die letzten 20 /testblock oder /reset rückgängig
REGION_REGION_HELP_REDO=§8/§eregion redo §8- §7Wiederhole die letzten 20 §8/§7rg undo REGION_REGION_HELP_REDO=§8/§eregion redo §8- §7Wiederhole die letzten 20 §8/§7rg undo
REGION_REGION_HELP_RESTORE=§8/§eregion restore §8- §7Setzte die Region zurück, ohne das Gebaute zu löschen REGION_REGION_HELP_RESTORE=§8/§eregion restore §8- §7Setzte die Region zurück, ohne das Gebaute zu löschen
@@ -40,10 +40,13 @@ import de.steamwar.bausystem.worlddata.WorldData;
import de.steamwar.command.AbstractValidator; import de.steamwar.command.AbstractValidator;
import de.steamwar.command.SWCommandUtils; import de.steamwar.command.SWCommandUtils;
import de.steamwar.core.CRIUSleepEvent; import de.steamwar.core.CRIUSleepEvent;
import de.steamwar.core.Core;
import de.steamwar.core.WorldEditRendererCUIEditor; import de.steamwar.core.WorldEditRendererCUIEditor;
import de.steamwar.core.WorldIdentifier;
import de.steamwar.linkage.AbstractLinker; import de.steamwar.linkage.AbstractLinker;
import de.steamwar.linkage.SpigotLinker; import de.steamwar.linkage.SpigotLinker;
import de.steamwar.message.Message; import de.steamwar.message.Message;
import de.steamwar.providers.BauServerInfo;
import lombok.Getter; import lombok.Getter;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.GameRule; import org.bukkit.GameRule;
@@ -121,6 +124,7 @@ public class BauSystem extends JavaPlugin implements Listener {
} catch (AbstractLinker.LinkException e) { } catch (AbstractLinker.LinkException e) {
getLogger().log(Level.SEVERE, "Could not link a class.", e); getLogger().log(Level.SEVERE, "Could not link a class.", e);
Bukkit.shutdown(); Bukkit.shutdown();
return;
} }
TickListener.impl.init(); TickListener.impl.init();
@@ -131,6 +135,9 @@ public class BauSystem extends JavaPlugin implements Listener {
new WorldEditRendererCUIEditor(); new WorldEditRendererCUIEditor();
Bukkit.getWorlds().get(0).setGameRule(GameRule.SEND_COMMAND_FEEDBACK, false); Bukkit.getWorlds().get(0).setGameRule(GameRule.SEND_COMMAND_FEEDBACK, false);
String identifier = BauServerInfo.getOwnerUser().getUUID().toString().replace("-", "");
WorldIdentifier.set("bau/" + Core.getVersion() + "/" + identifier);
} }
@EventHandler @EventHandler
@@ -59,7 +59,7 @@ public class BackupCommand extends SWCommand {
if (checkGlobalRegion(region, p)) { if (checkGlobalRegion(region, p)) {
return; return;
} }
if (region.getFlags().get(Flag.CHANGED).isWithDefault(ChangedMode.NO_CHANGE)) { if (region.getRegionData().get(Flag.CHANGED).isWithDefault(ChangedMode.NO_CHANGE)) {
BauSystem.MESSAGE.send("BACKUP_CREATE_NO_CHANGE", p); BauSystem.MESSAGE.send("BACKUP_CREATE_NO_CHANGE", p);
return; return;
} }
@@ -56,8 +56,8 @@ public class BauInfoBauGuiItem extends BauGuiItem {
Region region = Region.getRegion(player.getLocation()); Region region = Region.getRegion(player.getLocation());
List<String> stringList = new ArrayList<>(); List<String> stringList = new ArrayList<>();
for (Flag flag : Flag.getFlags()) { for (Flag flag : Flag.getFlags()) {
if (!region.getFlags().has(flag).isApplicable()) continue; if (!region.getRegionData().has(flag).isApplicable()) continue;
FlagOptional<?> value = region.getFlags().get(flag); FlagOptional<?> value = region.getRegionData().get(flag);
if (value.isPresent()) { if (value.isPresent()) {
stringList.add(BauSystem.MESSAGE.parse("BAU_INFO_ITEM_LORE_" + flag.name(), player, BauSystem.MESSAGE.parse(value.getWithDefault().getChatValue(), player))); stringList.add(BauSystem.MESSAGE.parse("BAU_INFO_ITEM_LORE_" + flag.name(), player, BauSystem.MESSAGE.parse(value.getWithDefault().getChatValue(), player)));
} }
@@ -50,8 +50,8 @@ public class InfoCommand extends SWCommand {
BauSystem.MESSAGE.send("BAU_INFO_COMMAND_OWNER", p, SteamwarUser.byId(bauServer.getOwnerID()).getUserName()); BauSystem.MESSAGE.send("BAU_INFO_COMMAND_OWNER", p, SteamwarUser.byId(bauServer.getOwnerID()).getUserName());
Region region = Region.getRegion(p.getLocation()); Region region = Region.getRegion(p.getLocation());
for (Flag flag : Flag.getFlags()) { for (Flag flag : Flag.getFlags()) {
if (!region.getFlags().has(flag).isApplicable()) continue; if (!region.getRegionData().has(flag).isApplicable()) continue;
FlagOptional<?> value = region.getFlags().get(flag); FlagOptional<?> value = region.getRegionData().get(flag);
if (value.isPresent()) { if (value.isPresent()) {
BauSystem.MESSAGE.send("BAU_INFO_COMMAND_FLAG", p, BauSystem.MESSAGE.parse(flag.getChatValue(), p), BauSystem.MESSAGE.parse(value.getWithDefault().getChatValue(), p)); BauSystem.MESSAGE.send("BAU_INFO_COMMAND_FLAG", p, BauSystem.MESSAGE.parse(flag.getChatValue(), p), BauSystem.MESSAGE.parse(value.getWithDefault().getChatValue(), p));
} }
@@ -46,8 +46,8 @@ public class ObserverTracerListener implements Listener {
public ObserverTracerListener() { public ObserverTracerListener() {
Bukkit.getScheduler().runTaskTimer(BauSystem.getInstance(), () -> { Bukkit.getScheduler().runTaskTimer(BauSystem.getInstance(), () -> {
SWPlayer.allWithSingleComponent(ObserverTracer.class).forEach(pair -> { SWPlayer.allWithSingleComponent(ObserverTracer.class).forEach(pair -> {
if (pair.getKey().getGameMode() != GameMode.SPECTATOR) return; if (pair.getPlayer().getGameMode() != GameMode.SPECTATOR) return;
pair.getValue().show(); pair.getComponent().show();
}); });
}, 15L, 15L); }, 15L, 15L);
} }
@@ -64,7 +64,7 @@ public class ObserverTracerListener implements Listener {
createNew(event); createNew(event);
} }
SWPlayer.allWithSingleComponent(ObserverTracer.class).forEach(pair -> { SWPlayer.allWithSingleComponent(ObserverTracer.class).forEach(pair -> {
pair.getValue().trace(); pair.getComponent().trace();
}); });
}, 1L); }, 1L);
} else { } else {
@@ -51,17 +51,17 @@ public class ColorCommand extends SWCommand {
public void genericColorSet(@Validator Player p, ColorMode color, ColorizationType colorizationType) { public void genericColorSet(@Validator Player p, ColorMode color, ColorizationType colorizationType) {
if (colorizationType == ColorizationType.GLOBAL) { if (colorizationType == ColorizationType.GLOBAL) {
Region.getRegions().forEach(region -> { Region.getRegions().forEach(region -> {
region.getFlags().set(Flag.COLOR, color); region.getRegionData().set(Flag.COLOR, color);
}); });
BauSystem.MESSAGE.send("REGION_COLOR_GLOBAL", p, BauSystem.MESSAGE.parse(color.getChatValue(), p)); BauSystem.MESSAGE.send("REGION_COLOR_GLOBAL", p, BauSystem.MESSAGE.parse(color.getChatValue(), p));
return; return;
} }
Region region = Region.getRegion(p.getLocation()); Region region = Region.getRegion(p.getLocation());
if (!region.getFlags().has(Flag.COLOR).isWritable()) { if (!region.getRegionData().has(Flag.COLOR).isWritable()) {
BauSystem.MESSAGE.send("REGION_COLOR_NO_REGION", p); BauSystem.MESSAGE.send("REGION_COLOR_NO_REGION", p);
return; return;
} }
region.getFlags().set(Flag.COLOR, color); region.getRegionData().set(Flag.COLOR, color);
try { try {
PasteBuilder pasteBuilder = new PasteBuilder(new PasteBuilder.FileProvider(region.getArea().getResetFile())) PasteBuilder pasteBuilder = new PasteBuilder(new PasteBuilder.FileProvider(region.getArea().getResetFile()))
.ignoreAir(true) .ignoreAir(true)
@@ -53,11 +53,11 @@ public class FireCommand extends SWCommand {
} }
private boolean toggle(Region region) { private boolean toggle(Region region) {
if (region.getFlags().get(Flag.FIRE).isWithDefault(FireMode.ALLOW)) { if (region.getRegionData().get(Flag.FIRE).isWithDefault(FireMode.ALLOW)) {
region.getFlags().set(Flag.FIRE, FireMode.DENY); region.getRegionData().set(Flag.FIRE, FireMode.DENY);
return true; return true;
} else { } else {
region.getFlags().set(Flag.FIRE, FireMode.ALLOW); region.getRegionData().set(Flag.FIRE, FireMode.ALLOW);
return false; return false;
} }
} }
@@ -36,12 +36,12 @@ public class FireListener implements Listener, ScoreboardElement {
@EventHandler @EventHandler
public void onFireDamage(BlockBurnEvent e) { public void onFireDamage(BlockBurnEvent e) {
if (Region.getRegion(e.getBlock().getLocation()).getFlags().get(Flag.FIRE).isWithDefault(FireMode.DENY)) e.setCancelled(true); if (Region.getRegion(e.getBlock().getLocation()).getRegionData().get(Flag.FIRE).isWithDefault(FireMode.DENY)) e.setCancelled(true);
} }
@EventHandler @EventHandler
public void onFireSpread(BlockSpreadEvent e) { public void onFireSpread(BlockSpreadEvent e) {
if (Region.getRegion(e.getBlock().getLocation()).getFlags().get(Flag.FIRE).isWithDefault(FireMode.DENY)) e.setCancelled(true); if (Region.getRegion(e.getBlock().getLocation()).getRegionData().get(Flag.FIRE).isWithDefault(FireMode.DENY)) e.setCancelled(true);
} }
@Override @Override
@@ -56,7 +56,7 @@ public class FireListener implements Listener, ScoreboardElement {
@Override @Override
public String get(Region region, Player p) { public String get(Region region, Player p) {
if (region.getFlags().get(Flag.FIRE).isWithDefault(FireMode.DENY)) return null; if (region.getRegionData().get(Flag.FIRE).isWithDefault(FireMode.DENY)) return null;
return "§e" + BauSystem.MESSAGE.parse(Flag.FIRE.getChatValue(), p) + "§8: " + BauSystem.MESSAGE.parse(region.getFlags().get(Flag.FIRE).getWithDefault().getChatValue(), p); return "§e" + BauSystem.MESSAGE.parse(Flag.FIRE.getChatValue(), p) + "§8: " + BauSystem.MESSAGE.parse(region.getRegionData().get(Flag.FIRE).getWithDefault().getChatValue(), p);
} }
} }
@@ -53,11 +53,11 @@ public class FreezeCommand extends SWCommand {
} }
private boolean toggle(Region region) { private boolean toggle(Region region) {
if (region.getFlags().get(Flag.FREEZE).isWithDefault(FreezeMode.ACTIVE)) { if (region.getRegionData().get(Flag.FREEZE).isWithDefault(FreezeMode.ACTIVE)) {
region.getFlags().set(Flag.FREEZE, FreezeMode.INACTIVE); region.getRegionData().set(Flag.FREEZE, FreezeMode.INACTIVE);
return false; return false;
} else { } else {
region.getFlags().set(Flag.FREEZE, FreezeMode.ACTIVE); region.getRegionData().set(Flag.FREEZE, FreezeMode.ACTIVE);
return true; return true;
} }
} }
@@ -48,7 +48,7 @@ public class FreezeListener implements Listener, ScoreboardElement {
@EventHandler @EventHandler
public void onEntitySpawn(EntitySpawnEvent e) { public void onEntitySpawn(EntitySpawnEvent e) {
if (Region.getRegion(e.getLocation()).getFlags().get(Flag.FREEZE).isWithDefault(FreezeMode.INACTIVE)) return; if (Region.getRegion(e.getLocation()).getRegionData().get(Flag.FREEZE).isWithDefault(FreezeMode.INACTIVE)) return;
e.setCancelled(true); e.setCancelled(true);
if (e.getEntityType() == TrickyTrialsWrapper.impl.getTntEntityType()) { if (e.getEntityType() == TrickyTrialsWrapper.impl.getTntEntityType()) {
Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), () -> { Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), () -> {
@@ -60,7 +60,7 @@ public class FreezeListener implements Listener, ScoreboardElement {
@EventHandler @EventHandler
public void onBlockCanBuild(BlockCanBuildEvent e) { public void onBlockCanBuild(BlockCanBuildEvent e) {
if (!e.isBuildable()) return; if (!e.isBuildable()) return;
if (Region.getRegion(e.getBlock().getLocation()).getFlags().get(Flag.FREEZE).isWithDefault(FreezeMode.INACTIVE)) return; if (Region.getRegion(e.getBlock().getLocation()).getRegionData().get(Flag.FREEZE).isWithDefault(FreezeMode.INACTIVE)) return;
if (e.getMaterial() == Material.TNT) { if (e.getMaterial() == Material.TNT) {
e.setBuildable(false); e.setBuildable(false);
e.getBlock().setType(Material.TNT, false); e.getBlock().setType(Material.TNT, false);
@@ -69,14 +69,14 @@ public class FreezeListener implements Listener, ScoreboardElement {
@EventHandler @EventHandler
public void onEntityChangeBlock(EntityChangeBlockEvent e) { public void onEntityChangeBlock(EntityChangeBlockEvent e) {
if (Region.getRegion(e.getBlock().getLocation()).getFlags().get(Flag.FREEZE).isWithDefault(FreezeMode.ACTIVE)) { if (Region.getRegion(e.getBlock().getLocation()).getRegionData().get(Flag.FREEZE).isWithDefault(FreezeMode.ACTIVE)) {
e.setCancelled(true); e.setCancelled(true);
} }
} }
@EventHandler @EventHandler
public void onPhysicsEvent(BlockPhysicsEvent e) { public void onPhysicsEvent(BlockPhysicsEvent e) {
if (Region.getRegion(e.getBlock().getLocation()).getFlags().get(Flag.FREEZE).isWithDefault(FreezeMode.ACTIVE)) { if (Region.getRegion(e.getBlock().getLocation()).getRegionData().get(Flag.FREEZE).isWithDefault(FreezeMode.ACTIVE)) {
if (e.getSourceBlock().getType() == Material.NOTE_BLOCK) { if (e.getSourceBlock().getType() == Material.NOTE_BLOCK) {
BlockState state = e.getSourceBlock().getState(); BlockState state = e.getSourceBlock().getState();
NoteBlock noteBlock = (NoteBlock) state.getBlockData(); NoteBlock noteBlock = (NoteBlock) state.getBlockData();
@@ -101,44 +101,44 @@ public class FreezeListener implements Listener, ScoreboardElement {
@EventHandler @EventHandler
public void onPistonExtend(BlockPistonExtendEvent e) { public void onPistonExtend(BlockPistonExtendEvent e) {
if (Region.getRegion(e.getBlock().getLocation()).getFlags().get(Flag.FREEZE).isWithDefault(FreezeMode.ACTIVE)) { if (Region.getRegion(e.getBlock().getLocation()).getRegionData().get(Flag.FREEZE).isWithDefault(FreezeMode.ACTIVE)) {
e.setCancelled(true); e.setCancelled(true);
} }
} }
@EventHandler @EventHandler
public void onPistonRetract(BlockPistonRetractEvent e) { public void onPistonRetract(BlockPistonRetractEvent e) {
if (Region.getRegion(e.getBlock().getLocation()).getFlags().get(Flag.FREEZE).isWithDefault(FreezeMode.ACTIVE)) { if (Region.getRegion(e.getBlock().getLocation()).getRegionData().get(Flag.FREEZE).isWithDefault(FreezeMode.ACTIVE)) {
e.setCancelled(true); e.setCancelled(true);
} }
} }
@EventHandler @EventHandler
public void onBlockGrow(BlockGrowEvent e) { public void onBlockGrow(BlockGrowEvent e) {
if (Region.getRegion(e.getBlock().getLocation()).getFlags().get(Flag.FREEZE).isWithDefault(FreezeMode.ACTIVE)) { if (Region.getRegion(e.getBlock().getLocation()).getRegionData().get(Flag.FREEZE).isWithDefault(FreezeMode.ACTIVE)) {
e.setCancelled(true); e.setCancelled(true);
} }
} }
@EventHandler @EventHandler
public void onRedstoneEvent(BlockRedstoneEvent e) { public void onRedstoneEvent(BlockRedstoneEvent e) {
if (Region.getRegion(e.getBlock().getLocation()).getFlags().get(Flag.FREEZE).isWithDefault(FreezeMode.ACTIVE)) { if (Region.getRegion(e.getBlock().getLocation()).getRegionData().get(Flag.FREEZE).isWithDefault(FreezeMode.ACTIVE)) {
e.setNewCurrent(e.getOldCurrent()); e.setNewCurrent(e.getOldCurrent());
} }
} }
@EventHandler @EventHandler
public void onBlockDispense(BlockDispenseEvent e) { public void onBlockDispense(BlockDispenseEvent e) {
if (Region.getRegion(e.getBlock().getLocation()).getFlags().get(Flag.FREEZE).isWithDefault(FreezeMode.ACTIVE)) { if (Region.getRegion(e.getBlock().getLocation()).getRegionData().get(Flag.FREEZE).isWithDefault(FreezeMode.ACTIVE)) {
e.setCancelled(true); e.setCancelled(true);
} }
} }
@EventHandler @EventHandler
public void onInventoryMoveEvent(InventoryMoveItemEvent e) { public void onInventoryMoveEvent(InventoryMoveItemEvent e) {
if (e.getDestination().getLocation() != null && Region.getRegion(e.getDestination().getLocation()).getFlags().get(Flag.FREEZE).isWithDefault(FreezeMode.ACTIVE)) { if (e.getDestination().getLocation() != null && Region.getRegion(e.getDestination().getLocation()).getRegionData().get(Flag.FREEZE).isWithDefault(FreezeMode.ACTIVE)) {
e.setCancelled(true); e.setCancelled(true);
} else if (e.getSource().getLocation() != null && Region.getRegion(e.getSource().getLocation()).getFlags().get(Flag.FREEZE).isWithDefault(FreezeMode.ACTIVE)) { } else if (e.getSource().getLocation() != null && Region.getRegion(e.getSource().getLocation()).getRegionData().get(Flag.FREEZE).isWithDefault(FreezeMode.ACTIVE)) {
e.setCancelled(true); e.setCancelled(true);
} }
} }
@@ -147,7 +147,7 @@ public class FreezeListener implements Listener, ScoreboardElement {
public void onBlockBreak(BlockBreakEvent e) { public void onBlockBreak(BlockBreakEvent e) {
if (Core.getVersion() < 19) return; if (Core.getVersion() < 19) return;
if (e.getPlayer().getInventory().getItemInMainHand().getType() == Material.DEBUG_STICK) return; if (e.getPlayer().getInventory().getItemInMainHand().getType() == Material.DEBUG_STICK) return;
if (Region.getRegion(e.getBlock().getLocation()).getFlags().get(Flag.FREEZE).isWithDefault(FreezeMode.ACTIVE)) { if (Region.getRegion(e.getBlock().getLocation()).getRegionData().get(Flag.FREEZE).isWithDefault(FreezeMode.ACTIVE)) {
e.setCancelled(true); e.setCancelled(true);
e.getBlock().setType(Material.BARRIER, false); e.getBlock().setType(Material.BARRIER, false);
e.getBlock().setType(Material.AIR, false); e.getBlock().setType(Material.AIR, false);
@@ -170,35 +170,35 @@ public class FreezeListener implements Listener, ScoreboardElement {
@EventHandler @EventHandler
public void onFluidLevelChange(FluidLevelChangeEvent e) { public void onFluidLevelChange(FluidLevelChangeEvent e) {
if (Region.getRegion(e.getBlock().getLocation()).getFlags().get(Flag.FREEZE).isWithDefault(FreezeMode.ACTIVE)) { if (Region.getRegion(e.getBlock().getLocation()).getRegionData().get(Flag.FREEZE).isWithDefault(FreezeMode.ACTIVE)) {
e.setCancelled(true); e.setCancelled(true);
} }
} }
@EventHandler @EventHandler
public void onBlockSpread(BlockSpreadEvent e) { public void onBlockSpread(BlockSpreadEvent e) {
if (Region.getRegion(e.getBlock().getLocation()).getFlags().get(Flag.FREEZE).isWithDefault(FreezeMode.ACTIVE)) { if (Region.getRegion(e.getBlock().getLocation()).getRegionData().get(Flag.FREEZE).isWithDefault(FreezeMode.ACTIVE)) {
e.setCancelled(true); e.setCancelled(true);
} }
} }
@EventHandler @EventHandler
public void onBlockFromTo(BlockFromToEvent e) { public void onBlockFromTo(BlockFromToEvent e) {
if (Region.getRegion(e.getBlock().getLocation()).getFlags().get(Flag.FREEZE).isWithDefault(FreezeMode.ACTIVE)) { if (Region.getRegion(e.getBlock().getLocation()).getRegionData().get(Flag.FREEZE).isWithDefault(FreezeMode.ACTIVE)) {
e.setCancelled(true); e.setCancelled(true);
} }
} }
@EventHandler @EventHandler
public void onSpongeAbsorb(SpongeAbsorbEvent e) { public void onSpongeAbsorb(SpongeAbsorbEvent e) {
if (Region.getRegion(e.getBlock().getLocation()).getFlags().get(Flag.FREEZE).isWithDefault(FreezeMode.ACTIVE)) { if (Region.getRegion(e.getBlock().getLocation()).getRegionData().get(Flag.FREEZE).isWithDefault(FreezeMode.ACTIVE)) {
e.setCancelled(true); e.setCancelled(true);
} }
} }
@EventHandler @EventHandler
public void onBlockForm(BlockFormEvent e) { public void onBlockForm(BlockFormEvent e) {
if (Region.getRegion(e.getBlock().getLocation()).getFlags().get(Flag.FREEZE).isWithDefault(FreezeMode.ACTIVE)) { if (Region.getRegion(e.getBlock().getLocation()).getRegionData().get(Flag.FREEZE).isWithDefault(FreezeMode.ACTIVE)) {
e.setCancelled(true); e.setCancelled(true);
} }
} }
@@ -206,7 +206,7 @@ public class FreezeListener implements Listener, ScoreboardElement {
@EventHandler @EventHandler
public void onPlayerInteract(PlayerInteractEvent e) { public void onPlayerInteract(PlayerInteractEvent e) {
if (e.getAction() != Action.RIGHT_CLICK_BLOCK) return; if (e.getAction() != Action.RIGHT_CLICK_BLOCK) return;
if (Region.getRegion(e.getClickedBlock().getLocation()).getFlags().get(Flag.FREEZE).isWithDefault(FreezeMode.ACTIVE)) { if (Region.getRegion(e.getClickedBlock().getLocation()).getRegionData().get(Flag.FREEZE).isWithDefault(FreezeMode.ACTIVE)) {
Block block = e.getClickedBlock(); Block block = e.getClickedBlock();
if (block.getType() == Material.LEVER) { if (block.getType() == Material.LEVER) {
Switch data = ((Switch) block.getBlockData()); Switch data = ((Switch) block.getBlockData());
@@ -218,7 +218,7 @@ public class FreezeListener implements Listener, ScoreboardElement {
@EventHandler @EventHandler
public void onBlockFade(BlockFadeEvent e) { public void onBlockFade(BlockFadeEvent e) {
if (Region.getRegion(e.getBlock().getLocation()).getFlags().get(Flag.FREEZE).isWithDefault(FreezeMode.ACTIVE)) { if (Region.getRegion(e.getBlock().getLocation()).getRegionData().get(Flag.FREEZE).isWithDefault(FreezeMode.ACTIVE)) {
e.setCancelled(true); e.setCancelled(true);
} }
} }
@@ -235,7 +235,7 @@ public class FreezeListener implements Listener, ScoreboardElement {
@Override @Override
public String get(Region region, Player p) { public String get(Region region, Player p) {
if (region.getFlags().get(Flag.FREEZE).isWithDefault(FreezeMode.INACTIVE)) return null; if (region.getRegionData().get(Flag.FREEZE).isWithDefault(FreezeMode.INACTIVE)) return null;
return "§e" + BauSystem.MESSAGE.parse(Flag.FREEZE.getChatValue(), p) + "§8: " + BauSystem.MESSAGE.parse(region.getFlags().get(Flag.FREEZE).getWithDefault().getChatValue(), p); return "§e" + BauSystem.MESSAGE.parse(Flag.FREEZE.getChatValue(), p) + "§8: " + BauSystem.MESSAGE.parse(region.getRegionData().get(Flag.FREEZE).getWithDefault().getChatValue(), p);
} }
} }
@@ -55,11 +55,11 @@ public class ItemsCommand extends SWCommand {
} }
private boolean toggle(Region region) { private boolean toggle(Region region) {
if (region.getFlags().get(Flag.ITEMS).isWithDefault(ItemMode.ACTIVE)) { if (region.getRegionData().get(Flag.ITEMS).isWithDefault(ItemMode.ACTIVE)) {
region.getFlags().set(Flag.ITEMS, ItemMode.INACTIVE); region.getRegionData().set(Flag.ITEMS, ItemMode.INACTIVE);
return false; return false;
} else { } else {
region.getFlags().set(Flag.ITEMS, ItemMode.ACTIVE); region.getRegionData().set(Flag.ITEMS, ItemMode.ACTIVE);
return true; return true;
} }
} }
@@ -37,7 +37,7 @@ public class ItemsListener implements Listener, ScoreboardElement {
@EventHandler @EventHandler
public void onItemSpawn(ItemSpawnEvent event) { public void onItemSpawn(ItemSpawnEvent event) {
if (Region.getRegion(event.getLocation()).getFlags().get(Flag.ITEMS).isWithDefault(ItemMode.INACTIVE)) { if (Region.getRegion(event.getLocation()).getRegionData().get(Flag.ITEMS).isWithDefault(ItemMode.INACTIVE)) {
event.setCancelled(true); event.setCancelled(true);
} }
} }
@@ -54,7 +54,7 @@ public class ItemsListener implements Listener, ScoreboardElement {
@Override @Override
public String get(Region region, Player p) { public String get(Region region, Player p) {
if (region.getFlags().get(Flag.ITEMS).isWithDefault(ItemMode.INACTIVE)) return null; if (region.getRegionData().get(Flag.ITEMS).isWithDefault(ItemMode.INACTIVE)) return null;
return "§e" + BauSystem.MESSAGE.parse(Flag.ITEMS.getChatValue(), p) + "§8: " + BauSystem.MESSAGE.parse(region.getFlags().get(Flag.ITEMS).getWithDefault().getChatValue(), p); return "§e" + BauSystem.MESSAGE.parse(Flag.ITEMS.getChatValue(), p) + "§8: " + BauSystem.MESSAGE.parse(region.getRegionData().get(Flag.ITEMS).getWithDefault().getChatValue(), p);
} }
} }
@@ -53,11 +53,11 @@ public class NoGravityCommand extends SWCommand {
} }
private boolean toggle(Region region) { private boolean toggle(Region region) {
if (region.getFlags().get(Flag.NO_GRAVITY).isWithDefault(NoGravityMode.ACTIVE)) { if (region.getRegionData().get(Flag.NO_GRAVITY).isWithDefault(NoGravityMode.ACTIVE)) {
region.getFlags().set(Flag.NO_GRAVITY, NoGravityMode.INACTIVE); region.getRegionData().set(Flag.NO_GRAVITY, NoGravityMode.INACTIVE);
return false; return false;
} else { } else {
region.getFlags().set(Flag.NO_GRAVITY, NoGravityMode.ACTIVE); region.getRegionData().set(Flag.NO_GRAVITY, NoGravityMode.ACTIVE);
return true; return true;
} }
} }
@@ -37,7 +37,7 @@ public class NoGravityListener implements Listener, ScoreboardElement {
@EventHandler @EventHandler
public void onEntitySpawn(EntitySpawnEvent event) { public void onEntitySpawn(EntitySpawnEvent event) {
if (event.getEntityType() == EntityType.PLAYER) return; if (event.getEntityType() == EntityType.PLAYER) return;
if (Region.getRegion(event.getLocation()).getFlags().get(Flag.NO_GRAVITY).isWithDefault(NoGravityMode.ACTIVE)) { if (Region.getRegion(event.getLocation()).getRegionData().get(Flag.NO_GRAVITY).isWithDefault(NoGravityMode.ACTIVE)) {
event.getEntity().setGravity(false); event.getEntity().setGravity(false);
} }
} }
@@ -54,7 +54,7 @@ public class NoGravityListener implements Listener, ScoreboardElement {
@Override @Override
public String get(Region region, Player p) { public String get(Region region, Player p) {
if (region.getFlags().get(Flag.NO_GRAVITY).isWithDefault(NoGravityMode.INACTIVE)) return null; if (region.getRegionData().get(Flag.NO_GRAVITY).isWithDefault(NoGravityMode.INACTIVE)) return null;
return "§e" + BauSystem.MESSAGE.parse(Flag.NO_GRAVITY.getChatValue(), p) + "§8: " + BauSystem.MESSAGE.parse(region.getFlags().get(Flag.NO_GRAVITY).getWithDefault().getChatValue(), p); return "§e" + BauSystem.MESSAGE.parse(Flag.NO_GRAVITY.getChatValue(), p) + "§8: " + BauSystem.MESSAGE.parse(region.getRegionData().get(Flag.NO_GRAVITY).getWithDefault().getChatValue(), p);
} }
} }
@@ -39,18 +39,18 @@ public class ProtectCommand extends SWCommand {
public void genericProtectCommand(@Validator Player p) { public void genericProtectCommand(@Validator Player p) {
Region region = regionCheck(p); Region region = regionCheck(p);
if (region == null) return; if (region == null) return;
if (region.getFlags().get(Flag.PROTECT).isWithDefault(ProtectMode.ACTIVE)) { if (region.getRegionData().get(Flag.PROTECT).isWithDefault(ProtectMode.ACTIVE)) {
region.getFlags().set(Flag.PROTECT, ProtectMode.INACTIVE); region.getRegionData().set(Flag.PROTECT, ProtectMode.INACTIVE);
RegionUtils.actionBar(region, "REGION_PROTECT_DISABLE"); RegionUtils.actionBar(region, "REGION_PROTECT_DISABLE");
} else { } else {
region.getFlags().set(Flag.PROTECT, ProtectMode.ACTIVE); region.getRegionData().set(Flag.PROTECT, ProtectMode.ACTIVE);
RegionUtils.actionBar(region, "REGION_PROTECT_ENABLE"); RegionUtils.actionBar(region, "REGION_PROTECT_ENABLE");
} }
} }
private Region regionCheck(Player player) { private Region regionCheck(Player player) {
Region region = Region.getRegion(player.getLocation()); Region region = Region.getRegion(player.getLocation());
if (!region.getFlags().has(Flag.PROTECT).isApplicable()) { if (!region.getRegionData().has(Flag.PROTECT).isApplicable()) {
BauSystem.MESSAGE.send("REGION_PROTECT_FALSE_REGION", player); BauSystem.MESSAGE.send("REGION_PROTECT_FALSE_REGION", player);
return null; return null;
} }
@@ -41,7 +41,7 @@ public class ProtectListener implements Listener, ScoreboardElement {
private void explode(List<Block> blockList, Location location) { private void explode(List<Block> blockList, Location location) {
Region region = Region.getRegion(location); Region region = Region.getRegion(location);
if (region.getFlags().get(Flag.PROTECT).isWithDefault(ProtectMode.INACTIVE)) return; if (region.getRegionData().get(Flag.PROTECT).isWithDefault(ProtectMode.INACTIVE)) return;
Point p1 = region.getBuildArea().getMinPoint(true); Point p1 = region.getBuildArea().getMinPoint(true);
Point p2 = region.getTestblockArea().getMinPoint(true); Point p2 = region.getTestblockArea().getMinPoint(true);
int floorLevel = Math.min(p1.getY(), p2.getY()); int floorLevel = Math.min(p1.getY(), p2.getY());
@@ -70,7 +70,7 @@ public class ProtectListener implements Listener, ScoreboardElement {
@Override @Override
public String get(Region region, Player p) { public String get(Region region, Player p) {
if (region.getFlags().get(Flag.PROTECT).isWithDefault(ProtectMode.INACTIVE)) return null; if (region.getRegionData().get(Flag.PROTECT).isWithDefault(ProtectMode.INACTIVE)) return null;
return "§e" + BauSystem.MESSAGE.parse(Flag.PROTECT.getChatValue(), p) + "§8: " + BauSystem.MESSAGE.parse(region.getFlags().get(Flag.PROTECT).getWithDefault().getChatValue(), p); return "§e" + BauSystem.MESSAGE.parse(Flag.PROTECT.getChatValue(), p) + "§8: " + BauSystem.MESSAGE.parse(region.getRegionData().get(Flag.PROTECT).getWithDefault().getChatValue(), p);
} }
} }
@@ -102,7 +102,7 @@ public class RegionCommand extends SWCommand {
try { try {
PasteBuilder pasteBuilder = new PasteBuilder(new PasteBuilder.FileProvider(region.getArea().getResetFile())) PasteBuilder pasteBuilder = new PasteBuilder(new PasteBuilder.FileProvider(region.getArea().getResetFile()))
.ignoreAir(true) .ignoreAir(true)
.color(region.getFlags().get(Flag.COLOR).getWithDefault()); .color(region.getRegionData().get(Flag.COLOR).getWithDefault());
region.getArea().reset(pasteBuilder, false); region.getArea().reset(pasteBuilder, false);
RegionUtils.message(region, "REGION_REGION_RESTORED"); RegionUtils.message(region, "REGION_REGION_RESTORED");
} catch (SecurityException e) { } catch (SecurityException e) {
@@ -124,7 +124,7 @@ public class RegionCommand extends SWCommand {
try { try {
PasteBuilder pasteBuilder = new PasteBuilder(new PasteBuilder.SchematicProvider(node)) PasteBuilder pasteBuilder = new PasteBuilder(new PasteBuilder.SchematicProvider(node))
.ignoreAir(true) .ignoreAir(true)
.color(region.getFlags().get(Flag.COLOR).getWithDefault()); .color(region.getRegionData().get(Flag.COLOR).getWithDefault());
region.getArea().reset(pasteBuilder, false); region.getArea().reset(pasteBuilder, false);
RegionUtils.message(region, "REGION_REGION_RESTORED"); RegionUtils.message(region, "REGION_REGION_RESTORED");
} catch (SecurityException e) { } catch (SecurityException e) {
@@ -182,6 +182,6 @@ public class RegionListener implements Listener {
} }
private static void tagChangedRegion(final Location location) { private static void tagChangedRegion(final Location location) {
Region.getRegion(location).getFlags().set(Flag.CHANGED, ChangedMode.HAS_CHANGE); Region.getRegion(location).getRegionData().set(Flag.CHANGED, ChangedMode.HAS_CHANGE);
} }
} }
@@ -53,9 +53,8 @@ public class ResetCommand extends SWCommand {
if (region == null) return; if (region == null) return;
try { try {
PasteBuilder pasteBuilder = new PasteBuilder(new PasteBuilder.FileProvider(region.getArea().getResetFile())) PasteBuilder pasteBuilder = new PasteBuilder(new PasteBuilder.FileProvider(region.getArea().getResetFile()))
.color(region.getFlags().get(Flag.COLOR).getWithDefault()); .color(region.getRegionData().get(Flag.COLOR).getWithDefault());
region.getArea().reset(pasteBuilder, false); region.getArea().reset(pasteBuilder, false);
region.getFlags().clear();
region.getRegionData().clear(); region.getRegionData().clear();
RegionUtils.message(region, "REGION_RESET_RESETED"); RegionUtils.message(region, "REGION_RESET_RESETED");
} catch (SecurityException e) { } catch (SecurityException e) {
@@ -84,7 +83,7 @@ public class ResetCommand extends SWCommand {
} }
try { try {
PasteBuilder pasteBuilder = new PasteBuilder(new PasteBuilder.SchematicProvider(node)) PasteBuilder pasteBuilder = new PasteBuilder(new PasteBuilder.SchematicProvider(node))
.color(region.getFlags().get(Flag.COLOR).getWithDefault()); .color(region.getRegionData().get(Flag.COLOR).getWithDefault());
region.getArea().reset(pasteBuilder, true); region.getArea().reset(pasteBuilder, true);
RegionUtils.message(region, "REGION_RESET_RESETED"); RegionUtils.message(region, "REGION_RESET_RESETED");
} catch (SecurityException e) { } catch (SecurityException e) {
@@ -92,7 +92,7 @@ public class TNTCommand extends SWCommand {
@Override @Override
public List<String> tabCompletes(CommandSender sender, PreviousArguments previousArguments, String s) { public List<String> tabCompletes(CommandSender sender, PreviousArguments previousArguments, String s) {
Region region = Region.getRegion(((Player) sender).getLocation()); Region region = Region.getRegion(((Player) sender).getLocation());
if (region.getFlags().get(Flag.TESTBLOCK).isNotWithDefault(TestblockMode.NO_VALUE)) { if (region.getRegionData().get(Flag.TESTBLOCK).isNotWithDefault(TestblockMode.NO_VALUE)) {
return new ArrayList<>(tntModeMap.keySet()); return new ArrayList<>(tntModeMap.keySet());
} else { } else {
return new ArrayList<>(tntModeMapReduced.keySet()); return new ArrayList<>(tntModeMapReduced.keySet());
@@ -102,7 +102,7 @@ public class TNTCommand extends SWCommand {
@Override @Override
public TNTMode map(CommandSender sender, PreviousArguments previousArguments, String s) { public TNTMode map(CommandSender sender, PreviousArguments previousArguments, String s) {
Region region = Region.getRegion(((Player) sender).getLocation()); Region region = Region.getRegion(((Player) sender).getLocation());
if (region.getFlags().get(Flag.TESTBLOCK).isNotWithDefault(TestblockMode.NO_VALUE)) { if (region.getRegionData().get(Flag.TESTBLOCK).isNotWithDefault(TestblockMode.NO_VALUE)) {
return tntModeMap.getOrDefault(s, null); return tntModeMap.getOrDefault(s, null);
} else { } else {
return tntModeMapReduced.getOrDefault(s, null); return tntModeMapReduced.getOrDefault(s, null);
@@ -124,23 +124,23 @@ public class TNTCommand extends SWCommand {
} }
private void tntToggle(Region region, TNTMode requestedMode, String requestedMessage) { private void tntToggle(Region region, TNTMode requestedMode, String requestedMessage) {
if (requestedMode != null && region.getFlags().get(Flag.TESTBLOCK).isNotWithDefault(TestblockMode.NO_VALUE)) { if (requestedMode != null && region.getRegionData().get(Flag.TESTBLOCK).isNotWithDefault(TestblockMode.NO_VALUE)) {
region.getFlags().set(Flag.TNT, requestedMode); region.getRegionData().set(Flag.TNT, requestedMode);
RegionUtils.actionBar(region, requestedMessage); RegionUtils.actionBar(region, requestedMessage);
return; return;
} }
switch (region.getFlags().get(Flag.TNT).getWithDefault()) { switch (region.getRegionData().get(Flag.TNT).getWithDefault()) {
case ALLOW: case ALLOW:
case ONLY_TB: case ONLY_TB:
region.getFlags().set(Flag.TNT, TNTMode.DENY); region.getRegionData().set(Flag.TNT, TNTMode.DENY);
RegionUtils.actionBar(region, getDisableMessage()); RegionUtils.actionBar(region, getDisableMessage());
break; break;
case DENY: case DENY:
if (region.getFlags().get(Flag.TESTBLOCK).isNotWithDefault(TestblockMode.NO_VALUE)) { if (region.getRegionData().get(Flag.TESTBLOCK).isNotWithDefault(TestblockMode.NO_VALUE)) {
region.getFlags().set(Flag.TNT, TNTMode.ONLY_TB); region.getRegionData().set(Flag.TNT, TNTMode.ONLY_TB);
RegionUtils.actionBar(region, getTestblockEnableMessage()); RegionUtils.actionBar(region, getTestblockEnableMessage());
} else { } else {
region.getFlags().set(Flag.TNT, TNTMode.ALLOW); region.getRegionData().set(Flag.TNT, TNTMode.ALLOW);
RegionUtils.actionBar(region, getEnableMessage()); RegionUtils.actionBar(region, getEnableMessage());
} }
break; break;
@@ -44,7 +44,7 @@ public class TNTListener implements Listener, ScoreboardElement {
private void explode(List<Block> blockList, boolean destroy) { private void explode(List<Block> blockList, boolean destroy) {
blockList.removeIf(block -> { blockList.removeIf(block -> {
Region region = Region.getRegion(block.getLocation()); Region region = Region.getRegion(block.getLocation());
TNTMode value = region.getFlags().get(Flag.TNT).getWithDefault(); TNTMode value = region.getRegionData().get(Flag.TNT).getWithDefault();
if (value == TNTMode.ALLOW) { if (value == TNTMode.ALLOW) {
if (destroy && block.getType() != Material.TNT) { if (destroy && block.getType() != Material.TNT) {
block.setType(Material.AIR); block.setType(Material.AIR);
@@ -86,7 +86,7 @@ public class TNTListener implements Listener, ScoreboardElement {
@Override @Override
public String get(Region region, Player p) { public String get(Region region, Player p) {
if (region.getFlags().get(Flag.TNT).isWithDefault(TNTMode.ALLOW)) return null; if (region.getRegionData().get(Flag.TNT).isWithDefault(TNTMode.ALLOW)) return null;
return "§e" + BauSystem.MESSAGE.parse(Flag.TNT.getChatValue(), p) + "§8: " + BauSystem.MESSAGE.parse(region.getFlags().get(Flag.TNT).getWithDefault().getChatValue(), p); return "§e" + BauSystem.MESSAGE.parse(Flag.TNT.getChatValue(), p) + "§8: " + BauSystem.MESSAGE.parse(region.getRegionData().get(Flag.TNT).getWithDefault().getChatValue(), p);
} }
} }
@@ -119,7 +119,7 @@ public class TestblockCommand extends SWCommand {
.onlyColors(onlyColors) .onlyColors(onlyColors)
.removeTNT(removeTNT) .removeTNT(removeTNT)
.removeWater(removeWater) .removeWater(removeWater)
.color(region.getFlags().get(Flag.COLOR).getWithDefault()); .color(region.getRegionData().get(Flag.COLOR).getWithDefault());
region.getTestblockArea().reset(pasteBuilder, regionExtensionType == RegionExtensionType.EXTENSION); region.getTestblockArea().reset(pasteBuilder, regionExtensionType == RegionExtensionType.EXTENSION);
RegionUtils.message(region, "REGION_TB_DONE"); RegionUtils.message(region, "REGION_TB_DONE");
} catch (SecurityException e) { } catch (SecurityException e) {
@@ -0,0 +1,64 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2025 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.region;
import de.steamwar.bausystem.region.Region;
import de.steamwar.bausystem.region.RegionUtils;
import de.steamwar.bausystem.region.flags.Flag;
import de.steamwar.bausystem.region.flags.WaterDestroyMode;
import de.steamwar.command.SWCommand;
import de.steamwar.linkage.Linked;
import org.bukkit.entity.Player;
@Linked
public class WaterDestroyCommand extends SWCommand {
public WaterDestroyCommand() {
super("waterdestroy");
}
private String getEnableMessage(){
return "REGION_WATER_ENABLED";
}
private String getDisableMessage(){
return "REGION_WATER_DISABLED";
}
@Register(description = "REGION_WATER_HELP")
public void toggleCommand(@Validator Player p) {
Region region = Region.getRegion(p.getLocation());
if (toggle(region)) {
RegionUtils.actionBar(region, getEnableMessage());
} else {
RegionUtils.actionBar(region, getDisableMessage());
}
}
private boolean toggle(Region region) {
if (region.getRegionData().get(Flag.WATER_DESTROY).isWithDefault(WaterDestroyMode.DENY)) {
region.getRegionData().set(Flag.WATER_DESTROY, WaterDestroyMode.ALLOW);
return false;
} else {
region.getRegionData().set(Flag.WATER_DESTROY, WaterDestroyMode.DENY);
return true;
}
}
}
@@ -0,0 +1,57 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2025 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.region;
import de.steamwar.bausystem.BauSystem;
import de.steamwar.bausystem.region.Region;
import de.steamwar.bausystem.region.flags.Flag;
import de.steamwar.bausystem.region.flags.WaterDestroyMode;
import de.steamwar.bausystem.utils.ScoreboardElement;
import de.steamwar.linkage.Linked;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockFromToEvent;
@Linked
public class WaterDestroyListener implements Listener, ScoreboardElement {
@EventHandler
public void onBlockFromTo(BlockFromToEvent event) {
if (event.getBlock().getType() == Material.WATER && event.getToBlock().getType() != Material.AIR && Region.getRegion(event.getBlock().getLocation()).getRegionData().get(Flag.WATER_DESTROY).isWithDefault(WaterDestroyMode.DENY)) event.setCancelled(true);
}
@Override
public ScoreboardGroup getGroup() {
return ScoreboardGroup.REGION;
}
@Override
public int order() {
return 5;
}
@Override
public String get(Region region, Player p) {
if (region.getRegionData().get(Flag.WATER_DESTROY).isWithDefault(WaterDestroyMode.ALLOW)) return null;
return "§e" + BauSystem.MESSAGE.parse(Flag.WATER_DESTROY.getChatValue(), p) + "§8: " + BauSystem.MESSAGE.parse(region.getRegionData().get(Flag.WATER_DESTROY).getWithDefault().getChatValue(), p);
}
}
@@ -84,14 +84,14 @@ public class ColorBauGuiItem extends BauGuiItem {
@Override @Override
public ItemStack getItem(Player player) { public ItemStack getItem(Player player) {
Region region = Region.getRegion(player.getLocation()); Region region = Region.getRegion(player.getLocation());
ColorMode mode = region.getFlags().get(Flag.COLOR).orElse(ColorMode.PINK); ColorMode mode = region.getRegionData().get(Flag.COLOR).orElse(ColorMode.PINK);
return new SWItem(mapColor(mode), BauSystem.MESSAGE.parse("REGION_ITEM_COLOR", player, BauSystem.MESSAGE.parse(mode.getChatValue(), player))).getItemStack(); return new SWItem(mapColor(mode), BauSystem.MESSAGE.parse("REGION_ITEM_COLOR", player, BauSystem.MESSAGE.parse(mode.getChatValue(), player))).getItemStack();
} }
@Override @Override
public boolean click(ClickType click, Player p) { public boolean click(ClickType click, Player p) {
p.closeInventory(); p.closeInventory();
ColorMode current = Region.getRegion(p.getLocation()).getFlags().get(Flag.COLOR).orElse(ColorMode.PINK); ColorMode current = Region.getRegion(p.getLocation()).getRegionData().get(Flag.COLOR).orElse(ColorMode.PINK);
List<SWListInv.SWListEntry<ColorMode>> items = new ArrayList<>(); List<SWListInv.SWListEntry<ColorMode>> items = new ArrayList<>();
for (ColorMode value : ColorMode.values()) { for (ColorMode value : ColorMode.values()) {
items.add(new SWListInv.SWListEntry<>(new SWItem(mapColor(value), (byte) 0, "§f" + BauSystem.MESSAGE.parse(value.getChatValue(), p), Collections.emptyList(), value == current, clickType -> { items.add(new SWListInv.SWListEntry<>(new SWItem(mapColor(value), (byte) 0, "§f" + BauSystem.MESSAGE.parse(value.getChatValue(), p), Collections.emptyList(), value == current, clickType -> {
@@ -42,10 +42,10 @@ public class FireBauGuiItem extends BauGuiItem {
@Override @Override
public ItemStack getItem(Player player) { public ItemStack getItem(Player player) {
Region region = Region.getRegion(player.getLocation()); Region region = Region.getRegion(player.getLocation());
if (!region.getFlags().has(Flag.FIRE).isApplicable()) { if (!region.getRegionData().has(Flag.FIRE).isApplicable()) {
return new SWItem(Material.BARRIER, "").getItemStack(); return new SWItem(Material.BARRIER, "").getItemStack();
} }
if (region.getFlags().get(Flag.FIRE).isWithDefault(FireMode.ALLOW)) { if (region.getRegionData().get(Flag.FIRE).isWithDefault(FireMode.ALLOW)) {
return new SWItem(Material.FIRE_CHARGE, BauSystem.MESSAGE.parse("REGION_ITEM_FIRE_ALLOW", player)).getItemStack(); return new SWItem(Material.FIRE_CHARGE, BauSystem.MESSAGE.parse("REGION_ITEM_FIRE_ALLOW", player)).getItemStack();
} else { } else {
return new SWItem(Material.FIREWORK_STAR, BauSystem.MESSAGE.parse("REGION_ITEM_FIRE_DISALLOW", player)).getItemStack(); return new SWItem(Material.FIREWORK_STAR, BauSystem.MESSAGE.parse("REGION_ITEM_FIRE_DISALLOW", player)).getItemStack();
@@ -42,10 +42,10 @@ public class FreezeBauGuiItem extends BauGuiItem {
@Override @Override
public ItemStack getItem(Player player) { public ItemStack getItem(Player player) {
Region region = Region.getRegion(player.getLocation()); Region region = Region.getRegion(player.getLocation());
if (!region.getFlags().has(Flag.FREEZE).isApplicable()) { if (!region.getRegionData().has(Flag.FREEZE).isApplicable()) {
return new SWItem(Material.BARRIER, "").getItemStack(); return new SWItem(Material.BARRIER, "").getItemStack();
} }
if (region.getFlags().get(Flag.FREEZE).isWithDefault(FreezeMode.ACTIVE)) { if (region.getRegionData().get(Flag.FREEZE).isWithDefault(FreezeMode.ACTIVE)) {
return new SWItem(Material.GUNPOWDER, BauSystem.MESSAGE.parse("REGION_ITEM_FREEZE_ALLOW", player)).getItemStack(); return new SWItem(Material.GUNPOWDER, BauSystem.MESSAGE.parse("REGION_ITEM_FREEZE_ALLOW", player)).getItemStack();
} else { } else {
return new SWItem(Material.REDSTONE, BauSystem.MESSAGE.parse("REGION_ITEM_FREEZE_DISALLOW", player)).getItemStack(); return new SWItem(Material.REDSTONE, BauSystem.MESSAGE.parse("REGION_ITEM_FREEZE_DISALLOW", player)).getItemStack();
@@ -43,10 +43,10 @@ public class ProtectBauGuiItem extends BauGuiItem {
@Override @Override
public ItemStack getItem(Player player) { public ItemStack getItem(Player player) {
Region region = Region.getRegion(player.getLocation()); Region region = Region.getRegion(player.getLocation());
if (!region.getFlags().has(Flag.PROTECT).isApplicable()) { if (!region.getRegionData().has(Flag.PROTECT).isApplicable()) {
return new SWItem(Material.BARRIER, "").getItemStack(); return new SWItem(Material.BARRIER, "").getItemStack();
} }
if (region.getFlags().get(Flag.PROTECT).isWithDefault(ProtectMode.ACTIVE)) { if (region.getRegionData().get(Flag.PROTECT).isWithDefault(ProtectMode.ACTIVE)) {
return SWUtils.setCustomModelData(new SWItem(Material.OBSIDIAN, BauSystem.MESSAGE.parse("REGION_ITEM_PROTECT_ALLOW", player)), 1).getItemStack(); return SWUtils.setCustomModelData(new SWItem(Material.OBSIDIAN, BauSystem.MESSAGE.parse("REGION_ITEM_PROTECT_ALLOW", player)), 1).getItemStack();
} else { } else {
return SWUtils.setCustomModelData(new SWItem(Material.STONE, BauSystem.MESSAGE.parse("REGION_ITEM_PROTECT_DISALLOW", player)), 1).getItemStack(); return SWUtils.setCustomModelData(new SWItem(Material.STONE, BauSystem.MESSAGE.parse("REGION_ITEM_PROTECT_DISALLOW", player)), 1).getItemStack();
@@ -42,7 +42,7 @@ public class TntBauGuiItem extends BauGuiItem {
@Override @Override
public ItemStack getItem(Player player) { public ItemStack getItem(Player player) {
switch (Region.getRegion(player.getLocation()).getFlags().get(Flag.TNT).getWithDefault()) { switch (Region.getRegion(player.getLocation()).getRegionData().get(Flag.TNT).getWithDefault()) {
case DENY: case DENY:
return new SWItem(Material.MINECART, BauSystem.MESSAGE.parse("REGION_ITEM_TNT_OFF", player)).getItemStack(); return new SWItem(Material.MINECART, BauSystem.MESSAGE.parse("REGION_ITEM_TNT_OFF", player)).getItemStack();
case ONLY_TB: case ONLY_TB:
@@ -55,7 +55,7 @@ public class TntBauGuiItem extends BauGuiItem {
@Override @Override
public boolean click(ClickType click, Player p) { public boolean click(ClickType click, Player p) {
if (click == ClickType.LEFT) { if (click == ClickType.LEFT) {
switch (Region.getRegion(p.getLocation()).getFlags().get(Flag.TNT).getWithDefault()) { switch (Region.getRegion(p.getLocation()).getRegionData().get(Flag.TNT).getWithDefault()) {
case DENY: case DENY:
updateTntMode(TNTMode.ALLOW, p); updateTntMode(TNTMode.ALLOW, p);
break; break;
@@ -51,8 +51,8 @@ public class EventListener implements Listener {
Bukkit.getScheduler().runTaskTimer(BauSystem.getInstance(), () -> { Bukkit.getScheduler().runTaskTimer(BauSystem.getInstance(), () -> {
long millis = System.currentTimeMillis(); long millis = System.currentTimeMillis();
SWPlayer.allWithSingleComponent(ScriptRunner.ScriptData.class) SWPlayer.allWithSingleComponent(ScriptRunner.ScriptData.class)
.filter(pair -> millis - pair.getValue().getLastF() > 200) .filter(pair -> millis - pair.getComponent().getLastF() > 200)
.forEach(pair -> pair.getValue().setLastF(Long.MAX_VALUE)); .forEach(pair -> pair.getComponent().setLastF(Long.MAX_VALUE));
}, 1, 1); }, 1, 1);
} }
@@ -59,14 +59,14 @@ public class RegionLib implements LuaLib {
})); }));
LuaValue tntLib = LuaValue.tableOf(); LuaValue tntLib = LuaValue.tableOf();
tntLib.set("mode", getter(() -> region.get().getFlags().get(Flag.TNT).nameWithDefault())); tntLib.set("mode", getter(() -> region.get().getRegionData().get(Flag.TNT).nameWithDefault()));
tntLib.set("enabled", getter(() -> region.get().getFlags().get(Flag.TNT).orElse(null) != TNTMode.DENY)); tntLib.set("enabled", getter(() -> region.get().getRegionData().get(Flag.TNT).orElse(null) != TNTMode.DENY));
tntLib.set("onlyTb", getter(() -> region.get().getFlags().get(Flag.TNT).orElse(null) == TNTMode.ONLY_TB)); tntLib.set("onlyTb", getter(() -> region.get().getRegionData().get(Flag.TNT).orElse(null) == TNTMode.ONLY_TB));
table.set("tnt", tntLib); table.set("tnt", tntLib);
table.set("fire", getter(() -> region.get().getFlags().get(Flag.FIRE).orElse(null) == FireMode.ALLOW)); table.set("fire", getter(() -> region.get().getRegionData().get(Flag.FIRE).orElse(null) == FireMode.ALLOW));
table.set("freeze", getter(() -> region.get().getFlags().get(Flag.FREEZE).orElse(null) == FreezeMode.ACTIVE)); table.set("freeze", getter(() -> region.get().getRegionData().get(Flag.FREEZE).orElse(null) == FreezeMode.ACTIVE));
table.set("protect", getter(() -> region.get().getFlags().get(Flag.PROTECT).orElse(null) == ProtectMode.ACTIVE)); table.set("protect", getter(() -> region.get().getRegionData().get(Flag.PROTECT).orElse(null) == ProtectMode.ACTIVE));
//LuaValue traceLib = LuaValue.tableOf(); //LuaValue traceLib = LuaValue.tableOf();
//traceLib.set("active", getter(() -> !region.get().isGlobal() && Recorder.INSTANCE.get(region.get()) instanceof ActiveTracer)); //traceLib.set("active", getter(() -> !region.get().isGlobal() && Recorder.INSTANCE.get(region.get()) instanceof ActiveTracer));
@@ -65,7 +65,7 @@ public final class TNTPhase extends SimulatorPhase {
@Override @Override
public void accept(World world) { public void accept(World world) {
Location location = position.toLocation(world); Location location = position.toLocation(world);
if (Region.getRegion(location).getFlags().get(Flag.FREEZE).isWithDefault(FreezeMode.ACTIVE)) return; if (Region.getRegion(location).getRegionData().get(Flag.FREEZE).isWithDefault(FreezeMode.ACTIVE)) return;
TNTPrimed tnt = world.spawn(location, TNTPrimed.class); TNTPrimed tnt = world.spawn(location, TNTPrimed.class);
if (!xJump) tnt.setVelocity(tnt.getVelocity().setX(0)); if (!xJump) tnt.setVelocity(tnt.getVelocity().setX(0));
if (!yJump) tnt.setVelocity(tnt.getVelocity().setY(0)); if (!yJump) tnt.setVelocity(tnt.getVelocity().setY(0));
@@ -35,8 +35,8 @@ public class StabFinalizer extends StabStep {
try { try {
PasteBuilder.ClipboardProvider clipboardProvider = new PasteBuilder.ClipboardProviderImpl(data.clipboard); PasteBuilder.ClipboardProvider clipboardProvider = new PasteBuilder.ClipboardProviderImpl(data.clipboard);
PasteBuilder pasteBuilder = new PasteBuilder(clipboardProvider); PasteBuilder pasteBuilder = new PasteBuilder(clipboardProvider);
if (data.region.getFlags().has(Flag.COLOR).isReadable()) { if (data.region.getRegionData().has(Flag.COLOR).isReadable()) {
pasteBuilder.color(data.region.getFlags().get(Flag.COLOR).getWithDefault()); pasteBuilder.color(data.region.getRegionData().get(Flag.COLOR).getWithDefault());
} }
data.region.getTestblockArea().reset(pasteBuilder, true); data.region.getTestblockArea().reset(pasteBuilder, true);
} catch (SecurityException e) { } catch (SecurityException e) {
@@ -73,8 +73,8 @@ public class StabGenerator extends StabStep implements Listener {
try { try {
PasteBuilder.ClipboardProvider clipboardProvider = new PasteBuilder.ClipboardProviderImpl(data.clipboard); PasteBuilder.ClipboardProvider clipboardProvider = new PasteBuilder.ClipboardProviderImpl(data.clipboard);
PasteBuilder pasteBuilder = new PasteBuilder(clipboardProvider); PasteBuilder pasteBuilder = new PasteBuilder(clipboardProvider);
if (data.region.getFlags().has(Flag.COLOR).isReadable()) { if (data.region.getRegionData().has(Flag.COLOR).isReadable()) {
pasteBuilder.color(data.region.getFlags().get(Flag.COLOR).getWithDefault()); pasteBuilder.color(data.region.getRegionData().get(Flag.COLOR).getWithDefault());
} }
data.region.getTestblockArea().reset(pasteBuilder, true); data.region.getTestblockArea().reset(pasteBuilder, true);
} catch (SecurityException e) { } catch (SecurityException e) {
@@ -45,8 +45,6 @@ public class TraceManager implements Listener {
instance = this; instance = this;
} }
public void init() { public void init() {
if (!tracesFolder.exists()) if (!tracesFolder.exists())
tracesFolder.mkdir(); tracesFolder.mkdir();
@@ -121,8 +121,8 @@ public class BauScoreboard implements Listener {
Region region = Region.getRegion(player.getLocation()); Region region = Region.getRegion(player.getLocation());
if (region.getType().isGlobal()) return "§eSteam§8War"; if (region.getType().isGlobal()) return "§eSteam§8War";
String colorCode = "§e"; String colorCode = "§e";
if (region.getFlags().has(Flag.COLOR).isReadable()) { if (region.getRegionData().has(Flag.COLOR).isReadable()) {
colorCode = "§" + region.getFlags().get(Flag.COLOR).orElse(ColorMode.PINK).getColorCode(); colorCode = "§" + region.getRegionData().get(Flag.COLOR).orElse(ColorMode.PINK).getColorCode();
} }
return colorCode + "■ §eSteam§8War " + colorCode + "■"; // ■ return colorCode + "■ §eSteam§8War " + colorCode + "■"; // ■
} }
@@ -26,6 +26,7 @@ import com.sk89q.worldedit.extension.input.ParserContext;
import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.mask.Mask;
import de.steamwar.bausystem.features.worldedit.utils.FAWEMaskParser; import de.steamwar.bausystem.features.worldedit.utils.FAWEMaskParser;
import de.steamwar.linkage.Linked; import de.steamwar.linkage.Linked;
import de.steamwar.linkage.MinVersion;
import de.steamwar.linkage.PluginCheck; import de.steamwar.linkage.PluginCheck;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
@@ -33,6 +34,7 @@ import java.util.stream.Stream;
@Linked @Linked
@PluginCheck("FastAsyncWorldEdit") @PluginCheck("FastAsyncWorldEdit")
@MinVersion(19)
public class FAWEAboveMaskParser extends FAWEMaskParser { public class FAWEAboveMaskParser extends FAWEMaskParser {
public FAWEAboveMaskParser() { public FAWEAboveMaskParser() {
@@ -26,6 +26,7 @@ import com.sk89q.worldedit.extension.input.ParserContext;
import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.mask.Mask;
import de.steamwar.bausystem.features.worldedit.utils.FAWEMaskParser; import de.steamwar.bausystem.features.worldedit.utils.FAWEMaskParser;
import de.steamwar.linkage.Linked; import de.steamwar.linkage.Linked;
import de.steamwar.linkage.MinVersion;
import de.steamwar.linkage.PluginCheck; import de.steamwar.linkage.PluginCheck;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
@@ -33,6 +34,7 @@ import java.util.stream.Stream;
@Linked @Linked
@PluginCheck("FastAsyncWorldEdit") @PluginCheck("FastAsyncWorldEdit")
@MinVersion(19)
public class FAWEBelowMaskParser extends FAWEMaskParser { public class FAWEBelowMaskParser extends FAWEMaskParser {
public FAWEBelowMaskParser() { public FAWEBelowMaskParser() {
@@ -25,6 +25,7 @@ import com.sk89q.worldedit.extension.input.ParserContext;
import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.mask.Mask;
import de.steamwar.bausystem.features.worldedit.utils.FAWEMaskParser; import de.steamwar.bausystem.features.worldedit.utils.FAWEMaskParser;
import de.steamwar.linkage.Linked; import de.steamwar.linkage.Linked;
import de.steamwar.linkage.MinVersion;
import de.steamwar.linkage.PluginCheck; import de.steamwar.linkage.PluginCheck;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
@@ -32,6 +33,7 @@ import java.util.stream.Stream;
@Linked @Linked
@PluginCheck("FastAsyncWorldEdit") @PluginCheck("FastAsyncWorldEdit")
@MinVersion(19)
public class FAWECheckerboard3DMaskParser extends FAWEMaskParser { public class FAWECheckerboard3DMaskParser extends FAWEMaskParser {
public FAWECheckerboard3DMaskParser() { public FAWECheckerboard3DMaskParser() {
@@ -25,6 +25,7 @@ import com.sk89q.worldedit.extension.input.ParserContext;
import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.mask.Mask;
import de.steamwar.bausystem.features.worldedit.utils.FAWEMaskParser; import de.steamwar.bausystem.features.worldedit.utils.FAWEMaskParser;
import de.steamwar.linkage.Linked; import de.steamwar.linkage.Linked;
import de.steamwar.linkage.MinVersion;
import de.steamwar.linkage.PluginCheck; import de.steamwar.linkage.PluginCheck;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
@@ -32,6 +33,7 @@ import java.util.stream.Stream;
@Linked @Linked
@PluginCheck("FastAsyncWorldEdit") @PluginCheck("FastAsyncWorldEdit")
@MinVersion(19)
public class FAWECheckerboardMaskParser extends FAWEMaskParser { public class FAWECheckerboardMaskParser extends FAWEMaskParser {
public FAWECheckerboardMaskParser() { public FAWECheckerboardMaskParser() {
@@ -25,6 +25,7 @@ import com.sk89q.worldedit.extension.input.ParserContext;
import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.mask.Mask;
import de.steamwar.bausystem.features.worldedit.utils.FAWEMaskParser; import de.steamwar.bausystem.features.worldedit.utils.FAWEMaskParser;
import de.steamwar.linkage.Linked; import de.steamwar.linkage.Linked;
import de.steamwar.linkage.MinVersion;
import de.steamwar.linkage.PluginCheck; import de.steamwar.linkage.PluginCheck;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
@@ -32,6 +33,7 @@ import java.util.stream.Stream;
@Linked @Linked
@PluginCheck("FastAsyncWorldEdit") @PluginCheck("FastAsyncWorldEdit")
@MinVersion(19)
public class FAWEGridMaskParser extends FAWEMaskParser { public class FAWEGridMaskParser extends FAWEMaskParser {
public FAWEGridMaskParser() { public FAWEGridMaskParser() {
@@ -27,6 +27,7 @@ import com.sk89q.worldedit.regions.Region;
import de.steamwar.bausystem.features.worldedit.utils.FAWEPatternParser; import de.steamwar.bausystem.features.worldedit.utils.FAWEPatternParser;
import de.steamwar.bausystem.utils.WorldEditUtils; import de.steamwar.bausystem.utils.WorldEditUtils;
import de.steamwar.linkage.Linked; import de.steamwar.linkage.Linked;
import de.steamwar.linkage.MinVersion;
import de.steamwar.linkage.PluginCheck; import de.steamwar.linkage.PluginCheck;
import org.bukkit.Axis; import org.bukkit.Axis;
@@ -35,6 +36,7 @@ import java.util.stream.Stream;
@Linked @Linked
@PluginCheck("FastAsyncWorldEdit") @PluginCheck("FastAsyncWorldEdit")
@MinVersion(19)
public class FAWEGradientPatternParser extends FAWEPatternParser { public class FAWEGradientPatternParser extends FAWEPatternParser {
public FAWEGradientPatternParser() { public FAWEGradientPatternParser() {
@@ -41,8 +41,8 @@ public class BackupScheduler implements Enable {
@Override @Override
public void run() { public void run() {
Iterator<Region> regionsToBackup = RegionSystem.INSTANCE.getRegions() Iterator<Region> regionsToBackup = RegionSystem.INSTANCE.getRegions()
.filter(region -> region.getFlags().has(Flag.CHANGED).isReadable()) .filter(region -> region.getRegionData().has(Flag.CHANGED).isReadable())
.filter(region -> region.getFlags().get(Flag.CHANGED).getWithDefault() == ChangedMode.HAS_CHANGE) .filter(region -> region.getRegionData().get(Flag.CHANGED).isWithDefault(ChangedMode.HAS_CHANGE))
.iterator(); .iterator();
if (!regionsToBackup.hasNext()) return; if (!regionsToBackup.hasNext()) return;
doBackup(regionsToBackup); doBackup(regionsToBackup);
@@ -63,7 +63,7 @@ public class BackupScheduler implements Enable {
Optional<RegionBackups.Backup> backup = region.getBackups() Optional<RegionBackups.Backup> backup = region.getBackups()
.create(RegionBackups.BackupType.AUTOMATIC); .create(RegionBackups.BackupType.AUTOMATIC);
if (backup.isPresent()) { if (backup.isPresent()) {
region.getFlags().set(Flag.CHANGED, ChangedMode.NO_CHANGE); region.getRegionData().set(Flag.CHANGED, ChangedMode.NO_CHANGE);
} }
} }
}.runTaskTimer(BauSystem.getInstance(), 0, 20 * 60); }.runTaskTimer(BauSystem.getInstance(), 0, 20 * 60);
@@ -23,7 +23,6 @@ import com.sk89q.worldedit.extent.clipboard.Clipboard;
import de.steamwar.bausystem.utils.FlatteningWrapper; import de.steamwar.bausystem.utils.FlatteningWrapper;
import de.steamwar.bausystem.utils.PasteBuilder; import de.steamwar.bausystem.utils.PasteBuilder;
import de.steamwar.sql.GameModeConfig; import de.steamwar.sql.GameModeConfig;
import de.steamwar.sql.SchematicType;
import lombok.NonNull; import lombok.NonNull;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Material; import org.bukkit.Material;
@@ -55,7 +54,7 @@ public interface Region {
RegionType getType(); RegionType getType();
@NonNull @NonNull
FlagStorage getFlags(); RegionData getRegionData();
@NonNull @NonNull
Area getArea(); Area getArea();
@@ -75,9 +74,6 @@ public interface Region {
@NonNull @NonNull
RegionBackups getBackups(); RegionBackups getBackups();
@NonNull
RegionData getRegionData();
interface Area { interface Area {
Area EMPTY = new Area() { Area EMPTY = new Area() {
@@ -49,7 +49,7 @@ public interface RegionBackups {
private final String name; private final String name;
@NonNull @NonNull
private final FlagStorage flags; private final RegionData data;
@CheckReturnValue @CheckReturnValue
public abstract boolean load(); public abstract boolean load();
@@ -19,75 +19,134 @@
package de.steamwar.bausystem.region; package de.steamwar.bausystem.region;
import de.steamwar.bausystem.region.flags.Flag;
import de.steamwar.sql.SchematicNode; import de.steamwar.sql.SchematicNode;
import lombok.NonNull;
import yapion.hierarchy.types.YAPIONObject; import yapion.hierarchy.types.YAPIONObject;
import java.util.Objects; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
public interface RegionData { public abstract class RegionData {
void clear(); private final List<Property<?, ?>> properties = new ArrayList<>();
SchematicNode getTestblockSchematic(); protected final YAPIONObject data;
protected final YAPIONObject flagData;
protected final Runnable onChange;
protected final Map<Flag<?>, Flag.Value<?>> flagMap = new HashMap<>();
void setTestblockSchematic(SchematicNode schematic); private final class Property<T, K> {
private final String field;
private final Function<K, T> loader;
private final Function<T, K> writer;
RegionData EMPTY = new RegionData() { private T value;
@Override public Property(String field, Function<K, T> loader, Function<T, K> writer) {
public void clear() { this.field = field;
this.loader = loader;
this.writer = writer;
properties.add(this);
} }
@Override public void load() {
public SchematicNode getTestblockSchematic() { if (flagData.containsKey(field)) {
return null; value = loader.apply(flagData.getPlainValue(field));
}
@Override
public void setTestblockSchematic(SchematicNode schematic) {
}
};
class RegionDataImpl implements RegionData {
private final YAPIONObject yapionObject;
private final Runnable onChange;
public RegionDataImpl(YAPIONObject yapionObject, Runnable onChange) {
this.yapionObject = yapionObject;
this.onChange = onChange;
if (yapionObject.containsKey("testblockSchematic")) {
testblockSchematic = SchematicNode.getSchematicNode(yapionObject.getInt("testblockSchematic"));
}
}
@Override
public void clear() {
testblockSchematic = null;
yapionObject.remove("testblockSchematic");
onChange.run();
}
private SchematicNode testblockSchematic = null;
@Override
public SchematicNode getTestblockSchematic() {
return testblockSchematic;
}
@Override
public void setTestblockSchematic(SchematicNode schematic) {
if (Objects.equals(this.testblockSchematic, schematic)) {
return;
}
this.testblockSchematic = schematic;
if (schematic == null) {
yapionObject.remove("testblockSchematic");
} else { } else {
yapionObject.put("testblockSchematic", testblockSchematic.getId()); value = null;
}
}
public T get() {
return value;
}
public void set(T value) {
this.value = value;
if (value == null) {
flagData.remove(field);
} else {
flagData.put(field, writer.apply(value));
} }
onChange.run();
} }
} }
private Property<SchematicNode, Integer> testblockSchematic = new Property<>("testblockSchematic", SchematicNode::byId, SchematicNode::getId);
protected RegionData(YAPIONObject data, Runnable onChange) {
this.data = data;
this.flagData = data.getObjectOrSetDefault("flagStorage", new YAPIONObject());
this.onChange = onChange;
initialize();
for (final Flag flag : Flag.getFlags()) {
if (!has(flag).isWritable()) continue;
try {
String s = flagData.getPlainValue(flag.name());
flagMap.put(flag, flag.valueOfValue(s));
} catch (Exception e) {
flagMap.put(flag, (Flag.Value<?>) flag.getDefaultValue());
}
}
properties.forEach(Property::load);
}
protected void initialize() {
}
@NonNull
public abstract <T extends Enum<T> & Flag.Value<T>> RegionFlagPolicy has(@NonNull Flag<T> flag);
/**
* Returns true if the flag was changed and did not already contain the provided value
*/
public final <T extends Enum<T> & Flag.Value<T>> boolean set(@NonNull Flag<T> flag, @NonNull T value) {
if (has(flag).isWritable()) {
if (flagMap.put(flag, value) != value) {
flagData.put(flag.name(), value.name());
onChange.run();
return true;
}
}
return false;
}
@NonNull
public final <T extends Enum<T> & Flag.Value<T>> FlagOptional<T> get(@NonNull Flag<T> flag) {
return FlagOptional.of(flag, (T) flagMap.get(flag));
}
public final void clear() {
for (Flag flag : Flag.getFlags()) {
if (has(flag).isWritable()) {
flagMap.remove(flag);
flagData.remove(flag.name());
}
}
properties.forEach(property -> property.set(null));
onChange.run();
}
public final Map<Flag<?>, Flag.Value<?>> getBackedMap() {
return flagMap;
}
public SchematicNode getTestblockSchematic() {
return testblockSchematic.get();
}
public void setTestblockSchematic(SchematicNode schematic) {
testblockSchematic.set(schematic);
onChange.run();
}
@Override
public final String toString() {
return getClass().getSimpleName() + "{" +
"flagMap=" + flagMap +
'}';
}
} }
@@ -43,6 +43,7 @@ public final class Flag<T extends Enum<T> & Flag.Value<T>> implements EnumDispla
public static final Flag<NoGravityMode> NO_GRAVITY = new Flag<>("NO_GRAVITY", "FLAG_NO_GRAVITY", NoGravityMode.class, NoGravityMode.INACTIVE); public static final Flag<NoGravityMode> NO_GRAVITY = new Flag<>("NO_GRAVITY", "FLAG_NO_GRAVITY", NoGravityMode.class, NoGravityMode.INACTIVE);
public static final Flag<TestblockMode> TESTBLOCK = new Flag<>("TESTBLOCK", "FLAG_TESTBLOCK", TestblockMode.class, TestblockMode.NO_VALUE); public static final Flag<TestblockMode> TESTBLOCK = new Flag<>("TESTBLOCK", "FLAG_TESTBLOCK", TestblockMode.class, TestblockMode.NO_VALUE);
public static final Flag<ChangedMode> CHANGED = new Flag<>("CHANGED", "FLAG_CHANGED", ChangedMode.class, ChangedMode.NO_CHANGE); public static final Flag<ChangedMode> CHANGED = new Flag<>("CHANGED", "FLAG_CHANGED", ChangedMode.class, ChangedMode.NO_CHANGE);
public static final Flag<WaterDestroyMode> WATER_DESTROY = new Flag<>("WATER_DESTROY", "FLAG_WATER_DESTROY", WaterDestroyMode.class, WaterDestroyMode.ALLOW);
private String name; private String name;
private int ordinal; private int ordinal;
@@ -0,0 +1,56 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2025 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.region.flags;
import lombok.AllArgsConstructor;
import lombok.Getter;
@Getter
@AllArgsConstructor
public enum WaterDestroyMode implements Flag.Value<WaterDestroyMode> {
ALLOW("FLAG_WATER_DESTROY_ALLOW"),
DENY("FLAG_WATER_DESTROY_DENY");
private static WaterDestroyMode[] values;
private final String chatValue;
@Override
public WaterDestroyMode[] getValues() {
if (WaterDestroyMode.values == null) {
WaterDestroyMode.values = WaterDestroyMode.values();
}
return WaterDestroyMode.values;
}
@Override
public WaterDestroyMode getValue() {
return this;
}
@Override
public WaterDestroyMode getValueOf(final String name) {
try {
return WaterDestroyMode.valueOf(name.toUpperCase());
} catch (IllegalArgumentException e) {
return ALLOW;
}
}
}
@@ -1,106 +0,0 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2025 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.region.fixed;
import de.steamwar.bausystem.region.FlagOptional;
import de.steamwar.bausystem.region.FlagStorage;
import de.steamwar.bausystem.region.RegionFlagPolicy;
import de.steamwar.bausystem.region.flags.Flag;
import de.steamwar.bausystem.worlddata.WorldData;
import de.steamwar.core.Core;
import lombok.NonNull;
import yapion.hierarchy.types.YAPIONObject;
import java.util.HashMap;
import java.util.Map;
public class FixedFlagStorage implements FlagStorage {
private Map<Flag<?>, Flag.Value<?>> flagMap = new HashMap<>();
private YAPIONObject data;
public FixedFlagStorage(YAPIONObject data) {
this.data = data;
for (final Flag flag : Flag.getFlags()) {
if (!has(flag).isWritable()) continue;
try {
String s = data.getPlainValue(flag.name());
flagMap.put(flag, flag.valueOfValue(s));
} catch (Exception e) {
flagMap.put(flag, (Flag.Value<?>) flag.getDefaultValue());
}
}
}
@Override
public @NonNull <T extends Enum<T> & Flag.Value<T>> RegionFlagPolicy has(@NonNull Flag<T> flag) {
if (flag.oneOf(Flag.COLOR, Flag.TNT, Flag.FIRE, Flag.FREEZE, Flag.PROTECT, Flag.NO_GRAVITY, Flag.CHANGED)) {
return RegionFlagPolicy.WRITABLE;
}
if (flag.oneOf(Flag.ITEMS) && Core.getVersion() >= 20) {
return RegionFlagPolicy.WRITABLE;
}
if (flag.oneOf(Flag.TESTBLOCK)) {
return RegionFlagPolicy.READ_ONLY;
}
return RegionFlagPolicy.NOT_APPLICABLE;
}
@Override
public <T extends Enum<T> & Flag.Value<T>> boolean set(@NonNull Flag<T> flag, @NonNull T value) {
if (has(flag).isWritable()) {
boolean hasChanged = flagMap.put(flag, value) != value;
if (hasChanged) {
data.put(flag.name(), value.name());
WorldData.write();
}
return hasChanged;
} else {
return false;
}
}
@Override
public @NonNull <T extends Enum<T> & Flag.Value<T>> FlagOptional<T> get(@NonNull Flag<T> flag) {
return FlagOptional.of(flag, (T) flagMap.get(flag));
}
@Override
public void clear() {
for (Flag flag : Flag.getFlags()) {
if (flag == Flag.TESTBLOCK) continue;
if (flag == Flag.COLOR) continue;
if (flag == Flag.CHANGED) continue;
flagMap.remove(flag);
}
}
@Override
public Map<Flag<?>, Flag.Value<?>> getBackedMap() {
return flagMap;
}
@Override
public String toString() {
return "FixedFlagStorage{" +
"flagMap=" + flagMap +
'}';
}
}
@@ -1,113 +0,0 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2025 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.region.fixed;
import de.steamwar.bausystem.region.FlagOptional;
import de.steamwar.bausystem.region.FlagStorage;
import de.steamwar.bausystem.region.RegionFlagPolicy;
import de.steamwar.bausystem.region.flags.ColorMode;
import de.steamwar.bausystem.region.flags.Flag;
import de.steamwar.bausystem.region.flags.ProtectMode;
import de.steamwar.bausystem.region.flags.TNTMode;
import de.steamwar.bausystem.worlddata.WorldData;
import de.steamwar.core.Core;
import lombok.NonNull;
import yapion.hierarchy.types.YAPIONObject;
import java.util.HashMap;
import java.util.Map;
public class FixedGlobalFlagStorage implements FlagStorage {
private Map<Flag<?>, Flag.Value<?>> flagMap = new HashMap<>();
private YAPIONObject data;
public FixedGlobalFlagStorage(YAPIONObject data) {
flagMap.put(Flag.TNT, TNTMode.DENY);
this.data = data;
for (final Flag flag : Flag.getFlags()) {
if (!has(flag).isWritable()) continue;
try {
String s = data.getPlainValue(flag.name());
flagMap.put(flag, flag.valueOfValue(s));
} catch (Exception e) {
flagMap.put(flag, (Flag.Value<?>) flag.getDefaultValue());
}
}
}
@Override
public @NonNull <T extends Enum<T> & Flag.Value<T>> RegionFlagPolicy has(@NonNull Flag<T> flag) {
if (flag.oneOf(Flag.COLOR)) {
return RegionFlagPolicy.READ_ONLY;
}
if (flag.oneOf(Flag.ITEMS) && Core.getVersion() >= 20) {
return RegionFlagPolicy.WRITABLE;
}
if (flag.oneOf(Flag.TNT, Flag.FIRE, Flag.FREEZE)) {
return RegionFlagPolicy.WRITABLE;
}
return RegionFlagPolicy.NOT_APPLICABLE;
}
@Override
public <T extends Enum<T> & Flag.Value<T>> boolean set(@NonNull Flag<T> flag, @NonNull T value) {
if (has(flag).isWritable()) {
data.put(flag.name(), value.name());
WorldData.write();
return flagMap.put(flag, value) != value;
} else {
return false;
}
}
@Override
public @NonNull <T extends Enum<T> & Flag.Value<T>> FlagOptional<T> get(@NonNull Flag<T> flag) {
if (flag.oneOf(Flag.COLOR)) {
return FlagOptional.of((Flag) flag, ColorMode.YELLOW);
}
if (flag.oneOf(Flag.PROTECT)) {
return FlagOptional.of((Flag) flag, ProtectMode.INACTIVE);
}
return FlagOptional.of(flag, (T) flagMap.get(flag));
}
@Override
public void clear() {
for (Flag flag : Flag.getFlags()) {
if (flag == Flag.TESTBLOCK) continue;
if (flag == Flag.COLOR) continue;
if (flag == Flag.CHANGED) continue;
flagMap.remove(flag);
}
}
@Override
public Map<Flag<?>, Flag.Value<?>> getBackedMap() {
return flagMap;
}
@Override
public String toString() {
return "FixedGlobalFlagStorage{" +
"flagMap=" + flagMap +
'}';
}
}
@@ -41,7 +41,7 @@ public final class FixedGlobalRegion implements Region {
private static final Point MAX_POINT = new Point(Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE); private static final Point MAX_POINT = new Point(Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE);
@Setter @Setter
private static FlagStorage FLAG_STORAGE; private static RegionData FLAG_STORAGE;
private static final UUID GLOBAL_REGION_ID = new UUID(0, 0); private static final UUID GLOBAL_REGION_ID = new UUID(0, 0);
@@ -106,7 +106,7 @@ public final class FixedGlobalRegion implements Region {
} }
@Override @Override
public @NonNull FlagStorage getFlags() { public @NonNull RegionData getRegionData() {
return FLAG_STORAGE; return FLAG_STORAGE;
} }
@@ -139,9 +139,4 @@ public final class FixedGlobalRegion implements Region {
public @NonNull RegionBackups getBackups() { public @NonNull RegionBackups getBackups() {
return RegionBackups.EMPTY; return RegionBackups.EMPTY;
} }
@Override
public @NonNull RegionData getRegionData() {
return RegionData.EMPTY;
}
} }
@@ -0,0 +1,58 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2025 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.region.fixed;
import de.steamwar.bausystem.region.RegionData;
import de.steamwar.bausystem.region.RegionFlagPolicy;
import de.steamwar.bausystem.region.flags.ColorMode;
import de.steamwar.bausystem.region.flags.Flag;
import de.steamwar.bausystem.region.flags.ProtectMode;
import de.steamwar.bausystem.region.flags.TNTMode;
import de.steamwar.core.Core;
import lombok.NonNull;
import yapion.hierarchy.types.YAPIONObject;
public class FixedGlobalRegionData extends RegionData {
public FixedGlobalRegionData(YAPIONObject data, Runnable onChange) {
super(data, onChange);
}
@Override
protected void initialize() {
flagMap.put(Flag.TNT, TNTMode.DENY);
flagMap.put(Flag.COLOR, ColorMode.YELLOW);
flagMap.put(Flag.PROTECT, ProtectMode.INACTIVE);
}
@Override
public @NonNull <T extends Enum<T> & Flag.Value<T>> RegionFlagPolicy has(@NonNull Flag<T> flag) {
if (flag.oneOf(Flag.COLOR, Flag.PROTECT)) {
return RegionFlagPolicy.READ_ONLY;
}
if (flag.oneOf(Flag.ITEMS) && Core.getVersion() >= 20) {
return RegionFlagPolicy.WRITABLE;
}
if (flag.oneOf(Flag.TNT, Flag.FIRE, Flag.FREEZE)) {
return RegionFlagPolicy.WRITABLE;
}
return RegionFlagPolicy.NOT_APPLICABLE;
}
}
@@ -26,7 +26,6 @@ import de.steamwar.bausystem.region.flags.Flag;
import de.steamwar.bausystem.region.flags.TestblockMode; import de.steamwar.bausystem.region.flags.TestblockMode;
import de.steamwar.bausystem.utils.FlatteningWrapper; import de.steamwar.bausystem.utils.FlatteningWrapper;
import de.steamwar.bausystem.utils.PasteBuilder; import de.steamwar.bausystem.utils.PasteBuilder;
import de.steamwar.bausystem.worlddata.WorldData;
import de.steamwar.core.Core; import de.steamwar.core.Core;
import de.steamwar.sql.GameModeConfig; import de.steamwar.sql.GameModeConfig;
import de.steamwar.sql.SchematicType; import de.steamwar.sql.SchematicType;
@@ -50,7 +49,7 @@ public class FixedRegion implements Region {
private final String name; private final String name;
private final UUID uuid; private final UUID uuid;
private final FixedFlagStorage flagStorage; private final FixedRegionData flagStorage;
private final Prototype prototype; private final Prototype prototype;
private final String skin; private final String skin;
@@ -60,7 +59,6 @@ public class FixedRegion implements Region {
private final int floorLevel; private final int floorLevel;
private final int waterLevel; private final int waterLevel;
private final GameModeConfig<Material, String> gameModeConfig; private final GameModeConfig<Material, String> gameModeConfig;
private final RegionData regionData;
private final RegionHistory regionHistory = new RegionHistory.Impl(20); private final RegionHistory regionHistory = new RegionHistory.Impl(20);
private final RegionBackups regionBackups = new RegionBackups() { private final RegionBackups regionBackups = new RegionBackups() {
@@ -141,7 +139,7 @@ public class FixedRegion implements Region {
} }
} }
public FixedRegion(String name, FixedFlagStorage flagStorage, Prototype prototype, YAPIONObject regionConfig, YAPIONObject regionData) { public FixedRegion(String name, FixedRegionData flagStorage, Prototype prototype, YAPIONObject regionConfig, YAPIONObject regionData) {
this.name = name; this.name = name;
uuid = UUID.nameUUIDFromBytes(name.getBytes(StandardCharsets.UTF_8)); uuid = UUID.nameUUIDFromBytes(name.getBytes(StandardCharsets.UTF_8));
this.flagStorage = flagStorage; this.flagStorage = flagStorage;
@@ -343,7 +341,6 @@ public class FixedRegion implements Region {
} else { } else {
this.gameModeConfig = GameModeConfig.getByFileName(found); this.gameModeConfig = GameModeConfig.getByFileName(found);
} }
this.regionData = new RegionData.RegionDataImpl(regionData, WorldData::write);
} }
@Override @Override
@@ -357,7 +354,7 @@ public class FixedRegion implements Region {
} }
@Override @Override
public @NonNull FlagStorage getFlags() { public @NonNull RegionData getRegionData() {
return flagStorage; return flagStorage;
} }
@@ -390,9 +387,4 @@ public class FixedRegion implements Region {
public @NonNull RegionBackups getBackups() { public @NonNull RegionBackups getBackups() {
return regionBackups; return regionBackups;
} }
@Override
public @NonNull RegionData getRegionData() {
return regionData;
}
} }
@@ -0,0 +1,48 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2025 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.region.fixed;
import de.steamwar.bausystem.region.RegionData;
import de.steamwar.bausystem.region.RegionFlagPolicy;
import de.steamwar.bausystem.region.flags.Flag;
import de.steamwar.core.Core;
import lombok.NonNull;
import yapion.hierarchy.types.YAPIONObject;
public class FixedRegionData extends RegionData {
public FixedRegionData(YAPIONObject data, Runnable onChange) {
super(data, onChange);
}
@Override
public @NonNull <T extends Enum<T> & Flag.Value<T>> RegionFlagPolicy has(@NonNull Flag<T> flag) {
if (flag.oneOf(Flag.COLOR, Flag.TNT, Flag.FIRE, Flag.FREEZE, Flag.PROTECT, Flag.NO_GRAVITY, Flag.CHANGED, Flag.WATER_DESTROY)) {
return RegionFlagPolicy.WRITABLE;
}
if (flag.oneOf(Flag.ITEMS) && Core.getVersion() >= 20) {
return RegionFlagPolicy.WRITABLE;
}
if (flag.oneOf(Flag.TESTBLOCK)) {
return RegionFlagPolicy.READ_ONLY;
}
return RegionFlagPolicy.NOT_APPLICABLE;
}
}
@@ -20,6 +20,7 @@
package de.steamwar.bausystem.region.fixed; package de.steamwar.bausystem.region.fixed;
import de.steamwar.bausystem.region.FixedRegionSystem; import de.steamwar.bausystem.region.FixedRegionSystem;
import de.steamwar.bausystem.worlddata.WorldData;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
import yapion.hierarchy.types.YAPIONObject; import yapion.hierarchy.types.YAPIONObject;
@@ -216,7 +217,7 @@ public class Prototype {
} else { } else {
prototype = PROTOTYPE_MAP.get(regionConfig.getPlainValue("prototype")); prototype = PROTOTYPE_MAP.get(regionConfig.getPlainValue("prototype"));
} }
FixedFlagStorage flagStorage = new FixedFlagStorage(regionData.getObjectOrSetDefault("flagStorage", new YAPIONObject())); FixedRegionData flagStorage = new FixedRegionData(regionData, WorldData::write);
FixedRegionSystem.addRegion(new FixedRegion(name, flagStorage, prototype, regionConfig, regionData)); FixedRegionSystem.addRegion(new FixedRegion(name, flagStorage, prototype, regionConfig, regionData));
} }
} }
@@ -19,7 +19,7 @@
package de.steamwar.bausystem.region.fixed.loader; package de.steamwar.bausystem.region.fixed.loader;
import de.steamwar.bausystem.region.fixed.FixedGlobalFlagStorage; import de.steamwar.bausystem.region.fixed.FixedGlobalRegionData;
import de.steamwar.bausystem.region.fixed.FixedGlobalRegion; import de.steamwar.bausystem.region.fixed.FixedGlobalRegion;
import de.steamwar.bausystem.region.fixed.Prototype; import de.steamwar.bausystem.region.fixed.Prototype;
import de.steamwar.bausystem.worlddata.WorldData; import de.steamwar.bausystem.worlddata.WorldData;
@@ -80,6 +80,6 @@ public class RegionLoader {
globalOptions = new YAPIONObject(); globalOptions = new YAPIONObject();
optionsYapionObject.add("global", globalOptions); optionsYapionObject.add("global", globalOptions);
} }
FixedGlobalRegion.setFLAG_STORAGE(new FixedGlobalFlagStorage(globalOptions.getObjectOrSetDefault("flagStorage", new YAPIONObject()))); FixedGlobalRegion.setFLAG_STORAGE(new FixedGlobalRegionData(globalOptions, WorldData::write));
} }
} }
@@ -56,7 +56,9 @@ public abstract class AbstractLinker<T> {
.map(s -> { .map(s -> {
try { try {
return Class.forName(s, false, plugin.getClass().getClassLoader()); return Class.forName(s, false, plugin.getClass().getClassLoader());
} catch (ClassNotFoundException | NoClassDefFoundError e) { } catch (NoClassDefFoundError error) {
return null;
} catch (ClassNotFoundException e) {
throw new SecurityException(e.getMessage(), e); throw new SecurityException(e.getMessage(), e);
} }
}) })
@@ -44,6 +44,10 @@ object LeaderboardTable : CompositeIdTable("Leaderboard") {
val bestTime = bool("BestTime") val bestTime = bool("BestTime")
override val primaryKey = PrimaryKey(userId, name) override val primaryKey = PrimaryKey(userId, name)
init {
addIdColumn(userId)
}
} }
class Leaderboard(id: EntityID<CompositeID>) : CompositeEntity(id) { class Leaderboard(id: EntityID<CompositeID>) : CompositeEntity(id) {
@@ -33,8 +33,8 @@ object PersonalKitTable: CompositeIdTable("PersonalKit") {
val userId = reference("UserId", SteamwarUserTable) val userId = reference("UserId", SteamwarUserTable)
val gamemode = varchar("Gamemode", 64).entityId() val gamemode = varchar("Gamemode", 64).entityId()
val kitName = varchar("Name", 64).entityId() val kitName = varchar("Name", 64).entityId()
val inventory = text("Inventory") val inventory = text("Inventory", eagerLoading = true)
val armor = text("Armor") val armor = text("Armor", eagerLoading = true)
val inUse = bool("InUse") val inUse = bool("InUse")
override val primaryKey = PrimaryKey(userId, gamemode, kitName) override val primaryKey = PrimaryKey(userId, gamemode, kitName)
@@ -48,14 +48,17 @@ class InternalKit(id: EntityID<CompositeID>): CompositeEntity(id) {
companion object: CompositeEntityClass<InternalKit>(PersonalKitTable) { companion object: CompositeEntityClass<InternalKit>(PersonalKitTable) {
@JvmStatic @JvmStatic
fun get(userId: Int, gamemode: String) = useDb { fun get(userId: Int, gamemode: String) = useDb {
find { PersonalKitTable.userId eq userId and (PersonalKitTable.gamemode eq gamemode) and (PersonalKitTable.inUse eq true) } find { PersonalKitTable.userId eq userId and (PersonalKitTable.gamemode eq gamemode) }
.toList() .toList()
} }
@JvmStatic @JvmStatic
fun get(userId: Int, gamemode: String, kitName: String) = useDb { fun get(userId: Int, gamemode: String, kitName: String) = useDb {
find { PersonalKitTable.userId eq userId and (PersonalKitTable.gamemode eq gamemode) and (PersonalKitTable.kitName eq kitName) and (PersonalKitTable.inUse eq true) } findById(CompositeID {
.firstOrNull() it[PersonalKitTable.userId] = EntityID(userId, SteamwarUserTable)
it[PersonalKitTable.gamemode] = gamemode
it[PersonalKitTable.kitName] = kitName
})
} }
@JvmStatic @JvmStatic
@@ -67,10 +70,10 @@ class InternalKit(id: EntityID<CompositeID>): CompositeEntity(id) {
it[PersonalKitTable.kitName] = kitName it[PersonalKitTable.kitName] = kitName
} }
) { ) {
this.inventory = rawInventory this.rawInventory = rawInventory
this.armor = rawArmor this.rawArmor = rawArmor
this.inUse = true this.inUse = false
} }.also { it.setDefault() }
} }
@JvmStatic @JvmStatic
@@ -107,6 +110,7 @@ class InternalKit(id: EntityID<CompositeID>): CompositeEntity(id) {
fun setDefault() = useDb { fun setDefault() = useDb {
find { PersonalKitTable.userId eq userID and (PersonalKitTable.gamemode eq gameMode) and (PersonalKitTable.inUse eq true) } find { PersonalKitTable.userId eq userID and (PersonalKitTable.gamemode eq gameMode) and (PersonalKitTable.inUse eq true) }
.filter { it.id.value != this@InternalKit.id.value }
.forEach { it.inUse = false } .forEach { it.inUse = false }
inUse = true inUse = true
} }
@@ -1,78 +0,0 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2025 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.sql
import de.steamwar.sql.internal.useDb
import org.jetbrains.exposed.v1.core.VarCharColumnType
import org.jetbrains.exposed.v1.core.and
import org.jetbrains.exposed.v1.core.dao.id.CompositeID
import org.jetbrains.exposed.v1.core.dao.id.CompositeIdTable
import org.jetbrains.exposed.v1.core.dao.id.EntityID
import org.jetbrains.exposed.v1.core.eq
import org.jetbrains.exposed.v1.dao.CompositeEntity
import org.jetbrains.exposed.v1.dao.CompositeEntityClass
object PollAnswerTable: CompositeIdTable("PollAnswer") {
val userId = reference("UserID", SteamwarUserTable)
val question = varchar("Question", 150)
val answer = integer("Answer")
}
class PollAnswer(id: EntityID<CompositeID>): CompositeEntity(id) {
var userId by PollAnswerTable.userId
private set
var question by PollAnswerTable.question
private set
private var answerId by PollAnswerTable.answer
var answer: Int
get() = answerId
set(value) = useDb {
answerId = value
}
companion object: CompositeEntityClass<PollAnswer>(PollAnswerTable) {
@JvmStatic
var currentPoll: String? = null
@JvmStatic
fun get(userId: Int) = useDb {
find { (PollAnswerTable.userId eq userId) and (PollAnswerTable.question eq currentPoll!!) }.firstOrNull()
?: new {
this.userId = EntityID(userId, SteamwarUserTable)
this.question = currentPoll!!
this.answerId = 0
}
}
@JvmStatic
fun getCurrentResults(): Map<Int, Int> = useDb {
exec("SELECT Count(UserID) AS Times, Answer FROM PollAnswer WHERE Question = ? GROUP BY Answer ORDER BY Times ASC",
args = listOf(VarCharColumnType() to currentPoll!!)) {
val result = mutableMapOf<Int, Int>()
while (it.next()) {
result[it.getInt("Answer")] = it.getInt("Times")
}
result
} ?: emptyMap()
}
}
fun hasAnswered() = answerId != 0
}
@@ -1,74 +0,0 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2025 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.sql
import de.steamwar.sql.internal.useDb
import org.jetbrains.exposed.v1.core.and
import org.jetbrains.exposed.v1.core.dao.id.CompositeID
import org.jetbrains.exposed.v1.core.dao.id.CompositeIdTable
import org.jetbrains.exposed.v1.core.dao.id.EntityID
import org.jetbrains.exposed.v1.core.eq
import org.jetbrains.exposed.v1.dao.CompositeEntity
import org.jetbrains.exposed.v1.dao.CompositeEntityClass
import org.jetbrains.exposed.v1.jdbc.insertIgnore
object SchemEloTable: CompositeIdTable("SchemElo") {
val schemId = reference("SchemId", SchematicNodeTable)
val season = integer("Season").entityId()
val elo = integer("Elo")
override val primaryKey = PrimaryKey(schemId, season)
init {
addIdColumn(schemId)
}
}
class SchemElo(id: EntityID<CompositeID>): CompositeEntity(id) {
companion object: CompositeEntityClass<SchemElo>(SchemEloTable) {
@JvmStatic
fun getElo(node: SchematicNode, season: Int, defaultElo: Int = 0) = useDb {
find { (SchemEloTable.schemId eq node.id) and (SchemEloTable.season eq season) }.firstOrNull()?.elo ?: defaultElo
}
@JvmStatic
fun getCurrentElo(schemId: Int) = getElo(SchematicNode.byId(schemId)!!, Season.getSeason())
@JvmStatic
fun setElo(node: Int, elo: Int) = useDb {
findByIdAndUpdate(CompositeID {
it[SchemEloTable.schemId] = node
it[SchemEloTable.season] = Season.getSeason()
}) {
it.elo = elo
} ?: SchemEloTable.insertIgnore {
it[SchemEloTable.schemId] = node
it[SchemEloTable.season] = Season.getSeason()
it[SchemEloTable.elo] = elo
}
return@useDb
}
}
var node by SchemEloTable.schemId
var season by SchemEloTable.season
var elo by SchemEloTable.elo
}
@@ -116,7 +116,7 @@ class SchematicNode(id: EntityID<Int>) : IntEntity(id) {
@JvmStatic @JvmStatic
fun schematicAccessibleForUser(user: SteamwarUser, schematicId: Int?) = fromSql( fun schematicAccessibleForUser(user: SteamwarUser, schematicId: Int?) = fromSql(
"WITH RECURSIVE Nodes AS (SELECT NodeId, ParentId as ParentNode FROM NodeMember WHERE UserId = ? UNION SELECT NodeId, ParentNode FROM SchematicNode WHERE NodeOwner = ?), RSN AS ( SELECT NodeId, ParentNode FROM Nodes UNION SELECT SN.NodeId, SN.ParentNode FROM SchematicNode SN, RSN WHERE SN.ParentNode = RSN.NodeId ) SELECT SN.*, ? AS EffectiveOwner FROM RSN INNER JOIN SchematicNode SN ON RSN.NodeId = SN.NodeId WHERE NodeId = ?", "WITH RECURSIVE Nodes AS (SELECT NodeId, ParentId as ParentNode FROM NodeMember WHERE UserId = ? UNION SELECT NodeId, ParentNode FROM SchematicNode WHERE NodeOwner = ?), RSN AS ( SELECT NodeId, ParentNode FROM Nodes UNION SELECT SN.NodeId, SN.ParentNode FROM SchematicNode SN, RSN WHERE SN.ParentNode = RSN.NodeId ) SELECT SN.*, ? AS EffectiveOwner FROM RSN INNER JOIN SchematicNode SN ON RSN.NodeId = SN.NodeId WHERE SN.NodeId = ?",
listOf( listOf(
IntegerColumnType() to user.getId(), IntegerColumnType() to user.getId(),
IntegerColumnType() to user.getId(), IntegerColumnType() to user.getId(),
@@ -365,8 +365,6 @@ class SchematicNode(id: EntityID<Int>) : IntEntity(id) {
} }
} }
fun getElo(season: Int) = SchemElo.getElo(this, season)
override fun delete() = useDb { override fun delete() = useDb {
super.delete() super.delete()
} }
@@ -1,61 +0,0 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2025 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.sql;
import java.util.Calendar;
public class Season {
private Season() {}
public static int getSeason() {
Calendar calendar = Calendar.getInstance();
int yearIndex = calendar.get(Calendar.MONTH) / 4;
return (calendar.get(Calendar.YEAR) * 3 + yearIndex);
}
public static String getSeasonStart() {
Calendar calendar = Calendar.getInstance();
int month = calendar.get(Calendar.MONTH);
if (month <= 3) {
return calendar.get(Calendar.YEAR) + "-1-1";
} else if (month <= 7) {
return calendar.get(Calendar.YEAR) + "-5-1";
} else {
return calendar.get(Calendar.YEAR) + "-9-1";
}
}
public static String convertSeasonToString(int season){
if (season == -1) return "";
int yearSeason = season % 3;
int year = (season - yearSeason) / 3;
return String.format("%d-%d", year, yearSeason + 1);
}
public static int convertSeasonToNumber(String season){
if (season.isEmpty()) return -1;
String[] split = season.split("-");
try {
return Integer.parseInt(split[0]) * 3 + Integer.parseInt(split[1]) - 1;
} catch (NumberFormatException e) {
return -1;
}
}
}
@@ -170,7 +170,7 @@ class SteamwarUser(id: EntityID<Int>): IntEntity(id) {
fun isLeader() = leader fun isLeader() = leader
var locale: Locale by SteamwarUserTable.locale var locale: Locale by SteamwarUserTable.locale
.transform({ it.toLanguageTag() }, { it?.let { Locale.forLanguageTag(it) } ?: Locale.getDefault()}) .transform({ it.toLanguageTag() }, { it?.let { Locale.forLanguageTag(it) } ?: Locale.ENGLISH })
var manualLocale by SteamwarUserTable.manualLocale var manualLocale by SteamwarUserTable.manualLocale
var bedrock by SteamwarUserTable.bedrock var bedrock by SteamwarUserTable.bedrock
private var passwordInternal by SteamwarUserTable.password private var passwordInternal by SteamwarUserTable.password
+3 -3
View File
@@ -33,7 +33,7 @@ object TeamTable : IntIdTable("Team", "TeamID") {
val name = varchar("TeamName", 16) val name = varchar("TeamName", 16)
val deleted = bool("TeamDeleted").default(false) val deleted = bool("TeamDeleted").default(false)
val address = text("Address").nullable() val address = text("Address").nullable()
val port = ushort("Port") val port = ushort("Port").default(25565u)
} }
class Team(id: EntityID<Int>) : IntEntity(id) { class Team(id: EntityID<Int>) : IntEntity(id) {
@@ -41,10 +41,10 @@ class Team(id: EntityID<Int>) : IntEntity(id) {
private val teamCache = mutableMapOf<Int, Team>() private val teamCache = mutableMapOf<Int, Team>()
@JvmStatic @JvmStatic
fun clear() = teamCache.clear() fun clear() = synchronized(teamCache) { teamCache.clear() }
@JvmStatic @JvmStatic
fun byId(id: Int) = teamCache.computeIfAbsent(id) { useDb { Team[id] } } fun byId(id: Int) = synchronized(teamCache) { teamCache.computeIfAbsent(id) { useDb { Team[id] } } }
@JvmStatic @JvmStatic
fun get(name: String) = useDb { find { (TeamTable.name.lowerCase() eq name.lowercase() or (TeamTable.kuerzel.lowerCase() eq name.lowercase())) and not(TeamTable.deleted) }.firstOrNull() } fun get(name: String) = useDb { find { (TeamTable.name.lowerCase() eq name.lowercase() or (TeamTable.kuerzel.lowerCase() eq name.lowercase())) and not(TeamTable.deleted) }.firstOrNull() }
@@ -1,170 +0,0 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2025 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.sql
import de.steamwar.sql.internal.useDb
import org.jetbrains.exposed.v1.core.*
import org.jetbrains.exposed.v1.core.dao.id.CompositeID
import org.jetbrains.exposed.v1.core.dao.id.CompositeIdTable
import org.jetbrains.exposed.v1.core.dao.id.EntityID
import org.jetbrains.exposed.v1.dao.CompositeEntity
import org.jetbrains.exposed.v1.dao.CompositeEntityClass
import org.jetbrains.exposed.v1.jdbc.insertIgnore
import org.jetbrains.exposed.v1.jdbc.select
import java.util.concurrent.ConcurrentHashMap
object UserEloTable : CompositeIdTable("UserElo") {
val season = integer("Season").entityId()
val gameMode = varchar("GameMode", 16).entityId()
val userId = reference("UserID", SteamwarUserTable)
val elo = integer("Elo")
override val primaryKey = PrimaryKey(season, gameMode, userId)
init {
addIdColumn(season)
addIdColumn(gameMode)
}
}
class UserElo(id: EntityID<CompositeID>) : CompositeEntity(id) {
companion object : CompositeEntityClass<UserElo>(UserEloTable) {
private const val ELO_DEFAULT = 0
private val gameModeUserEloCache: MutableMap<String, MutableMap<Int, Int?>> = ConcurrentHashMap()
private val emblemCache: MutableMap<Int, String> = ConcurrentHashMap()
@JvmStatic
fun clear() {
gameModeUserEloCache.clear()
emblemCache.clear()
}
@JvmStatic
fun getEloOrDefault(userId: Int, gameMode: String) =
getElo(userId, gameMode) ?: ELO_DEFAULT
@JvmStatic
fun getElo(userId: Int, gameMode: String) =
gameModeUserEloCache.getOrPut(gameMode) { mutableMapOf() }
.getOrPut(userId) { getEloFromDb(userId, gameMode)?.elo }
private fun getEloFromDb(userId: Int, gameMode: String) = useDb {
find { (UserEloTable.userId eq userId) and (UserEloTable.gameMode eq gameMode) and (UserEloTable.season eq Season.getSeason()) }.firstOrNull()
}
@JvmStatic
fun getFightsOfSeason(userId: Int, gamemode: String) = useDb {
exec(
"SELECT COUNT(*) AS Fights FROM FightPlayer INNER JOIN Fight F on FightPlayer.FightID = F.FightID WHERE UserID = ? AND GameMode = ? AND UNIX_TIMESTAMP(StartTime) + Duration >= UNIX_TIMESTAMP(?)",
args = listOf(
IntegerColumnType() to userId,
VarCharColumnType() to gamemode,
VarCharColumnType() to Season.getSeasonStart()
)
) {
return@exec if (it.next()) {
it.getInt("Fights")
} else {
0
}
} ?: 0
}
@JvmStatic
fun setElo(userId: Int, gameMode: String, elo: Int) {
emblemCache.remove(userId)
gameModeUserEloCache.getOrDefault(gameMode, mutableMapOf()).remove(userId)
useDb {
findByIdAndUpdate(CompositeID {
it[UserEloTable.userId] = userId
it[UserEloTable.gameMode] = gameMode
it[UserEloTable.season] = Season.getSeason()
}) {
it.elo = elo
} ?: UserEloTable.insertIgnore {
it[UserEloTable.userId] = userId
it[UserEloTable.gameMode] = gameMode
it[UserEloTable.season] = Season.getSeason()
it[UserEloTable.elo] = elo
}
}
}
@JvmStatic
fun getPlacement(elo: Int, gamemode: String) = useDb {
UserEloTable.select(UserEloTable.userId.count()).where {
(UserEloTable.gameMode eq gamemode) and (UserEloTable.elo greater elo) and (UserEloTable.season eq Season.getSeason())
}.firstOrNull()?.get(UserEloTable.userId.count())?.let { it + 1 }?.toInt() ?: -1
}
@JvmStatic
fun getEmblem(user: SteamwarUser, rankedModes: List<String>) =
emblemCache.getOrPut(user.id.value) {
var emblemProgression = -1
for (mode in rankedModes) {
if (getFightsOfSeason(user.id.value, mode) == 0) continue
val progression = getProgression(user.id.value, mode)
if (progression > emblemProgression) {
emblemProgression = progression
}
}
return toEmblem(emblemProgression)
}
@JvmStatic
fun getEmblemProgression(gameMode: String, userId: Int): String =
when (getProgression(userId, gameMode)) {
-1 -> "§8❱❱❱❱ ❂"
0 -> "§e❱§8❱❱❱ ❂"
1 -> "§e❱❱§8❱❱ ❂"
2 -> "§e❱❱❱§8❱ ❂"
3 -> "§e❱❱❱❱§8 ❂"
4 -> "§8❱❱❱❱ §5❂"
else -> throw SecurityException("Progression is not in range")
}
@JvmStatic
fun getProgression(userId: Int, gameMode: String) = useDb { getElo(userId, gameMode) ?: -1 }.let {
when {
it < 0 -> -1
it < 150 -> 0
it < 350 -> 1
it < 600 -> 2
it < 900 -> 3
else -> 4
}
}
@JvmStatic
fun toEmblem(progression: Int) = when (progression) {
-1 -> ""
0 -> "§e❱ "
1 -> "§e❱❱ "
2 -> "§e❱❱❱ "
3 -> "§e❱❱❱❱ "
4 -> "§5❂ "
else -> throw SecurityException("Progression out of range")
}
}
var elo by UserEloTable.elo
}
@@ -60,7 +60,7 @@ enum class UserPerm {
@JvmField @JvmField
val prefixes = mapOf( val prefixes = mapOf(
PREFIX_NONE to emptyPrefix, PREFIX_NONE to emptyPrefix,
PREFIX_YOUTUBER to Prefix("§7", "YT"), PREFIX_YOUTUBER to Prefix("§x§8§A§2§B§E§5", "CC"), // 8A2BE5
PREFIX_GUIDE to Prefix("§x§e§7§6§2§e§d", "Guide"), // E762ED PREFIX_GUIDE to Prefix("§x§e§7§6§2§e§d", "Guide"), // E762ED
PREFIX_SUPPORTER to Prefix("§x§6§0§9§5§F§B", "Sup"), // 6095FB PREFIX_SUPPORTER to Prefix("§x§6§0§9§5§F§B", "Sup"), // 6095FB
PREFIX_MODERATOR to Prefix("§x§F§F§A§2§5§C", "Mod"), // FFA25C PREFIX_MODERATOR to Prefix("§x§F§F§A§2§5§C", "Mod"), // FFA25C
@@ -23,6 +23,7 @@ import org.intellij.lang.annotations.Language
import org.jetbrains.exposed.v1.core.ColumnType import org.jetbrains.exposed.v1.core.ColumnType
import org.jetbrains.exposed.v1.core.Expression import org.jetbrains.exposed.v1.core.Expression
import org.jetbrains.exposed.v1.core.ResultRow import org.jetbrains.exposed.v1.core.ResultRow
import org.jetbrains.exposed.v1.core.StdOutSqlLogger
import org.jetbrains.exposed.v1.core.statements.StatementType import org.jetbrains.exposed.v1.core.statements.StatementType
import org.jetbrains.exposed.v1.dao.IntEntity import org.jetbrains.exposed.v1.dao.IntEntity
import org.jetbrains.exposed.v1.dao.IntEntityClass import org.jetbrains.exposed.v1.dao.IntEntityClass
@@ -27,9 +27,7 @@ import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.bukkit.BukkitWorld; import com.sk89q.worldedit.bukkit.BukkitWorld;
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard; import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
import com.sk89q.worldedit.extent.clipboard.Clipboard; import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.extent.clipboard.io.BuiltInClipboardFormat; import com.sk89q.worldedit.extent.clipboard.io.*;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardWriter;
import com.sk89q.worldedit.extent.clipboard.io.SpongeSchematicReader;
import com.sk89q.worldedit.function.operation.ForwardExtentCopy; import com.sk89q.worldedit.function.operation.ForwardExtentCopy;
import com.sk89q.worldedit.function.operation.Operations; import com.sk89q.worldedit.function.operation.Operations;
import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.BlockVector3;
@@ -120,7 +118,12 @@ public class WorldeditWrapper14 implements WorldeditWrapper {
@Override @Override
public Clipboard loadChar(String charName) throws IOException { public Clipboard loadChar(String charName) throws IOException {
return new SpongeSchematicReader(new NBTInputStream(new GZIPInputStream(new FileInputStream(new File(FightSystem.getPlugin().getDataFolder(), "text/" + charName + ".schem"))))).read(); File file = new File(FightSystem.getPlugin().getDataFolder(), "text/" + charName + ".schem");
Clipboard clipboard;
try (ClipboardReader reader = Objects.requireNonNull(ClipboardFormats.findByFile(file)).getReader(new FileInputStream(file))) {
clipboard = reader.read();
}
return clipboard;
} }
@Override @Override
@@ -19,11 +19,27 @@
package de.steamwar.fightsystem.utils; package de.steamwar.fightsystem.utils;
import io.papermc.paper.datacomponent.DataComponentType;
import io.papermc.paper.datacomponent.DataComponentTypes; import io.papermc.paper.datacomponent.DataComponentTypes;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import java.util.HashSet;
import java.util.Set;
public class ReflectionWrapper21 implements ReflectionWrapper { public class ReflectionWrapper21 implements ReflectionWrapper {
private static final Set<DataComponentType> FORBIDDEN_TYPES = new HashSet<>();
static {
FORBIDDEN_TYPES.add(DataComponentTypes.CUSTOM_NAME);
FORBIDDEN_TYPES.add(DataComponentTypes.PROFILE);
FORBIDDEN_TYPES.add(DataComponentTypes.UNBREAKABLE);
FORBIDDEN_TYPES.add(DataComponentTypes.BLOCK_DATA);
FORBIDDEN_TYPES.add(DataComponentTypes.BLOCKS_ATTACKS);
FORBIDDEN_TYPES.add(DataComponentTypes.BUNDLE_CONTENTS);
FORBIDDEN_TYPES.add(DataComponentTypes.CUSTOM_MODEL_DATA);
}
@Override @Override
public Object explosionHider(Player player, Object packet, PacketHiderFunction packetHiderFunction) { public Object explosionHider(Player player, Object packet, PacketHiderFunction packetHiderFunction) {
return packet; return packet;
@@ -31,6 +47,7 @@ public class ReflectionWrapper21 implements ReflectionWrapper {
@Override @Override
public boolean hasItems(ItemStack stack) { public boolean hasItems(ItemStack stack) {
return stack.getDataTypes().stream().anyMatch(dataComponentType -> dataComponentType != DataComponentTypes.ENCHANTMENTS || dataComponentType != DataComponentTypes.DAMAGE); FORBIDDEN_TYPES.forEach(stack::resetData);
return false;
} }
} }
@@ -44,7 +44,6 @@ REMOVE_HELP=§8/§eremove §8[§eplayer§8]
NOT_FIGHTLEADER=§cYou are not the fight leader NOT_FIGHTLEADER=§cYou are not the fight leader
WIN_HELP=§8/§7win §8[§eteam §8or §etie§8] WIN_HELP=§8/§7win §8[§eteam §8or §etie§8]
INFO_RANKED=§7Ranked§8: §e{0}
INFO_LEADER=§7Leader {0}§8: {1} INFO_LEADER=§7Leader {0}§8: {1}
INFO_SCHEMATIC=§7Schematic {0}§8: §e{1} §7from {2}, Rank: {3} INFO_SCHEMATIC=§7Schematic {0}§8: §e{1} §7from {2}, Rank: {3}
@@ -167,7 +166,6 @@ TPS_WARNING=§c{0} §7TPS
UI_PRE_RUNNING=§7Kits distributed UI_PRE_RUNNING=§7Kits distributed
UI_RUNNING=§aFight started UI_RUNNING=§aFight started
UI_SKIP=§7Skipping to next event UI_SKIP=§7Skipping to next event
UI_UNRANKED=§7Unranked match
UI_PLAYER_JOINS=§a§l» {0}{1} UI_PLAYER_JOINS=§a§l» {0}{1}
UI_PLAYER_LEAVES=§c§l« {0}{1} UI_PLAYER_LEAVES=§c§l« {0}{1}
UI_LEADER_JOINS=§a§l» {0}Leader {1} UI_LEADER_JOINS=§a§l» {0}Leader {1}
@@ -154,7 +154,6 @@ COMMAND_CURRENTLY_UNAVAILABLE=§cDieser Befehl ist zu diesem Kampfzeitpunkt nich
UI_PRE_RUNNING=§7Kits verteilt UI_PRE_RUNNING=§7Kits verteilt
UI_RUNNING=§aArena freigegeben UI_RUNNING=§aArena freigegeben
UI_SKIP=§7Sprung zum nächsten Ereignis UI_SKIP=§7Sprung zum nächsten Ereignis
UI_UNRANKED=§7Ungewerteter Kampf
UI_LEADER_JOINS=§a§l» {0}Leader {1} UI_LEADER_JOINS=§a§l» {0}Leader {1}
UI_PLAYER_DEATH={0}{1} §7ist gestorben UI_PLAYER_DEATH={0}{1} §7ist gestorben
UI_PLAYER_LEAVE={0}{1} §7hat den Kampf verlassen UI_PLAYER_LEAVE={0}{1} §7hat den Kampf verlassen
@@ -37,7 +37,6 @@ public class DummyAI extends AI {
public DummyAI(FightTeam team) { public DummyAI(FightTeam team) {
super(team, SteamwarUser.get("public")); super(team, SteamwarUser.get("public"));
FightStatistics.unrank();
getEntity().setInvulnerable(true); getEntity().setInvulnerable(true);
} }
@@ -182,7 +182,7 @@ public class GUI {
} }
Kit prototype = Kit.getAvailableKits(Fight.getFightPlayer(p).isLeader()).get(0); Kit prototype = Kit.getAvailableKits(Fight.getFightPlayer(p).isLeader()).get(0);
PersonalKit kit = PersonalKit.create(user.getId(), Config.GameModeConfig.Schematic.Type.toDB(), s, prototype.getInventory(), prototype.getArmor()); PersonalKit kit = PersonalKit.create(user.getId(), Config.GameModeConfig.Schematic.Type.toDB(), s, prototype.getInventory(), prototype.getArmor());
PersonalKitCreator.openKitCreator(p, kit); Bukkit.getScheduler().runTask(FightSystem.getPlugin(), () -> PersonalKitCreator.openKitCreator(p, kit));
}); });
anvilInv.open(); anvilInv.open();
}); });
@@ -51,7 +51,6 @@ public class InfoCommand implements CommandExecutor {
if(!SteamwarUser.get(player.getUniqueId()).hasPerm(UserPerm.CHECK)) if(!SteamwarUser.get(player.getUniqueId()).hasPerm(UserPerm.CHECK))
return false; return false;
FightSystem.getMessage().send("INFO_RANKED", player, !FightStatistics.isUnranked());
for(FightTeam team : Fight.teams()) { for(FightTeam team : Fight.teams()) {
if(!team.isLeaderless()) if(!team.isLeaderless())
FightSystem.getMessage().send("INFO_LEADER", player, team.getColoredName(), team.getLeader().getEntity().getName()); FightSystem.getMessage().send("INFO_LEADER", player, team.getColoredName(), team.getLeader().getEntity().getName());
@@ -1,51 +0,0 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2025 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.fightsystem.commands;
import de.steamwar.fightsystem.ArenaMode;
import de.steamwar.fightsystem.states.FightState;
import de.steamwar.fightsystem.states.StateDependentCommand;
import de.steamwar.fightsystem.utils.FightStatistics;
import de.steamwar.linkage.Linked;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
@Linked
public class UnrankCommand implements CommandExecutor {
public UnrankCommand () {
new StateDependentCommand(ArenaMode.VariableTeams, FightState.Setup, "unrank", this);
}
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
if(!(sender instanceof Player))
return false;
Player player = (Player) sender;
if(Commands.checkGetLeader(player) == null)
return false;
FightStatistics.unrank();
return false;
}
}
@@ -32,10 +32,10 @@ public class TNTDistributor {
public TNTDistributor() { public TNTDistributor() {
new StateDependentTask(Winconditions.TNT_DISTRIBUTION, FightState.Running, () -> Fight.teams().forEach(team -> team.getPlayers().forEach(fp -> { new StateDependentTask(Winconditions.TNT_DISTRIBUTION, FightState.Running, () -> Fight.teams().forEach(team -> team.getPlayers().forEach(fp -> {
if(!fp.isLiving()) if (!fp.isLiving())
return; return;
fp.ifPlayer(player -> player.getInventory().addItem(new ItemStack(Material.TNT, 20))); fp.ifPlayer(player -> player.getInventory().addItem(new ItemStack(Material.TNT, 1)));
})), 300, 300); })), 20, 20);
} }
} }
@@ -203,13 +203,23 @@ public class FightSchematic extends StateDependent {
for(int i = 0; i < chars.length; i++){ for(int i = 0; i < chars.length; i++){
Clipboard character; Clipboard character;
try { try {
character = WorldeditWrapper.impl.loadChar(chars[i] == '/' ? "slash" : String.valueOf(chars[i])); if (Character.isLowerCase(chars[i])) {
character = WorldeditWrapper.impl.loadChar("lower/" + chars[i]);
} else if (Character.isUpperCase(chars[i])) {
character = WorldeditWrapper.impl.loadChar("upper/" + chars[i]);
} else {
character = WorldeditWrapper.impl.loadChar(chars[i] == '/' ? "slash" : String.valueOf(chars[i]));
}
} catch (IOException e) { } catch (IOException e) {
Bukkit.getLogger().log(Level.WARNING, "Could not display character {} due to missing file!", chars[i]);
try { try {
character = WorldeditWrapper.impl.loadChar(""); character = WorldeditWrapper.impl.loadChar(chars[i] == '/' ? "slash" : String.valueOf(chars[i]));
}catch (IOException ex) { } catch (IOException ex) {
throw new SecurityException("Could not load text", ex); Bukkit.getLogger().log(Level.WARNING, "Could not display character {} due to missing file!", chars[i]);
try {
character = WorldeditWrapper.impl.loadChar("");
}catch (IOException exc) {
throw new SecurityException("Could not load text", exc);
}
} }
} }
@@ -393,7 +393,6 @@ public class FightTeam {
public void pasteSchem(SchematicNode schematic){ public void pasteSchem(SchematicNode schematic){
if(schematic.getSchemtype().check()) { if(schematic.getSchemtype().check()) {
FightStatistics.unrank();
FightSystem.getMessage().broadcast("SCHEMATIC_UNCHECKED", getColoredName()); FightSystem.getMessage().broadcast("SCHEMATIC_UNCHECKED", getColoredName());
} }
@@ -34,6 +34,7 @@ import org.bukkit.event.block.Action;
import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.inventory.EquipmentSlot; import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.PlayerInventory;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
@@ -62,6 +63,7 @@ public class HotbarKitListener implements Listener {
public void onInventoryClick(InventoryClickEvent event) { public void onInventoryClick(InventoryClickEvent event) {
int slot = event.getSlot(); int slot = event.getSlot();
if (slot < 0 || slot >= HotbarKit.HOTBAR_SIZE) return; if (slot < 0 || slot >= HotbarKit.HOTBAR_SIZE) return;
if (!(event.getClickedInventory() instanceof PlayerInventory)) return;
Player player = (Player) event.getWhoClicked(); Player player = (Player) event.getWhoClicked();
click(player, slot, event); click(player, slot, event);
@@ -117,7 +117,7 @@ public class Kit {
if(kit.isList("Armor")) if(kit.isList("Armor"))
armor = Objects.requireNonNull(kit.getList("Armor")).toArray(new ItemStack[0]); armor = Objects.requireNonNull(kit.getList("Armor")).toArray(new ItemStack[0]);
else else
armor = null; armor = new ItemStack[]{ null, null, null, null};
leaderAllowed = kit.getBoolean("LeaderAllowed"); leaderAllowed = kit.getBoolean("LeaderAllowed");
memberAllowed = kit.getBoolean("MemberAllowed"); memberAllowed = kit.getBoolean("MemberAllowed");
if(kit.isList("Effects")) if(kit.isList("Effects"))
@@ -261,7 +261,7 @@ public class Kit {
player.getInventory().setContents(inventory); player.getInventory().setContents(inventory);
if(armor != null) if(armor != null)
player.getInventory().setArmorContents(armor); player.getInventory().setArmorContents(armor);
player.updateInventory(); player.updateInventory(); //TODO issue in 1.21.6?
if(effects != null) if(effects != null)
player.addPotionEffects(effects); player.addPotionEffects(effects);
} }
@@ -35,6 +35,7 @@ import org.bukkit.GameMode;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.entity.TNTPrimed;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority; import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
@@ -180,6 +181,7 @@ public class Permanent implements Listener {
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onExplosion(EntityExplodeEvent e) { public void onExplosion(EntityExplodeEvent e) {
if (!(e.getEntity() instanceof TNTPrimed)) return;
e.blockList().removeIf(block -> { e.blockList().removeIf(block -> {
if(block.getType() == Material.TNT) { if(block.getType() == Material.TNT) {
return false; return false;
@@ -32,20 +32,16 @@ import de.steamwar.fightsystem.states.FightState;
import de.steamwar.fightsystem.states.OneShotStateDependent; import de.steamwar.fightsystem.states.OneShotStateDependent;
import de.steamwar.fightsystem.winconditions.Wincondition; import de.steamwar.fightsystem.winconditions.Wincondition;
import de.steamwar.linkage.Linked; import de.steamwar.linkage.Linked;
import de.steamwar.network.NetworkSender;
import de.steamwar.network.packets.common.FightEndsPacket;
import de.steamwar.sql.EventFight; import de.steamwar.sql.EventFight;
import de.steamwar.sql.EventRelation; import de.steamwar.sql.EventRelation;
import de.steamwar.sql.SchematicNode; import de.steamwar.sql.SchematicNode;
import de.steamwar.sql.SteamwarUser; import de.steamwar.sql.SteamwarUser;
import lombok.Getter;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import java.nio.file.Files; import java.nio.file.Files;
import java.sql.Timestamp; import java.sql.Timestamp;
import java.time.Instant; import java.time.Instant;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.stream.Collectors;
import static de.steamwar.sql.Fight.create; import static de.steamwar.sql.Fight.create;
import static de.steamwar.sql.Fight.markReplayAvailable; import static de.steamwar.sql.Fight.markReplayAvailable;
@@ -53,14 +49,6 @@ import static de.steamwar.sql.Fight.markReplayAvailable;
@Linked @Linked
public class FightStatistics { public class FightStatistics {
@Getter
private static boolean unranked = false;
public static void unrank() {
unranked = true;
FightUI.addSubtitle("UI_UNRANKED");
}
private Timestamp starttime = Timestamp.from(Instant.now()); private Timestamp starttime = Timestamp.from(Instant.now());
public FightStatistics() { public FightStatistics() {
@@ -145,12 +133,6 @@ public class FightStatistics {
} catch (Exception e) { } catch (Exception e) {
Bukkit.getLogger().log(Level.SEVERE, "Failed to save statistics", e); Bukkit.getLogger().log(Level.SEVERE, "Failed to save statistics", e);
} }
if (!Bukkit.getOnlinePlayers().isEmpty() && !unranked) {
NetworkSender.send(new FightEndsPacket((byte) win, blueSchem == null ? 0 : blueSchem, redSchem == null ? 0 : redSchem, Fight.getBlueTeam().getPlayers().stream().map(FightPlayer::getUser).map(SteamwarUser::getId).collect(Collectors.toList()), Fight.getRedTeam().getPlayers().stream().map(FightPlayer::getUser).map(SteamwarUser::getId).collect(Collectors.toList()), gameMode, (int)(endTime.getEpochSecond() - starttime.toInstant().getEpochSecond())));
}
unranked = false;
} }
private int getLeader(FightTeam team) { private int getLeader(FightTeam team) {
@@ -91,7 +91,7 @@ public abstract class WinconditionBasePercent extends Wincondition implements Pr
@EventHandler @EventHandler
public void onEntityExplode(EntityExplodeEvent event) { public void onEntityExplode(EntityExplodeEvent event) {
if ( if (
event.getEntityType() == EntityType.FIREBALL || event.getEntityType() != EntityType.PRIMED_TNT ||
!team.getExtendRegion().inRegion(event.getEntity().getLocation()) || !team.getExtendRegion().inRegion(event.getEntity().getLocation()) ||
(!Config.GameModeConfig.WinConditionParams.PercentEntern && !Config.GameModeConfig.EnterStages.isEmpty() && Config.GameModeConfig.EnterStages.get(0) >= Wincondition.getTimeOverCountdown().getTimeLeft()) (!Config.GameModeConfig.WinConditionParams.PercentEntern && !Config.GameModeConfig.EnterStages.isEmpty() && Config.GameModeConfig.EnterStages.get(0) >= Wincondition.getTimeOverCountdown().getTimeLeft())
) { ) {
+22
View File
@@ -50,6 +50,18 @@ tasks.register<FightServer>("WarGear20") {
config = "WarGear20.yml" config = "WarGear20.yml"
} }
tasks.register<FightServer>("HalloweenWS") {
group = "run"
description = "Run a Halloween 1.21 Fight Replay Server"
dependsOn(":SpigotCore:shadowJar")
dependsOn(":FightSystem:shadowJar")
template = "HalloweenWS"
worldName = "arenas/Lucifus"
config = "HalloweenWS.yml"
replay = 179786
jar = "/jars/paper-1.21.6.jar"
}
tasks.register<FightServer>("WarGear21") { tasks.register<FightServer>("WarGear21") {
group = "run" group = "run"
description = "Run a WarGear 1.21 Fight Server" description = "Run a WarGear 1.21 Fight Server"
@@ -70,3 +82,13 @@ tasks.register<FightServer>("SpaceCraftDev20") {
worldName = "arenas/AS_Horizon" worldName = "arenas/AS_Horizon"
config = "SpaceCraftDev20.yml" config = "SpaceCraftDev20.yml"
} }
tasks.register<FightServer>("QuickGear20") {
group = "run"
description = "Run a QuickGear 1.20 Fight Server"
dependsOn(":SpigotCore:shadowJar")
dependsOn(":FightSystem:shadowJar")
template = "QuickGear20"
worldName = "arenas/WarGearPark"
config = "QuickGear20.yml"
}
@@ -17,7 +17,7 @@
# along with this program. If not, see <https://www.gnu.org/licenses/>. # along with this program. If not, see <https://www.gnu.org/licenses/>.
# #
PREFIX=§eSchematic§8» §7 PREFIX=§eSchematic§8»§7
ON=§aon ON=§aon
OFF=§coff OFF=§coff
CHANGE=§7To change CHANGE=§7To change
@@ -59,7 +59,6 @@ UTIL_INFO_TYPE_DIR=§eDIR
UTIL_INFO_RANK=§7Rank: §e{0} UTIL_INFO_RANK=§7Rank: §e{0}
UTIL_INFO_COLOR=§7Color translation: {0} UTIL_INFO_COLOR=§7Color translation: {0}
UTIL_INFO_REPLAY=§7Replay playback: {0} UTIL_INFO_REPLAY=§7Replay playback: {0}
UTIL_INFO_ELO=§7Elo: §e{0}
UTIL_INFO_FORMAT=§7Format: §e{0} UTIL_INFO_FORMAT=§7Format: §e{0}
UTIL_INFO_STATUS=§cState: §c{0}: {1} UTIL_INFO_STATUS=§cState: §c{0}: {1}
UTIL_INFO_MEMBER=§7Members: §e{0} UTIL_INFO_MEMBER=§7Members: §e{0}
@@ -105,6 +104,7 @@ UTIL_SUBMIT_COLOR_ON=§aReplace pink to team color
UTIL_SUBMIT_COLOR_OFF=§cDo not replace pink UTIL_SUBMIT_COLOR_OFF=§cDo not replace pink
UTIL_SUBMIT_DIRECT=§eSubmit directly UTIL_SUBMIT_DIRECT=§eSubmit directly
UTIL_SUBMIT_DIRECT_DONE=§aThe Schematic will be reviewed in a timely manner UTIL_SUBMIT_DIRECT_DONE=§aThe Schematic will be reviewed in a timely manner
UTIL_SUBMIT_DIRECT_PLAYABLE=§aYou can now use this Schematic in the arena! Good luck and have fun.
UTIL_SUBMIT_EXTEND=§eExtend Schematic UTIL_SUBMIT_EXTEND=§eExtend Schematic
UTIL_SUBMIT_EXTEND_DONE=§aThe preparation server is starting UTIL_SUBMIT_EXTEND_DONE=§aThe preparation server is starting
UTIL_CHECK_TYPE_NOT_FOUND=§cThe type {0} was not found UTIL_CHECK_TYPE_NOT_FOUND=§cThe type {0} was not found
@@ -88,6 +88,7 @@ UTIL_SUBMIT_COLOR_ON=§aPink zu Teamfarbe ersetzen
UTIL_SUBMIT_COLOR_OFF=§cPink nicht ersetzen UTIL_SUBMIT_COLOR_OFF=§cPink nicht ersetzen
UTIL_SUBMIT_DIRECT=§eDirekt einsenden UTIL_SUBMIT_DIRECT=§eDirekt einsenden
UTIL_SUBMIT_DIRECT_DONE=§aDie Schematic wird zeitnah überprüft UTIL_SUBMIT_DIRECT_DONE=§aDie Schematic wird zeitnah überprüft
UTIL_SUBMIT_DIRECT_PLAYABLE=§aDu kannst die Schematic jetzt in der Arena verwenden! Viel Glück und viel Spaß.
UTIL_SUBMIT_EXTEND=§eSchematic ausfahren UTIL_SUBMIT_EXTEND=§eSchematic ausfahren
UTIL_SUBMIT_EXTEND_DONE=§aDer Vorbereitungsserver wird gestartet UTIL_SUBMIT_EXTEND_DONE=§aDer Vorbereitungsserver wird gestartet
UTIL_INFO_ACTION_REVISIONS_HOVER=§eVersionen anzeigen UTIL_INFO_ACTION_REVISIONS_HOVER=§eVersionen anzeigen
@@ -248,7 +248,6 @@ public class SchematicCommandUtils {
if (node.getSchemtype().fightType()) { if (node.getSchemtype().fightType()) {
SchematicSystem.MESSAGE.sendPrefixless("UTIL_INFO_COLOR", player, SchematicSystem.MESSAGE.parse(node.replaceColor() ? "ON" : "OFF", player)); SchematicSystem.MESSAGE.sendPrefixless("UTIL_INFO_COLOR", player, SchematicSystem.MESSAGE.parse(node.replaceColor() ? "ON" : "OFF", player));
SchematicSystem.MESSAGE.sendPrefixless("UTIL_INFO_REPLAY", player, SchematicSystem.MESSAGE.parse(node.allowReplay() ? "ON" : "OFF", player)); SchematicSystem.MESSAGE.sendPrefixless("UTIL_INFO_REPLAY", player, SchematicSystem.MESSAGE.parse(node.allowReplay() ? "ON" : "OFF", player));
SchematicSystem.MESSAGE.sendPrefixless("UTIL_INFO_ELO", player, node.getElo(Season.getSeason()));
} }
SchematicSystem.MESSAGE.sendPrefixless("UTIL_INFO_FORMAT", player, node.getFileEnding()); SchematicSystem.MESSAGE.sendPrefixless("UTIL_INFO_FORMAT", player, node.getFileEnding());
@@ -482,7 +481,7 @@ public class SchematicCommandUtils {
SchematicSystem.MESSAGE.send("UTIL_TYPE_EXTEND", player); SchematicSystem.MESSAGE.send("UTIL_TYPE_EXTEND", player);
} else { } else {
node.setSchemtype(type.checkType()); node.setSchemtype(type.checkType());
SchematicSystem.MESSAGE.send("UTIL_SUBMIT_DIRECT_DONE", player); SchematicSystem.MESSAGE.send(type.getManualCheck() ? "UTIL_SUBMIT_DIRECT_DONE" : "UTIL_SUBMIT_DIRECT_PLAYABLE", player);
} }
} }
} }
@@ -499,7 +498,7 @@ public class SchematicCommandUtils {
}); });
inv.setItem(7, SWItem.getDye(7), (byte) 7, SchematicSystem.MESSAGE.parse("UTIL_SUBMIT_DIRECT", player), click -> { inv.setItem(7, SWItem.getDye(7), (byte) 7, SchematicSystem.MESSAGE.parse("UTIL_SUBMIT_DIRECT", player), click -> {
node.setSchemtype(type.checkType()); node.setSchemtype(type.checkType());
SchematicSystem.MESSAGE.send("UTIL_SUBMIT_DIRECT_DONE", player); SchematicSystem.MESSAGE.send(type.getManualCheck() ? "UTIL_SUBMIT_DIRECT_DONE" : "UTIL_SUBMIT_DIRECT_PLAYABLE", player);
player.closeInventory(); player.closeInventory();
}); });
inv.setItem(8, SWItem.getDye(10), (byte) 10, SchematicSystem.MESSAGE.parse("UTIL_SUBMIT_EXTEND", player), click -> { inv.setItem(8, SWItem.getDye(10), (byte) 10, SchematicSystem.MESSAGE.parse("UTIL_SUBMIT_EXTEND", player), click -> {
@@ -0,0 +1,355 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2026 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.core
import com.sk89q.jnbt.ByteArrayTag
import com.sk89q.jnbt.ByteTag
import com.sk89q.jnbt.CompoundTag
import com.sk89q.jnbt.DoubleTag
import com.sk89q.jnbt.EndTag
import com.sk89q.jnbt.FloatTag
import com.sk89q.jnbt.IntArrayTag
import com.sk89q.jnbt.IntTag
import com.sk89q.jnbt.ListTag
import com.sk89q.jnbt.LongArrayTag
import com.sk89q.jnbt.LongTag
import com.sk89q.jnbt.ShortTag
import com.sk89q.jnbt.StringTag
import com.sk89q.jnbt.Tag
import com.sk89q.worldedit.WorldEdit
import com.sk89q.worldedit.WorldEditException
import com.sk89q.worldedit.extension.input.ParserContext
import com.sk89q.worldedit.extension.platform.Capability
import com.sk89q.worldedit.extension.platform.Platform
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard
import com.sk89q.worldedit.math.BlockVector3
import com.sk89q.worldedit.regions.CuboidRegion
import com.sk89q.worldedit.world.DataFixer
import com.sk89q.worldedit.world.block.BaseBlock
import com.sk89q.worldedit.world.block.BlockState
import com.sk89q.worldedit.world.block.BlockTypes
import java.io.DataInputStream
import java.io.IOException
import kotlin.collections.map
import kotlin.collections.set
class ChaosSchematicReader(
val stream: DataInputStream,
val wrapper: WorldEditWrapper14
) {
init {
println("ChaosSchematicReader init")
}
/**
* In reinen Unit-Tests (ohne Bukkit/WorldEdit-Plugin-Lifecycle) ist keine WorldEdit-Platform registriert.
* Daher darf der Reader beim Laden nicht hart daran scheitern.
*/
private val platform: Platform? = runCatching {
WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.WORLD_EDITING)
}.getOrNull()
private val liveDataVersion: Int? = platform?.dataVersion
private var wrapped = false
var schematicVersion: Int? = null
var dataVersion: Int? = null
var metadata: Map<String, Any>? = null
var width: Short? = null
var height: Short? = null
var length: Short? = null
var offset: IntArray? = null
val blocks: Blocks = Blocks(null, null, null)
val entities = mutableListOf<Any>()
var fixer: DataFixer? = null
fun read(): BlockArrayClipboard {
require(stream.readByte() == 0x0A.toByte())
val tagName = stream.readUTF()
if (tagName != "Schematic") {
wrapped = true
stream.readByte()
stream.readUTF()
}
while (stream.readByte() != 0.toByte()) {
val name = stream.readUTF()
when (name) {
"Version" -> schematicVersion = stream.readInt()
"DataVersion" -> {
dataVersion = stream.readInt()
val targetVersion = liveDataVersion
if (targetVersion != null && dataVersion!! < targetVersion) {
fixer = platform?.dataFixer
}
}
"Metadata" -> metadata = readCompoundTag()
"Width" -> width = stream.readShort()
"Height" -> height = stream.readShort()
"Length" -> length = stream.readShort()
"Blocks" -> {
while (stream.readByte() != 0.toByte()) {
val n = stream.readUTF()
when (n) {
"Palette" -> blocks.palette = readCompoundTag() as Map<String, Int>
"Data" -> blocks.data = readTag(7.toByte()) as ByteArray
"BlockEntities" -> blocks.blockEntities = readTagCompoundList()
}
}
}
"PaletteMax" -> stream.readInt()
"Palette" -> blocks.palette = readCompoundTag() as Map<String, Int>
"BlockEntities" -> blocks.blockEntities = readTagCompoundList()
"BlockData" -> blocks.data = readTag(7.toByte()) as ByteArray
"Offset" -> offset = readTag(11.toByte()) as IntArray
"Entities" -> entities.addAll(readTagCompoundList() as List<Any>)
"BiomePaletteMax" -> stream.readInt()
"BiomePalette" -> readCompoundTag()
"BiomeData" -> readTag(7.toByte())
"Biomes" -> {
while (stream.readByte() != 0.toByte()) {
val n = stream.readUTF()
when (n) {
"Palette" -> readCompoundTag()
"Data" -> readTag(7.toByte()) as ByteArray
}
}
}
else -> {
println(this)
error("Unknown tag $name")
}
}
}
if (wrapped) {
stream.readByte()
}
val parserContext = ParserContext()
parserContext.setRestricted(false)
parserContext.setTryLegacy(false)
parserContext.setPreferringWildcard(false)
val dv = dataVersion
val blockStates = blocks.palette!!.map {
val fixed = if (fixer != null && dv != null) {
fixer!!.fixUp(DataFixer.FixTypes.BLOCK_STATE, it.key, dv)
} else {
it.key
}
val blockstate = try {
WorldEdit.getInstance().blockFactory.parseFromInput(fixed, parserContext).toImmutableState()
} catch (e: Exception) {
BlockTypes.AIR!!.defaultState
}
it.value to blockstate
}.toMap()
val tileEntities = blocks.blockEntities!!.map {
val entity = it as? Map<String, Any?> ?: error("Invalid entity")
val pos = entity["Pos"] as? IntArray ?: error("Invalid pos")
val x = pos[0]
val y = pos[1]
val z = pos[2]
val data = mutableMapOf<String, Any?>()
data.putAll(entity)
if (entity.containsKey("Data")) {
//data.putAll(entity["Data"] as Map<String, Any?>)
}
val fixed = if (fixer != null) {
wrapper.applyDataFixer(fixer!!, dataVersion!!, (wrapNbt(data) as CompoundTag).value)
} else (wrapNbt(data) as CompoundTag).value
BlockVector3.at(x, y, z) to fixed
}.toMap()
val offset = BlockVector3.at(offset!![0], offset!![1], offset!![2])
val region = CuboidRegion(offset, offset.add(width!! - 1, height!! - 1, length!! - 1))
val clipboard = BlockArrayClipboard(region)
clipboard.setOrigin(offset)
var index = 0
var i = 0
var value: Int
var varintLength: Int
while (i < blocks.data!!.size) {
value = 0
varintLength = 0
while (true) {
value = value or ((blocks.data!![i].toInt() and 127) shl (varintLength++ * 7))
if (varintLength > 5) {
throw IOException("VarInt too big (probably corrupted data)")
}
if ((blocks.data!![i].toInt() and 128) != 128) {
i++
break
}
i++
}
// index = (y * length * width) + (z * width) + x
val y = index / (width!! * length!!)
val z = (index % (width!! * length!!)) / width!!
val x = (index % (width!! * length!!)) % width!!
val state: BlockState = blockStates[value] ?: error("Unknown block state $value")
val pt = BlockVector3.at(x, y, z)
try {
if (tileEntities.containsKey(pt)) {
clipboard.setBlock<BaseBlock?>(
clipboard.minimumPoint.add(pt),
state.toBaseBlock(CompoundTag(tileEntities[pt])
))
} else {
clipboard.setBlock<BlockState?>(clipboard.minimumPoint.add(pt), state)
}
} catch (e: WorldEditException) {
throw IOException("Failed to load a block in the schematic")
}
index++
}
return clipboard
}
private fun readCompoundTag(): Map<String, Any> {
var tagId = 0.toByte()
val map = mutableMapOf<String, Any>()
while (stream.readByte().also { tagId = it } != 0.toByte()) {
val name = stream.readUTF()
map[name] = readTag(tagId)!!
}
return map
}
private fun readTagCompoundList(): List<Any?> {
val typeId = stream.readByte()
val length = stream.readInt()
if (typeId == 0.toByte()) {
if (length != 0) {
throw IOException("Invalid TAG_List: typeId=TAG_End but length=$length")
}
return emptyList()
}
if (typeId != 10.toByte()) {
throw IOException("Invalid TAG_List element type for (Block)Entities: expected TAG_Compound(10) but got $typeId")
}
val list = ArrayList<Any?>(length)
repeat(length) { list.add(readCompoundTag()) }
return list
}
private fun readTag(tagId: Byte): Any? = when (tagId.toInt()) {
0 -> null
1 -> stream.readByte()
2 -> stream.readShort()
3 -> stream.readInt()
4 -> stream.readLong()
5 -> stream.readFloat()
6 -> stream.readDouble()
7 -> {
val length = stream.readInt()
val ba = ByteArray(length)
stream.readFully(ba)
ba
}
8 -> stream.readUTF()
9 -> {
val typeId = stream.readByte()
val length = stream.readInt()
if (typeId == 0.toByte() && length != 0) {
throw IOException("Invalid TAG_List: typeId=TAG_End but length=$length")
}
val list = mutableListOf<Any?>()
repeat(length) { list.add(readTag(typeId)) }
list
}
10 -> readCompoundTag()
11 -> {
val length = stream.readInt()
IntArray(length) { stream.readInt() }
}
12 -> {
val length = stream.readInt()
LongArray(length) { stream.readLong() }
}
else -> error("Unknown tag type $tagId")
}
private fun wrapNbt(data: Any): Tag = when (data) {
is Byte -> ByteTag(data)
is Short -> ShortTag(data)
is Int -> IntTag(data)
is Long -> LongTag(data)
is Float -> FloatTag(data)
is Double -> DoubleTag(data)
is String -> StringTag(data)
is ByteArray -> ByteArrayTag(data)
is IntArray -> IntArrayTag(data)
is LongArray -> LongArrayTag(data)
is Map<*, *> -> CompoundTag(data.map { it.key as String to wrapNbt(it.value!!) }.toMap())
is List<*> -> ListTag(data.firstOrNull()?.let { nbtClass(it) } ?: EndTag::class.java, data.map { wrapNbt(it!!) })
else -> error("Unknown tag type $data")
}
private fun nbtClass(data: Any): Class<out Tag> = when (data) {
is Byte -> ByteTag::class.java
is Short -> ShortTag::class.java
is Int -> IntTag::class.java
is Long -> LongTag::class.java
is Float -> FloatTag::class.java
is Double -> DoubleTag::class.java
is String -> StringTag::class.java
is ByteArray -> ByteArrayTag::class.java
is IntArray -> IntArrayTag::class.java
is LongArray -> LongArrayTag::class.java
is Map<*, *> -> CompoundTag::class.java
is List<*> -> ListTag::class.java
else -> error("Unknown tag type $data, ${data::class.java.simpleName}")
}
override fun toString(): String {
return "ChaosSchematicReader(platform=$platform, liveDataVersion=$liveDataVersion, wrapped=$wrapped, schematicVersion=$schematicVersion, dataVersion=$dataVersion, metadata=$metadata, width=$width, height=$height, length=$length, offset=${offset.contentToString()}, blocks=$blocks, entities=$entities, fixer=$fixer)"
}
data class Blocks(
var data: ByteArray?,
var palette: Map<String, Int>?,
var blockEntities: List<Any?>?
)
}
@@ -300,10 +300,10 @@ public class FlatteningWrapper14 implements FlatteningWrapper.IFlatteningWrapper
return head; return head;
} }
private static final Class<?> entityPose = Reflection.getClass("net.minecraft.world.entity.Pose"); protected static final Class<?> entityPose = Reflection.getClass("net.minecraft.world.entity.Pose");
private static final Object standing = entityPose.getEnumConstants()[0]; protected static final Object standing = entityPose.getEnumConstants()[0];
private static final Object swimming = entityPose.getEnumConstants()[3]; protected static final Object swimming = entityPose.getEnumConstants()[3];
private static final Object sneaking = entityPose.getEnumConstants()[5]; protected static final Object sneaking = entityPose.getEnumConstants()[5];
@Override @Override
public Object getPose(FlatteningWrapper.EntityPose pose) { public Object getPose(FlatteningWrapper.EntityPose pose) {
switch (pose) { switch (pose) {
@@ -89,7 +89,7 @@ public class WorldEditWrapper14 implements WorldEditWrapper {
switch (schemFormat) { switch (schemFormat) {
case SPONGE_V2: case SPONGE_V2:
case SPONGE_V3: case SPONGE_V3:
return new SpongeSchematicReader(new NBTInputStream(is), this).read(); return new ChaosSchematicReader(new DataInputStream(is), this).read();
case MCEDIT: case MCEDIT:
return new MCEditSchematicReader(new NBTInputStream(is)).read(); return new MCEditSchematicReader(new NBTInputStream(is)).read();
default: default:
@@ -576,8 +576,6 @@ public class WorldEditWrapper14 implements WorldEditWrapper {
values.putIfAbsent("z", new IntTag(pt.getBlockZ())); values.putIfAbsent("z", new IntTag(pt.getBlockZ()));
} }
values.putIfAbsent("id", values.get("Id")); values.putIfAbsent("id", values.get("Id"));
values.remove("Id");
values.remove("Pos");
if (fixer != null) { if (fixer != null) {
tileEntity = wrapper.applyDataFixer(fixer, dataVersion, values); tileEntity = wrapper.applyDataFixer(fixer, dataVersion, values);
} else { } else {
@@ -22,6 +22,7 @@ plugins {
} }
dependencies { dependencies {
compileOnly(project(":CommonCore", "default"))
compileOnly(project(":SpigotCore:SpigotCore_Main", "default")) compileOnly(project(":SpigotCore:SpigotCore_Main", "default"))
compileOnly(project(":SpigotCore:SpigotCore_14", "default")) compileOnly(project(":SpigotCore:SpigotCore_14", "default"))
compileOnly(project(":SpigotCore:SpigotCore_18", "default")) compileOnly(project(":SpigotCore:SpigotCore_18", "default"))
@@ -0,0 +1,68 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2025 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.core;
import com.comphenix.tinyprotocol.TinyProtocol;
import de.steamwar.Reflection;
import net.minecraft.network.protocol.game.PacketPlayOutLogin;
import net.minecraft.resources.ResourceKey;
import net.minecraft.world.level.World;
public class WorldIdentifier19 implements WorldIdentifier.IWorldIdentifier {
private static ResourceKey<World> resourceKey = null;
private static final Class<?> resourceKeyClass = Reflection.getClass("net.minecraft.resources.ResourceKey");
private static final Class<?> minecraftKeyClass = Reflection.getClass("net.minecraft.resources.MinecraftKey");
private static final Reflection.Constructor resourceKeyConstructor = Reflection.getConstructor(resourceKeyClass, minecraftKeyClass, minecraftKeyClass);
private static final Reflection.Constructor minecraftKeyConstructor = Reflection.getConstructor(minecraftKeyClass, String.class, String.class);
@Override
public void setResourceKey(String name) {
resourceKey = (ResourceKey<World>) resourceKeyConstructor.invoke(minecraftKeyConstructor.invoke("minecraft", "dimension"), minecraftKeyConstructor.invoke("steamwar", name));
}
public WorldIdentifier19() {
TinyProtocol.instance.addFilter(PacketPlayOutLogin.class, (player, o) -> {
if (resourceKey == null) return o;
PacketPlayOutLogin packet = (PacketPlayOutLogin) o;
return new PacketPlayOutLogin(
packet.b(),
packet.c(),
packet.d(),
packet.e(),
packet.f(),
packet.g(),
packet.h(),
resourceKey,
packet.j(),
packet.k(),
packet.l(),
packet.m(),
packet.n(),
packet.o(),
packet.p(),
packet.q(),
packet.r()
);
});
}
}
@@ -0,0 +1,68 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2025 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.core.authlib;
import com.mojang.authlib.Agent;
import com.mojang.authlib.GameProfile;
import com.mojang.authlib.GameProfileRepository;
import com.mojang.authlib.ProfileLookupCallback;
import de.steamwar.Reflection;
import de.steamwar.sql.SteamwarUser;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.Services;
import java.util.ArrayList;
import java.util.List;
public class SteamwarGameProfileRepository19 extends SteamwarGameProfileRepository {
private static final GameProfileRepository fallback;
private static final Reflection.Field<Services> field;
private static final Services current;
static {
Class<?> clazz = MinecraftServer.getServer().getClass();
field = Reflection.getField(clazz, Services.class, 0);
current = field.get(MinecraftServer.getServer());
fallback = current.c();
}
@Override
public void inject() {
Services newServices = new Services(current.a(), current.b(), this, current.d(), current.paperConfigurations());
field.set(MinecraftServer.getServer(), newServices);
}
@Override
public void findProfilesByNames(String[] strings, Agent agent, ProfileLookupCallback profileLookupCallback) {
List<String> unknownNames = new ArrayList<>();
for (String name:strings) {
SteamwarUser user = SteamwarUser.get(name);
if(user == null) {
unknownNames.add(name);
continue;
}
profileLookupCallback.onProfileLookupSucceeded(new GameProfile(user.getUUID(), user.getUserName()));
}
if(!unknownNames.isEmpty()) {
fallback.findProfilesByNames(unknownNames.toArray(new String[0]), agent, profileLookupCallback);
}
}
}
@@ -0,0 +1,70 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2025 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.core;
import com.comphenix.tinyprotocol.TinyProtocol;
import de.steamwar.Reflection;
import net.minecraft.network.protocol.game.PacketPlayOutLogin;
import net.minecraft.resources.ResourceKey;
import net.minecraft.world.level.World;
public class WorldIdentifier20 implements WorldIdentifier.IWorldIdentifier {
private static ResourceKey<World> resourceKey = null;
private static final Reflection.Field<Integer> playerId = Reflection.getField(PacketPlayOutLogin.class, int.class, 0);
private static final Class<?> resourceKeyClass = Reflection.getClass("net.minecraft.resources.ResourceKey");
private static final Class<?> minecraftKeyClass = Reflection.getClass("net.minecraft.resources.MinecraftKey");
private static final Reflection.Constructor resourceKeyConstructor = Reflection.getConstructor(resourceKeyClass, minecraftKeyClass, minecraftKeyClass);
private static final Reflection.Constructor minecraftKeyConstructor = Reflection.getConstructor(minecraftKeyClass, String.class, String.class);
@Override
public void setResourceKey(String name) {
resourceKey = (ResourceKey<World>) resourceKeyConstructor.invoke(minecraftKeyConstructor.invoke("minecraft", "dimension"), minecraftKeyConstructor.invoke("steamwar", name));
}
public WorldIdentifier20() {
TinyProtocol.instance.addFilter(PacketPlayOutLogin.class, (player, o) -> {
if (resourceKey == null) return o;
PacketPlayOutLogin packet = (PacketPlayOutLogin) o;
return new PacketPlayOutLogin(
playerId.get(packet),
packet.c(),
packet.d(),
packet.e(),
packet.f(),
packet.g(),
packet.h(),
resourceKey,
packet.j(),
packet.k(),
packet.l(),
packet.m(),
packet.n(),
packet.o(),
packet.p(),
packet.q(),
packet.r(),
packet.s()
);
});
}
}
@@ -37,6 +37,7 @@ dependencies {
compileOnly(libs.paperapi21) compileOnly(libs.paperapi21)
compileOnly(libs.nms21) compileOnly(libs.nms21)
compileOnly(libs.authlib2)
compileOnly(libs.datafixer) compileOnly(libs.datafixer)
compileOnly(libs.netty) compileOnly(libs.netty)
compileOnly(libs.authlib) compileOnly(libs.authlib)
@@ -43,4 +43,11 @@ public class FlatteningWrapper21 extends FlatteningWrapper14 implements Flatteni
}); });
return head; return head;
} }
protected static final Object shooting = entityPose.getEnumConstants()[16];
@Override
public Object getPose(FlatteningWrapper.EntityPose pose) {
if (pose == FlatteningWrapper.EntityPose.SHOOTING) return shooting;
return super.getPose(pose);
}
} }

Some files were not shown because too many files have changed in this diff Show More