+ The 'YT' button is back

+ Now adds protocol automatically on URLs
* Fix of remote URL peripheral
* Updated README
This commit is contained in:
Nicolas BARBOTIN 2018-02-04 00:37:06 +01:00
parent ce2c1d881f
commit 3136dd7697
14 changed files with 283 additions and 117 deletions

View File

@ -7,14 +7,10 @@ This is the unfinished port of the WebDisplays mod for Minecraft 1.12.2. The tex
* Read config (see "Config elements" below)
### TODO
* GuiSetURL2 missing buttons
* Automatically add protocol to URLs
* Using the remote control tool too far away (with a chunk loader ofc) may trigger distance guard in SMessageScreenCtrl
* French translations
* minePad management: check GuiContainer.draggedStack for minePad
* Change mod name to WD2
* Put a limit on screen resolution
* YT button (also add it to the redstone controller gui)
### Config elements
* Site blacklist

View File

@ -19,10 +19,7 @@ import net.montoyo.wd.core.IUpgrade;
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 net.montoyo.wd.utilities.*;
import java.util.ArrayDeque;
import java.util.ArrayList;
@ -336,7 +333,7 @@ public final class JSQueryDispatcher {
sb.append(',');
sb.append('\"');
sb.append(((IUpgrade) upgrades.get(i).getItem()).getJSName(upgrades.get(i)));
sb.append(Util.addSlashes(((IUpgrade) upgrades.get(i).getItem()).getJSName(upgrades.get(i))));
sb.append('\"');
}

View File

