diff --git a/src/main/java/net/montoyo/wd/SharedProxy.java b/src/main/java/net/montoyo/wd/SharedProxy.java index f7433b8..e5817c7 100644 --- a/src/main/java/net/montoyo/wd/SharedProxy.java +++ b/src/main/java/net/montoyo/wd/SharedProxy.java @@ -10,6 +10,7 @@ import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.MinecraftServer; import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.Level; import net.minecraftforge.common.MinecraftForge; @@ -75,7 +76,7 @@ public class SharedProxy { public void screenUpdateAutoVolumeInGui(Vector3i pos, BlockSide side, boolean av) { } - public void displaySetPadURLGui(String padURL) { + public void displaySetPadURLGui(ItemStack is, String padURL) { Log.error("Called SharedProxy.displaySetPadURLGui() on server side..."); } diff --git a/src/main/java/net/montoyo/wd/client/ClientProxy.java b/src/main/java/net/montoyo/wd/client/ClientProxy.java index be3d80b..25cd46c 100644 --- a/src/main/java/net/montoyo/wd/client/ClientProxy.java +++ b/src/main/java/net/montoyo/wd/client/ClientProxy.java @@ -85,10 +85,10 @@ public class ClientProxy extends SharedProxy implements IDisplayHandler, IJSQuer public IBrowser view; private boolean isInHotbar; - private final int id; + private final UUID id; private long lastURLSent; - private PadData(String url, int id) { + private PadData(String url, UUID id) { String webUrl; try { webUrl = TileEntityScreen.url(url); @@ -130,7 +130,7 @@ public class ClientProxy extends SharedProxy implements IDisplayHandler, IJSQuer private int lastTracked = 0; //MinePads Management - private final HashMap padMap = new HashMap<>(); + private final HashMap padMap = new HashMap<>(); private final ArrayList padList = new ArrayList<>(); private int minePadTickCounter = 0; @@ -268,8 +268,8 @@ public class ClientProxy extends SharedProxy implements IDisplayHandler, IJSQuer } @Override - public void displaySetPadURLGui(String padURL) { - mc.setScreen(new GuiSetURL2(padURL)); + public void displaySetPadURLGui(ItemStack is, String padURL) { + mc.setScreen(new GuiSetURL2(is, padURL)); } @Override @@ -729,13 +729,13 @@ public class ClientProxy extends SharedProxy implements IDisplayHandler, IJSQuer CompoundTag tag = item.getTag(); if (tag != null && tag.contains("PadID")) - updatePad(tag.getInt("PadID"), tag, item == heldStack); + updatePad(tag.getUUID("PadID"), tag, item == heldStack); } } } } - private void updatePad(int id, CompoundTag tag, boolean isSelected) { + private void updatePad(UUID id, CompoundTag tag, boolean isSelected) { PadData pd = padMap.get(id); if(pd != null) @@ -751,7 +751,7 @@ public class ClientProxy extends SharedProxy implements IDisplayHandler, IJSQuer return minePadRenderer; } - public PadData getPadByID(int id) { + public PadData getPadByID(UUID id) { return padMap.get(id); } diff --git a/src/main/java/net/montoyo/wd/client/gui/GuiSetURL2.java b/src/main/java/net/montoyo/wd/client/gui/GuiSetURL2.java index 0b8e93e..4ba1cb9 100644 --- a/src/main/java/net/montoyo/wd/client/gui/GuiSetURL2.java +++ b/src/main/java/net/montoyo/wd/client/gui/GuiSetURL2.java @@ -7,7 +7,6 @@ package net.montoyo.wd.client.gui; import net.minecraft.core.BlockPos; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.InteractionHand; import net.minecraft.world.item.ItemStack; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.fml.common.Mod; @@ -17,120 +16,138 @@ 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.entity.TileEntityScreen; -import net.montoyo.wd.init.ItemInit; +import net.montoyo.wd.item.ItemMinePad2; import net.montoyo.wd.net.WDNetworkRegistry; import net.montoyo.wd.net.server_bound.C2SMessageScreenCtrl; +import net.montoyo.wd.net.server_bound.C2SMinepadUrl; import net.montoyo.wd.utilities.BlockSide; import net.montoyo.wd.utilities.Util; import net.montoyo.wd.utilities.Vector3i; import java.io.IOException; import java.util.Map; +import java.util.UUID; @Mod.EventBusSubscriber(Dist.CLIENT) public class GuiSetURL2 extends WDScreen { - - //Screen data - private TileEntityScreen tileEntity; - private BlockSide screenSide; - private Vector3i remoteLocation; - - //Pad data - private final boolean isPad; - - //Common - private final String screenURL; - - @FillControl - private TextField tfURL; - - @FillControl - private Button btnShutDown; - - @FillControl - private Button btnCancel; - - @FillControl - private Button btnOk; - - public GuiSetURL2(TileEntityScreen tes, BlockSide side, String url, Vector3i rl) { - super(Component.nullToEmpty(null)); - tileEntity = tes; - screenSide = side; - remoteLocation = rl; - isPad = false; - screenURL = url; - } - - public GuiSetURL2(String url) { - super(Component.nullToEmpty(null)); - isPad = true; - screenURL = url; - } - - @Override - public void init() { - super.init(); - loadFrom(new ResourceLocation("webdisplays", "gui/seturl.json")); - tfURL.setText(screenURL); - } - - @Override - protected void addLoadCustomVariables(Map vars) { - vars.put("isPad", isPad ? 1.0 : 0.0); - } - - @GuiSubscribe - public void onButtonClicked(Button.ClickEvent ev) { - if(ev.getSource() == btnCancel) - minecraft.setScreen(null); - else if(ev.getSource() == btnOk) - validate(tfURL.getText()); - else if(ev.getSource() == btnShutDown) { -// if(isPad) -// WDNetworkRegistry.INSTANCE.sendToServer(new SMessagePadCtrl("")); - - minecraft.setScreen(null); - } - } - - @GuiSubscribe - public void onEnterPressed(TextField.EnterPressedEvent ev) { - validate(ev.getText()); - } - - private void validate(String url) { - if(!url.isEmpty()) { - - try { - TileEntityScreen.url(url); - } catch (IOException e) { - throw new RuntimeException(e); - } - - url = Util.addProtocol(url); - url = ((ClientProxy) WebDisplays.PROXY).getMCEF().punycode(url); - - if(isPad) { -// WDNetworkRegistry.INSTANCE.sendToServer(new SMessagePadCtrl(url)); - ItemStack held = minecraft.player.getItemInHand(InteractionHand.MAIN_HAND); - - if(held.getItem().equals(ItemInit.itemMinePad.get()) && held.getTag() != null && held.getTag().contains("PadID")) { - ClientProxy.PadData pd = ((ClientProxy) WebDisplays.PROXY).getPadByID(held.getTag().getInt("PadID")); - - if(pd != null && pd.view != null) { - pd.view.loadURL(WebDisplays.applyBlacklist(url)); - } - } - } else WDNetworkRegistry.INSTANCE.sendToServer(C2SMessageScreenCtrl.setURL(tileEntity, screenSide, url, remoteLocation)); - } - - minecraft.setScreen(null); - } - - @Override - public boolean isForBlock(BlockPos bp, BlockSide side) { - return (remoteLocation != null && remoteLocation.equalsBlockPos(bp)) || (bp.equals(tileEntity.getBlockPos()) && side == screenSide); - } - + + //Screen data + private TileEntityScreen tileEntity; + private BlockSide screenSide; + private Vector3i remoteLocation; + + //Pad data + private ItemStack stack; + private final boolean isPad; + + //Common + private final String screenURL; + + @FillControl + private TextField tfURL; + + @FillControl + private Button btnShutDown; + + @FillControl + private Button btnCancel; + + @FillControl + private Button btnOk; + + public GuiSetURL2(TileEntityScreen tes, BlockSide side, String url, Vector3i rl) { + super(Component.nullToEmpty(null)); + tileEntity = tes; + screenSide = side; + remoteLocation = rl; + isPad = false; + screenURL = url; + } + + public GuiSetURL2(ItemStack is, String url) { + super(Component.nullToEmpty(null)); + isPad = true; + stack = is; + screenURL = url; + } + + @Override + public void init() { + super.init(); + loadFrom(new ResourceLocation("webdisplays", "gui/seturl.json")); + tfURL.setText(screenURL); + } + + @Override + protected void addLoadCustomVariables(Map vars) { + vars.put("isPad", isPad ? 1.0 : 0.0); + } + + protected UUID getUUID() { + if (stack == null || !(stack.getItem() instanceof ItemMinePad2)) + throw new RuntimeException("Get UUID is being called for a non-minepad UI"); + if (!stack.hasTag()) + stack.getOrCreateTag().putUUID("PadID", UUID.randomUUID()); + + return stack.getTag().getUUID("PadID"); + } + + @GuiSubscribe + public void onButtonClicked(Button.ClickEvent ev) { + if (ev.getSource() == btnCancel) + minecraft.setScreen(null); + else if (ev.getSource() == btnOk) + validate(tfURL.getText()); + else if (ev.getSource() == btnShutDown) { + if (isPad) { + WDNetworkRegistry.INSTANCE.sendToServer(new C2SMinepadUrl( + getUUID(), + "" + )); + stack.getTag().remove("PadURL"); + } + + minecraft.setScreen(null); + } + } + + @GuiSubscribe + public void onEnterPressed(TextField.EnterPressedEvent ev) { + validate(ev.getText()); + } + + private void validate(String url) { + if (!url.isEmpty()) { + + try { + TileEntityScreen.url(url); + } catch (IOException e) { + throw new RuntimeException(e); + } + + url = Util.addProtocol(url); + url = ((ClientProxy) WebDisplays.PROXY).getMCEF().punycode(url); + + if (isPad) { + UUID uuid = getUUID(); + WDNetworkRegistry.INSTANCE.sendToServer(new C2SMinepadUrl(uuid, url)); + stack.getTag().putString("PadURL", url); + + ClientProxy.PadData pd = ((ClientProxy) WebDisplays.PROXY).getPadByID(uuid); + + if (pd != null && pd.view != null) { + pd.view.loadURL(WebDisplays.applyBlacklist(url)); + } + } else + WDNetworkRegistry.INSTANCE.sendToServer(C2SMessageScreenCtrl.setURL(tileEntity, screenSide, url, remoteLocation)); + } + + minecraft.setScreen(null); + } + + @Override + public boolean isForBlock(BlockPos bp, BlockSide side) { + return (remoteLocation != null && remoteLocation.equalsBlockPos(bp)) || (bp.equals(tileEntity.getBlockPos()) && side == screenSide); + } + } diff --git a/src/main/java/net/montoyo/wd/client/renderers/MinePadRenderer.java b/src/main/java/net/montoyo/wd/client/renderers/MinePadRenderer.java index 3768189..c500017 100644 --- a/src/main/java/net/montoyo/wd/client/renderers/MinePadRenderer.java +++ b/src/main/java/net/montoyo/wd/client/renderers/MinePadRenderer.java @@ -6,11 +6,8 @@ package net.montoyo.wd.client.renderers; import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.math.Matrix3f; -import com.mojang.math.Matrix4f; import com.mojang.math.Vector3f; import net.minecraft.client.Minecraft; -import net.minecraft.client.player.AbstractClientPlayer; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.entity.player.PlayerRenderer; import net.minecraft.resources.ResourceLocation; @@ -20,8 +17,6 @@ import net.minecraftforge.api.distmarker.OnlyIn; import net.montoyo.wd.WebDisplays; import net.montoyo.wd.client.ClientProxy; -import static org.lwjgl.opengl.GL12.GL_RESCALE_NORMAL; - @OnlyIn(Dist.CLIENT) public final class MinePadRenderer implements IItemRenderer { @@ -94,7 +89,7 @@ public final class MinePadRenderer implements IItemRenderer { //Render web view if(is.getTag() != null && is.getTag().contains("PadID")) { - ClientProxy.PadData pd = clientProxy.getPadByID(is.getTag().getInt("PadID")); + ClientProxy.PadData pd = clientProxy.getPadByID(is.getTag().getUUID("PadID")); if(pd != null) { stack.translate(0.063f, 0.28f, 0.001f); diff --git a/src/main/java/net/montoyo/wd/item/ItemMinePad2.java b/src/main/java/net/montoyo/wd/item/ItemMinePad2.java index 3801d3a..026bb73 100644 --- a/src/main/java/net/montoyo/wd/item/ItemMinePad2.java +++ b/src/main/java/net/montoyo/wd/item/ItemMinePad2.java @@ -25,85 +25,85 @@ import javax.annotation.Nullable; import java.util.UUID; public class ItemMinePad2 extends Item implements WDItem { - - public ItemMinePad2(Properties properties) { - super(properties - //setRegistryName("minepad"); - .stacksTo(1) - //TODO what is Full3D(); - .defaultDurability(0) - .tab(WebDisplays.CREATIVE_TAB)); - } - - private static String getURL(ItemStack is) { - if(is.getTag() == null || !is.getTag().contains("PadURL")) - return WebDisplays.INSTANCE.homePage; - else - return is.getTag().getString("PadURL"); - } - - @Override - @Nonnull - public InteractionResultHolder use(Level world, Player ply, @Nonnull InteractionHand hand) { - ItemStack is = ply.getItemInHand(hand); - boolean ok; - - if(ply.isShiftKeyDown()) { - if(world.isClientSide) - WebDisplays.PROXY.displaySetPadURLGui(getURL(is)); - - ok = true; - } else if(is.getTag() != null && is.getTag().contains("PadID")) { - if(world.isClientSide) - WebDisplays.PROXY.openMinePadGui(is.getTag().getInt("PadID")); - - ok = true; - } else - ok = false; - - return new InteractionResultHolder<>(ok ? InteractionResult.SUCCESS : InteractionResult.PASS, is); - } - - - @Override - public boolean onEntityItemUpdate(ItemStack stack, ItemEntity ent) { - if(ent.isOnGround() && !ent.getLevel().isClientSide) { - CompoundTag tag = ent.getItem().getTag(); - - if(tag != null && tag.contains("ThrowHeight")) { - //Delete it, it touched the ground - double height = tag.getDouble("ThrowHeight"); - UUID thrower = null; - - if(tag.contains("ThrowerMSB") && tag.contains("ThrowerLSB")) - thrower = new UUID(tag.getLong("ThrowerMSB"), tag.getLong("ThrowerLSB")); - - if(tag.contains("PadID") || tag.contains("PadURL")) { - tag.remove("ThrowerMSB"); - tag.remove("ThrowerLSB"); - tag.remove("ThrowHeight"); - } else //We can delete the whole tag - ent.getItem().setTag(null); - - if(thrower != null && height - ent.getBlockY() >= 20.0) { - ent.getLevel().playSound(null, ent.getBlockX(), ent.getBlockY(), ent.getBlockZ(), SoundEvents.GLASS_BREAK, SoundSource.BLOCKS, 4.0f, 1.0f); - ent.getLevel().addFreshEntity(new ItemEntity(ent.getLevel(), ent.getBlockX(), ent.getBlockY(), ent.getBlockZ(), CraftComponent.EXTCARD.makeItemStack())); - ent.setRemoved(Entity.RemovalReason.CHANGED_DIMENSION); - - Player ply = ent.getLevel().getPlayerByUUID(thrower); - if(ply != null && ply instanceof ServerPlayer) - WebDisplays.INSTANCE.criterionPadBreak.trigger(((ServerPlayer) ply).getAdvancements()); - } - } - } - - return false; - } - - @Nullable - @Override - public String getWikiName(@Nonnull ItemStack is) { - return is.getItem().getName(is).getString(); - } - + + public ItemMinePad2(Properties properties) { + super(properties + //setRegistryName("minepad"); + .stacksTo(1) + //TODO what is Full3D(); + .defaultDurability(0) + .tab(WebDisplays.CREATIVE_TAB)); + } + + private static String getURL(ItemStack is) { + if (is.getTag() == null || !is.getTag().contains("PadURL")) + return WebDisplays.INSTANCE.homePage; + else + return is.getTag().getString("PadURL"); + } + + @Override + @Nonnull + public InteractionResultHolder use(Level world, Player ply, @Nonnull InteractionHand hand) { + ItemStack is = ply.getItemInHand(hand); + boolean ok; + + if (ply.isShiftKeyDown()) { + if (world.isClientSide) + WebDisplays.PROXY.displaySetPadURLGui(is, getURL(is)); + + ok = true; + } else if (is.getTag() != null && is.getTag().contains("PadID")) { + if (world.isClientSide) + WebDisplays.PROXY.openMinePadGui(is.getTag().getInt("PadID")); + + ok = true; + } else + ok = false; + + return new InteractionResultHolder<>(ok ? InteractionResult.SUCCESS : InteractionResult.PASS, is); + } + + + @Override + public boolean onEntityItemUpdate(ItemStack stack, ItemEntity ent) { + if (ent.isOnGround() && !ent.getLevel().isClientSide) { + CompoundTag tag = ent.getItem().getTag(); + + if (tag != null && tag.contains("ThrowHeight")) { + //Delete it, it touched the ground + double height = tag.getDouble("ThrowHeight"); + UUID thrower = null; + + if (tag.contains("ThrowerMSB") && tag.contains("ThrowerLSB")) + thrower = new UUID(tag.getLong("ThrowerMSB"), tag.getLong("ThrowerLSB")); + + if (tag.contains("PadID") || tag.contains("PadURL")) { + tag.remove("ThrowerMSB"); + tag.remove("ThrowerLSB"); + tag.remove("ThrowHeight"); + } else //We can delete the whole tag + ent.getItem().setTag(null); + + if (thrower != null && height - ent.getBlockY() >= 20.0) { + ent.getLevel().playSound(null, ent.getBlockX(), ent.getBlockY(), ent.getBlockZ(), SoundEvents.GLASS_BREAK, SoundSource.BLOCKS, 4.0f, 1.0f); + ent.getLevel().addFreshEntity(new ItemEntity(ent.getLevel(), ent.getBlockX(), ent.getBlockY(), ent.getBlockZ(), CraftComponent.EXTCARD.makeItemStack())); + ent.setRemoved(Entity.RemovalReason.CHANGED_DIMENSION); + + Player ply = ent.getLevel().getPlayerByUUID(thrower); + if (ply != null && ply instanceof ServerPlayer) + WebDisplays.INSTANCE.criterionPadBreak.trigger(((ServerPlayer) ply).getAdvancements()); + } + } + } + + return false; + } + + @Nullable + @Override + public String getWikiName(@Nonnull ItemStack is) { + return is.getItem().getName(is).getString(); + } + } diff --git a/src/main/java/net/montoyo/wd/net/WDNetworkRegistry.java b/src/main/java/net/montoyo/wd/net/WDNetworkRegistry.java index 6fbc7b5..faf519d 100644 --- a/src/main/java/net/montoyo/wd/net/WDNetworkRegistry.java +++ b/src/main/java/net/montoyo/wd/net/WDNetworkRegistry.java @@ -4,10 +4,7 @@ import net.minecraft.resources.ResourceLocation; import net.minecraftforge.network.NetworkRegistry; import net.minecraftforge.network.simple.SimpleChannel; import net.montoyo.wd.net.client_bound.*; -import net.montoyo.wd.net.server_bound.C2SMessageACQuery; -import net.montoyo.wd.net.server_bound.C2SMessageMiniservConnect; -import net.montoyo.wd.net.server_bound.C2SMessageRedstoneCtrl; -import net.montoyo.wd.net.server_bound.C2SMessageScreenCtrl; +import net.montoyo.wd.net.server_bound.*; import java.util.ArrayList; @@ -53,6 +50,9 @@ public class WDNetworkRegistry { // jsquery entries.add(new NetworkEntry<>(S2CMessageJSResponse.class, S2CMessageJSResponse::new)); + // minepad + entries.add(new NetworkEntry<>(C2SMinepadUrl.class, C2SMinepadUrl::new)); + for (int i = 0; i < entries.size(); i++) entries.get(i).register(i, INSTANCE); } diff --git a/src/main/java/net/montoyo/wd/net/server_bound/C2SMinepadUrl.java b/src/main/java/net/montoyo/wd/net/server_bound/C2SMinepadUrl.java new file mode 100644 index 0000000..29fede8 --- /dev/null +++ b/src/main/java/net/montoyo/wd/net/server_bound/C2SMinepadUrl.java @@ -0,0 +1,43 @@ +package net.montoyo.wd.net.server_bound; + +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.item.ItemStack; +import net.minecraftforge.network.NetworkEvent; +import net.montoyo.wd.item.ItemMinePad2; +import net.montoyo.wd.net.Packet; + +import java.util.UUID; + +public class C2SMinepadUrl extends Packet { + UUID id; + String url; + + public C2SMinepadUrl(UUID id, String url) { + this.id = id; + this.url = url; + } + + public C2SMinepadUrl(FriendlyByteBuf buf) { + super(buf); + this.id = buf.readUUID(); + this.url = buf.readUtf(); + } + + @Override + public void write(FriendlyByteBuf buf) { + buf.writeUUID(id); + buf.writeUtf(url); + } + + @Override + public void handle(NetworkEvent.Context ctx) { + for (InteractionHand value : InteractionHand.values()) { + ItemStack stack = ctx.getSender().getItemInHand(value); + if (stack.getItem() instanceof ItemMinePad2 pad) { + stack.getOrCreateTag().putUUID("PadID", id); + stack.getOrCreateTag().putString("PadURL", url); + } + } + } +} diff --git a/src/main/resources/assets/webdisplays/lang/en_us.json b/src/main/resources/assets/webdisplays/lang/en_us.json index c96ad5c..c891b92 100644 --- a/src/main/resources/assets/webdisplays/lang/en_us.json +++ b/src/main/resources/assets/webdisplays/lang/en_us.json @@ -12,15 +12,15 @@ "item.webdisplays.ownerthief": "Ownership Thief [ADMIN]", "item.webdisplays.linker": "Linking Tool", "item.webdisplays.craftcomp": "Craft Component", - "item.webdisplays.craftcomp.stonekey": "Stone Key", - "item.webdisplays.craftcomp.upgrade": "Blank Upgrade", - "item.webdisplays.craftcomp.peripheral": "Peripheral Base", - "item.webdisplays.craftcomp.batcell": "Battery Cell", - "item.webdisplays.craftcomp.batpack": "Battery Pack", - "item.webdisplays.craftcomp.laserdiode": "650nm Laser Diode", - "item.webdisplays.craftcomp.backlight": "Backlight", - "item.webdisplays.craftcomp.extcard": "Extension Card", - "item.webdisplays.craftcomp.badextcard": "Bad Extension Card", + "item.webdisplays.craftcomp_stonekey": "Stone Key", + "item.webdisplays.craftcomp_upgrade": "Blank Upgrade", + "item.webdisplays.craftcomp_peripheral": "Peripheral Base", + "item.webdisplays.craftcomp_batcell": "Battery Cell", + "item.webdisplays.craftcomp_batpack": "Battery Pack", + "item.webdisplays.craftcomp_laserdiode": "650nm Laser Diode", + "item.webdisplays.craftcomp_backlight": "Backlight", + "item.webdisplays.craftcomp_extcard": "Extension Card", + "item.webdisplays.craftcomp_badextcard": "Bad Extension Card", "item.webdisplays.minepad": "minePad", "item.webdisplays.minepad2": "minePad 2", "item.webdisplays.upgrade": "Screen Upgrade", @@ -45,7 +45,7 @@ "webdisplays.message.linked": "Linked!", "webdisplays.message.linkError": "Link error :( Check logs...", "webdisplays.message.notAScreen": "Please right click on the screen first...", - "webdisplays.message.screenSet2": "Screen set! Now right click on the periphe,ral...", + "webdisplays.message.screenSet2": "Screen set! Now right click on the peripheral...", "webdisplays.message.chunkUnloaded": "The chunk the screen is placed in is no,t loaded!", "webdisplays.message.notLinked": "This peripheral has not been linked yet.", "webdisplays.message.missingCC": "ComputerCraft is not available.", @@ -108,7 +108,7 @@ "advancements.webdisplays.minepad2.title": "Pigeon", "advancements.webdisplays.minepad2.description": "Craft a minePad 2. Look, I know it's expensive, but that means it's better than anything else, right? ...right?", "advancements.webdisplays.linkperipheral.title": "It's wireless!", - "advancements.webdisplays.linkperipheral.description": "Link a peripheral to ,a screen", + "advancements.webdisplays.linkperipheral.description": "Link a peripheral to a screen", "advancements.webdisplays.keyboardcat.title": "DAMN CATS", "advancements.webdisplays.keyboardcat.description": "Have an ocelot walk on y,our keyboard", "advancements.webdisplays.upgrade.title": "More than a screen",