+ Redstone output (working)

This commit is contained in:
Nicolas BARBOTIN 2018-02-01 02:27:25 +01:00
parent fbfae32c84
commit 3d9b7be33d
13 changed files with 220 additions and 39 deletions

View File

@ -3,15 +3,13 @@ This is the unfinished port of the WebDisplays mod for Minecraft 1.12.2. The tex
### Missing features
* Crafts: upgrades, laser pointer, peripherals
* Screen upgrade: redstone input
* Screen upgrade: redstone output
* ~~Peripheral: ComputerCraft interface~~ (CC not up to date)
* Peripheral: OpenComputers interface
* Server blocks (to store some of the player's web pages)
* Read config (see "Config elements" below)
### TODO
* REDSTONE INPUT OPTIMIZATIONssss!!!
* GPS Upgrade
* Achievements (minePad 2 and all that stuff)
* Top/bottom screen orientation
* GuiSetURL2 missing buttons

View File

@ -42,7 +42,8 @@ import javax.annotation.Nullable;
public class BlockScreen extends WDBlockContainer {
public static final PropertyBool hasTE = PropertyBool.create("haste");
private static final IProperty[] properties = new IProperty[] { hasTE };
public static final PropertyBool emitting = PropertyBool.create("emitting");
private static final IProperty[] properties = new IProperty[] { hasTE, emitting };
public static final IUnlistedProperty<Integer>[] sideFlags = new IUnlistedProperty[6];
static {
for(int i = 0; i < sideFlags.length; i++)
@ -96,12 +97,19 @@ public class BlockScreen extends WDBlockContainer {
@Override
public IBlockState getStateFromMeta(int meta) {
return getDefaultState().withProperty(hasTE, meta != 0);
return getDefaultState().withProperty(hasTE, (meta & 1) != 0).withProperty(emitting, (meta & 2) != 0);
}
@Override
public int getMetaFromState(IBlockState state) {
return state.getValue(hasTE) ? 1 : 0;
int ret = 0;
if(state.getValue(hasTE))
ret |= 1;
if(state.getValue(emitting))
ret |= 2;
return ret;
}
@Override
@ -181,12 +189,12 @@ public class BlockScreen extends WDBlockContainer {
if(te == null) {
BlockPos bp = pos.toBlock();
world.setBlockState(bp, getDefaultState().withProperty(hasTE, true));
world.setBlockState(bp, world.getBlockState(bp).withProperty(hasTE, true));
te = (TileEntityScreen) world.getTileEntity(bp);
created = true;
}
te.addScreen(side, size, null, !created).setOwner(player);
te.addScreen(side, size, null, player, !created);
return true;
}
@ -243,7 +251,7 @@ public class BlockScreen extends WDBlockContainer {
@Nullable
@Override
public TileEntity createNewTileEntity(World world, int meta) {
return meta == 0 ? null : new TileEntityScreen();
return ((meta & 1) == 0) ? null : new TileEntityScreen();
}
/************************************************* DESTRUCTION HANDLING *************************************************/
@ -265,7 +273,7 @@ public class BlockScreen extends WDBlockContainer {
if(te != null && te instanceof TileEntityScreen) {
((TileEntityScreen) te).onDestroy(source);
world.setBlockState(bp, getDefaultState().withProperty(hasTE, false)); //Destroy tile entity
world.setBlockState(bp, world.getBlockState(bp).withProperty(hasTE, false)); //Destroy tile entity.
}
}
@ -308,4 +316,14 @@ public class BlockScreen extends WDBlockContainer {
return EnumPushReaction.IGNORE;
}
@Override
public int getWeakPower(IBlockState state, IBlockAccess world, BlockPos pos, EnumFacing side) {
return state.getValue(emitting) ? 15 : 0;
}
@Override
public boolean canProvidePower(IBlockState state) {
return state.getValue(emitting);
}
}

View File

@ -208,8 +208,9 @@ public class ClientProxy extends SharedProxy implements IResourceManagerReloadLi
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
if(type == JSServerRequest.CLEAR_REDSTONE || type == JSServerRequest.SET_REDSTONE_AT)
q.success("{\"status\":\"success\"}");
else
Log.warning("Received success response for query ID %d, but type is invalid", reqId);
}
}

View File

@ -4,6 +4,7 @@
package net.montoyo.wd.client;
import net.minecraft.client.Minecraft;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraftforge.fml.relauncher.Side;
@ -23,6 +24,7 @@ import net.montoyo.wd.utilities.Vector3i;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
@SideOnly(Side.CLIENT)
@ -272,6 +274,45 @@ public final class JSQueryDispatcher {
} else
cb.failure(403, "Missing upgrade");
});
register("ClearRedstone", (cb, tes, side, args) -> {
if(tes.hasUpgrade(side, WebDisplays.INSTANCE.itemUpgrade, DefaultUpgrade.REDSTONE_OUTPUT.ordinal())) {
if(tes.getScreen(side).owner.uuid.equals(Minecraft.getMinecraft().player.getGameProfile().getId()))
makeServerQuery(tes, side, cb, JSServerRequest.CLEAR_REDSTONE);
else
cb.success("{\"status\":\"notOwner\"}");
} else
cb.failure(403, "Missing upgrade");
});
register("SetRedstoneAt", (cb, tes, side, args) -> {
if(args.length != 3 || !Arrays.stream(args).allMatch((obj) -> obj instanceof Double)) {
cb.failure(400, "Wrong arguments");
return;
}
if(!tes.hasUpgrade(side, WebDisplays.INSTANCE.itemUpgrade, DefaultUpgrade.REDSTONE_OUTPUT.ordinal())) {
cb.failure(403, "Missing upgrade");
return;
}
if(!tes.getScreen(side).owner.uuid.equals(Minecraft.getMinecraft().player.getGameProfile().getId())) {
cb.success("{\"status\":\"notOwner\"}");
return;
}
int x = ((Double) args[0]).intValue();
int y = ((Double) args[1]).intValue();
boolean state = ((Double) args[2]) > 0.0;
Vector2i size = tes.getScreen(side).size;
if(x < 0 || x >= size.x || y < 0 || y >= size.y) {
cb.failure(403, "Out of range");
return;
}
makeServerQuery(tes, side, cb, JSServerRequest.SET_REDSTONE_AT, x, y, state);
});
}
}

