forked from SteamWar/SteamWar
Add CornerInnerGlobal and CornerOuterGlobal
Improve the selecting code
This commit is contained in:
+1
-11
@@ -71,17 +71,7 @@ public abstract class DynamicRegion implements Region {
|
|||||||
|
|
||||||
Point minPoint = getArea().getMinPoint(false);
|
Point minPoint = getArea().getMinPoint(false);
|
||||||
Point maxPoint = getArea().getMaxPoint(false);
|
Point maxPoint = getArea().getMaxPoint(false);
|
||||||
|
PasteUtils.reset(minPoint, maxPoint);
|
||||||
EditSession editSession = WorldEdit.getInstance()
|
|
||||||
.newEditSessionBuilder()
|
|
||||||
.world(BukkitAdapter.adapt(Bukkit.getWorlds().get(0)))
|
|
||||||
.checkMemory(false)
|
|
||||||
.allowedRegionsEverywhere()
|
|
||||||
.limitUnlimited()
|
|
||||||
.changeSetNull()
|
|
||||||
.build();
|
|
||||||
editSession.setBlocks((com.sk89q.worldedit.regions.Region) new CuboidRegion(minPoint.toBlockVector3(), maxPoint.toBlockVector3()), BlockTypes.AIR.getDefaultState());
|
|
||||||
editSession.close();
|
|
||||||
|
|
||||||
DynamicRegionSystem.INSTANCE.getNeighbours(this).collect(Collectors.toList())
|
DynamicRegionSystem.INSTANCE.getNeighbours(this).collect(Collectors.toList())
|
||||||
.forEach(r -> r.update(this));
|
.forEach(r -> r.update(this));
|
||||||
|
|||||||
+17
@@ -19,10 +19,14 @@
|
|||||||
|
|
||||||
package de.steamwar.bausystem.region.dynamic;
|
package de.steamwar.bausystem.region.dynamic;
|
||||||
|
|
||||||
|
import com.sk89q.worldedit.EditSession;
|
||||||
|
import com.sk89q.worldedit.WorldEdit;
|
||||||
import com.sk89q.worldedit.bukkit.BukkitAdapter;
|
import com.sk89q.worldedit.bukkit.BukkitAdapter;
|
||||||
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
||||||
import com.sk89q.worldedit.math.BlockVector3;
|
import com.sk89q.worldedit.math.BlockVector3;
|
||||||
import com.sk89q.worldedit.math.transform.AffineTransform;
|
import com.sk89q.worldedit.math.transform.AffineTransform;
|
||||||
|
import com.sk89q.worldedit.regions.CuboidRegion;
|
||||||
|
import com.sk89q.worldedit.world.block.BlockTypes;
|
||||||
import de.steamwar.bausystem.region.Point;
|
import de.steamwar.bausystem.region.Point;
|
||||||
import de.steamwar.bausystem.utils.FlatteningWrapper;
|
import de.steamwar.bausystem.utils.FlatteningWrapper;
|
||||||
import lombok.experimental.UtilityClass;
|
import lombok.experimental.UtilityClass;
|
||||||
@@ -33,6 +37,19 @@ import java.io.File;
|
|||||||
@UtilityClass
|
@UtilityClass
|
||||||
public class PasteUtils {
|
public class PasteUtils {
|
||||||
|
|
||||||
|
public static void reset(Point minPoint, Point maxPoint) {
|
||||||
|
EditSession editSession = WorldEdit.getInstance()
|
||||||
|
.newEditSessionBuilder()
|
||||||
|
.world(BukkitAdapter.adapt(Bukkit.getWorlds().get(0)))
|
||||||
|
.checkMemory(false)
|
||||||
|
.allowedRegionsEverywhere()
|
||||||
|
.limitUnlimited()
|
||||||
|
.changeSetNull()
|
||||||
|
.build();
|
||||||
|
editSession.setBlocks((com.sk89q.worldedit.regions.Region) new CuboidRegion(minPoint.toBlockVector3(), maxPoint.toBlockVector3()), BlockTypes.AIR.getDefaultState());
|
||||||
|
editSession.close();
|
||||||
|
}
|
||||||
|
|
||||||
public static void paste(File file, Point minPoint, int rotate) {
|
public static void paste(File file, Point minPoint, int rotate) {
|
||||||
Clipboard clipboard = FlatteningWrapper.impl.loadSchematic(file);
|
Clipboard clipboard = FlatteningWrapper.impl.loadSchematic(file);
|
||||||
BlockVector3 offset = clipboard.getRegion().getMinimumPoint().subtract(clipboard.getOrigin());
|
BlockVector3 offset = clipboard.getRegion().getMinimumPoint().subtract(clipboard.getOrigin());
|
||||||
|
|||||||
+53
-72
@@ -26,6 +26,7 @@ import de.steamwar.bausystem.region.RegionType;
|
|||||||
import de.steamwar.bausystem.region.dynamic.PasteUtils;
|
import de.steamwar.bausystem.region.dynamic.PasteUtils;
|
||||||
import de.steamwar.bausystem.region.dynamic.Tile;
|
import de.steamwar.bausystem.region.dynamic.Tile;
|
||||||
import de.steamwar.bausystem.region.dynamic.VariantSelector;
|
import de.steamwar.bausystem.region.dynamic.VariantSelector;
|
||||||
|
import de.steamwar.bausystem.shared.Pair;
|
||||||
import de.steamwar.bausystem.utils.PasteBuilder;
|
import de.steamwar.bausystem.utils.PasteBuilder;
|
||||||
import lombok.NonNull;
|
import lombok.NonNull;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
@@ -36,15 +37,34 @@ import java.io.File;
|
|||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import static de.steamwar.bausystem.region.RegionType.ConnectionType.Global;
|
||||||
|
import static de.steamwar.bausystem.region.RegionType.ConnectionType.Path;
|
||||||
|
|
||||||
public class PathArea implements Region.Area {
|
public class PathArea implements Region.Area {
|
||||||
|
|
||||||
private static final File PATH_DIR = new File(Bukkit.getWorlds().get(0).getWorldFolder(), "sections/path");
|
private static final File PATH_DIR = new File(Bukkit.getWorlds().get(0).getWorldFolder(), "sections/path");
|
||||||
|
|
||||||
private static final VariantSelector CENTER_NORMAL = VariantSelector.Get(new File(PATH_DIR, "center/normal"));
|
private static final VariantSelector CENTER_NORMAL = VariantSelector.Get(new File(PATH_DIR, "center/normal"));
|
||||||
private static final VariantSelector SIDE_GLOBAL = VariantSelector.Get(new File(PATH_DIR, "side/global"));
|
private static final VariantSelector SIDE_GLOBAL = VariantSelector.Get(new File(PATH_DIR, "side/global"));
|
||||||
|
private static final VariantSelector CORNER_INNER_GLOBAL = VariantSelector.Get(new File(PATH_DIR, "cinner/global"));
|
||||||
|
private static final VariantSelector CORNER_OUTER_GLOBAL = VariantSelector.Get(new File(PATH_DIR, "couter/global"));
|
||||||
|
|
||||||
|
private static final SelectorSide SELECTOR_SIDE = new SelectorSide()
|
||||||
|
.Case(Path, CENTER_NORMAL)
|
||||||
|
.Case(Global, SIDE_GLOBAL);
|
||||||
|
|
||||||
|
private static final SelectorCorner SELECTOR_CORNER = new SelectorCorner()
|
||||||
|
.Case(Path, Global, Global, SIDE_GLOBAL, RotationCorrection.WithCorrection)
|
||||||
|
.Case(Global, Path, Path, SIDE_GLOBAL)
|
||||||
|
.Case(Global, Path, Global, SIDE_GLOBAL)
|
||||||
|
.Case(Path, Global, Path, SIDE_GLOBAL, RotationCorrection.WithCorrection)
|
||||||
|
.Case(Path, Path, Path, CENTER_NORMAL, RotationCorrection.UsingOrdinal)
|
||||||
|
.Case(Global, Global, Global, CORNER_OUTER_GLOBAL, RotationCorrection.UsingOrdinal)
|
||||||
|
.Case(Path, Path, Global, CORNER_INNER_GLOBAL, RotationCorrection.UsingOrdinal)
|
||||||
|
;
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
private enum Side {
|
protected enum Side {
|
||||||
North(0, -1, 7, 0, 0),
|
North(0, -1, 7, 0, 0),
|
||||||
South(0, 1, 7, 14, 180),
|
South(0, 1, 7, 14, 180),
|
||||||
West(-1, 0, 0, 7, 90),
|
West(-1, 0, 0, 7, 90),
|
||||||
@@ -59,21 +79,27 @@ public class PathArea implements Region.Area {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
private enum Corner {
|
protected enum Corner {
|
||||||
NorthEast(Side.North, Side.East, 14, 0, 0, -90),
|
NorthEast(Side.North, Side.East, 14, 0, 0, -90),
|
||||||
NorthWest(Side.North, Side.West, 0, 0, 0, 90),
|
NorthWest(Side.North, Side.West, 0, 0, 0, 90),
|
||||||
SouthEast(Side.South, Side.East, 14, 14, 180, 90),
|
SouthEast(Side.South, Side.East, 14, 14, 180, 90),
|
||||||
SouthWest(Side.South, Side.West, 0, 14, 180, -90),
|
SouthWest(Side.South, Side.West, 0, 14, 180, -90),
|
||||||
;
|
;
|
||||||
|
|
||||||
private final Side side1;
|
protected final Side side1;
|
||||||
private final Side side2;
|
protected final Side side2;
|
||||||
private final int pasteOffsetX;
|
private final int pasteOffsetX;
|
||||||
private final int pasteOffsetZ;
|
private final int pasteOffsetZ;
|
||||||
private final int rotate;
|
private final int rotate;
|
||||||
private final int rotateCorrection;
|
private final int rotateCorrection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected enum RotationCorrection {
|
||||||
|
Unchanged,
|
||||||
|
WithCorrection,
|
||||||
|
UsingOrdinal,
|
||||||
|
}
|
||||||
|
|
||||||
private final UUID regionIdentifier;
|
private final UUID regionIdentifier;
|
||||||
private final Tile tile;
|
private final Tile tile;
|
||||||
private final Point minPoint;
|
private final Point minPoint;
|
||||||
@@ -121,79 +147,34 @@ public class PathArea implements Region.Area {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (Side side : Side.values()) {
|
for (Side side : Side.values()) {
|
||||||
RegionType.ConnectionType connectionType = getConnectionType(side, null);
|
VariantSelector selector = SELECTOR_SIDE.Select(tile, side);
|
||||||
|
if (selector == null) continue;
|
||||||
VariantSelector selector = switch (connectionType) {
|
|
||||||
case Path -> CENTER_NORMAL;
|
|
||||||
case Water -> null;
|
|
||||||
case Closed -> null;
|
|
||||||
case Global -> SIDE_GLOBAL;
|
|
||||||
};
|
|
||||||
if (selector == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
resetFile = selector.select(regionIdentifier, side.ordinal() + side.rotate).orElse(null);
|
resetFile = selector.select(regionIdentifier, side.ordinal() + side.rotate).orElse(null);
|
||||||
if (resetFile == null) {
|
if (resetFile == null) continue;
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
PasteUtils.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()) {
|
for (Corner corner : Corner.values()) {
|
||||||
RegionType.ConnectionType connectionType1 = getConnectionType(corner.side1, null);
|
Pair<VariantSelector, RotationCorrection> pair = SELECTOR_CORNER.Select(tile, corner);
|
||||||
RegionType.ConnectionType connectionType2 = getConnectionType(corner.side2, null);
|
VariantSelector selector = pair.getKey();
|
||||||
RegionType.ConnectionType connectionType3 = getConnectionType(corner.side1, corner.side2);
|
if (selector == null) continue;
|
||||||
|
RotationCorrection rotationCorrection = pair.getValue();
|
||||||
VariantSelector selector = null;
|
|
||||||
int rotate = corner.rotate;
|
|
||||||
if (connectionType1 == RegionType.ConnectionType.Path && connectionType2 == connectionType3) {
|
|
||||||
selector = switch (connectionType2) {
|
|
||||||
case Global -> SIDE_GLOBAL;
|
|
||||||
case Closed -> null;
|
|
||||||
case Water -> null;
|
|
||||||
case Path -> null;
|
|
||||||
};
|
|
||||||
rotate += corner.rotateCorrection;
|
|
||||||
}
|
|
||||||
if (connectionType1 == RegionType.ConnectionType.Global && connectionType2 == connectionType3) {
|
|
||||||
selector = switch (connectionType2) {
|
|
||||||
case Global -> null;
|
|
||||||
case Closed -> null;
|
|
||||||
case Water -> null;
|
|
||||||
case Path -> SIDE_GLOBAL;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (connectionType2 == RegionType.ConnectionType.Path && connectionType1 == connectionType3) {
|
|
||||||
selector = switch (connectionType1) {
|
|
||||||
case Global -> SIDE_GLOBAL;
|
|
||||||
case Closed -> null;
|
|
||||||
case Water -> null;
|
|
||||||
case Path -> null;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
if (connectionType2 == RegionType.ConnectionType.Global && connectionType1 == connectionType3) {
|
|
||||||
selector = switch (connectionType1) {
|
|
||||||
case Global -> null;
|
|
||||||
case Closed -> null;
|
|
||||||
case Water -> null;
|
|
||||||
case Path -> SIDE_GLOBAL;
|
|
||||||
};
|
|
||||||
rotate += corner.rotateCorrection;
|
|
||||||
}
|
|
||||||
if (connectionType1 == RegionType.ConnectionType.Path && connectionType1 == connectionType2 && connectionType1 == connectionType3) {
|
|
||||||
selector = CENTER_NORMAL;
|
|
||||||
rotate = 90 * corner.ordinal();
|
|
||||||
}
|
|
||||||
if (selector == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
resetFile = selector.select(regionIdentifier, corner.side1.ordinal() * corner.side2.ordinal() + corner.side1.rotate * corner.side2.rotate).orElse(null);
|
resetFile = selector.select(regionIdentifier, corner.side1.ordinal() * corner.side2.ordinal() + corner.side1.rotate * corner.side2.rotate).orElse(null);
|
||||||
if (resetFile == null) {
|
if (resetFile == null) continue;
|
||||||
continue;
|
|
||||||
|
int rotate = corner.rotate;
|
||||||
|
switch (rotationCorrection) {
|
||||||
|
case Unchanged:
|
||||||
|
break;
|
||||||
|
case UsingOrdinal:
|
||||||
|
rotate = corner.ordinal() * 90;
|
||||||
|
break;
|
||||||
|
case WithCorrection:
|
||||||
|
rotate += corner.rotateCorrection;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
PasteUtils.paste(resetFile, minPoint.add(corner.pasteOffsetX, 0, corner.pasteOffsetZ), rotate);
|
PasteUtils.paste(resetFile, minPoint.add(corner.pasteOffsetX, 0, corner.pasteOffsetZ), rotate);
|
||||||
@@ -216,12 +197,12 @@ public class PathArea implements Region.Area {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private RegionType.ConnectionType getConnectionType(Side side, Side optionalSide) {
|
protected static RegionType.ConnectionType getConnectionType(Tile tile, Side side, Side optionalSide) {
|
||||||
Optional<Tile> optionalTile = this.tile.add(side.tileOffsetX, side.tileOffsetZ);
|
Optional<Tile> optionalTile = tile.add(side.tileOffsetX, side.tileOffsetZ);
|
||||||
if (optionalSide != null) {
|
if (optionalSide != null) {
|
||||||
optionalTile = optionalTile.flatMap(tile -> tile.add(optionalSide.tileOffsetX, optionalSide.tileOffsetZ));
|
optionalTile = optionalTile.flatMap(t -> t.add(optionalSide.tileOffsetX, optionalSide.tileOffsetZ));
|
||||||
}
|
}
|
||||||
return optionalTile.map(tile -> DynamicRegionSystem.INSTANCE.get(tile.getCenterLocation()).getType().getConnectionType())
|
return optionalTile.map(t -> DynamicRegionSystem.INSTANCE.get(t.getCenterLocation()).getType().getConnectionType())
|
||||||
.orElse(RegionType.ConnectionType.Global);
|
.orElse(RegionType.ConnectionType.Global);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+68
@@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
* 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.bausystem.region.dynamic.path;
|
||||||
|
|
||||||
|
import de.steamwar.bausystem.region.RegionType;
|
||||||
|
import de.steamwar.bausystem.region.dynamic.Tile;
|
||||||
|
import de.steamwar.bausystem.region.dynamic.VariantSelector;
|
||||||
|
import de.steamwar.bausystem.shared.Pair;
|
||||||
|
|
||||||
|
class SelectorCorner {
|
||||||
|
|
||||||
|
private static final int BITS;
|
||||||
|
private static final int SELECTOR_COUNT;
|
||||||
|
|
||||||
|
static {
|
||||||
|
int values = RegionType.ConnectionType.values().length;
|
||||||
|
BITS = (int) (Math.log(values) / Math.log(2));
|
||||||
|
SELECTOR_COUNT = (int) Math.pow(2, BITS * 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
private VariantSelector[] selectors = new VariantSelector[SELECTOR_COUNT];
|
||||||
|
private PathArea.RotationCorrection[] rotationCorrections = new PathArea.RotationCorrection[SELECTOR_COUNT];
|
||||||
|
|
||||||
|
private int getIndex(RegionType.ConnectionType left, RegionType.ConnectionType right, RegionType.ConnectionType diagonal) {
|
||||||
|
int index = left.ordinal();
|
||||||
|
index = index << BITS | right.ordinal();
|
||||||
|
return index << BITS | diagonal.ordinal();
|
||||||
|
}
|
||||||
|
|
||||||
|
public SelectorCorner Case(RegionType.ConnectionType left, RegionType.ConnectionType right, RegionType.ConnectionType diagonal, VariantSelector selector) {
|
||||||
|
int index = getIndex(left, right, diagonal);
|
||||||
|
selectors[index] = selector;
|
||||||
|
rotationCorrections[index] = PathArea.RotationCorrection.Unchanged;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SelectorCorner Case(RegionType.ConnectionType left, RegionType.ConnectionType right, RegionType.ConnectionType diagonal, VariantSelector selector, PathArea.RotationCorrection rotationCorrection) {
|
||||||
|
int index = getIndex(left, right, diagonal);
|
||||||
|
selectors[index] = selector;
|
||||||
|
rotationCorrections[index] = rotationCorrection;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Pair<VariantSelector, PathArea.RotationCorrection> Select(Tile tile, PathArea.Corner corner) {
|
||||||
|
RegionType.ConnectionType left = PathArea.getConnectionType(tile, corner.side1, null);
|
||||||
|
RegionType.ConnectionType right = PathArea.getConnectionType(tile, corner.side2, null);
|
||||||
|
RegionType.ConnectionType diagonal = PathArea.getConnectionType(tile, corner.side1, corner.side2);
|
||||||
|
int index = getIndex(left, right, diagonal);
|
||||||
|
return new Pair<>(selectors[index], rotationCorrections[index]);
|
||||||
|
}
|
||||||
|
}
|
||||||
+39
@@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* 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.bausystem.region.dynamic.path;
|
||||||
|
|
||||||
|
import de.steamwar.bausystem.region.RegionType;
|
||||||
|
import de.steamwar.bausystem.region.dynamic.Tile;
|
||||||
|
import de.steamwar.bausystem.region.dynamic.VariantSelector;
|
||||||
|
|
||||||
|
class SelectorSide {
|
||||||
|
|
||||||
|
private VariantSelector[] selectors = new VariantSelector[RegionType.ConnectionType.values().length];
|
||||||
|
|
||||||
|
protected SelectorSide Case(RegionType.ConnectionType type, VariantSelector selector) {
|
||||||
|
selectors[type.ordinal()] = selector;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public VariantSelector Select(Tile tile, PathArea.Side side) {
|
||||||
|
RegionType.ConnectionType type = PathArea.getConnectionType(tile, side, null);
|
||||||
|
return selectors[type.ordinal()];
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user