Proof of concept server-side CUI handler. Note: This pollutes the world with blocks atm

This commit is contained in:
Matthew Miller 2018-08-18 14:22:08 +10:00
parent bc5609114b
commit cf10f8ff8a
2 changed files with 209 additions and 0 deletions

View File

@ -25,6 +25,8 @@ import com.sk89q.jchronic.Chronic;
import com.sk89q.jchronic.Options;
import com.sk89q.jchronic.utils.Span;
import com.sk89q.jchronic.utils.Time;
import com.sk89q.jnbt.IntTag;
import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.command.tool.BlockTool;
import com.sk89q.worldedit.command.tool.BrushTool;
import com.sk89q.worldedit.command.tool.InvalidToolBindException;
@ -37,6 +39,7 @@ import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.internal.cui.CUIEvent;
import com.sk89q.worldedit.internal.cui.CUIRegion;
import com.sk89q.worldedit.internal.cui.SelectionShapeEvent;
import com.sk89q.worldedit.internal.cui.ServerCUIHandler;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.regions.RegionSelector;
import com.sk89q.worldedit.regions.selector.CuboidRegionSelector;
@ -44,6 +47,8 @@ import com.sk89q.worldedit.regions.selector.RegionSelectorType;
import com.sk89q.worldedit.session.ClipboardHolder;
import com.sk89q.worldedit.session.request.Request;
import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockTypes;
import com.sk89q.worldedit.world.item.ItemType;
import com.sk89q.worldedit.world.item.ItemTypes;
import com.sk89q.worldedit.world.snapshot.Snapshot;
@ -87,10 +92,12 @@ public class LocalSession {
private transient boolean fastMode = false;
private transient Mask mask;
private transient TimeZone timezone = TimeZone.getDefault();
private transient Vector cuiTemporaryBlock;
// Saved properties
private String lastScript;
private RegionSelectorType defaultSelector;
private boolean useServerCUI = true; // Save this to not annoy players.
/**
* Construct the object.
@ -612,6 +619,52 @@ public class LocalSession {
public void tellVersion(Actor player) {
}
/**
* Update server-side WorldEdit CUI.
*
* @param actor The player
*/
public void updateServerCUI(Actor actor) {
if (!actor.isPlayer()) {
return; // This is for players only.
}
if (!useServerCUI || hasCUISupport) {
return; // If it's not enabled, ignore this.
}
Player player = (Player) actor;
// Remove the old block.
if (cuiTemporaryBlock != null) {
// TODO Tell server to reset fake block.
try {
createEditSession(player).setBlock(cuiTemporaryBlock, BlockTypes.AIR.getDefaultState());
} catch (MaxChangedBlocksException e) {
e.printStackTrace();
}
cuiTemporaryBlock = null;
}
BaseBlock block = ServerCUIHandler.createStructureBlock(player);
if (block != null) {
// If it's null, we don't need to do anything. The old was already removed.
Map<String, Tag> tags = block.getNbtData().getValue();
cuiTemporaryBlock = new Vector(
((IntTag) tags.get("x")).getValue(),
((IntTag) tags.get("y")).getValue(),
((IntTag) tags.get("z")).getValue()
);
// TODO Send temporary block at that pos to the player.
try {
createEditSession(player).setBlock(cuiTemporaryBlock, block);
} catch (MaxChangedBlocksException e) {
e.printStackTrace();
}
}
}
/**
* Dispatch a CUI event but only if the actor has CUI support.
*
@ -624,6 +677,8 @@ public class LocalSession {
if (hasCUISupport) {
actor.dispatchCUIEvent(event);
} else if (useServerCUI) {
updateServerCUI(actor);
}
}
@ -647,6 +702,9 @@ public class LocalSession {
checkNotNull(actor);
if (!hasCUISupport) {
if (useServerCUI) {
updateServerCUI(actor);
}
return;
}

View File

@ -0,0 +1,151 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser 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 Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.internal.cui;
import com.sk89q.jnbt.ByteTag;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.IntTag;
import com.sk89q.jnbt.StringTag;
import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.IncompleteRegionException;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.regions.RegionSelector;
import com.sk89q.worldedit.regions.selector.CuboidRegionSelector;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockTypes;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.Nullable;
/**
* Handles creation of server-side CUI systems.
*/
public class ServerCUIHandler {
private ServerCUIHandler() {
}
/**
* Creates a structure block that shows the region.
*
* <p>
* Null symbolises removal of the CUI.
* </p>
*
* @param player The player to create the structure block for.
* @return The structure block, or null
*/
@Nullable
public static BaseBlock createStructureBlock(Player player) {
LocalSession session = WorldEdit.getInstance().getSessionManager().get(player);
RegionSelector regionSelector = session.getRegionSelector(player.getWorld());
int posX, posY, posZ;
int width, height, length;
if (regionSelector instanceof CuboidRegionSelector) {
if (regionSelector.isDefined()) {
try {
CuboidRegion region = ((CuboidRegionSelector) regionSelector).getRegion();
posX = region.getMinimumPoint().getBlockX();
posY = region.getMinimumPoint().getBlockY();
posZ = region.getMinimumPoint().getBlockZ();
width = region.getWidth();
height = region.getHeight();
length = region.getLength();
} catch (IncompleteRegionException e) {
// This will never happen.
e.printStackTrace();
return null;
}
} else {
CuboidRegion region = ((CuboidRegionSelector) regionSelector).getIncompleteRegion();
Vector point;
if (region.getPos1() != null) {
point = region.getPos1();
} else if (region.getPos2() != null) {
point = region.getPos2();
} else {
// No more selection
return null;
}
// Just select the point.
posX = point.getBlockX();
posY = point.getBlockY();
posZ = point.getBlockZ();
width = 1;
height = 1;
length = 1;
}
} else {
// We only support cuboid regions right now.
return null;
}
if (width > 32 || length > 32 || height > 32) {
// Structure blocks have a limit of 32x32x32
return null;
}
// Borrowed this math from FAWE
double rotX = player.getLocation().getYaw();
double rotY = player.getLocation().getPitch();
double xz = Math.cos(Math.toRadians(rotY));
int x = (int) (player.getLocation().getX() - (-xz * Math.sin(Math.toRadians(rotX))) * 12);
int z = (int) (player.getLocation().getZ() - (xz * Math.cos(Math.toRadians(rotX))) * 12);
int y = Math.max(0, Math.min(Math.min(255, posY + 32), posY + 3));
Map<String, Tag> structureTag = new HashMap<>();
posX -= x;
posY -= y;
posZ -= z;
structureTag.put("name", new StringTag(player.getUniqueId().toString()));
structureTag.put("author", new StringTag(player.getName()));
structureTag.put("metadata", new StringTag(""));
structureTag.put("x", new IntTag(x));
structureTag.put("y", new IntTag(y));
structureTag.put("z", new IntTag(z));
structureTag.put("posX", new IntTag(posX));
structureTag.put("posY", new IntTag(posY));
structureTag.put("posZ", new IntTag(posZ));
structureTag.put("sizeX", new IntTag(width));
structureTag.put("sizeY", new IntTag(height));
structureTag.put("sizeZ", new IntTag(length));
structureTag.put("rotation", new StringTag("NONE"));
structureTag.put("mirror", new StringTag("NONE"));
structureTag.put("mode", new StringTag("SAVE"));
structureTag.put("ignoreEntities", new ByteTag((byte) 1));
structureTag.put("showboundingbox", new ByteTag((byte) 1));
structureTag.put("id", new StringTag(BlockTypes.STRUCTURE_BLOCK.getId()));
return BlockTypes.STRUCTURE_BLOCK.getDefaultState().toBaseBlock(new CompoundTag(structureTag));
}
}