Add new //placement types

- //placement min - selection min X/Y/Z
- //placement max - selection max X/Y/Z
- //placement world - absolute world location
- //placement here - This puts the placement position at the current player position.
This commit is contained in:
TomyLobo 2023-03-14 03:13:00 +01:00 committed by Maddy Miller
parent d28fadb842
commit 4fc62d98cb
7 changed files with 123 additions and 0 deletions

View File

@ -582,6 +582,10 @@ public Placement getPlacement() {
* @param placement the placement.
*/
public void setPlacement(Placement placement) {
if (placement.getPlacementType() == PlacementType.HERE) {
throw new IllegalStateException("PlacementType.HERE cannot be used. Use PLAYER or WORLD instead.");
}
this.placement = placement;
}

View File

@ -32,6 +32,7 @@
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extension.platform.Capability;
import com.sk89q.worldedit.extension.platform.Locatable;
import com.sk89q.worldedit.function.RegionFunction;
import com.sk89q.worldedit.function.RegionMaskingFilter;
import com.sk89q.worldedit.function.block.ApplySideEffect;
@ -460,6 +461,15 @@ public void placement(Actor actor, LocalSession session,
@Offset
BlockVector3 offset) {
offset = offset.multiply(multiplier);
if (placementType == PlacementType.HERE) {
if (!placementType.canBeUsedBy(actor)) {
actor.printError(TranslatableComponent.of("worldedit.toggleplace.not-locatable"));
return;
}
// Replace "//placement here" by "//placement <current player coordinates>"
placementType = PlacementType.WORLD;
offset = offset.add(((Locatable) actor).getBlockLocation().toVector().toBlockPoint());
}
placementImpl(actor, session, new Placement(placementType, offset));
}

View File

@ -28,6 +28,13 @@
import static com.google.common.base.Preconditions.checkNotNull;
public enum PlacementType {
WORLD("worldedit.toggleplace.world", "worldedit.toggleplace.world-offset") {
@Override
public BlockVector3 getPlacementPosition(RegionSelector selector, Actor actor) throws IncompleteRegionException {
return BlockVector3.ZERO;
}
},
PLAYER("worldedit.toggleplace.player", "worldedit.toggleplace.player-offset") {
@Override
public BlockVector3 getPlacementPosition(RegionSelector selector, Actor actor) throws IncompleteRegionException {
@ -44,11 +51,47 @@ public boolean canBeUsedBy(Actor actor) {
}
},
HERE(null, null) {
@Override
public BlockVector3 getPlacementPosition(RegionSelector selector, Actor actor) throws IncompleteRegionException {
throw new IllegalStateException("PlacementType.HERE cannot be used. Use PLAYER or WORLD instead.");
}
@Override
public boolean canBeUsedBy(Actor actor) {
return PLAYER.canBeUsedBy(actor);
}
@Override
public String getTranslationKey() {
throw new IllegalStateException("PlacementType.HERE cannot be used. Use PLAYER or WORLD instead.");
}
@Override
public String getTranslationKeyWithOffset() {
throw new IllegalStateException("PlacementType.HERE cannot be used. Use PLAYER or WORLD instead.");
}
},
POS1("worldedit.toggleplace.pos1", "worldedit.toggleplace.pos1-offset") {
@Override
public BlockVector3 getPlacementPosition(RegionSelector selector, Actor actor) throws IncompleteRegionException {
return selector.getPrimaryPosition();
}
},
MIN("worldedit.toggleplace.min", "worldedit.toggleplace.min-offset") {
@Override
public BlockVector3 getPlacementPosition(RegionSelector selector, Actor actor) throws IncompleteRegionException {
return selector.getRegion().getMinimumPoint();
}
},
MAX("worldedit.toggleplace.max", "worldedit.toggleplace.max-offset") {
@Override
public BlockVector3 getPlacementPosition(RegionSelector selector, Actor actor) throws IncompleteRegionException {
return selector.getRegion().getMaximumPoint();
}
};
private final String translationKey;

View File

@ -72,6 +72,12 @@
"worldedit.toggleplace.pos1-offset": "Now placing at an offset of ({0}, {1}, {2}) from pos #1.",
"worldedit.toggleplace.player": "Now placing at the block you stand in.",
"worldedit.toggleplace.player-offset": "Now placing at an offset of ({0}, {1}, {2}) from the block you stand in.",
"worldedit.toggleplace.min": "Now placing at the minimum of the current selection.",
"worldedit.toggleplace.min-offset": "Now placing at an offset of ({0}, {1}, {2}) from the minimum of the current selection.",
"worldedit.toggleplace.max": "Now placing at the maximum of the current selection.",
"worldedit.toggleplace.max-offset": "Now placing at an offset of ({0}, {1}, {2}) from the maximum of the current selection.",
"worldedit.toggleplace.world": "Now placing at world origin.",
"worldedit.toggleplace.world-offset": "Now placing at ({0}, {1}, {2}).",
"worldedit.toggleplace.not-locatable": "Cannot toggle placing in this context.",
"worldedit.searchitem.too-short": "Enter a longer search string (len > 2).",
"worldedit.searchitem.either-b-or-i": "You cannot use both the 'b' and 'i' flags simultaneously.",

View File

@ -131,6 +131,11 @@ void testPlacementPlayer() throws Exception {
@ParameterizedTest
@EnumSource(PlacementType.class)
void testPlacementGeneric(PlacementType placementType) throws Exception {
if (placementType == PlacementType.HERE) {
// HERE is a special case that's handled in command code and doesn't have an actual implementation
return;
}
final ActorSelectorLimits limits = ActorSelectorLimits.forActor(player);
final RegionSelector regionSelector = session.getRegionSelector(world);

View File

@ -50,6 +50,11 @@ void setUp() {
@ParameterizedTest
@EnumSource(PlacementType.class)
void testPlacementGeneric(PlacementType placementType) throws Exception {
if (placementType == PlacementType.HERE) {
// HERE is a special case that's handled in command code and doesn't have an actual implementation
return;
}
final ActorSelectorLimits limits = mock(ActorSelectorLimits.class, Answers.RETURNS_SMART_NULLS);
final RegionSelector regionSelector = new CuboidRegionSelector();

View File

@ -22,6 +22,7 @@
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.regions.RegionSelector;
import com.sk89q.worldedit.util.Location;
import com.sk89q.worldedit.world.World;
@ -38,6 +39,17 @@
import static org.mockito.Mockito.verifyNoMoreInteractions;
class PlacementTypeTest {
@Test
void testPlacementWORLD() throws Exception {
final RegionSelector regionSelector = mock(RegionSelector.class, Answers.RETURNS_SMART_NULLS);
final Player player = mock(Player.class, Answers.RETURNS_SMART_NULLS);
assertEquals(BlockVector3.ZERO, PlacementType.WORLD.getPlacementPosition(regionSelector, player));
verifyNoInteractions(regionSelector);
verifyNoInteractions(player);
}
@Test
void testPlacementPLAYER() throws Exception {
final RegionSelector regionSelector = mock(RegionSelector.class, Answers.RETURNS_SMART_NULLS);
@ -70,4 +82,42 @@ void testPlacementPOS1() throws Exception {
verifyNoMoreInteractions(regionSelector);
verifyNoInteractions(actor);
}
@Test
void testPlacementMIN() throws Exception {
final Region region = mock(Region.class, Answers.RETURNS_SMART_NULLS);
final RegionSelector regionSelector = mock(RegionSelector.class, Answers.RETURNS_SMART_NULLS);
final Actor actor = mock(Actor.class, Answers.RETURNS_SMART_NULLS);
final BlockVector3 min = BlockVector3.at(1337, 42, 23);
doReturn(min).when(region).getMinimumPoint();
doReturn(region).when(regionSelector).getRegion();
assertEquals(min, PlacementType.MIN.getPlacementPosition(regionSelector, actor));
verify(region, times(1)).getMinimumPoint();
verifyNoMoreInteractions(region);
verify(regionSelector, times(1)).getRegion();
verifyNoMoreInteractions(regionSelector);
verifyNoInteractions(actor);
}
@Test
void testPlacementMAX() throws Exception {
final Region region = mock(Region.class, Answers.RETURNS_SMART_NULLS);
final RegionSelector regionSelector = mock(RegionSelector.class, Answers.RETURNS_SMART_NULLS);
final Actor actor = mock(Actor.class, Answers.RETURNS_SMART_NULLS);
final BlockVector3 max = BlockVector3.at(1337, 42, 23);
doReturn(max).when(region).getMaximumPoint();
doReturn(region).when(regionSelector).getRegion();
assertEquals(max, PlacementType.MAX.getPlacementPosition(regionSelector, actor));
verify(region, times(1)).getMaximumPoint();
verifyNoMoreInteractions(region);
verify(regionSelector, times(1)).getRegion();
verifyNoMoreInteractions(regionSelector);
verifyNoInteractions(actor);
}
}