@ -10,6 +10,7 @@ import net.montoyo.wd.client.gui.controls.Button;
import net.montoyo.wd.client.gui.controls.TextField;
import net.montoyo.wd.client.gui.loading.FillControl;
import net.montoyo.wd.net.SMessageRedstoneCtrl;
import net.montoyo.wd.utilities.Util;
import net.montoyo.wd.utilities.Vector3i;
public class GuiRedstoneCtrl extends WDScreen {
@ -48,8 +49,11 @@ public class GuiRedstoneCtrl extends WDScreen {
@GuiSubscribe
public void onClick(Button.ClickEvent ev) {
if(ev.getSource() == btnOk)
WebDisplays.NET_HANDLER.sendToServer(new SMessageRedstoneCtrl(dimension, pos, tfRisingEdge.getText(), tfFallingEdge.getText()));
if(ev.getSource() == btnOk) {
String rising = Util.addProtocol(tfRisingEdge.getText());
String falling = Util.addProtocol(tfFallingEdge.getText());
WebDisplays.NET_HANDLER.sendToServer(new SMessageRedstoneCtrl(dimension, pos, rising, falling));
}
mc.displayGuiScreen(null);
}

View File

@ -13,7 +13,8 @@ import net.montoyo.wd.entity.TileEntityScreen;
import net.montoyo.wd.net.SMessagePadCtrl;
import net.montoyo.wd.net.SMessageScreenCtrl;
import net.montoyo.wd.utilities.BlockSide;
import net.montoyo.wd.utilities.Log;
import net.montoyo.wd.utilities.Util;
import net.montoyo.wd.utilities.Vector3i;
import java.util.Map;
@ -22,6 +23,7 @@ public class GuiSetURL2 extends WDScreen {
//Screen data
private TileEntityScreen tileEntity;
private BlockSide screenSide;
private Vector3i remoteLocation;
//Pad data
private boolean isPad;
@ -41,19 +43,17 @@ public class GuiSetURL2 extends WDScreen {
@FillControl
private Button btnOk;
@FillControl
private Button btnYT;
public GuiSetURL2(TileEntityScreen tes, BlockSide side, String url) {
public GuiSetURL2(TileEntityScreen tes, BlockSide side, String url, Vector3i rl) {
tileEntity = tes;
screenSide = side;
screenURL = url;
remoteLocation = rl;
isPad = false;
screenURL = url;
}
public GuiSetURL2(String url) {
screenURL = url;
isPad = true;
screenURL = url;
}
@Override
@ -79,8 +79,7 @@ public class GuiSetURL2 extends WDScreen {
WebDisplays.NET_HANDLER.sendToServer(new SMessagePadCtrl(""));
mc.displayGuiScreen(null);
} else
Log.info("GuiSetURL2: TODO"); //TODO
}
}
@GuiSubscribe
@ -90,10 +89,12 @@ public class GuiSetURL2 extends WDScreen {
private void validate(String url) {
if(!url.isEmpty()) {
url = Util.addProtocol(url);
if(isPad)
WebDisplays.NET_HANDLER.sendToServer(new SMessagePadCtrl(url));
else
WebDisplays.NET_HANDLER.sendToServer(new SMessageScreenCtrl(tileEntity, screenSide, url));
WebDisplays.NET_HANDLER.sendToServer(SMessageScreenCtrl.setURL(tileEntity, screenSide, url, remoteLocation));
}
mc.displayGuiScreen(null);

View File

@ -12,11 +12,11 @@ import java.io.IOException;
public class Button extends Control {
private final GuiButton btn;
private boolean selected = false;
private boolean shiftDown = false;
private int originalColor = 0;
private int shiftColor = 0;
protected final GuiButton btn;
protected boolean selected = false;
protected boolean shiftDown = false;
protected int originalColor = 0;
protected int shiftColor = 0;
public static class ClickEvent extends Event<Button> {
@ -50,7 +50,9 @@ public class Button extends Control {
if(mouseButton == 0 && btn.mousePressed(mc, mouseX, mouseY)) {
selected = true;
btn.playPressSound(mc.getSoundHandler());
parent.actionPerformed(new ClickEvent(this));
if(!onClick())
parent.actionPerformed(new ClickEvent(this));
}
}
@ -187,13 +189,17 @@ public class Button extends Control {
btn.x = json.getInt("x", 0);
btn.y = json.getInt("y", 0);
btn.width = json.getInt("width", 200);
btn.displayString = tr(json.getString("label", ""));
btn.enabled = !json.getBool("disabled", false);
btn.visible = json.getBool("visible", true);
btn.displayString = tr(json.getString("label", btn.displayString));
btn.enabled = !json.getBool("disabled", !btn.enabled);
btn.visible = json.getBool("visible", btn.visible);
originalColor = json.getColor("color", 0);
shiftColor = json.getColor("shiftColor", 0);
originalColor = json.getColor("color", originalColor);
shiftColor = json.getColor("shiftColor", shiftColor);
btn.packedFGColour = originalColor;
}
protected boolean onClick() {
return false;
}
}

View File

@ -9,6 +9,7 @@ import net.montoyo.wd.client.gui.loading.JsonOWrapper;
import org.lwjgl.input.Keyboard;
import java.io.IOException;
import java.util.ArrayList;
public class TextField extends Control {
@ -75,6 +76,12 @@ public class TextField extends Control {
}
public interface TextChangeListener {
void onTextChange(TextField tf, String oldContent, String newContent);
}
public static final int DEFAULT_TEXT_COLOR = 14737632;
public static final int DEFAULT_DISABLED_COLOR = 7368816;
@ -82,6 +89,7 @@ public class TextField extends Control {
private boolean enabled = true;
private int textColor = DEFAULT_TEXT_COLOR;
private int disabledColor = DEFAULT_DISABLED_COLOR;
private ArrayList<TextChangeListener> listeners = new ArrayList<>();
public TextField() {
field = new GuiTextField(0, font, 1, 1, 198, 20);
@ -111,8 +119,12 @@ public class TextField extends Control {
field.textboxKeyTyped(typedChar, keyCode);
if(enabled && field.isFocused() && !field.getText().equals(old))
if(enabled && field.isFocused() && !field.getText().equals(old)) {
for(TextChangeListener tcl : listeners)
tcl.onTextChange(this, old, field.getText());
parent.actionPerformed(new TextChangedEvent(this, old));
}
}
}
@ -127,7 +139,13 @@ public class TextField extends Control {
}
public void setText(String text) {
String old = field.getText();
field.setText(text);
if(!old.equals(text)) {
for(TextChangeListener tcl : listeners)
tcl.onTextChange(this, old, text);
}
}
public void clear() {
@ -258,6 +276,15 @@ public class TextField extends Control {
return field;
}
public void addTextChangeListener(TextChangeListener l) {
if(l != null && !listeners.contains(l))
listeners.add(l);
}
public void removeTextChangeListener(TextChangeListener l) {
listeners.remove(l);
}
@Override
public void load(JsonOWrapper json) {
super.load(json);

View File

@ -0,0 +1,78 @@
/*
* Copyright (C) 2018 BARBOTIN Nicolas
*/
package net.montoyo.wd.client.gui.controls;
import net.montoyo.wd.client.gui.loading.JsonOWrapper;
import net.montoyo.wd.utilities.Util;
import net.montoyo.wd.utilities.VideoType;
import java.net.MalformedURLException;
import java.net.URL;
public class YTButton extends Button implements TextField.TextChangeListener {
private TextField urlField;
public YTButton() {
btn.displayString = "YT";
btn.enabled = false;
shiftColor = 0xFFFF6464;
}
@Override
protected boolean onClick() {
if(urlField != null) {
String urlStr = Util.addProtocol(urlField.getText());
URL url;
try {
url = new URL(urlStr);
} catch(MalformedURLException ex) {
return true;
}
VideoType vt = VideoType.getTypeFromURL(url);
if(vt == VideoType.YOUTUBE)
urlField.setText(VideoType.YOUTUBE_EMBED.getURLFromID(vt.getVideoIDFromURL(url), shiftDown));
}
return true;
}
public void setURLField(TextField tf) {
if(urlField != null)
tf.removeTextChangeListener(this);
urlField = tf;
if(urlField != null)
tf.addTextChangeListener(this);
}
public TextField getURLField() {
return urlField;
}
@Override
public void load(JsonOWrapper json) {
super.load(json);
String tfName = json.getString("urlField", null);
if(tfName != null) {
Control ctrl = parent.getControlByName(tfName);
if(ctrl != null && ctrl instanceof TextField) {
urlField = (TextField) ctrl;
urlField.addTextChangeListener(this);
}
}
}
@Override
public void onTextChange(TextField tf, String oldContent, String newContent) {
btn.enabled = (VideoType.getTypeFromURL(Util.addProtocol(newContent)) == VideoType.YOUTUBE);
}
}

View File

@ -43,6 +43,7 @@ public class GuiLoader {
register(TextField.class);
register(Icon.class);
register(UpgradeGroup.class);
register(YTButton.class);
}
public static Control create(JsonOWrapper json) {

View File

@ -6,6 +6,7 @@ package net.montoyo.wd.data;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
@ -20,6 +21,8 @@ public class SetURLData extends GuiData {
public Vector3i pos;
public BlockSide side;
public String url;
public boolean isRemote;
public Vector3i remoteLocation;
public SetURLData() {
}
@ -28,6 +31,16 @@ public class SetURLData extends GuiData {
this.pos = pos;
this.side = side;
this.url = url;
isRemote = false;
remoteLocation = new Vector3i();
}
public SetURLData(Vector3i pos, BlockSide side, String url, BlockPos rl) {
this.pos = pos;
this.side = side;
this.url = url;
isRemote = true;
remoteLocation = new Vector3i(rl);
}
@SideOnly(Side.CLIENT)
@ -39,7 +52,7 @@ public class SetURLData extends GuiData {
return null;
}
return new GuiSetURL2((TileEntityScreen) te, side, url);
return new GuiSetURL2((TileEntityScreen) te, side, url, isRemote ? remoteLocation : null);
}
@Override

View File

@ -36,7 +36,7 @@ public class TileEntityRCtrl extends TileEntityPeripheralBase {
return true;
}
(new SetURLData(screenPos, screenSide, scr.url)).sendTo((EntityPlayerMP) player);
(new SetURLData(screenPos, screenSide, scr.url, pos)).sendTo((EntityPlayerMP) player);
return true;
}

View File

@ -5,6 +5,8 @@
package net.montoyo.wd.net;
import io.netty.buffer.ByteBuf;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
@ -16,6 +18,9 @@ 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.WebDisplays;
import net.montoyo.wd.block.BlockPeripheral;
import net.montoyo.wd.core.DefaultPeripheral;
import net.montoyo.wd.core.JSServerRequest;
import net.montoyo.wd.core.MissingPermissionException;
import net.montoyo.wd.core.ScreenRights;
@ -38,6 +43,7 @@ public class SMessageScreenCtrl implements IMessage, Runnable {
public static final int CTRL_LASER_UP = 10;
public static final int CTRL_JS_REQUEST = 11;
public static final int CTRL_SET_ROTATION = 12;
public static final int CTRL_SET_URL_REMOTE = 13;
private int ctrl;
private int dim;
@ -56,24 +62,23 @@ public class SMessageScreenCtrl implements IMessage, Runnable {
private JSServerRequest jsReqType;
private Object[] jsReqData;
private Rotation rotation;
private Vector3i remoteLoc;
public SMessageScreenCtrl() {
}
public SMessageScreenCtrl(TileEntityScreen tes, BlockSide side, String url) {
ctrl = CTRL_SET_URL;
dim = tes.getWorld().provider.getDimension();
pos = new Vector3i(tes.getPos());
this.side = side;
this.url = url;
}
public static SMessageScreenCtrl setURL(TileEntityScreen tes, BlockSide side, String url, Vector3i remoteLocation) {
SMessageScreenCtrl ret = new SMessageScreenCtrl();
ret.ctrl = (remoteLocation == null) ? CTRL_SET_URL : CTRL_SET_URL_REMOTE;
ret.dim = tes.getWorld().provider.getDimension();
ret.pos = new Vector3i(tes.getPos());
ret.side = side;
ret.url = url;
public SMessageScreenCtrl(TileEntityScreen tes, BlockSide side) {
ctrl = CTRL_SHUT_DOWN;
dim = tes.getWorld().provider.getDimension();
pos = new Vector3i(tes.getPos());
this.side = side;
this.url = url;
if(remoteLocation != null)
ret.remoteLoc = remoteLocation;
return ret;
}
public SMessageScreenCtrl(TileEntityScreen tes, BlockSide side, NameUUIDPair friend, boolean del) {
@ -195,6 +200,10 @@ public class SMessageScreenCtrl implements IMessage, Runnable {
jsReqData = jsReqType.deserialize(buf);
} else if(ctrl == CTRL_SET_ROTATION)
rotation = Rotation.values()[buf.readByte() & 3];
else if(ctrl == CTRL_SET_URL_REMOTE) {
url = ByteBufUtils.readUTF8String(buf);
remoteLoc = new Vector3i(buf);
}
}
@Override
@ -228,6 +237,10 @@ public class SMessageScreenCtrl implements IMessage, Runnable {
throw new RuntimeException("Could not serialize CTRL_JS_REQUEST " + jsReqType);
} else if(ctrl == CTRL_SET_ROTATION)
buf.writeByte(rotation.ordinal());
else if(ctrl == CTRL_SET_URL_REMOTE) {
ByteBufUtils.writeUTF8String(buf, url);
remoteLoc.writeTo(buf);
}
}
@Override
@ -254,8 +267,21 @@ public class SMessageScreenCtrl implements IMessage, Runnable {
World world = player.world;
BlockPos bp = pos.toBlock();
if(world.provider.getDimension() != dim || player.getDistanceSq(bp) > 512.0 * 512.0)
return; //Out of range
if(world.provider.getDimension() != dim)
return; //Out of range (dimension mismatch)
if(ctrl == CTRL_SET_URL_REMOTE) {
double reachDist = player.getEntityAttribute(EntityPlayer.REACH_DISTANCE).getAttributeValue();
BlockPos blockPos = remoteLoc.toBlock();
if(player.getDistanceSq(blockPos) > reachDist * reachDist)
return; //Out of range (player reach distance)
IBlockState bs = world.getBlockState(blockPos);
if(bs.getBlock() != WebDisplays.INSTANCE.blockPeripheral || bs.getValue(BlockPeripheral.type) != DefaultPeripheral.REMOTE_CONTROLLER)
return; //I call it hax...
} else if(player.getDistanceSq(bp) > 128.0 * 128.0)
return; //Out of range (range problem)
TileEntity te = world.getTileEntity(bp);
if(te == null || !(te instanceof TileEntityScreen)) {
@ -265,12 +291,13 @@ public class SMessageScreenCtrl implements IMessage, Runnable {
TileEntityScreen tes = (TileEntityScreen) te;
if(ctrl == CTRL_SET_URL) {
if(ctrl == CTRL_SET_URL || ctrl == CTRL_SET_URL_REMOTE) {
checkPermission(tes, ScreenRights.CHANGE_URL);
tes.setScreenURL(side, url);
} else if(ctrl == CTRL_SHUT_DOWN) {
checkPermission(tes, ScreenRights.CHANGE_URL);
tes.removeScreen(side);
//TODO
//checkPermission(tes, ScreenRights.CHANGE_URL);
//tes.removeScreen(side);
} else if(ctrl == CTRL_ADD_FRIEND) {
checkPermission(tes, ScreenRights.MANAGE_FRIEND_LIST);
tes.addFriend(player, side, friend);

View File

@ -38,12 +38,12 @@ public abstract class Util {
Object[] ray = (Object[]) f;
bb.writeInt(ray.length);
for(Object o: ray)
for(Object o : ray)
serialize(bb, o);
} else if(!cls.isPrimitive()) {
Field[] fields = cls.getFields();
for(Field ff: fields) {
for(Field ff : fields) {
try {
if(ff.getAnnotation(DontSerialize.class) == null && !Modifier.isStatic(ff.getModifiers()))
serialize(bb, ff.get(f));
@ -92,7 +92,7 @@ public abstract class Util {
throw new RuntimeException(String.format("Caught IllegalAccessException for class %s", cls.getName()));
}
for(Field ff: fields) {
for(Field ff : fields) {
try {
if(ff.getAnnotation(DontSerialize.class) == null && !Modifier.isStatic(ff.getModifiers()))
ff.set(ret, unserialize(bb, ff.getType()));
@ -123,7 +123,7 @@ public abstract class Util {
Object[] ray = (Object[]) f;
NBTTagList ret = new NBTTagList();
for(Object o: ray)
for(Object o : ray)
ret.appendTag(serialize(o));
return ret;
@ -197,17 +197,16 @@ public abstract class Util {
return out;
}
public static int scrambleKey(int idx)
{
public static int scrambleKey(int idx) {
idx = idx * 0x9E3779B9;
return idx ^ (idx >> 16);
}
public static void toast(EntityPlayer player, String key, Object ... data) {
public static void toast(EntityPlayer player, String key, Object... data) {
toast(player, TextFormatting.RED, key, data);
}
public static void toast(EntityPlayer player, TextFormatting color, String key, Object ... data) {
public static void toast(EntityPlayer player, TextFormatting color, String key, Object... data) {
ITextComponent root = new TextComponentString("[WebDisplays] ");
root.setStyle((new Style()).setColor(color));
root.appendSibling(new TextComponentTranslation("webdisplays.message." + key, data));
@ -221,4 +220,8 @@ public abstract class Util {
} catch(Throwable t) {}
}
public static String addProtocol(String str) {
return str.contains("://") ? str : ("http://" + str);
}
}

View File

@ -15,7 +15,15 @@
"name": "tfRisingEdge",
"x": 20,
"y": 0,
"width": 280
"width": 280,
"maxLength": 65535
},
{
"type": "YTButton",
"x": 305,
"y": 0,
"width": 20,
"urlField": "tfRisingEdge"
},
{
"type": "Icon",
@ -32,7 +40,15 @@
"name": "tfFallingEdge",
"x": 20,
"y": 24,
"width": 280
"width": 280,
"maxLength": 65535
},
{
"type": "YTButton",
"x": 305,
"y": 24,
"width": 20,
"urlField": "tfFallingEdge"
},
{
"type": "Button",

View File

@ -1,56 +1,53 @@
{
"controls": [
{
"type": "Label",
"label": "$webdisplays.gui.seturl.url",
"x": 0,
"y": 0,
"shadowed": true
},
{
"type": "TextField",
"name": "tfURL",
"x": 0,
"y": 12,
"width": 272,
"maxLength": 65535
},
{
"type": "Button",
"name": "btnYT",
"label": "YT",
"x": 276,
"y": 13,
"width": 20,
"shiftColor": [ 255, 100, 100 ]
},
{
"type": "Button",
"name": "btnShutDown",
"label": "$webdisplays.gui.seturl.shutdown",
"x": 0,
"y": 38,
"width": 96,
"visible": "isPad",
"disabled": "1 - isPad"
},
{
"type": "Button",
"name": "btnCancel",
"label": "$webdisplays.gui.seturl.cancel",
"x": "isPad & 100 | 0",
"y": 38,
"width": "isPad & 96 | 146"
},
{
"type": "Button",
"name": "btnOk",
"label": "$webdisplays.gui.seturl.ok",
"x": "isPad & 200 | 150",
"y": 38,
"width": "isPad & 96 | 146"
}
],
"center": true
"controls": [
{
"type": "Label",
"label": "$webdisplays.gui.seturl.url",
"x": 0,
"y": 0,
"shadowed": true
},
{
"type": "TextField",
"name": "tfURL",
"x": 0,
"y": 12,
"width": 272,
"maxLength": 65535
},
{
"type": "YTButton",
"x": 276,
"y": 13,
"width": 20,
"urlField": "tfURL"
},
{
"type": "Button",
"name": "btnShutDown",
"label": "$webdisplays.gui.seturl.shutdown",
"x": 0,
"y": 38,
"width": 96,
"visible": "isPad",
"disabled": "1 - isPad"
},
{
"type": "Button",
"name": "btnCancel",
"label": "$webdisplays.gui.seturl.cancel",
"x": "isPad & 100 | 0",
"y": 38,
"width": "isPad & 96 | 146"
},
{
"type": "Button",
"name": "btnOk",
"label": "$webdisplays.gui.seturl.ok",
"x": "isPad & 200 | 150",
"y": 38,
"width": "isPad & 96 | 146"
}
],
"center": true
}