From 09be2b434d904c2195d9674c7c8ab3ad8d5757a8 Mon Sep 17 00:00:00 2001 From: YoyoNow Date: Wed, 4 Mar 2026 11:50:42 +0100 Subject: [PATCH] Add DryRegion and WetRegion Add SpecialArea Add SpecialRegionData Add RegionData.connectedRegions Add PasteUtils --- .../steamwar/bausystem/region/RegionData.java | 34 +++++-- .../bausystem/region/dynamic/PasteUtils.java | 42 ++++++++ .../region/dynamic/path/PathArea.java | 19 +--- .../region/dynamic/special/SpecialArea.java | 84 ++++++++++++++++ .../dynamic/special/SpecialRegionData.java | 63 ++++++++++++ .../region/dynamic/special/dry/DryRegion.java | 99 +++++++++++++++++++ .../region/dynamic/special/wet/WetRegion.java | 99 +++++++++++++++++++ 7 files changed, 417 insertions(+), 23 deletions(-) create mode 100644 BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/PasteUtils.java create mode 100644 BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/special/SpecialArea.java create mode 100644 BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/special/SpecialRegionData.java create mode 100644 BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/special/dry/DryRegion.java create mode 100644 BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/special/wet/WetRegion.java diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/region/RegionData.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/region/RegionData.java index 285d11b5..7b9cada5 100644 --- a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/region/RegionData.java +++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/region/RegionData.java @@ -23,11 +23,9 @@ import de.steamwar.bausystem.region.flags.Flag; import de.steamwar.sql.SchematicNode; import lombok.NonNull; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.function.Function; +import java.util.stream.Stream; public abstract class RegionData { @@ -52,6 +50,13 @@ public abstract class RegionData { protected void initialize() { } + /** + * All connected Regions are required to have the same type as their RegionData. + */ + protected Stream connectedRegions() { + return Stream.empty(); + } + @NonNull public abstract & Flag.Value> RegionFlagPolicy has(@NonNull Flag flag); @@ -60,10 +65,15 @@ public abstract class RegionData { */ public final & Flag.Value> boolean set(@NonNull Flag flag, @NonNull T value) { if (has(flag).isWritable()) { - if (flagMap.put(flag, value) != value) { - store.saveRegion(); - return true; - } + boolean needsSave = flagMap.put(flag, value) != value; + if (needsSave) store.saveRegion(); + + connectedRegions().forEach(region -> { + if (region.getRegionData().flagMap.put(flag, value) != value) { + region.saveRegion(); + } + }); + return needsSave; } return false; } @@ -74,13 +84,21 @@ public abstract class RegionData { } public final void clear() { + Set remove = new HashSet<>(); for (Flag flag : Flag.getFlags()) { if (has(flag).isWritable()) { flagMap.remove(flag); + remove.add(flag); } } properties.forEach(property -> property.set(null)); store.saveRegion(); + + connectedRegions().forEach(region -> { + region.getRegionData().flagMap.keySet().removeAll(remove); + region.getRegionData().properties.forEach(property -> property.set(null)); + region.saveRegion(); + }); } public final Map, Flag.Value> getBackedMap() { diff --git a/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/PasteUtils.java b/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/PasteUtils.java new file mode 100644 index 00000000..02b5be6c --- /dev/null +++ b/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/PasteUtils.java @@ -0,0 +1,42 @@ +/* + * 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 . + */ + +package de.steamwar.bausystem.region.dynamic; + +import com.sk89q.worldedit.bukkit.BukkitAdapter; +import com.sk89q.worldedit.extent.clipboard.Clipboard; +import com.sk89q.worldedit.math.BlockVector3; +import com.sk89q.worldedit.math.transform.AffineTransform; +import de.steamwar.bausystem.region.Point; +import de.steamwar.bausystem.utils.FlatteningWrapper; +import lombok.experimental.UtilityClass; +import org.bukkit.Bukkit; + +import java.io.File; + +@UtilityClass +public class PasteUtils { + + public static void paste(File file, Point minPoint, int rotate) { + Clipboard clipboard = FlatteningWrapper.impl.loadSchematic(file); + BlockVector3 offset = clipboard.getRegion().getMinimumPoint().subtract(clipboard.getOrigin()); + BlockVector3 to = minPoint.toBlockVector3().subtract(offset); + clipboard.paste(BukkitAdapter.adapt(Bukkit.getWorlds().get(0)), to, false, true, new AffineTransform().rotateY(rotate)); + } +} diff --git a/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/path/PathArea.java b/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/path/PathArea.java index 9d83cd78..33581e20 100644 --- a/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/path/PathArea.java +++ b/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/path/PathArea.java @@ -19,17 +19,13 @@ package de.steamwar.bausystem.region.dynamic.path; -import com.sk89q.worldedit.bukkit.BukkitAdapter; -import com.sk89q.worldedit.extent.clipboard.Clipboard; -import com.sk89q.worldedit.math.BlockVector3; -import com.sk89q.worldedit.math.transform.AffineTransform; import de.steamwar.bausystem.region.DynamicRegionSystem; import de.steamwar.bausystem.region.Point; import de.steamwar.bausystem.region.Region; import de.steamwar.bausystem.region.RegionType; +import de.steamwar.bausystem.region.dynamic.PasteUtils; import de.steamwar.bausystem.region.dynamic.Tile; import de.steamwar.bausystem.region.dynamic.VariantSelector; -import de.steamwar.bausystem.utils.FlatteningWrapper; import de.steamwar.bausystem.utils.PasteBuilder; import lombok.NonNull; import lombok.RequiredArgsConstructor; @@ -120,7 +116,7 @@ public class PathArea implements Region.Area { File resetFile = CENTER_NORMAL.select(regionIdentifier, 0).orElse(null); if (resetFile != null) { - paste(resetFile, minPoint.add(7, 0, 7), 0); + PasteUtils.paste(resetFile, minPoint.add(7, 0, 7), 0); } for (Side side : Side.values()) { @@ -141,7 +137,7 @@ public class PathArea implements Region.Area { continue; } - paste(resetFile, minPoint.add(side.pasteOffsetX, 0, side.pasteOffsetZ), side.rotate); + PasteUtils.paste(resetFile, minPoint.add(side.pasteOffsetX, 0, side.pasteOffsetZ), side.rotate); } for (Corner corner : Corner.values()) { @@ -199,7 +195,7 @@ public class PathArea implements Region.Area { continue; } - paste(resetFile, minPoint.add(corner.pasteOffsetX, 0, corner.pasteOffsetZ), rotate); + PasteUtils.paste(resetFile, minPoint.add(corner.pasteOffsetX, 0, corner.pasteOffsetZ), rotate); } } @@ -228,11 +224,4 @@ public class PathArea implements Region.Area { } return DynamicRegionSystem.INSTANCE.get(tile).getType().getConnectionType(); } - - private void paste(File file, Point minPoint, int rotate) { - Clipboard clipboard = FlatteningWrapper.impl.loadSchematic(file); - BlockVector3 offset = clipboard.getRegion().getMinimumPoint().subtract(clipboard.getOrigin()); - BlockVector3 to = minPoint.toBlockVector3().subtract(offset); - clipboard.paste(BukkitAdapter.adapt(Bukkit.getWorlds().get(0)), to, false, true, new AffineTransform().rotateY(rotate)); - } } diff --git a/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/special/SpecialArea.java b/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/special/SpecialArea.java new file mode 100644 index 00000000..8f3c2762 --- /dev/null +++ b/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/special/SpecialArea.java @@ -0,0 +1,84 @@ +/* + * 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 . + */ + +package de.steamwar.bausystem.region.dynamic.special; + +import de.steamwar.bausystem.region.Point; +import de.steamwar.bausystem.region.Region; +import de.steamwar.bausystem.region.dynamic.DynamicRegion; +import de.steamwar.bausystem.region.dynamic.PasteUtils; +import de.steamwar.bausystem.region.dynamic.Tile; +import de.steamwar.bausystem.region.dynamic.VariantSelector; +import de.steamwar.bausystem.utils.PasteBuilder; +import lombok.NonNull; +import org.bukkit.Bukkit; +import org.jetbrains.annotations.Nullable; + +import java.io.File; +import java.util.UUID; + +public class SpecialArea implements Region.Area { + + public static final File SPECIAL_PATH_DIR = new File(Bukkit.getWorlds().get(0).getWorldFolder(), "sections/special"); + + private final UUID regionIdentifier; + private final Tile tile; + private final Point minPoint; + private final Point maxPoint; + private final Point copyPoint; + private final VariantSelector resetFiles; + + public SpecialArea(Tile tile, DynamicRegion region, VariantSelector resetFiles) { + this.regionIdentifier = region.getID(); + this.tile = tile; + + minPoint = Point.fromLocation(tile.getMinLocation()).setY(WORLD_MIN_Y); + maxPoint = Point.fromLocation(tile.getMaxLocation()).setY(WORLD_MAX_Y); + copyPoint = Point.fromLocation(tile.getCenterLocation()); + + this.resetFiles = resetFiles; + } + + @Override + public @NonNull Point getMinPoint(boolean extension) { + return minPoint; + } + + @Override + public @NonNull Point getMaxPoint(boolean extension) { + return maxPoint; + } + + @Override + public @NonNull Point getCopyPoint() { + return copyPoint; + } + + @Override + public @Nullable File getResetFile() { + return null; + } + + @Override + public void reset(PasteBuilder pasteBuilder, boolean extension) { + File resetFile = resetFiles.select(regionIdentifier, 0).orElse(null); + if (resetFile == null) return; + PasteUtils.paste(resetFile, minPoint, 0); + } +} diff --git a/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/special/SpecialRegionData.java b/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/special/SpecialRegionData.java new file mode 100644 index 00000000..b3c15ee0 --- /dev/null +++ b/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/special/SpecialRegionData.java @@ -0,0 +1,63 @@ +/* + * 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 . + */ + +package de.steamwar.bausystem.region.dynamic.special; + +import de.steamwar.bausystem.region.DynamicRegionSystem; +import de.steamwar.bausystem.region.Region; +import de.steamwar.bausystem.region.RegionData; +import de.steamwar.bausystem.region.RegionFlagPolicy; +import de.steamwar.bausystem.region.dynamic.DynamicRegion; +import de.steamwar.bausystem.region.flags.Flag; +import de.steamwar.bausystem.region.flags.TNTMode; +import de.steamwar.core.Core; +import lombok.NonNull; + +import java.util.stream.Stream; + +public class SpecialRegionData extends RegionData { + + private final DynamicRegion region; + + public SpecialRegionData(DynamicRegion region) { + super(region); + this.region = region; + } + + @Override + protected void initialize() { + flagMap.put(Flag.TNT, TNTMode.DENY); + } + + @Override + protected Stream connectedRegions() { + return DynamicRegionSystem.INSTANCE.getConnectedRegions(region); + } + + @Override + public @NonNull & Flag.Value> RegionFlagPolicy has(@NonNull Flag flag) { + if (flag.oneOf(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; + } + return RegionFlagPolicy.NOT_APPLICABLE; + } +} diff --git a/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/special/dry/DryRegion.java b/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/special/dry/DryRegion.java new file mode 100644 index 00000000..beb46d81 --- /dev/null +++ b/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/special/dry/DryRegion.java @@ -0,0 +1,99 @@ +/* + * 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 . + */ + +package de.steamwar.bausystem.region.dynamic.special.dry; + +import de.steamwar.bausystem.region.RegionBackups; +import de.steamwar.bausystem.region.RegionData; +import de.steamwar.bausystem.region.RegionHistory; +import de.steamwar.bausystem.region.RegionType; +import de.steamwar.bausystem.region.dynamic.*; +import de.steamwar.bausystem.region.dynamic.special.SpecialArea; +import de.steamwar.bausystem.region.dynamic.special.SpecialRegionData; +import de.steamwar.sql.GameModeConfig; +import lombok.NonNull; +import org.bukkit.Material; + +import java.io.File; +import java.util.UUID; + +import static de.steamwar.bausystem.region.dynamic.special.SpecialArea.SPECIAL_PATH_DIR; + +@RegionConstructorData( + identifier = "special_dry", + widthX = Tile.tileSize, + widthZ = Tile.tileSize +) +public class DryRegion extends DynamicRegion { + + private static final VariantSelector DRY = VariantSelector.Get(new File(SPECIAL_PATH_DIR, "dry")); + + private final SpecialArea area; + + public DryRegion(UUID id, int minX, int minZ) { + super(id, minX, minZ); + area = new SpecialArea(Tile.fromXZ(minX, minZ).valid().orElseThrow(), this, DRY); + regionData = new SpecialRegionData(this); + } + + @Override + public @NonNull RegionType getType() { + return RegionType.DRY_SPECIAL; + } + + @Override + public @NonNull Area getArea() { + return area; + } + + @Override + public @NonNull Area getBuildArea() { + return Area.EMPTY; + } + + @Override + public @NonNull Area getTestblockArea() { + return Area.EMPTY; + } + + @Override + public @NonNull GameModeConfig getGameModeConfig() { + return GameModeConfig.getDefaults(); + } + + @Override + public @NonNull RegionHistory getHistory() { + return RegionHistory.EMPTY; + } + + @Override + public @NonNull RegionBackups getBackups() { + return RegionBackups.EMPTY; + } + + @Override + public void saveRegion() { + DynamicRegionRepository.saveRegion(this); + } + + @Override + public void loadRegion(RegionData regionData) { + DynamicRegionRepository.loadRegionData(this, regionData); + } +} diff --git a/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/special/wet/WetRegion.java b/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/special/wet/WetRegion.java new file mode 100644 index 00000000..cd6963e8 --- /dev/null +++ b/BauSystem/BauSystem_RegionDynamic/src/de/steamwar/bausystem/region/dynamic/special/wet/WetRegion.java @@ -0,0 +1,99 @@ +/* + * 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 . + */ + +package de.steamwar.bausystem.region.dynamic.special.wet; + +import de.steamwar.bausystem.region.RegionBackups; +import de.steamwar.bausystem.region.RegionData; +import de.steamwar.bausystem.region.RegionHistory; +import de.steamwar.bausystem.region.RegionType; +import de.steamwar.bausystem.region.dynamic.*; +import de.steamwar.bausystem.region.dynamic.special.SpecialArea; +import de.steamwar.bausystem.region.dynamic.special.SpecialRegionData; +import de.steamwar.sql.GameModeConfig; +import lombok.NonNull; +import org.bukkit.Material; + +import java.io.File; +import java.util.UUID; + +import static de.steamwar.bausystem.region.dynamic.special.SpecialArea.SPECIAL_PATH_DIR; + +@RegionConstructorData( + identifier = "special_wet", + widthX = Tile.tileSize, + widthZ = Tile.tileSize +) +public class WetRegion extends DynamicRegion { + + private static final VariantSelector WET = VariantSelector.Get(new File(SPECIAL_PATH_DIR, "wet")); + + private final SpecialArea area; + + public WetRegion(UUID id, int minX, int minZ) { + super(id, minX, minZ); + area = new SpecialArea(Tile.fromXZ(minX, minZ).valid().orElseThrow(), this, WET); + regionData = new SpecialRegionData(this); + } + + @Override + public @NonNull RegionType getType() { + return RegionType.WET_SPECIAL; + } + + @Override + public @NonNull Area getArea() { + return area; + } + + @Override + public @NonNull Area getBuildArea() { + return Area.EMPTY; + } + + @Override + public @NonNull Area getTestblockArea() { + return Area.EMPTY; + } + + @Override + public @NonNull GameModeConfig getGameModeConfig() { + return GameModeConfig.getDefaults(); + } + + @Override + public @NonNull RegionHistory getHistory() { + return RegionHistory.EMPTY; + } + + @Override + public @NonNull RegionBackups getBackups() { + return RegionBackups.EMPTY; + } + + @Override + public void saveRegion() { + DynamicRegionRepository.saveRegion(this); + } + + @Override + public void loadRegion(RegionData regionData) { + DynamicRegionRepository.loadRegionData(this, regionData); + } +}