From 2d8a3792b77eaca1bf6c300d9ef862d7cafedb10 Mon Sep 17 00:00:00 2001 From: Nicolas BARBOTIN Date: Sun, 28 Jan 2018 02:04:44 +0100 Subject: [PATCH] * WIP screen upgrades * Updated README --- README.md | 7 +- .../net/montoyo/wd/block/BlockScreen.java | 19 +++- .../java/net/montoyo/wd/core/IUpgrade.java | 21 +++++ .../montoyo/wd/entity/TileEntityScreen.java | 87 ++++++++++++++++++- .../net/montoyo/wd/net/CMessageAddScreen.java | 12 +++ .../montoyo/wd/net/CMessageScreenUpdate.java | 32 +++++++ 6 files changed, 170 insertions(+), 8 deletions(-) create mode 100644 src/main/java/net/montoyo/wd/core/IUpgrade.java diff --git a/README.md b/README.md index c18a91e..b509dfd 100644 --- a/README.md +++ b/README.md @@ -2,13 +2,12 @@ This is the unfinished port of the WebDisplays mod for Minecraft 1.12.2. The text below is my "TODO" list. ### Missing features -* Redstone interface -* Server blocks (to store some of the player's web pages) * Screen upgrade: "laser" mouse * Screen upgrade: redstone input * Screen upgrade: redstone output -* Peripheral: ComputerCraft interface +* ~~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 @@ -30,5 +29,5 @@ This is the unfinished port of the WebDisplays mod for Minecraft 1.12.2. The tex * Homepage * RPMP (Real pixels per Minecraft pixels) * Browser language -* Screen load/unload distance +* Screen load/unload distance (max distance = 60.0) * Disable ownership thief item diff --git a/src/main/java/net/montoyo/wd/block/BlockScreen.java b/src/main/java/net/montoyo/wd/block/BlockScreen.java index 01401b9..f36908e 100644 --- a/src/main/java/net/montoyo/wd/block/BlockScreen.java +++ b/src/main/java/net/montoyo/wd/block/BlockScreen.java @@ -29,6 +29,7 @@ import net.minecraftforge.common.property.IUnlistedProperty; import net.minecraftforge.common.property.Properties; import net.montoyo.wd.WebDisplays; import net.montoyo.wd.core.ScreenRights; +import net.montoyo.wd.core.IUpgrade; import net.montoyo.wd.data.SetURLData; import net.montoyo.wd.entity.TileEntityScreen; import net.montoyo.wd.utilities.*; @@ -102,7 +103,10 @@ public class BlockScreen extends WDBlockContainer { @Override public boolean onBlockActivated(World world, BlockPos bpos, IBlockState state, EntityPlayer player, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ) { - if(!player.getHeldItem(hand).isEmpty()) + ItemStack heldItem = player.getHeldItem(hand); + if(heldItem.isEmpty()) + heldItem = null; //Easier to work with + else if(!(heldItem.getItem() instanceof IUpgrade)) return false; if(world.isRemote) @@ -125,7 +129,18 @@ public class BlockScreen extends WDBlockContainer { (new SetURLData(pos, scr.side, scr.url)).sendTo((EntityPlayerMP) player); return true; - } else { + } else if(heldItem != null && !te.hasUpgrade(side, heldItem)) { //Add upgrade + if((scr.rightsFor(player) & ScreenRights.MANAGE_UPGRADES) == 0) { + Util.toast(player, "restrictions"); + return true; + } + + te.addUpgrade(side, heldItem); + if(!player.isCreative()) + heldItem.shrink(1); + + return true; + } else { //Click if((scr.rightsFor(player) & ScreenRights.CLICK) == 0) { Util.toast(player, "restrictions"); return true; diff --git a/src/main/java/net/montoyo/wd/core/IUpgrade.java b/src/main/java/net/montoyo/wd/core/IUpgrade.java new file mode 100644 index 0000000..a71f402 --- /dev/null +++ b/src/main/java/net/montoyo/wd/core/IUpgrade.java @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2018 BARBOTIN Nicolas + */ + +package net.montoyo.wd.core; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.montoyo.wd.entity.TileEntityScreen; +import net.montoyo.wd.utilities.BlockSide; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public interface IUpgrade { + + void onInstall(@Nonnull TileEntityScreen tes, @Nonnull BlockSide screenSide, @Nullable EntityPlayer player, @Nonnull ItemStack is); + boolean onRemove(@Nonnull TileEntityScreen tes, @Nonnull BlockSide screenSide, @Nullable EntityPlayer player, @Nonnull ItemStack is); //Return true to prevent dropping + void updateUpgrade(@Nonnull TileEntityScreen tes, @Nonnull BlockSide screenSide, @Nonnull ItemStack is); + +} diff --git a/src/main/java/net/montoyo/wd/entity/TileEntityScreen.java b/src/main/java/net/montoyo/wd/entity/TileEntityScreen.java index 51495c9..a36f1b9 100644 --- a/src/main/java/net/montoyo/wd/entity/TileEntityScreen.java +++ b/src/main/java/net/montoyo/wd/entity/TileEntityScreen.java @@ -6,6 +6,7 @@ package net.montoyo.wd.entity; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; import net.minecraft.tileentity.TileEntity; @@ -16,6 +17,7 @@ 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.IUpgrade; import net.montoyo.wd.core.ScreenRights; import net.montoyo.wd.data.ScreenConfigData; import net.montoyo.wd.net.CMessageAddScreen; @@ -23,8 +25,9 @@ import net.montoyo.wd.net.CMessageScreenUpdate; import net.montoyo.wd.net.SMessageRequestTEData; import net.montoyo.wd.utilities.*; -import java.util.ArrayList; -import java.util.UUID; +import javax.annotation.Nullable; +import java.util.*; +import java.util.function.Predicate; public class TileEntityScreen extends TileEntity { @@ -43,6 +46,7 @@ public class TileEntityScreen extends TileEntity { public int friendRights; public int otherRights; public IBrowser browser; + public ArrayList upgrades; public static boolean isYouTubeURL(String url) { return url.matches(YT_REGEX1) || url.matches(YT_REGEX2); @@ -83,6 +87,13 @@ public class TileEntityScreen extends TileEntity { ret.friendRights = tag.getByte("FriendRights"); ret.otherRights = tag.getByte("OtherRights"); + + NBTTagList upgrades = tag.getTagList("Upgrades", 10); + ret.upgrades = new ArrayList<>(); + + for(int i = 0; i < upgrades.tagCount(); i++) + ret.upgrades.add(new ItemStack(upgrades.getCompoundTagAt(i))); + return ret; } @@ -114,6 +125,12 @@ public class TileEntityScreen extends TileEntity { tag.setTag("Friends", list); tag.setByte("FriendRights", (byte) friendRights); tag.setByte("OtherRights", (byte) otherRights); + + list = new NBTTagList(); + for(ItemStack is: upgrades) + list.appendTag(is.writeToNBT(new NBTTagCompound())); + + tag.setTag("Upgrades", list); return tag; } @@ -202,6 +219,7 @@ public class TileEntityScreen extends TileEntity { ret.friends = new ArrayList<>(); ret.friendRights = ScreenRights.DEFAULTS; ret.otherRights = ScreenRights.DEFAULTS; + ret.upgrades = new ArrayList<>(); if(resolution == null || resolution.x < 1 || resolution.y < 1) { float psx = ((float) size.x) * 16.f - 4.f; @@ -536,4 +554,69 @@ public class TileEntityScreen extends TileEntity { } } + public void updateUpgrades(BlockSide side, ItemStack[] upgrades) { + if(!world.isRemote) { + Log.error("Tried to call TileEntityScreen.updateUpgrades() from server side..."); + return; + } + + Screen scr = getScreen(side); + if(scr == null) { + Log.error("Tried to update upgrades on invalid screen on side %s", side.toString()); + return; + } + + scr.upgrades.clear(); + Collections.addAll(scr.upgrades, upgrades); + } + + //If equal is null, no duplicate check is preformed + public boolean addUpgrade(BlockSide side, ItemStack is, @Nullable Predicate equal) { + //TODO: Remove Predicate. It should be obtained from IUpgrade. + if(world.isRemote) + return false; + + Screen scr = getScreen(side); + if(scr == null) { + Log.error("Tried to add an upgrade on invalid screen on side %s", side.toString()); + return false; + } + + if(!(is.getItem() instanceof IUpgrade)) { + Log.error("Tried to add a non-upgrade item %s to screen (%s does not implement IUpgrade)", is.getItem().getRegistryName().toString(), is.getItem().getClass().getCanonicalName()); + return false; + } + + if(equal != null && scr.upgrades.stream().anyMatch(equal)) + return false; //Upgrade already exists + + scr.upgrades.add(is); + WebDisplays.NET_HANDLER.sendToAllAround(CMessageScreenUpdate.upgrade(this, side), point()); + ((IUpgrade) is.getItem()).onInstall(this, side, null, is); + return true; + } + + //Uses the default item stack comparing (same Item & metadata) + public boolean addUpgrade(BlockSide side, ItemStack is) { + return addUpgrade(side, is, (other) -> other.getItem() == is.getItem() && other.getMetadata() == is.getMetadata()); + } + + //Uses the default item stack comparing (same Item & metadata) + public boolean hasUpgrade(BlockSide side, ItemStack is) { + Screen scr = getScreen(side); + if(scr == null) + return false; + + return scr.upgrades.stream().anyMatch((other) -> other.getItem() == is.getItem() && other.getMetadata() == is.getMetadata()); + } + + public boolean hasUpgrade(BlockSide side, Predicate equal) { + //TODO: Remove Predicate. It should be obtained from IUpgrade. + Screen scr = getScreen(side); + if(scr == null) + return false; + + return scr.upgrades.stream().anyMatch(equal); + } + } diff --git a/src/main/java/net/montoyo/wd/net/CMessageAddScreen.java b/src/main/java/net/montoyo/wd/net/CMessageAddScreen.java index d85d386..09cf1fb 100644 --- a/src/main/java/net/montoyo/wd/net/CMessageAddScreen.java +++ b/src/main/java/net/montoyo/wd/net/CMessageAddScreen.java @@ -5,6 +5,7 @@ package net.montoyo.wd.net; import io.netty.buffer.ByteBuf; +import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; import net.minecraftforge.fml.common.network.ByteBufUtils; import net.minecraftforge.fml.common.network.simpleimpl.IMessage; @@ -17,6 +18,8 @@ import net.montoyo.wd.utilities.Log; import net.montoyo.wd.utilities.Vector2i; import net.montoyo.wd.utilities.Vector3i; +import java.util.ArrayList; + @Message(messageId = 0, side = Side.CLIENT) public class CMessageAddScreen implements IMessage, Runnable { @@ -55,6 +58,11 @@ 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].upgrades = new ArrayList<>(); + + int numUpgrades = buf.readByte(); + for(int j = 0; j < numUpgrades; j++) + screens[i].upgrades.add(ByteBufUtils.readItemStack(buf)); } } @@ -69,6 +77,10 @@ public class CMessageAddScreen implements IMessage, Runnable { scr.size.writeTo(buf); ByteBufUtils.writeUTF8String(buf, scr.url); scr.resolution.writeTo(buf); + buf.writeByte(scr.upgrades.size()); + + for(ItemStack is: scr.upgrades) + ByteBufUtils.writeItemStack(buf, is); } } diff --git a/src/main/java/net/montoyo/wd/net/CMessageScreenUpdate.java b/src/main/java/net/montoyo/wd/net/CMessageScreenUpdate.java index b009bbc..00943b0 100644 --- a/src/main/java/net/montoyo/wd/net/CMessageScreenUpdate.java +++ b/src/main/java/net/montoyo/wd/net/CMessageScreenUpdate.java @@ -5,6 +5,7 @@ package net.montoyo.wd.net; import io.netty.buffer.ByteBuf; +import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; import net.minecraftforge.fml.common.network.ByteBufUtils; import net.minecraftforge.fml.common.network.simpleimpl.IMessage; @@ -17,6 +18,8 @@ import net.montoyo.wd.utilities.Log; import net.montoyo.wd.utilities.Vector2i; import net.montoyo.wd.utilities.Vector3i; +import java.util.ArrayList; + @Message(messageId = 4, side = Side.CLIENT) public class CMessageScreenUpdate implements IMessage, Runnable { @@ -25,6 +28,7 @@ public class CMessageScreenUpdate implements IMessage, Runnable { public static final int UPDATE_DELETE = 2; public static final int UPDATE_CLICK = 3; public static final int UPDATE_TYPE = 4; + public static final int UPDATE_UPGRADES = 5; private Vector3i pos; private BlockSide side; @@ -33,6 +37,7 @@ public class CMessageScreenUpdate implements IMessage, Runnable { private Vector2i resolution; private Vector2i click; private String text; + private ItemStack[] upgrades; public CMessageScreenUpdate() { } @@ -83,6 +88,21 @@ public class CMessageScreenUpdate implements IMessage, Runnable { return ret; } + public static CMessageScreenUpdate upgrade(TileEntityScreen tes, BlockSide side) { + CMessageScreenUpdate ret = new CMessageScreenUpdate(); + ret.pos = new Vector3i(tes.getPos()); + ret.side = side; + ret.action = UPDATE_UPGRADES; + + ArrayList upgrades = tes.getScreen(side).upgrades; + ret.upgrades = new ItemStack[upgrades.size()]; + + for(int i = 0; i < upgrades.size(); i++) + ret.upgrades[i] = upgrades.get(i).copy(); + + return ret; + } + @Override public void fromBytes(ByteBuf buf) { pos = new Vector3i(buf); @@ -97,6 +117,12 @@ public class CMessageScreenUpdate implements IMessage, Runnable { resolution = new Vector2i(buf); else if(action == UPDATE_TYPE) text = ByteBufUtils.readUTF8String(buf); + else if(action == UPDATE_UPGRADES) { + upgrades = new ItemStack[buf.readByte()]; + + for(int i = 0; i < upgrades.length; i++) + upgrades[i] = ByteBufUtils.readItemStack(buf); + } } @Override @@ -113,6 +139,12 @@ public class CMessageScreenUpdate implements IMessage, Runnable { resolution.writeTo(buf); else if(action == UPDATE_TYPE) ByteBufUtils.writeUTF8String(buf, text); + else if(action == UPDATE_UPGRADES) { + buf.writeByte(upgrades.length); + + for(ItemStack is: upgrades) + ByteBufUtils.writeItemStack(buf, is); + } } @Override