Skip to content

Commit

Permalink
add schematic showfake option, fixes #1992
Browse files Browse the repository at this point in the history
  • Loading branch information
mcmonkey4eva committed Oct 14, 2019
1 parent 2974f1d commit 20e8781
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 21 deletions.
Expand Up @@ -697,9 +697,9 @@ public void adjust(Mechanism mechanism) {
new BukkitRunnable() {
@Override
public void run() {
for (Map<LocationTag, FakeBlock> blocks : FakeBlock.getBlocks().values()) {
for (Map.Entry<LocationTag, FakeBlock> locBlock : blocks.entrySet()) {
LocationTag location = locBlock.getKey();
for (Map<Location, FakeBlock> blocks : FakeBlock.getBlocks().values()) {
for (Map.Entry<Location, FakeBlock> locBlock : blocks.entrySet()) {
Location location = locBlock.getKey();
if (Math.floor(location.getX() / 16) == chunkX
&& Math.floor(location.getZ() / 16) == chunkZ) {
locBlock.getValue().updateBlock();
Expand Down
Expand Up @@ -178,7 +178,7 @@ public void registerCommands() {
}
registerCoreMember(ResetCommand.class, "RESET", "reset (<player>|...) [cooldown/saves/global_cooldown] (<script>)", 1);
registerCoreMember(RotateCommand.class, "ROTATE", "rotate (cancel) (<entity>|...) (yaw:<#.#>) (pitch:<#.#>) (infinite/duration:<duration>) (frequency:<duration>)", 0);
registerCoreMember(SchematicCommand.class, "SCHEMATIC", "schematic [create/load/unload/rotate/paste/save/flip_x/flip_y/flip_z] [name:<name>] (filename:<name>) (angle:<#>) (<location>) (<cuboid>) (delayed) (noair) (mask:<material>|...)", 2);
registerCoreMember(SchematicCommand.class, "SCHEMATIC", "schematic [create/load/unload/rotate/paste/save/flip_x/flip_y/flip_z] [name:<name>] (filename:<name>) (angle:<#>) (<location>) (<cuboid>) (delayed) (noair) (mask:<material>|...) (fake_to:<player>|...)", 2);
registerCoreMember(ScoreboardCommand.class, "SCOREBOARD", "scoreboard ({add}/remove) (viewers:<player>|...) (lines:<player>/<text>|...) (id:<value>/{main}) (objective:<value>) (criteria:<criteria>/{dummy}) (score:<#>) (displayslot:<value>/{sidebar}/none)", 1);
registerCoreMember(ScribeCommand.class, "SCRIBE", "scribe [<script>] (<item>/give/equip/{drop <location>})", 1);
registerCoreMember(ShootCommand.class, "SHOOT", "shoot [<entity>|...] (origin:<entity>/<location>) (destination:<location>) (height:<#.#>) (speed:<#.#>) (script:<name>) (def:<element>|...) (shooter:<entity>) (spread:<#.#>) (lead:<location>) (no_rotate)", 1);
Expand Down
Expand Up @@ -2,6 +2,7 @@

import com.denizenscript.denizen.nms.NMSHandler;
import com.denizenscript.denizen.nms.NMSVersion;
import com.denizenscript.denizen.objects.PlayerTag;
import com.denizenscript.denizen.utilities.DenizenAPI;
import com.denizenscript.denizen.utilities.Utilities;
import com.denizenscript.denizen.utilities.blocks.BlockSet;
Expand All @@ -15,6 +16,7 @@
import com.denizenscript.denizen.objects.MaterialTag;
import com.denizenscript.denizencore.exceptions.InvalidArgumentsException;
import com.denizenscript.denizencore.objects.*;
import com.denizenscript.denizencore.objects.core.DurationTag;
import com.denizenscript.denizencore.objects.core.ElementTag;
import com.denizenscript.denizencore.objects.core.ListTag;
import com.denizenscript.denizencore.scripts.ScriptEntry;
Expand Down Expand Up @@ -44,7 +46,7 @@ public class SchematicCommand extends AbstractCommand implements Holdable, Liste

// <--[command]
// @Name Schematic
// @Syntax schematic [create/load/unload/rotate/paste/save/flip_x/flip_y/flip_z] [name:<name>] (filename:<name>) (angle:<#>) (<location>) (<cuboid>) (delayed) (noair) (mask:<material>|...)
// @Syntax schematic [create/load/unload/rotate/paste/save/flip_x/flip_y/flip_z] [name:<name>] (filename:<name>) (angle:<#>) (<location>) (<cuboid>) (delayed) (noair) (mask:<material>|...) (fake_to:<player>|... fake_duration:<duration>)
// @Group World
// @Required 2
// @Short Creates, loads, pastes, and saves schematics (Sets of blocks).
Expand All @@ -56,17 +58,20 @@ public class SchematicCommand extends AbstractCommand implements Holdable, Liste
// Denizen offers a number of tools to manipulate and work with schematics.
// Schematics can be rotated, flipped, pasted with no air, or pasted with a delay.
//
// The "noair" option skips air blocks in the pasted schematics- this means those air blocks will not replace any blocks in the target location.
//
// The "mask" option can be specified to limit what block types the schematic will be pasted over.
//
// The "delayed" option makes the command non-instant. This is recommended for large schematics.
// For 'save', 'load', and 'rotate', this processes async to prevent server lockup.
// For 'paste' and 'create', this delays how many blocks can be processed at once, spread over many ticks.
//
// The "load" option by default will load '.schem' files. If no '.schem' file is available, will attempt to load a legacy '.schematic' file instead.
// The "save" option will save to '.schem' files, unless you are on MC 1.12.2 (in which case it will save legacy '.schematic' files).
//
// The "noair" option skips air blocks in the pasted schematics- this means those air blocks will not replace any blocks in the target location.
//
// The "mask" option can be specified to limit what block types the schematic will be pasted over.
//
// The "fake_to" option can be specified to cause the schematic paste to be a fake (packet-based, see <@link command showfake>)
// block set, instead of actually modifying the blocks in the world. This takes an optional duration for how long the fake blocks should remain.
//
// @Tags
// <schematic[<name>].height>
// <schematic[<name>].length>
Expand Down Expand Up @@ -161,6 +166,16 @@ else if (!scriptEntry.hasObject("mask")
&& arg.matchesArgumentList(MaterialTag.class)) {
scriptEntry.addObject("mask", arg.asType(ListTag.class).filter(MaterialTag.class, scriptEntry));
}
else if (!scriptEntry.hasObject("fake_to")
&& arg.matchesPrefix("fake_to")
&& arg.matchesArgumentList(PlayerTag.class)) {
scriptEntry.addObject("fake_to", arg.asType(ListTag.class).filter(PlayerTag.class, scriptEntry));
}
else if (!scriptEntry.hasObject("fake_duration")
&& arg.matchesPrefix("fake_duration")
&& arg.matchesArgumentType(DurationTag.class)) {
scriptEntry.addObject("fake_duration", arg.asType(DurationTag.class));
}
else if (!scriptEntry.hasObject("location")
&& arg.matchesArgumentType(LocationTag.class)) {
scriptEntry.addObject("location", arg.asType(LocationTag.class));
Expand Down Expand Up @@ -195,6 +210,8 @@ public void execute(final ScriptEntry scriptEntry) {
ElementTag delayed = scriptEntry.getElement("delayed");
LocationTag location = scriptEntry.getObjectTag("location");
List<MaterialTag> mask = (List<MaterialTag>) scriptEntry.getObject("mask");
List<PlayerTag> fakeTo = (List<PlayerTag>) scriptEntry.getObject("fake_to");
DurationTag fakeDuration = scriptEntry.getObjectTag("fake_duration");
CuboidTag cuboid = scriptEntry.getObjectTag("cuboid");

if (scriptEntry.dbCallShouldDebug()) {
Expand All @@ -207,7 +224,9 @@ public void execute(final ScriptEntry scriptEntry) {
+ (angle != null ? angle.debug() : "")
+ (noair != null ? noair.debug() : "")
+ (delayed != null ? delayed.debug() : "")
+ (mask != null ? ArgumentHelper.debugList("mask", mask) : ""));
+ (mask != null ? ArgumentHelper.debugList("mask", mask) : "")
+ (fakeTo != null ? ArgumentHelper.debugList("fake_to", fakeTo) : "")
+ (fakeDuration != null ? fakeDuration.debug() : ""));

}

Expand Down Expand Up @@ -383,6 +402,11 @@ public void execute(final ScriptEntry scriptEntry) {
BlockSet.InputParams input = new BlockSet.InputParams();
input.centerLocation = location;
input.noAir = noair != null && noair.asBoolean();
input.fakeTo = fakeTo;
if (fakeDuration == null) {
fakeDuration = new DurationTag(0);
}
input.fakeDuration = fakeDuration;
if (mask != null) {
input.mask = new HashSet<>();
for (MaterialTag material : mask) {
Expand Down
@@ -1,10 +1,13 @@
package com.denizenscript.denizen.utilities.blocks;

import com.denizenscript.denizen.nms.interfaces.BlockData;
import com.denizenscript.denizen.objects.PlayerTag;
import com.denizenscript.denizencore.objects.core.DurationTag;
import org.bukkit.Location;
import org.bukkit.Material;

import java.util.HashSet;
import java.util.List;

public interface BlockSet {

Expand All @@ -15,6 +18,10 @@ class InputParams {
public boolean noAir;

public HashSet<Material> mask;

public List<PlayerTag> fakeTo;

public DurationTag fakeDuration;
}

BlockData[] getBlocks();
Expand Down
Expand Up @@ -3,6 +3,8 @@
import com.denizenscript.denizen.nms.NMSHandler;
import com.denizenscript.denizen.nms.interfaces.BlockData;
import com.denizenscript.denizen.objects.CuboidTag;
import com.denizenscript.denizen.objects.MaterialTag;
import com.denizenscript.denizen.objects.PlayerTag;
import com.denizenscript.denizen.scripts.commands.world.SchematicCommand;
import com.denizenscript.denizen.utilities.DenizenAPI;
import org.bukkit.Location;
Expand Down Expand Up @@ -107,7 +109,12 @@ public void setBlockSingle(BlockData block, int x, int y, int z, InputParams inp
if (input.mask != null && !input.mask.contains(destBlock.getType())) {
return;
}
block.setBlock(destBlock, false);
if (input.fakeTo == null) {
block.setBlock(destBlock, false);
}
else {
FakeBlock.showFakeBlockTo(input.fakeTo, destBlock.getLocation(), new MaterialTag(block.modern()), input.fakeDuration);
}
}

@Override
Expand Down
Expand Up @@ -5,6 +5,7 @@
import com.denizenscript.denizen.objects.PlayerTag;
import com.denizenscript.denizen.utilities.DenizenAPI;
import com.denizenscript.denizencore.objects.core.DurationTag;
import org.bukkit.Location;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerQuitEvent;
Expand All @@ -18,21 +19,20 @@
*/
public class FakeBlock {

private final static Map<UUID, Map<LocationTag, FakeBlock>> blocks = new HashMap<>();
private final static Map<LocationTag, FakeBlock> blocksByLocation = new HashMap<>();
private final static Map<UUID, Map<Location, FakeBlock>> blocks = new HashMap<>();

private final PlayerTag player;
private final LocationTag location;
private final Location location;
private MaterialTag material;
private long cancelTime = -1;
private BukkitTask currentTask = null;

private FakeBlock(PlayerTag player, LocationTag location) {
private FakeBlock(PlayerTag player, Location location) {
this.player = player;
this.location = location;
}

public static void showFakeBlockTo(List<PlayerTag> players, LocationTag location, MaterialTag material, DurationTag duration) {
public static void showFakeBlockTo(List<PlayerTag> players, Location location, MaterialTag material, DurationTag duration) {
for (PlayerTag player : players) {
if (!player.isOnline() || !player.isValid()) {
continue;
Expand All @@ -41,7 +41,7 @@ public static void showFakeBlockTo(List<PlayerTag> players, LocationTag location
if (!blocks.containsKey(uuid)) {
blocks.put(uuid, new HashMap<>());
}
Map<LocationTag, FakeBlock> playerBlocks = blocks.get(uuid);
Map<Location, FakeBlock> playerBlocks = blocks.get(uuid);
if (!playerBlocks.containsKey(location)) {
playerBlocks.put(location, new FakeBlock(player, location));
}
Expand All @@ -58,7 +58,7 @@ public static void stopShowingTo(List<PlayerTag> players, final LocationTag loca
UUID uuid = player.getPlayerEntity().getUniqueId();
uuids.add(uuid);
if (blocks.containsKey(uuid)) {
Map<LocationTag, FakeBlock> playerBlocks = blocks.get(uuid);
Map<Location, FakeBlock> playerBlocks = blocks.get(uuid);
if (playerBlocks.containsKey(location)) {
playerBlocks.get(location).cancelBlock();
}
Expand All @@ -71,7 +71,7 @@ public void run() {
if (uuids.contains(uuid)) {
continue;
}
Map<LocationTag, FakeBlock> playerBlocks = blocks.get(uuid);
Map<Location, FakeBlock> playerBlocks = blocks.get(uuid);
if (playerBlocks.containsKey(location)) {
playerBlocks.get(location).updateBlock();
}
Expand All @@ -80,7 +80,7 @@ public void run() {
}.runTaskLater(DenizenAPI.getCurrentInstance(), 2);
}

public static Map<UUID, Map<LocationTag, FakeBlock>> getBlocks() {
public static Map<UUID, Map<Location, FakeBlock>> getBlocks() {
return blocks;
}

Expand All @@ -91,7 +91,7 @@ private void cancelBlock() {
}
cancelTime = -1;
material = null;
location.getBlockState().update();
location.getBlock().getState().update();
blocks.get(player.getOfflinePlayer().getUniqueId()).remove(location);
}

Expand Down

0 comments on commit 20e8781

Please sign in to comment.