View File

@ -16,6 +16,7 @@ import net.montoyo.wd.utilities.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.UUID;
public class GuiScreenConfig extends WDScreen {
@ -98,10 +99,9 @@ public class GuiScreenConfig extends WDScreen {
private CheckBox[] friendBoxes;
private CheckBox[] otherBoxes;
public GuiScreenConfig(TileEntityScreen tes, BlockSide side, NameUUIDPair owner, NameUUIDPair[] friends, int fr, int or) {
public GuiScreenConfig(TileEntityScreen tes, BlockSide side, NameUUIDPair[] friends, int fr, int or) {
this.tes = tes;
this.side = side;
this.owner = owner;
this.friends = friends;
friendRights = fr;
otherRights = or;
@ -128,6 +128,7 @@ public class GuiScreenConfig extends WDScreen {
TileEntityScreen.Screen scr = tes.getScreen(side);
if(scr != null) {
owner = scr.owner;
tfResX.setText("" + scr.resolution.x);
tfResY.setText("" + scr.resolution.y);
@ -135,6 +136,9 @@ public class GuiScreenConfig extends WDScreen {
ugUpgrades.setUpgrades(scr.upgrades);
}
if(owner == null)
owner = new NameUUIDPair("???", UUID.randomUUID());
lblOwner.setLabel(lblOwner.getLabel() + owner.name);
for(NameUUIDPair f : friends)
lstFriends.addElementRaw(f.name, f);

View File

@ -9,7 +9,8 @@ import net.montoyo.wd.utilities.Util;
public enum JSServerRequest {
WHATEVER;
CLEAR_REDSTONE,
SET_REDSTONE_AT(Integer.class, Integer.class, Boolean.class);
private final Class[] requestTypes;

View File

@ -24,7 +24,6 @@ public class ScreenConfigData extends GuiData {
public boolean onlyUpdate;
public Vector3i pos;
public BlockSide side;
public NameUUIDPair owner;
public NameUUIDPair[] friends;
public int friendRights;
public int otherRights;
@ -35,7 +34,6 @@ public class ScreenConfigData extends GuiData {
public ScreenConfigData(Vector3i pos, BlockSide side, TileEntityScreen.Screen scr) {
this.pos = pos;
this.side = side;
owner = scr.owner;
friends = scr.friends.toArray(new NameUUIDPair[0]);
friendRights = scr.friendRights;
otherRights = scr.otherRights;
@ -67,7 +65,7 @@ public class ScreenConfigData extends GuiData {
return null;
}
return new GuiScreenConfig((TileEntityScreen) te, side, owner, friends, friendRights, otherRights);
return new GuiScreenConfig((TileEntityScreen) te, side, friends, friendRights, otherRights);
}
@Override

View File

@ -4,6 +4,7 @@
package net.montoyo.wd.entity;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
@ -140,10 +141,6 @@ public class TileEntityScreen extends TileEntity {
return tag;
}
public void setOwner(EntityPlayer ply) {
owner = new NameUUIDPair(ply.getGameProfile());
}
public int rightsFor(EntityPlayer ply) {
final UUID uuid = ply.getGameProfile().getId();
if(owner.uuid.equals(uuid))
@ -238,7 +235,7 @@ public class TileEntityScreen extends TileEntity {
return new NetworkRegistry.TargetPoint(world.provider.getDimension(), (double) pos.getX(), (double) pos.getY(), (double) pos.getZ(), 64.0);
}
public Screen addScreen(BlockSide side, Vector2i size, Vector2i resolution, boolean sendUpdate) {
public Screen addScreen(BlockSide side, Vector2i size, @Nullable Vector2i resolution, @Nullable EntityPlayer owner, boolean sendUpdate) {
for(Screen scr: screens) {
if(scr.side == side)
return scr;
@ -253,6 +250,9 @@ public class TileEntityScreen extends TileEntity {
ret.otherRights = ScreenRights.DEFAULTS;
ret.upgrades = new ArrayList<>();
if(owner != null)
ret.owner = new NameUUIDPair(owner.getGameProfile());
if(resolution == null || resolution.x < 1 || resolution.y < 1) {
float psx = ((float) size.x) * 16.f - 4.f;
float psy = ((float) size.y) * 16.f - 4.f;
@ -494,12 +494,57 @@ public class TileEntityScreen extends TileEntity {
return;
}
if(!scr.owner.uuid.equals(src.getGameProfile().getId())) {
Log.warning("Player %s (UUID %s) tries to use the redstone output API on a screen he doesn't own!", src.getName(), src.getGameProfile().getId().toString());
WebDisplays.NET_HANDLER.sendTo(new CMessageJSResponse(reqId, req, 403, "Only the owner can do that"), 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
if(req == JSServerRequest.CLEAR_REDSTONE) {
final BlockPos.MutableBlockPos mbp = new BlockPos.MutableBlockPos();
final Vector3i vec1 = new Vector3i(pos);
final Vector3i vec2 = new Vector3i();
for(int y = 0; y < scr.size.y; y++) {
vec2.set(vec1);
for(int x = 0; x < scr.size.x; x++) {
vec2.toBlock(mbp);
IBlockState bs = world.getBlockState(mbp);
if(bs.getValue(BlockScreen.emitting))
world.setBlockState(mbp, bs.withProperty(BlockScreen.emitting, false));
vec2.add(side.right.x, side.right.y, side.right.z);
}
vec1.add(side.up.x, side.up.y, side.up.z);
}
WebDisplays.NET_HANDLER.sendTo(new CMessageJSResponse(reqId, req, new byte[0]), src);
} else if(req == JSServerRequest.SET_REDSTONE_AT) {
int x = (Integer) data[0];
int y = (Integer) data[1];
boolean state = (Boolean) data[2];
if(x < 0 || x >= scr.size.x || y < 0 || y >= scr.size.y)
WebDisplays.NET_HANDLER.sendTo(new CMessageJSResponse(reqId, req, 403, "Out of range"), src);
else {
BlockPos bp = (new Vector3i(pos)).addMul(side.right, x).addMul(side.up, y).toBlock();
IBlockState bs = world.getBlockState(bp);
if(bs.getValue(BlockScreen.emitting) != state)
world.setBlockState(bp, bs.withProperty(BlockScreen.emitting, state));
WebDisplays.NET_HANDLER.sendTo(new CMessageJSResponse(reqId, req, new byte[0]), src);
}
} else
WebDisplays.NET_HANDLER.sendTo(new CMessageJSResponse(reqId, req, 400, "Invalid request"), src);
}
@Override
@ -715,6 +760,9 @@ public class TileEntityScreen extends TileEntity {
scr.upgrades.clear();
Collections.addAll(scr.upgrades, upgrades);
if(scr.browser != null)
scr.browser.runJS("if(typeof webdisplaysUpgradesChanged == \"function\") webdisplaysUpgradesChanged();", "");
}
private static String safeName(ItemStack is) {
@ -891,4 +939,26 @@ public class TileEntityScreen extends TileEntity {
}
}
public void setOwner(BlockSide side, EntityPlayer newOwner) {
if(world.isRemote) {
Log.error("Called TileEntityScreen.setOwner() on client...");
return;
}
if(newOwner == null) {
Log.error("Called TileEntityScreen.setOwner() with null owner");
return;
}
Screen scr = getScreen(side);
if(scr == null) {
Log.error("Called TileEntityScreen.setOwner() on invalid screen on side %s", side.toString());
return;
}
scr.owner = new NameUUIDPair(newOwner.getGameProfile());
WebDisplays.NET_HANDLER.sendToAllAround(CMessageScreenUpdate.owner(this, side, scr.owner), point());
checkLaserUserRights(scr);
}
}

View File

@ -58,13 +58,14 @@ public class ItemOwnershipThief extends Item {
if(te == null || !(te instanceof TileEntityScreen))
return EnumActionResult.SUCCESS;
TileEntityScreen.Screen scr = ((TileEntityScreen) te).getScreen(side);
TileEntityScreen tes = (TileEntityScreen) te;
TileEntityScreen.Screen scr = tes.getScreen(side);
if(scr == null)
return EnumActionResult.SUCCESS;
Log.warning("Owner of screen at %d %d %d, side %s was changed from %s (UUID %s) to %s (UUID %s)", bp.getX(), bp.getY(), bp.getZ(), side.toString(), scr.owner.name, scr.owner.uuid.toString(), player.getName(), player.getGameProfile().getId().toString());
scr.setOwner(player);
player.setHeldItem(hand, ItemStack.EMPTY);
tes.setOwner(side, player);
Util.toast(player, TextFormatting.AQUA, "newOwner");
return EnumActionResult.SUCCESS;
}

View File

@ -13,10 +13,7 @@ import net.minecraftforge.fml.relauncher.Side;
import net.montoyo.wd.SharedProxy;
import net.montoyo.wd.WebDisplays;
import net.montoyo.wd.entity.TileEntityScreen;
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 net.montoyo.wd.utilities.*;
import java.util.ArrayList;
@ -58,6 +55,7 @@ public class CMessageAddScreen implements IMessage, Runnable {
screens[i].size = new Vector2i(buf);
screens[i].url = ByteBufUtils.readUTF8String(buf);
screens[i].resolution = new Vector2i(buf);
screens[i].owner = new NameUUIDPair(buf);
screens[i].upgrades = new ArrayList<>();
int numUpgrades = buf.readByte();
@ -77,6 +75,7 @@ public class CMessageAddScreen implements IMessage, Runnable {
scr.size.writeTo(buf);
ByteBufUtils.writeUTF8String(buf, scr.url);
scr.resolution.writeTo(buf);
scr.owner.writeTo(buf);
buf.writeByte(scr.upgrades.size());
for(ItemStack is: scr.upgrades)
@ -99,9 +98,10 @@ public class CMessageAddScreen implements IMessage, Runnable {
tes.clear();
for(TileEntityScreen.Screen entry: screens) {
TileEntityScreen.Screen scr = tes.addScreen(entry.side, entry.size, entry.resolution, false);
TileEntityScreen.Screen scr = tes.addScreen(entry.side, entry.size, entry.resolution, null, false);
scr.url = entry.url;
scr.upgrades = entry.upgrades;
scr.owner = entry.owner;
if(scr.browser != null)
scr.browser.loadURL(entry.url);

View File

@ -13,10 +13,7 @@ import net.minecraftforge.fml.relauncher.Side;
import net.montoyo.wd.SharedProxy;
import net.montoyo.wd.WebDisplays;
import net.montoyo.wd.entity.TileEntityScreen;
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 net.montoyo.wd.utilities.*;
import javax.annotation.Nullable;
import java.util.ArrayList;
@ -31,6 +28,7 @@ public class CMessageScreenUpdate implements IMessage, Runnable {
public static final int UPDATE_TYPE = 4;
public static final int UPDATE_UPGRADES = 5;
public static final int UPDATE_JS_REDSTONE = 6;
public static final int UPDATE_OWNER = 7;
public static final int MOUSE_CLICK = 0;
public static final int MOUSE_UP = 1;
@ -46,6 +44,7 @@ public class CMessageScreenUpdate implements IMessage, Runnable {
private String text;
private ItemStack[] upgrades;
private int redstoneLevel;
private NameUUIDPair owner;
public CMessageScreenUpdate() {
}
@ -123,6 +122,16 @@ public class CMessageScreenUpdate implements IMessage, Runnable {
return ret;
}
public static CMessageScreenUpdate owner(TileEntityScreen tes, BlockSide side, NameUUIDPair owner) {
CMessageScreenUpdate ret = new CMessageScreenUpdate();
ret.pos = new Vector3i(tes.getPos());
ret.side = side;
ret.action = UPDATE_OWNER;
ret.owner = owner;
return ret;
}
@Override
public void fromBytes(ByteBuf buf) {
pos = new Vector3i(buf);
@ -148,7 +157,8 @@ public class CMessageScreenUpdate implements IMessage, Runnable {
} else if(action == UPDATE_JS_REDSTONE) {
vec2i = new Vector2i(buf);
redstoneLevel = buf.readByte();
}
} else if(action == UPDATE_OWNER)
owner = new NameUUIDPair(buf);
}
@Override
@ -176,7 +186,8 @@ public class CMessageScreenUpdate implements IMessage, Runnable {
} else if(action == UPDATE_JS_REDSTONE) {
vec2i.writeTo(buf);
buf.writeByte(redstoneLevel);
}
} else if(action == UPDATE_OWNER)
owner.writeTo(buf);
}
@Override
@ -208,7 +219,12 @@ public class CMessageScreenUpdate implements IMessage, Runnable {
tes.updateUpgrades(side, upgrades);
else if(action == UPDATE_JS_REDSTONE)
tes.updateJSRedstone(side, vec2i, redstoneLevel);
else
else if(action == UPDATE_OWNER) {
TileEntityScreen.Screen scr = tes.getScreen(side);
if(scr != null)
scr.owner = owner;
} else
Log.warning("===> TODO"); //TODO
}

View File

@ -12,6 +12,7 @@
#content {
margin: 0;
padding: 0;
table-layout: fixed;
}
#content td {
@ -19,6 +20,7 @@
padding: 0;
text-align: center;
text-valign: middle;
font-size: 4vw;
}
#content tr {
@ -37,6 +39,10 @@
.redstone_on {
background-color: rgb(255, 0, 0);
}
.redstone_override {
background-color: rgb(0, 100, 255) !important;
}
</style>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="wdlib.js"></script>
@ -75,7 +81,7 @@
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 += "<td id=\"cell_" + x + "_" + y + "\" class=\"" + classes.join(" ") + "\" style=\"width: " + cw + "px; height: " + ch + "px;\" onclick=\"wdToggle(" + x + ", " + y + ")\">" + value + "</td>";
}
line += "</tr>";
@ -95,6 +101,11 @@
else if(value <= 0 && elem.hasClass("redstone_on"))
elem.removeClass("redstone_on");
}
/* This function also has to be named that way */
function webdisplaysUpgradesChanged() {
location.reload();
}
$(function() {
wdGetSize(function(w, h) {
@ -116,6 +127,19 @@
gotData = true;
});
});
function wdToggle(x, y) {
var elem = $("#cell_" + x + "_" + y);
y = screenH - y - 1;
if(elem.hasClass("redstone_override")) {
elem.removeClass("redstone_override");
wdSetRedstoneAt(x, y, false);
} else {
elem.addClass("redstone_override");
wdSetRedstoneAt(x, y, true);
}
}
</script>
</head>
<body>

View File

@ -36,3 +36,12 @@ function wdGetRedstoneArray(callback) {
callback(resp.levels);
});
}
function wdClearRedstone() {
wdExecRequest("ClearRedstone", function(resp) { /* console.log(resp.status); */ });
}
function wdSetRedstoneAt(x, y, state) {
var istate = state ? 1 : 0;
wdExecRequest("SetRedstoneAt(" + x + "," + y + "," + istate + ")", function(resp) { /* console.log(resp.status); */ });
}