+ Redstone input (working)
This commit is contained in:
parent
18b2aa5ac3
commit
fbfae32c84
|
|
@ -9,6 +9,7 @@ import net.minecraft.world.World;
|
|||
import net.minecraftforge.common.DimensionManager;
|
||||
import net.minecraftforge.fml.server.FMLServerHandler;
|
||||
import net.montoyo.mcef.utilities.Log;
|
||||
import net.montoyo.wd.core.JSServerRequest;
|
||||
import net.montoyo.wd.data.GuiData;
|
||||
import net.montoyo.wd.entity.TileEntityScreen;
|
||||
import net.montoyo.wd.utilities.BlockSide;
|
||||
|
|
@ -65,4 +66,12 @@ public class SharedProxy {
|
|||
Log.error("Called SharedProxy.openMinePadGui() on server side...");
|
||||
}
|
||||
|
||||
public void handleJSResponseSuccess(int reqId, JSServerRequest type, byte[] data) {
|
||||
Log.error("Called SharedProxy.handleJSResponseSuccess() on server side...");
|
||||
}
|
||||
|
||||
public void handleJSResponseError(int reqId, JSServerRequest type, int errCode, String err) {
|
||||
Log.error("Called SharedProxy.handleJSResponseError() on server side...");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -192,7 +192,7 @@ public class BlockScreen extends WDBlockContainer {
|
|||
|
||||
@Override
|
||||
public void neighborChanged(IBlockState state, World world, BlockPos pos, Block block, BlockPos source) {
|
||||
if(block != this && !world.isRemote) { //I'm worried this could blow up, hopefully this won't create a bug or something
|
||||
if(block != this && !world.isRemote) {
|
||||
for(BlockSide side: BlockSide.values()) {
|
||||
Vector3i vec = new Vector3i(pos);
|
||||
Multiblock.findOrigin(world, vec, side, null);
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ import net.montoyo.wd.client.gui.WDScreen;
|
|||
import net.montoyo.wd.client.gui.loading.GuiLoader;
|
||||
import net.montoyo.wd.client.renderers.*;
|
||||
import net.montoyo.wd.core.DefaultUpgrade;
|
||||
import net.montoyo.wd.core.JSServerRequest;
|
||||
import net.montoyo.wd.data.GuiData;
|
||||
import net.montoyo.wd.entity.TileEntityScreen;
|
||||
import net.montoyo.wd.net.SMessagePadCtrl;
|
||||
|
|
@ -200,6 +201,29 @@ public class ClientProxy extends SharedProxy implements IResourceManagerReloadLi
|
|||
mc.displayGuiScreen(new GuiMinePad(pd));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleJSResponseSuccess(int reqId, JSServerRequest type, byte[] data) {
|
||||
JSQueryDispatcher.ServerQuery q = jsDispatcher.fulfillQuery(reqId);
|
||||
|
||||
if(q == null)
|
||||
Log.warning("Received success response for invalid query ID %d of type %s", reqId, type.toString());
|
||||
else {
|
||||
if(type == JSServerRequest.WHATEVER) {
|
||||
} else
|
||||
Log.warning("Received success response for query ID %d, but type is invalid", reqId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleJSResponseError(int reqId, JSServerRequest type, int errCode, String err) {
|
||||
JSQueryDispatcher.ServerQuery q = jsDispatcher.fulfillQuery(reqId);
|
||||
|
||||
if(q == null)
|
||||
Log.warning("Received error response for invalid query ID %d of type %s", reqId, type.toString());
|
||||
else
|
||||
q.error(errCode, err);
|
||||
}
|
||||
|
||||
/**************************************** RESOURCE MANAGER METHODS ****************************************/
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -4,13 +4,22 @@
|
|||
|
||||
package net.montoyo.wd.client;
|
||||
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||
import net.montoyo.mcef.api.IBrowser;
|
||||
import net.montoyo.mcef.api.IJSQueryCallback;
|
||||
import net.montoyo.wd.WebDisplays;
|
||||
import net.montoyo.wd.core.DefaultUpgrade;
|
||||
import net.montoyo.wd.core.IScreenQueryHandler;
|
||||
import net.montoyo.wd.core.JSServerRequest;
|
||||
import net.montoyo.wd.entity.TileEntityScreen;
|
||||
import net.montoyo.wd.net.SMessageScreenCtrl;
|
||||
import net.montoyo.wd.utilities.BlockSide;
|
||||
import net.montoyo.wd.utilities.Log;
|
||||
import net.montoyo.wd.utilities.Vector2i;
|
||||
import net.montoyo.wd.utilities.Vector3i;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
|
|
@ -35,10 +44,49 @@ public final class JSQueryDispatcher {
|
|||
|
||||
}
|
||||
|
||||
public static final class ServerQuery {
|
||||
|
||||
private static int lastId = 0;
|
||||
|
||||
private final TileEntityScreen tes;
|
||||
private final BlockSide side;
|
||||
private final IJSQueryCallback callback;
|
||||
private final int id;
|
||||
|
||||
private ServerQuery(TileEntityScreen t, BlockSide s, IJSQueryCallback cb) {
|
||||
tes = t;
|
||||
side = s;
|
||||
callback = cb;
|
||||
id = lastId++;
|
||||
}
|
||||
|
||||
public TileEntityScreen getTileEntity() {
|
||||
return tes;
|
||||
}
|
||||
|
||||
public BlockSide getSide() {
|
||||
return side;
|
||||
}
|
||||
|
||||
public TileEntityScreen.Screen getScreen() {
|
||||
return tes.getScreen(side);
|
||||
}
|
||||
|
||||
public void success(String resp) {
|
||||
callback.success(resp);
|
||||
}
|
||||
|
||||
public void error(int errId, String errStr) {
|
||||
callback.failure(errId, errStr);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private final ClientProxy proxy;
|
||||
private final ArrayDeque<QueryData> queue = new ArrayDeque<>();
|
||||
private final ClientProxy.ScreenSidePair lookupResult = new ClientProxy.ScreenSidePair();
|
||||
private final HashMap<String, IScreenQueryHandler> handlers = new HashMap<>();
|
||||
private final ArrayList<ServerQuery> serverQueries = new ArrayList<>();
|
||||
|
||||
public JSQueryDispatcher(ClientProxy proxy) {
|
||||
this.proxy = proxy;
|
||||
|
|
@ -71,6 +119,7 @@ public final class JSQueryDispatcher {
|
|||
handlers.get(next.query).handleQuery(next.callback, lookupResult.tes, lookupResult.side, args);
|
||||
} catch(Throwable t) {
|
||||
Log.warningEx("Could not execute JS query %s(%s)", t, next.query, (next.args == null) ? "" : next.args);
|
||||
next.callback.failure(500, "Internal error");
|
||||
}
|
||||
}
|
||||
} else
|
||||
|
|
@ -143,11 +192,86 @@ public final class JSQueryDispatcher {
|
|||
handlers.put(query.toLowerCase(), handler);
|
||||
}
|
||||
|
||||
public ServerQuery fulfillQuery(int id) {
|
||||
int toRemove = -1;
|
||||
|
||||
for(int i = 0; i < serverQueries.size(); i++) {
|
||||
ServerQuery sq = serverQueries.get(i);
|
||||
|
||||
if(sq.id == id) {
|
||||
toRemove = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(toRemove < 0)
|
||||
return null;
|
||||
else
|
||||
return serverQueries.remove(toRemove);
|
||||
}
|
||||
|
||||
private void makeServerQuery(TileEntityScreen tes, BlockSide side, IJSQueryCallback cb, JSServerRequest type, Object ... data) {
|
||||
ServerQuery ret = new ServerQuery(tes, side, cb);
|
||||
serverQueries.add(ret);
|
||||
|
||||
WebDisplays.NET_HANDLER.sendToServer(SMessageScreenCtrl.jsRequest(tes, side, ret.id, type, data));
|
||||
}
|
||||
|
||||
private void registerDefaults() {
|
||||
register("getSize", (cb, tes, side, args) -> {
|
||||
register("GetSize", (cb, tes, side, args) -> {
|
||||
Vector2i size = tes.getScreen(side).size;
|
||||
cb.success("{\"x\":" + size.x + ",\"y\":" + size.y + "}");
|
||||
});
|
||||
|
||||
register("GetRedstoneAt", (cb, tes, side, args) -> {
|
||||
if(!tes.hasUpgrade(side, WebDisplays.INSTANCE.itemUpgrade, DefaultUpgrade.REDSTONE_INPUT.ordinal())) {
|
||||
cb.failure(403, "Missing upgrade");
|
||||
return;
|
||||
}
|
||||
|
||||
if(args.length == 2 && args[0] instanceof Double && args[1] instanceof Double) {
|
||||
TileEntityScreen.Screen scr = tes.getScreen(side);
|
||||
int x = ((Double) args[0]).intValue();
|
||||
int y = ((Double) args[1]).intValue();
|
||||
|
||||
if(x < 0 || x >= scr.size.x || y < 0 || y >= scr.size.y)
|
||||
cb.failure(403, "Out of range");
|
||||
else {
|
||||
int level = tes.getWorld().getRedstonePower((new Vector3i(tes.getPos())).addMul(side.right, x).addMul(side.up, y).toBlock(), EnumFacing.VALUES[side.reverse().ordinal()]);
|
||||
cb.success("{\"level\":" + level + "}");
|
||||
}
|
||||
} else
|
||||
cb.failure(400, "Wrong arguments");
|
||||
});
|
||||
|
||||
register("GetRedstoneArray", (cb, tes, side, args) -> {
|
||||
if(tes.hasUpgrade(side, WebDisplays.INSTANCE.itemUpgrade, DefaultUpgrade.REDSTONE_INPUT.ordinal())) {
|
||||
final Vector2i size = tes.getScreen(side).size;
|
||||
final EnumFacing facing = EnumFacing.VALUES[side.reverse().ordinal()];
|
||||
final BlockPos.MutableBlockPos mbp = new BlockPos.MutableBlockPos();
|
||||
final Vector3i vec1 = new Vector3i(tes.getPos());
|
||||
final Vector3i vec2 = new Vector3i();
|
||||
final StringBuilder resp = new StringBuilder("{\"levels\":[");
|
||||
|
||||
for(int y = 0; y < size.y; y++) {
|
||||
vec2.set(vec1);
|
||||
|
||||
for(int x = 0; x < size.x; x++) {
|
||||
if(x > 0 || y > 0)
|
||||
resp.append(',');
|
||||
|
||||
vec2.toBlock(mbp);
|
||||
resp.append(tes.getWorld().getRedstonePower(mbp, facing));
|
||||
vec2.add(side.right.x, side.right.y, side.right.z);
|
||||
}
|
||||
|
||||
vec1.add(side.up.x, side.up.y, side.up.z);
|
||||
}
|
||||
|
||||
cb.success(resp.append("]}").toString());
|
||||
} else
|
||||
cb.failure(403, "Missing upgrade");
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
53
src/main/java/net/montoyo/wd/core/JSServerRequest.java
Normal file
53
src/main/java/net/montoyo/wd/core/JSServerRequest.java
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* Copyright (C) 2018 BARBOTIN Nicolas
|
||||
*/
|
||||
|
||||
package net.montoyo.wd.core;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import net.montoyo.wd.utilities.Util;
|
||||
|
||||
public enum JSServerRequest {
|
||||
|
||||
WHATEVER;
|
||||
|
||||
private final Class[] requestTypes;
|
||||
|
||||
JSServerRequest(Class<?> ... requestTypes) {
|
||||
this.requestTypes = requestTypes;
|
||||
}
|
||||
|
||||
public static JSServerRequest fromID(int id) {
|
||||
JSServerRequest[] values = values();
|
||||
return (id >= 0 && id < values.length) ? values[id] : null;
|
||||
}
|
||||
|
||||
public boolean serialize(ByteBuf buf, Object[] data) {
|
||||
if(data.length != requestTypes.length)
|
||||
return false;
|
||||
|
||||
for(int i = 0; i < data.length; i++) {
|
||||
if(data[i].getClass() != requestTypes[i])
|
||||
return false;
|
||||
|
||||
Util.serialize(buf, data[i]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public Object[] deserialize(ByteBuf buf) {
|
||||
Object[] ret = new Object[requestTypes.length];
|
||||
|
||||
try {
|
||||
for(int i = 0; i < requestTypes.length; i++)
|
||||
ret[i] = Util.unserialize(buf, requestTypes[i]);
|
||||
} catch(Throwable t) {
|
||||
t.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
package net.montoyo.wd.core;
|
||||
|
||||
public class ScreenRights {
|
||||
public abstract class ScreenRights {
|
||||
|
||||
public static final int CHANGE_URL = 1;
|
||||
public static final int CLICK = 2;
|
||||
|
|
|
|||
|
|
@ -12,21 +12,21 @@ import net.minecraft.item.ItemStack;
|
|||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.nbt.NBTTagList;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.EnumHand;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.SoundCategory;
|
||||
import net.minecraft.util.SoundEvent;
|
||||
import net.minecraft.util.*;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.fml.common.network.NetworkRegistry;
|
||||
import net.montoyo.mcef.api.IBrowser;
|
||||
import net.montoyo.wd.WebDisplays;
|
||||
import net.montoyo.wd.block.BlockScreen;
|
||||
import net.montoyo.wd.core.DefaultUpgrade;
|
||||
import net.montoyo.wd.core.IUpgrade;
|
||||
import net.montoyo.wd.core.JSServerRequest;
|
||||
import net.montoyo.wd.core.ScreenRights;
|
||||
import net.montoyo.wd.data.ScreenConfigData;
|
||||
import net.montoyo.wd.net.CMessageAddScreen;
|
||||
import net.montoyo.wd.net.CMessageJSResponse;
|
||||
import net.montoyo.wd.net.CMessageScreenUpdate;
|
||||
import net.montoyo.wd.net.SMessageRequestTEData;
|
||||
import net.montoyo.wd.utilities.*;
|
||||
|
|
@ -53,6 +53,7 @@ public class TileEntityScreen extends TileEntity {
|
|||
public long turnOnTime;
|
||||
public EntityPlayer laserUser;
|
||||
public final Vector2i lastMousePos = new Vector2i();
|
||||
public NibbleArray redstoneStatus; //null on client
|
||||
|
||||
public static Screen deserialize(NBTTagCompound tag) {
|
||||
Screen ret = new Screen();
|
||||
|
|
@ -151,6 +152,37 @@ public class TileEntityScreen extends TileEntity {
|
|||
return friends.stream().anyMatch((f) -> f.uuid.equals(uuid)) ? friendRights : otherRights;
|
||||
}
|
||||
|
||||
public void setupRedstoneStatus(World world, BlockPos start) {
|
||||
if(world.isRemote) {
|
||||
Log.warning("Called Screen.setupRedstoneStatus() on client.");
|
||||
return;
|
||||
}
|
||||
|
||||
if(redstoneStatus != null) {
|
||||
Log.warning("Called Screen.setupRedstoneStatus() on server, but redstone status is non-null");
|
||||
return;
|
||||
}
|
||||
|
||||
redstoneStatus = new NibbleArray(size.x * size.y);
|
||||
final BlockPos.MutableBlockPos mbp = new BlockPos.MutableBlockPos();
|
||||
final Vector3i vec1 = new Vector3i(start);
|
||||
final Vector3i vec2 = new Vector3i();
|
||||
final EnumFacing facing = EnumFacing.VALUES[side.reverse().ordinal()];
|
||||
|
||||
for(int y = 0; y < size.y; y++) {
|
||||
final int base = y * size.x;
|
||||
vec2.set(vec1);
|
||||
|
||||
for(int x = 0; x < size.x; x++) {
|
||||
vec2.toBlock(mbp);
|
||||
redstoneStatus.set(base + x, world.getRedstonePower(mbp, facing));
|
||||
vec2.add(side.right.x, side.right.y, side.right.z);
|
||||
}
|
||||
|
||||
vec1.add(side.up.x, side.up.y, side.up.z);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private ArrayList<Screen> screens = new ArrayList<>();
|
||||
|
|
@ -231,9 +263,11 @@ public class TileEntityScreen extends TileEntity {
|
|||
} else
|
||||
ret.resolution = resolution;
|
||||
|
||||
if(sendUpdate && !world.isRemote) {
|
||||
CMessageAddScreen msg = new CMessageAddScreen(this, ret);
|
||||
WebDisplays.NET_HANDLER.sendToAllAround(msg, point());
|
||||
if(!world.isRemote) {
|
||||
ret.setupRedstoneStatus(world, pos);
|
||||
|
||||
if(sendUpdate)
|
||||
WebDisplays.NET_HANDLER.sendToAllAround(new CMessageAddScreen(this, ret), point());
|
||||
}
|
||||
|
||||
screens.add(ret);
|
||||
|
|
@ -427,8 +461,45 @@ public class TileEntityScreen extends TileEntity {
|
|||
if(world.isRemote) {
|
||||
if(scr.browser != null)
|
||||
scr.browser.runJS("if(typeof webdisplaysRedstoneCallback == \"function\") webdisplaysRedstoneCallback(" + vec.x + ", " + vec.y + ", " + redstoneLevel + ");", "");
|
||||
} else if(scr.upgrades.stream().anyMatch((is) -> is.getItem() == WebDisplays.INSTANCE.itemUpgrade && is.getMetadata() == DefaultUpgrade.REDSTONE_INPUT.ordinal()))
|
||||
WebDisplays.NET_HANDLER.sendToAllAround(CMessageScreenUpdate.jsRedstone(this, side, vec, redstoneLevel), point());
|
||||
} else {
|
||||
boolean sendMsg = false;
|
||||
|
||||
if(scr.redstoneStatus == null) {
|
||||
scr.setupRedstoneStatus(world, pos);
|
||||
sendMsg = true;
|
||||
} else {
|
||||
int idx = vec.y * scr.size.x + vec.x;
|
||||
|
||||
if(scr.redstoneStatus.get(idx) != redstoneLevel) {
|
||||
scr.redstoneStatus.set(idx, redstoneLevel);
|
||||
sendMsg = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(sendMsg)
|
||||
WebDisplays.NET_HANDLER.sendToAllAround(CMessageScreenUpdate.jsRedstone(this, side, vec, redstoneLevel), point());
|
||||
}
|
||||
}
|
||||
|
||||
public void handleJSRequest(EntityPlayerMP src, BlockSide side, int reqId, JSServerRequest req, Object[] data) {
|
||||
if(world.isRemote) {
|
||||
Log.error("Called handleJSRequest client-side");
|
||||
return;
|
||||
}
|
||||
|
||||
Screen scr = getScreen(side);
|
||||
if(scr == null) {
|
||||
Log.error("Called handleJSRequest on non-existing side %s", side.toString());
|
||||
WebDisplays.NET_HANDLER.sendTo(new CMessageJSResponse(reqId, req, 403, "Invalid side"), src);
|
||||
return;
|
||||
}
|
||||
|
||||
if(scr.upgrades.stream().noneMatch((is) -> is.getItem() == WebDisplays.INSTANCE.itemUpgrade && is.getMetadata() == DefaultUpgrade.REDSTONE_OUTPUT.ordinal())) {
|
||||
WebDisplays.NET_HANDLER.sendTo(new CMessageJSResponse(reqId, req, 403, "Missing upgrade"), src);
|
||||
return;
|
||||
}
|
||||
|
||||
//Meh, TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
85
src/main/java/net/montoyo/wd/net/CMessageJSResponse.java
Normal file
85
src/main/java/net/montoyo/wd/net/CMessageJSResponse.java
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* Copyright (C) 2018 BARBOTIN Nicolas
|
||||
*/
|
||||
|
||||
package net.montoyo.wd.net;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import net.minecraftforge.fml.common.network.ByteBufUtils;
|
||||
import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import net.montoyo.wd.WebDisplays;
|
||||
import net.montoyo.wd.core.JSServerRequest;
|
||||
import net.montoyo.wd.utilities.Log;
|
||||
|
||||
@Message(messageId = 9, side = Side.CLIENT)
|
||||
public class CMessageJSResponse implements IMessage, Runnable {
|
||||
|
||||
private int id;
|
||||
private JSServerRequest type;
|
||||
private boolean success;
|
||||
private byte[] data;
|
||||
private int errCode;
|
||||
private String errString;
|
||||
|
||||
public CMessageJSResponse() {
|
||||
}
|
||||
|
||||
public CMessageJSResponse(int id, JSServerRequest t, byte[] d) {
|
||||
this.id = id;
|
||||
type = t;
|
||||
success = true;
|
||||
data = d;
|
||||
}
|
||||
|
||||
public CMessageJSResponse(int id, JSServerRequest t, int code, String err) {
|
||||
this.id = id;
|
||||
type = t;
|
||||
success = false;
|
||||
errCode = code;
|
||||
errString = err;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromBytes(ByteBuf buf) {
|
||||
id = buf.readInt();
|
||||
type = JSServerRequest.fromID(buf.readByte());
|
||||
success = buf.readBoolean();
|
||||
|
||||
if(success) {
|
||||
data = new byte[buf.readByte()];
|
||||
buf.readBytes(data);
|
||||
} else {
|
||||
errCode = buf.readInt();
|
||||
errString = ByteBufUtils.readUTF8String(buf);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toBytes(ByteBuf buf) {
|
||||
buf.writeInt(id);
|
||||
buf.writeByte(type.ordinal());
|
||||
buf.writeBoolean(success);
|
||||
|
||||
if(success) {
|
||||
buf.writeByte(data.length);
|
||||
buf.writeBytes(data); //TODO: Eventually compress this data
|
||||
} else {
|
||||
buf.writeInt(errCode);
|
||||
ByteBufUtils.writeUTF8String(buf, errString);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
if(success)
|
||||
WebDisplays.PROXY.handleJSResponseSuccess(id, type, data);
|
||||
else
|
||||
WebDisplays.PROXY.handleJSResponseError(id, type, errCode, errString);
|
||||
} catch(Throwable t) {
|
||||
Log.warningEx("Could not handle JS response", t);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -26,6 +26,7 @@ public class Messages {
|
|||
l.add(CMessageACResult.class);
|
||||
l.add(SMessagePadCtrl.class);
|
||||
l.add(SMessageRedstoneCtrl.class);
|
||||
l.add(CMessageJSResponse.class);
|
||||
|
||||
messages = l.toArray(new Class[0]);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
|
|||
import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler;
|
||||
import net.minecraftforge.fml.common.network.simpleimpl.MessageContext;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import net.montoyo.wd.core.JSServerRequest;
|
||||
import net.montoyo.wd.core.MissingPermissionException;
|
||||
import net.montoyo.wd.core.ScreenRights;
|
||||
import net.montoyo.wd.entity.TileEntityScreen;
|
||||
|
|
@ -35,6 +36,7 @@ public class SMessageScreenCtrl implements IMessage, Runnable {
|
|||
public static final int CTRL_LASER_DOWN = 8;
|
||||
public static final int CTRL_LASER_MOVE = 9;
|
||||
public static final int CTRL_LASER_UP = 10;
|
||||
public static final int CTRL_JS_REQUEST = 11;
|
||||
|
||||
private int ctrl;
|
||||
private int dim;
|
||||
|
|
@ -49,6 +51,9 @@ public class SMessageScreenCtrl implements IMessage, Runnable {
|
|||
private String text;
|
||||
private BlockPos soundPos;
|
||||
private ItemStack toRemove;
|
||||
private int jsReqID;
|
||||
private JSServerRequest jsReqType;
|
||||
private Object[] jsReqData;
|
||||
|
||||
public SMessageScreenCtrl() {
|
||||
}
|
||||
|
|
@ -130,6 +135,19 @@ public class SMessageScreenCtrl implements IMessage, Runnable {
|
|||
return ret;
|
||||
}
|
||||
|
||||
public static SMessageScreenCtrl jsRequest(TileEntityScreen tes, BlockSide side, int reqId, JSServerRequest reqType, Object ... data) {
|
||||
SMessageScreenCtrl ret = new SMessageScreenCtrl();
|
||||
ret.ctrl = CTRL_JS_REQUEST;
|
||||
ret.pos = new Vector3i(tes.getPos());
|
||||
ret.dim = tes.getWorld().provider.getDimension();
|
||||
ret.side = side;
|
||||
ret.jsReqID = reqId;
|
||||
ret.jsReqType = reqType;
|
||||
ret.jsReqData = data;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static boolean isVec2Ctrl(int msg) {
|
||||
return msg == CTRL_SET_RESOLUTION || msg == CTRL_LASER_DOWN || msg == CTRL_LASER_MOVE;
|
||||
}
|
||||
|
|
@ -159,6 +177,13 @@ public class SMessageScreenCtrl implements IMessage, Runnable {
|
|||
soundPos = new BlockPos(sx, sy, sz);
|
||||
} else if(ctrl == CTRL_REMOVE_UPGRADE)
|
||||
toRemove = ByteBufUtils.readItemStack(buf);
|
||||
else if(ctrl == CTRL_JS_REQUEST) {
|
||||
jsReqID = buf.readInt();
|
||||
jsReqType = JSServerRequest.fromID(buf.readByte());
|
||||
|
||||
if(jsReqType != null)
|
||||
jsReqData = jsReqType.deserialize(buf);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -184,6 +209,13 @@ public class SMessageScreenCtrl implements IMessage, Runnable {
|
|||
buf.writeInt(soundPos.getZ());
|
||||
} else if(ctrl == CTRL_REMOVE_UPGRADE)
|
||||
ByteBufUtils.writeItemStack(buf, toRemove);
|
||||
else if(ctrl == CTRL_JS_REQUEST) {
|
||||
buf.writeInt(jsReqID);
|
||||
buf.writeByte(jsReqType.ordinal());
|
||||
|
||||
if(!jsReqType.serialize(buf, jsReqData))
|
||||
throw new RuntimeException("Could not serialize CTRL_JS_REQUEST " + jsReqType);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -248,7 +280,12 @@ public class SMessageScreenCtrl implements IMessage, Runnable {
|
|||
tes.laserDownMove(side, player, vec2i, ctrl == CTRL_LASER_DOWN);
|
||||
else if(ctrl == CTRL_LASER_UP)
|
||||
tes.laserUp(side, player);
|
||||
else
|
||||
else if(ctrl == CTRL_JS_REQUEST) {
|
||||
if(jsReqType == null || jsReqData == null)
|
||||
Log.warning("Caught invalid JS request from player %s (UUID %s)", player.getName(), player.getGameProfile().getId().toString());
|
||||
else
|
||||
tes.handleJSRequest(player, side, jsReqID, jsReqType, jsReqData);
|
||||
} else
|
||||
Log.info("SMessageScreenCtrl: TODO"); //TODO: other ctrl messages
|
||||
}
|
||||
|
||||
|
|
|
|||
47
src/main/java/net/montoyo/wd/utilities/NibbleArray.java
Normal file
47
src/main/java/net/montoyo/wd/utilities/NibbleArray.java
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright (C) 2018 BARBOTIN Nicolas
|
||||
*/
|
||||
|
||||
package net.montoyo.wd.utilities;
|
||||
|
||||
public final class NibbleArray {
|
||||
|
||||
private final byte[] data;
|
||||
|
||||
public NibbleArray(int count) {
|
||||
if((count & 1) != 0)
|
||||
count++;
|
||||
|
||||
data = new byte[count >> 1];
|
||||
}
|
||||
|
||||
public NibbleArray(byte[] d) {
|
||||
data = d;
|
||||
}
|
||||
|
||||
public final int get(int idx) {
|
||||
if((idx & 1) == 0)
|
||||
return (data[idx >> 1] >> 4) & 0x0F; //MSB
|
||||
else
|
||||
return data[idx >> 1] & 0x0F; //LSB
|
||||
}
|
||||
|
||||
public final void set(int idx, int val) {
|
||||
val &= 0x0F;
|
||||
|
||||
if((idx & 1) == 0) {
|
||||
idx >>= 1;
|
||||
data[idx] = (byte) ((data[idx] & 0x0F) | (val << 4)); //MSB
|
||||
} else {
|
||||
idx >>= 1;
|
||||
data[idx] = (byte) ((data[idx] & 0xF0) | val); //LSB
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] copyBytes() {
|
||||
byte[] ret = new byte[data.length];
|
||||
System.arraycopy(data, 0, ret, 0, data.length);
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
||||
125
src/main/resources/assets/webdisplays/html/io.html
Normal file
125
src/main/resources/assets/webdisplays/html/io.html
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<style type="text/css">
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#content {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#content td {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
text-align: center;
|
||||
text-valign: middle;
|
||||
}
|
||||
|
||||
#content tr {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.border_left {
|
||||
border-left: 1px solid black;
|
||||
}
|
||||
|
||||
.border_top {
|
||||
border-top: 1px solid black;
|
||||
}
|
||||
|
||||
.redstone_on {
|
||||
background-color: rgb(255, 0, 0);
|
||||
}
|
||||
</style>
|
||||
<script type="text/javascript" src="jquery.js"></script>
|
||||
<script type="text/javascript" src="wdlib.js"></script>
|
||||
<script type="text/javascript">
|
||||
var screenW = 1;
|
||||
var screenH = 1;
|
||||
var screenData = [ 0 ];
|
||||
var gotSize = false;
|
||||
var gotData = false;
|
||||
|
||||
function generateTable() {
|
||||
var ppp = $(window).width() / (screenW - 0.25);
|
||||
var border = Math.floor(ppp * 0.125);
|
||||
ppp = Math.floor(ppp);
|
||||
|
||||
for(y = 0; y < screenH; y++) {
|
||||
var line = "<tr>";
|
||||
for(x = 0; x < screenW; x++) {
|
||||
var classes = [];
|
||||
var cw = ppp;
|
||||
var ch = ppp;
|
||||
var value = screenData[(screenH - y - 1) * screenW + x];
|
||||
|
||||
if(x > 0)
|
||||
classes.push("border_left");
|
||||
|
||||
if(x <= 0 || x >= screenW - 1)
|
||||
cw -= border;
|
||||
|
||||
if(y > 0)
|
||||
classes.push("border_top");
|
||||
|
||||
if(y <= 0 || y >= screenH - 1)
|
||||
ch -= border;
|
||||
|
||||
if(value > 0)
|
||||
classes.push("redstone_on");
|
||||
|
||||
line += "<td id=\"cell_" + x + "_" + y + "\" class=\"" + classes.join(" ") + "\" style=\"width: " + cw + "px; height: " + ch + "px;\">" + value + "</td>";
|
||||
}
|
||||
|
||||
line += "</tr>";
|
||||
$("#content").append(line);
|
||||
}
|
||||
}
|
||||
|
||||
/* This function has to be named that way */
|
||||
function webdisplaysRedstoneCallback(x, y, value) {
|
||||
y = screenH - y - 1; //Flip Y axis
|
||||
var elem = $("#cell_" + x + "_" + y);
|
||||
|
||||
elem.html("" + value);
|
||||
|
||||
if(value > 0 && !elem.hasClass("redstone_on"))
|
||||
elem.addClass("redstone_on");
|
||||
else if(value <= 0 && elem.hasClass("redstone_on"))
|
||||
elem.removeClass("redstone_on");
|
||||
}
|
||||
|
||||
$(function() {
|
||||
wdGetSize(function(w, h) {
|
||||
screenW = w;
|
||||
screenH = h;
|
||||
|
||||
if(gotData)
|
||||
generateTable();
|
||||
else
|
||||
gotSize = true;
|
||||
});
|
||||
|
||||
wdGetRedstoneArray(function(array) {
|
||||
screenData = array;
|
||||
|
||||
if(gotSize)
|
||||
generateTable();
|
||||
else
|
||||
gotData = true;
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<table id="content" cellspacing="0" cellpadding="0">
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
2
src/main/resources/assets/webdisplays/html/jquery.js
vendored
Normal file
2
src/main/resources/assets/webdisplays/html/jquery.js
vendored
Normal file
File diff suppressed because one or more lines are too long
38
src/main/resources/assets/webdisplays/html/wdlib.js
Normal file
38
src/main/resources/assets/webdisplays/html/wdlib.js
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
/* This specific file is completely open-source,
|
||||
* comes without copyright and you can freely
|
||||
* copy-paste it wherever you want or do whatever
|
||||
* you want with it.
|
||||
*/
|
||||
|
||||
function wdExecRequest(name, func) {
|
||||
window.mcefQuery({ request: "WebDisplays_" + name,
|
||||
persistent: true,
|
||||
onSuccess: function(response) {
|
||||
try {
|
||||
func(JSON.parse(response));
|
||||
} catch(e) {
|
||||
document.write(response + "<br/>" + e);
|
||||
}
|
||||
},
|
||||
onFailure: function(errCode, errMsg) {
|
||||
document.write(errMsg);
|
||||
}});
|
||||
}
|
||||
|
||||
function wdGetSize(callback) {
|
||||
wdExecRequest("GetSize", function(size) {
|
||||
callback(size.x, size.y);
|
||||
});
|
||||
}
|
||||
|
||||
function wdGetRedstoneAt(x, y, callback) {
|
||||
wdExecRequest("GetRedstoneAt(" + x + "," + y + ")", function(resp) {
|
||||
callback(resp.level);
|
||||
});
|
||||
}
|
||||
|
||||
function wdGetRedstoneArray(callback) {
|
||||
wdExecRequest("GetRedstoneArray", function(resp) {
|
||||
callback(resp.levels);
|
||||
});
|
||||
}
|
||||
BIN
src/main/resources/assets/webdisplays/textures/items/input.png
Normal file
BIN
src/main/resources/assets/webdisplays/textures/items/input.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 203 B |
BIN
src/main/resources/assets/webdisplays/textures/items/output.png
Normal file
BIN
src/main/resources/assets/webdisplays/textures/items/output.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 200 B |
Loading…
Reference in New Issue
Block a user