From 684d9e9c9f878c6f45bbc545ad53a15e815be606 Mon Sep 17 00:00:00 2001 From: LordMZTE Date: Fri, 26 May 2023 18:40:04 +0200 Subject: [PATCH] feat: implement repairer --- .../net/anvilcraft/thaummach/ClientProxy.java | 7 + .../net/anvilcraft/thaummach/CommonProxy.java | 6 + .../java/net/anvilcraft/thaummach/GuiID.java | 1 + .../thaummach/blocks/BlockApparatusWood.java | 61 +-- .../container/ContainerRepairer.java | 81 ++++ .../thaummach/gui/GuiCondenser.java | 11 +- .../thaummach/gui/GuiCrystallizer.java | 12 +- .../anvilcraft/thaummach/gui/GuiRepairer.java | 47 ++ .../wood/RepairerAparatusRenderer.java | 104 ++++ .../thaummach/render/model/ModelGear.java | 56 +++ .../render/tile/TileBoreRenderer.java | 15 - .../render/tile/TileRepairerRenderer.java | 60 +++ .../thaummach/tiles/TileConduitTank.java | 3 + .../thaummach/tiles/TileRepairer.java | 448 ++++++++++++++++++ .../anvilcraft/thaummach/utils/UtilsFX.java | 15 + .../resources/assets/thaummach/sounds.json | 9 + .../assets/thaummach/sounds/tinkering.ogg | Bin 0 -> 22483 bytes .../thaummach/textures/guis/repairer.png | Bin 0 -> 3750 bytes .../assets/thaummach/textures/models/gear.png | Bin 0 -> 866 bytes 19 files changed, 856 insertions(+), 80 deletions(-) create mode 100644 src/main/java/net/anvilcraft/thaummach/container/ContainerRepairer.java create mode 100644 src/main/java/net/anvilcraft/thaummach/gui/GuiRepairer.java create mode 100644 src/main/java/net/anvilcraft/thaummach/render/apparatus/apparati/wood/RepairerAparatusRenderer.java create mode 100644 src/main/java/net/anvilcraft/thaummach/render/model/ModelGear.java create mode 100644 src/main/java/net/anvilcraft/thaummach/render/tile/TileRepairerRenderer.java create mode 100644 src/main/java/net/anvilcraft/thaummach/tiles/TileRepairer.java create mode 100644 src/main/resources/assets/thaummach/sounds/tinkering.ogg create mode 100644 src/main/resources/assets/thaummach/textures/guis/repairer.png create mode 100644 src/main/resources/assets/thaummach/textures/models/gear.png diff --git a/src/main/java/net/anvilcraft/thaummach/ClientProxy.java b/src/main/java/net/anvilcraft/thaummach/ClientProxy.java index d3961a0..083c3dc 100644 --- a/src/main/java/net/anvilcraft/thaummach/ClientProxy.java +++ b/src/main/java/net/anvilcraft/thaummach/ClientProxy.java @@ -9,6 +9,7 @@ import net.anvilcraft.thaummach.gui.GuiArcaneFurnace; import net.anvilcraft.thaummach.gui.GuiBore; import net.anvilcraft.thaummach.gui.GuiCondenser; import net.anvilcraft.thaummach.gui.GuiCrystallizer; +import net.anvilcraft.thaummach.gui.GuiRepairer; import net.anvilcraft.thaummach.gui.GuiSoulBrazier; import net.anvilcraft.thaummach.gui.GuiVoidChest; import net.anvilcraft.thaummach.gui.GuiVoidInterface; @@ -18,6 +19,7 @@ import net.anvilcraft.thaummach.render.tile.TileBoreRenderer; import net.anvilcraft.thaummach.render.tile.TileCondenserRenderer; import net.anvilcraft.thaummach.render.tile.TileConduitPumpRenderer; import net.anvilcraft.thaummach.render.tile.TileCrystallizerRenderer; +import net.anvilcraft.thaummach.render.tile.TileRepairerRenderer; import net.anvilcraft.thaummach.render.tile.TileSealRenderer; import net.anvilcraft.thaummach.render.tile.TileVoidChestRenderer; import net.anvilcraft.thaummach.render.tile.TileVoidInterfaceRenderer; @@ -33,6 +35,7 @@ import net.anvilcraft.thaummach.tiles.TileCrucible; import net.anvilcraft.thaummach.tiles.TileCrystallizer; import net.anvilcraft.thaummach.tiles.TileFilter; import net.anvilcraft.thaummach.tiles.TilePurifier; +import net.anvilcraft.thaummach.tiles.TileRepairer; import net.anvilcraft.thaummach.tiles.TileSeal; import net.anvilcraft.thaummach.tiles.TileSoulBrazier; import net.anvilcraft.thaummach.tiles.TileVoidChest; @@ -76,6 +79,7 @@ public class ClientProxy extends CommonProxy { ClientRegistry.registerTileEntity(TileCondenser.class, "condenser", new TileCondenserRenderer()); ClientRegistry.registerTileEntity(TileConduitPump.class, "conduit_pump", new TileConduitPumpRenderer()); ClientRegistry.registerTileEntity(TileCrystallizer.class, "crystallizer", new TileCrystallizerRenderer()); + ClientRegistry.registerTileEntity(TileRepairer.class, "repairer", new TileRepairerRenderer()); ClientRegistry.registerTileEntity(TileSeal.class, "seal", new TileSealRenderer()); ClientRegistry.registerTileEntity(TileVoidChest.class, "voidChest", new TileVoidChestRenderer()); ClientRegistry.registerTileEntity(TileVoidInterface.class, "voidInterface", new TileVoidInterfaceRenderer()); @@ -99,6 +103,9 @@ public class ClientProxy extends CommonProxy { case CRYSTALLIZER: return new GuiCrystallizer(player.inventory, (TileCrystallizer) te); + case REPAIRER: + return new GuiRepairer(player.inventory, (TileRepairer) te); + case SOUL_BRAZIER: return new GuiSoulBrazier(player.inventory, (TileSoulBrazier) te); diff --git a/src/main/java/net/anvilcraft/thaummach/CommonProxy.java b/src/main/java/net/anvilcraft/thaummach/CommonProxy.java index 2e53a28..b4b5ed5 100644 --- a/src/main/java/net/anvilcraft/thaummach/CommonProxy.java +++ b/src/main/java/net/anvilcraft/thaummach/CommonProxy.java @@ -6,6 +6,7 @@ import net.anvilcraft.thaummach.container.ContainerArcaneFurnace; import net.anvilcraft.thaummach.container.ContainerBore; import net.anvilcraft.thaummach.container.ContainerCondenser; import net.anvilcraft.thaummach.container.ContainerCrystallizer; +import net.anvilcraft.thaummach.container.ContainerRepairer; import net.anvilcraft.thaummach.container.ContainerSoulBrazier; import net.anvilcraft.thaummach.container.ContainerVoidChest; import net.anvilcraft.thaummach.container.ContainerVoidInterface; @@ -21,6 +22,7 @@ import net.anvilcraft.thaummach.tiles.TileCrucible; import net.anvilcraft.thaummach.tiles.TileCrystallizer; import net.anvilcraft.thaummach.tiles.TileFilter; import net.anvilcraft.thaummach.tiles.TilePurifier; +import net.anvilcraft.thaummach.tiles.TileRepairer; import net.anvilcraft.thaummach.tiles.TileSeal; import net.anvilcraft.thaummach.tiles.TileSoulBrazier; import net.anvilcraft.thaummach.tiles.TileVoidChest; @@ -48,6 +50,7 @@ public class CommonProxy implements IGuiHandler { GameRegistry.registerTileEntity(TileCrystallizer.class, "crystallizer"); GameRegistry.registerTileEntity(TileFilter.class, "filter"); GameRegistry.registerTileEntity(TilePurifier.class, "purifier"); + GameRegistry.registerTileEntity(TileRepairer.class, "repairer"); GameRegistry.registerTileEntity(TileSeal.class, "seal"); GameRegistry.registerTileEntity(TileSoulBrazier.class, "soulBrazier"); GameRegistry.registerTileEntity(TileVoidChest.class, "voidChest"); @@ -74,6 +77,9 @@ public class CommonProxy implements IGuiHandler { case CRYSTALLIZER: return new ContainerCrystallizer(player.inventory, (TileCrystallizer) te); + case REPAIRER: + return new ContainerRepairer(player.inventory, (TileRepairer) te); + case SOUL_BRAZIER: return new ContainerSoulBrazier(player.inventory, (TileSoulBrazier) te); diff --git a/src/main/java/net/anvilcraft/thaummach/GuiID.java b/src/main/java/net/anvilcraft/thaummach/GuiID.java index f670d37..58f1db0 100644 --- a/src/main/java/net/anvilcraft/thaummach/GuiID.java +++ b/src/main/java/net/anvilcraft/thaummach/GuiID.java @@ -5,6 +5,7 @@ public enum GuiID { BORE, CONDENSER, CRYSTALLIZER, + REPAIRER, SOUL_BRAZIER, VOID_CHEST, VOID_INTERFACE; diff --git a/src/main/java/net/anvilcraft/thaummach/blocks/BlockApparatusWood.java b/src/main/java/net/anvilcraft/thaummach/blocks/BlockApparatusWood.java index 6bd7428..e435b3b 100644 --- a/src/main/java/net/anvilcraft/thaummach/blocks/BlockApparatusWood.java +++ b/src/main/java/net/anvilcraft/thaummach/blocks/BlockApparatusWood.java @@ -11,7 +11,9 @@ import net.anvilcraft.thaummach.particles.FXWisp; import net.anvilcraft.thaummach.render.BlockApparatusRenderer; import net.anvilcraft.thaummach.render.apparatus.IApparatusRenderer; import net.anvilcraft.thaummach.render.apparatus.apparati.wood.CondenserApparatusRenderer; +import net.anvilcraft.thaummach.render.apparatus.apparati.wood.RepairerAparatusRenderer; import net.anvilcraft.thaummach.tiles.TileCondenser; +import net.anvilcraft.thaummach.tiles.TileRepairer; import net.minecraft.block.Block; import net.minecraft.block.material.Material; import net.minecraft.client.Minecraft; @@ -93,6 +95,9 @@ public class BlockApparatusWood extends BlockApparatus { case CONDENSER: return CondenserApparatusRenderer.INSTANCE; + case REPAIRER: + return RepairerAparatusRenderer.INSTANCE; + default: return null; } @@ -116,6 +121,9 @@ public class BlockApparatusWood extends BlockApparatus { case CONDENSER: return new TileCondenser(); + case REPAIRER: + return new TileRepairer(); + //case DUPLICATOR: // return new TileDuplicator(); // @@ -199,51 +207,6 @@ public class BlockApparatusWood extends BlockApparatus { } } - @Override - public void breakBlock(World world, int i, int j, int k, Block block, int meta_) { - // TODO: not sure if param 6 is meta - MetaVals meta = MetaVals.get(meta_); - if (meta == MetaVals.CONDENSER) { - // TODO: condenser - //TileCondenser tileentityCondenser - // = (TileCondenser) world.getBlockTileEntity(i, j, k); - //if (tileentityCondenser != null && tileentityCondenser.degredation > 0.0F) { - // int at = (int - // ) (25.0F * (4550.0F - tileentityCondenser.degredation) / 4550.0F); - // int auraX = i >> 4; - // int auraZ = k >> 4; - // SIAuraChunk ac = (SIAuraChunk) mod_ThaumCraft.AuraHM.get( - // Arrays.asList(auraX, auraZ, ThaumCraftCore.getDimension(world)) - // ); - // if (ac != null) { - // ac.taint = (short) (ac.taint + at); - // world.playSoundEffect( - // (double) i, - // (double) j, - // (double) k, - // "random.fizz", - // 0.2F, - // 2.0F + world.rand.nextFloat() * 0.4F - // ); - - // for (int a = 0; a < at; ++a) { - // world.spawnParticle( - // "largesmoke", - // (double) ((float) i + world.rand.nextFloat()), - // (double) ((float) j + world.rand.nextFloat()), - // (double) ((float) k + world.rand.nextFloat()), - // 0.0, - // 0.0, - // 0.0 - // ); - // } - // } - //} - } - - super.breakBlock(world, i, j, k, block, meta_); - } - @Override public void onNeighborBlockChange(World world, int i, int j, int k, Block l) { super.onNeighborBlockChange(world, i, j, k, l); @@ -311,9 +274,11 @@ public class BlockApparatusWood extends BlockApparatus { // return 72; // } - //} else if (md == 2) { - // return l <= 1 ? 86 : 87; - //} else if (md == 3) { + //} + else if (md == MetaVals.REPAIRER) { + return l <= 1 ? this.iconRestorerTop : this.iconRestorerSide; + } + //else if (md == 3) { // return l <= 1 ? 127 : 121 + Math.abs((i + j + k) % 6); //} else if (md == 4) { // return l <= 1 ? 143 : 137 + Math.abs((i + j + k) % 6); diff --git a/src/main/java/net/anvilcraft/thaummach/container/ContainerRepairer.java b/src/main/java/net/anvilcraft/thaummach/container/ContainerRepairer.java new file mode 100644 index 0000000..0b603a9 --- /dev/null +++ b/src/main/java/net/anvilcraft/thaummach/container/ContainerRepairer.java @@ -0,0 +1,81 @@ +package net.anvilcraft.thaummach.container; + +import net.anvilcraft.thaummach.OutputSlot; +import net.anvilcraft.thaummach.tiles.TileRepairer; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.InventoryPlayer; +import net.minecraft.inventory.Container; +import net.minecraft.inventory.Slot; +import net.minecraft.item.ItemStack; + +public class ContainerRepairer extends Container { + public ContainerRepairer(InventoryPlayer inventoryplayer, TileRepairer tileEntity) { + int j; + int k; + for (j = 0; j < 3; ++j) { + for (k = 0; k < 2; ++k) { + this.addSlotToContainer( + new Slot(tileEntity, k + j * 2, 37 + k * 18, 16 + j * 18) + ); + } + } + + for (j = 0; j < 3; ++j) { + for (k = 0; k < 2; ++k) { + this.addSlotToContainer( + new OutputSlot(tileEntity, 6 + k + j * 2, 90 + k * 18, 16 + j * 18) + ); + } + } + + for (j = 0; j < 3; ++j) { + for (k = 0; k < 9; ++k) { + this.addSlotToContainer( + new Slot(inventoryplayer, k + j * 9 + 9, 8 + k * 18, 84 + j * 18) + ); + } + } + + for (j = 0; j < 9; ++j) { + this.addSlotToContainer(new Slot(inventoryplayer, j, 8 + j * 18, 142)); + } + } + + @Override + public ItemStack transferStackInSlot(EntityPlayer pl, int i) { + ItemStack itemstack = null; + Slot slot = (Slot) super.inventorySlots.get(i); + if (slot != null && slot.getHasStack()) { + ItemStack itemstack1 = slot.getStack(); + itemstack = itemstack1.copy(); + if (i < 12) { + if (!this.mergeItemStack(itemstack1, 12, 48, true)) { + return null; + } + } else if (i >= 12 && i < 48) { + if (!this.mergeItemStack(itemstack1, 0, 6, false)) { + return null; + } + } else if (!this.mergeItemStack(itemstack1, 12, 48, false)) { + return null; + } + + if (itemstack1.stackSize == 0) { + slot.putStack((ItemStack) null); + } else { + slot.onSlotChanged(); + } + + if (itemstack1.stackSize == itemstack.stackSize) { + return null; + } + } + + return itemstack; + } + + @Override + public boolean canInteractWith(EntityPlayer p_75145_1_) { + return true; + } +} diff --git a/src/main/java/net/anvilcraft/thaummach/gui/GuiCondenser.java b/src/main/java/net/anvilcraft/thaummach/gui/GuiCondenser.java index 73424ff..12af2e3 100644 --- a/src/main/java/net/anvilcraft/thaummach/gui/GuiCondenser.java +++ b/src/main/java/net/anvilcraft/thaummach/gui/GuiCondenser.java @@ -3,6 +3,7 @@ package net.anvilcraft.thaummach.gui; import net.anvilcraft.thaummach.TMItems; import net.anvilcraft.thaummach.container.ContainerCondenser; import net.anvilcraft.thaummach.tiles.TileCondenser; +import net.anvilcraft.thaummach.utils.UtilsFX; import net.minecraft.client.gui.inventory.GuiContainer; import net.minecraft.client.renderer.texture.TextureMap; import net.minecraft.entity.player.InventoryPlayer; @@ -40,15 +41,7 @@ public class GuiCondenser extends GuiContainer { for (int upgIdx = 0; upgIdx <= 1; upgIdx++) { int upgMeta = this.arcaneCondenser.getUpgrades()[upgIdx]; - if (upgMeta >= 0) { - this.drawTexturedModelRectFromIcon( - l + 56 + 48 * upgIdx, - i1 + 56, - TMItems.upgrade.getIconFromDamage(upgMeta), - 16, - 16 - ); - } + UtilsFX.renderUpgradeIntoGUI(this, upgMeta, l + 56 + 48 * upgIdx, i1 + 56); } } } diff --git a/src/main/java/net/anvilcraft/thaummach/gui/GuiCrystallizer.java b/src/main/java/net/anvilcraft/thaummach/gui/GuiCrystallizer.java index a9351ea..4150339 100644 --- a/src/main/java/net/anvilcraft/thaummach/gui/GuiCrystallizer.java +++ b/src/main/java/net/anvilcraft/thaummach/gui/GuiCrystallizer.java @@ -1,12 +1,11 @@ package net.anvilcraft.thaummach.gui; -import net.anvilcraft.thaummach.TMItems; import net.anvilcraft.thaummach.container.ContainerCrystallizer; import net.anvilcraft.thaummach.tiles.TileCrystallizer; +import net.anvilcraft.thaummach.utils.UtilsFX; import net.minecraft.client.gui.inventory.GuiContainer; import net.minecraft.client.renderer.texture.TextureMap; import net.minecraft.entity.player.InventoryPlayer; -import net.minecraft.util.IIcon; import net.minecraft.util.ResourceLocation; import org.lwjgl.opengl.GL11; @@ -47,13 +46,10 @@ public class GuiCrystallizer extends GuiContainer { } if (this.crystallizerInventory.getUpgrades()[0] >= 0) { - IIcon itemIcon = TMItems.upgrade.getIconFromDamage( - this.crystallizerInventory.getUpgrades()[0] - ); - this.mc.renderEngine.bindTexture(TextureMap.locationItemsTexture); - - this.drawTexturedModelRectFromIcon(j + 8, k + 128, itemIcon, 16, 16); + UtilsFX.renderUpgradeIntoGUI( + this, this.crystallizerInventory.getUpgrades()[0], j + 8, k + 128 + ); } } } diff --git a/src/main/java/net/anvilcraft/thaummach/gui/GuiRepairer.java b/src/main/java/net/anvilcraft/thaummach/gui/GuiRepairer.java new file mode 100644 index 0000000..3a564a6 --- /dev/null +++ b/src/main/java/net/anvilcraft/thaummach/gui/GuiRepairer.java @@ -0,0 +1,47 @@ +package net.anvilcraft.thaummach.gui; + +import net.anvilcraft.thaummach.container.ContainerRepairer; +import net.anvilcraft.thaummach.tiles.TileRepairer; +import net.anvilcraft.thaummach.utils.UtilsFX; +import net.minecraft.client.gui.inventory.GuiContainer; +import net.minecraft.client.renderer.texture.TextureMap; +import net.minecraft.entity.player.InventoryPlayer; +import net.minecraft.util.ResourceLocation; +import org.lwjgl.opengl.GL11; + +public class GuiRepairer extends GuiContainer { + private TileRepairer repairerInventory; + + public GuiRepairer(InventoryPlayer inventoryplayer, TileRepairer tileEntity) { + super(new ContainerRepairer(inventoryplayer, tileEntity)); + this.repairerInventory = tileEntity; + } + + @Override + protected void drawGuiContainerForegroundLayer(int alec1, int alec2) { + super.fontRendererObj.drawString("Restorer", 30, 5, 0x404040); + super.fontRendererObj.drawString("Inventory", 30, super.ySize - 96 + 2, 0x404040); + } + + @Override + protected void drawGuiContainerBackgroundLayer(float f, int qq, int ww) { + GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); + super.mc.renderEngine.bindTexture( + new ResourceLocation("thaummach", "textures/guis/repairer.png") + ); + int j = (super.width - super.xSize) / 2; + int k = (super.height - super.ySize) / 2; + this.drawTexturedModalRect(j, k, 0, 0, super.xSize, super.ySize); + if (this.repairerInventory.boost > 0) { + int i1 = this.repairerInventory.getBoostScaled(); + this.drawTexturedModalRect(j + 135, k + 46 - i1, 208, 30 - i1, 7, i1); + } + + if (this.repairerInventory.getUpgrades()[0] >= 0) { + super.mc.renderEngine.bindTexture(TextureMap.locationItemsTexture); + UtilsFX.renderUpgradeIntoGUI( + this, this.repairerInventory.getUpgrades()[0], j + 130, k + 54 + ); + } + } +} diff --git a/src/main/java/net/anvilcraft/thaummach/render/apparatus/apparati/wood/RepairerAparatusRenderer.java b/src/main/java/net/anvilcraft/thaummach/render/apparatus/apparati/wood/RepairerAparatusRenderer.java new file mode 100644 index 0000000..0a33bf9 --- /dev/null +++ b/src/main/java/net/anvilcraft/thaummach/render/apparatus/apparati/wood/RepairerAparatusRenderer.java @@ -0,0 +1,104 @@ +package net.anvilcraft.thaummach.render.apparatus.apparati.wood; + +import net.anvilcraft.thaummach.TMBlocks; +import net.anvilcraft.thaummach.blocks.BlockApparatusMetal; +import net.anvilcraft.thaummach.blocks.BlockApparatusWood; +import net.anvilcraft.thaummach.render.apparatus.ApparatusRenderingHelper; +import net.anvilcraft.thaummach.render.apparatus.IApparatusRenderer; +import net.minecraft.block.Block; +import net.minecraft.client.renderer.RenderBlocks; +import net.minecraft.world.IBlockAccess; + +public class RepairerAparatusRenderer implements IApparatusRenderer { + public static final RepairerAparatusRenderer INSTANCE + = new RepairerAparatusRenderer(); + + @Override + public void renderApparatus( + IBlockAccess w, + RenderBlocks rb, + int x, + int y, + int z, + Block block_, + int meta, + boolean inv + ) { + BlockApparatusWood block = (BlockApparatusWood) block_; + if (block.getRenderBlockPass() == 0 || inv) { + rb.setRenderBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F); + if (inv) { + ApparatusRenderingHelper.drawFaces( + rb, + block, + block.iconRestorerBottom, + block.iconRestorerBottom, + block.iconRestorerBottom, + block.iconRestorerBottom, + block.iconRestorerBottom, + block.iconRestorerBottom, + false + ); + } else { + rb.renderStandardBlock(block, x, y, z); + } + + if (!inv) { + rb.renderFaceYPos( + block, + (double) x, + (double) ((float) y - 1.0F + 0.425F), + (double) z, + block.iconRestorerBottom + ); + rb.renderFaceYNeg( + block, + (double) x, + (double) ((float) (y + 1) - 0.425F), + (double) z, + block.iconRestorerBottom + ); + rb.renderFaceXPos( + block, + (double) ((float) (x - 1) + 0.425F), + (double) y, + (double) z, + block.iconRestorerBottom + ); + rb.renderFaceXNeg( + block, + (double) ((float) (x + 1) - 0.425F), + (double) y, + (double) z, + block.iconRestorerBottom + ); + rb.renderFaceZPos( + block, + (double) x, + (double) y, + (double) ((float) (z - 1) + 0.425F), + block.iconRestorerBottom + ); + rb.renderFaceZNeg( + block, + (double) x, + (double) y, + (double) ((float) (z + 1) - 0.425F), + block.iconRestorerBottom + ); + } else { + rb.setRenderBounds(0.01F, 0.01F, 0.01F, 0.99F, 0.99F, 0.99F); + ApparatusRenderingHelper.drawFaces( + rb, + block, + ((BlockApparatusMetal) TMBlocks.apparatusMetal) + .iconArcaneFurnaceInside, + false + ); + } + } + + rb.overrideBlockTexture = null; + rb.setRenderBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F); + } +} diff --git a/src/main/java/net/anvilcraft/thaummach/render/model/ModelGear.java b/src/main/java/net/anvilcraft/thaummach/render/model/ModelGear.java new file mode 100644 index 0000000..8969c9a --- /dev/null +++ b/src/main/java/net/anvilcraft/thaummach/render/model/ModelGear.java @@ -0,0 +1,56 @@ +package net.anvilcraft.thaummach.render.model; + +import net.minecraft.client.model.ModelBase; +import net.minecraft.client.model.ModelRenderer; +import net.minecraft.entity.Entity; + +public class ModelGear extends ModelBase { + ModelRenderer Shape1; + ModelRenderer Shape2; + ModelRenderer Shape3; + + public ModelGear() { + super.textureWidth = 64; + super.textureHeight = 32; + this.Shape1 = new ModelRenderer(this, 0, 0); + this.Shape1.addBox(-2.0F, -6.0F, -6.0F, 4, 12, 12); + this.Shape1.setRotationPoint(0.0F, 0.0F, 0.0F); + this.Shape1.setTextureSize(64, 32); + this.Shape1.mirror = true; + this.setRotation(this.Shape1, 0.0F, 0.0F, 0.0F); + this.Shape2 = new ModelRenderer(this, 0, 0); + this.Shape2.addBox(-2.0F, -6.0F, -6.0F, 4, 12, 12); + this.Shape2.setRotationPoint(0.0F, 0.0F, 0.0F); + this.Shape2.setTextureSize(64, 32); + this.Shape2.mirror = true; + this.setRotation(this.Shape2, 0.5235988F, 0.0F, 0.0F); + this.Shape3 = new ModelRenderer(this, 0, 0); + this.Shape3.addBox(-2.0F, -6.0F, -6.0F, 4, 12, 12); + this.Shape3.setRotationPoint(0.0F, 0.0F, 0.0F); + this.Shape3.setTextureSize(64, 32); + this.Shape3.mirror = true; + this.setRotation(this.Shape3, -0.5235988F, 0.0F, 0.0F); + } + + @Override + public void + render(Entity entity, float f, float f1, float f2, float f3, float f4, float f5) { + super.render(entity, f, f1, f2, f3, f4, f5); + this.setRotationAngles(f, f1, f2, f3, f4, f5, entity); + this.Shape1.render(f5); + this.Shape2.render(f5); + this.Shape3.render(f5); + } + + public void render() { + this.Shape1.render(0.0625F); + this.Shape2.render(0.0625F); + this.Shape3.render(0.0625F); + } + + private void setRotation(ModelRenderer model, float x, float y, float z) { + model.rotateAngleX = x; + model.rotateAngleY = y; + model.rotateAngleZ = z; + } +} diff --git a/src/main/java/net/anvilcraft/thaummach/render/tile/TileBoreRenderer.java b/src/main/java/net/anvilcraft/thaummach/render/tile/TileBoreRenderer.java index f2dea59..20c5d6e 100644 --- a/src/main/java/net/anvilcraft/thaummach/render/tile/TileBoreRenderer.java +++ b/src/main/java/net/anvilcraft/thaummach/render/tile/TileBoreRenderer.java @@ -31,21 +31,6 @@ public class TileBoreRenderer extends TileEntitySpecialRenderer { GL11.glRotatef(angleS, 0.0F, 0.0F, 1.0F); GL11.glTranslatef(0.25f, 0.25f, 0.0F); GL11.glScalef(-0.5f, -0.5f, 1f); - // TODO: rĂ¼ssel - //ThaumCraftRenderer.renderItemFromTexture( - // mc, - // "/thaumcraft/resources/items.png", - // 16, - // 43 + cr.focus, - // 0.4F, - // 1.5F + jitter, - // true, - // 1.0F, - // 1.0F, - // 1.0F, - // 220, - // 771 - //); if (cr.boreItemStacks[0] != null) { mc.renderEngine.bindTexture(TextureMap.locationItemsTexture); diff --git a/src/main/java/net/anvilcraft/thaummach/render/tile/TileRepairerRenderer.java b/src/main/java/net/anvilcraft/thaummach/render/tile/TileRepairerRenderer.java new file mode 100644 index 0000000..d39dfe6 --- /dev/null +++ b/src/main/java/net/anvilcraft/thaummach/render/tile/TileRepairerRenderer.java @@ -0,0 +1,60 @@ +package net.anvilcraft.thaummach.render.tile; + +import net.anvilcraft.thaummach.render.model.ModelGear; +import net.anvilcraft.thaummach.tiles.TileRepairer; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.ResourceLocation; +import org.lwjgl.opengl.GL11; + +public class TileRepairerRenderer extends TileEntitySpecialRenderer { + private ModelGear model = new ModelGear(); + + public void renderEntityAt(TileRepairer rp, double x, double y, double z, float fq) { + int count = Minecraft.getMinecraft().thePlayer.ticksExisted; + int angle = 0; + if (rp.worked) { + angle = count % 360; + } + + this.bindTexture(new ResourceLocation("thaummach", "textures/models/gear.png")); + GL11.glEnable(2977); + GL11.glEnable(3042); + GL11.glPushMatrix(); + GL11.glEnable(32826); + GL11.glBlendFunc(770, 771); + GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); + GL11.glTranslatef((float) x + 0.5F, (float) y + 0.5F, (float) z + 0.5F); + GL11.glPushMatrix(); + GL11.glScalef(0.43F, 0.94F, 0.94F); + GL11.glRotatef((float) angle, 1.0F, 0.0F, 0.0F); + this.model.render(); + GL11.glScalef(1.0F, 1.0F, 1.0F); + GL11.glPopMatrix(); + GL11.glPushMatrix(); + GL11.glScalef(0.94F, 0.94F, 0.43F); + GL11.glRotatef(90.0F, 0.0F, 1.0F, 0.0F); + GL11.glRotatef((float) angle, 1.0F, 0.0F, 0.0F); + this.model.render(); + GL11.glScalef(1.0F, 1.0F, 1.0F); + GL11.glPopMatrix(); + GL11.glPushMatrix(); + GL11.glScalef(0.94F, 0.43F, 0.94F); + GL11.glRotatef(90.0F, 0.0F, 0.0F, 1.0F); + GL11.glRotatef((float) angle, 1.0F, 0.0F, 0.0F); + this.model.render(); + GL11.glScalef(1.0F, 1.0F, 1.0F); + GL11.glPopMatrix(); + GL11.glDisable(32826); + GL11.glPopMatrix(); + GL11.glDisable(3042); + GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); + } + + @Override + public void + renderTileEntityAt(TileEntity te, double d, double d1, double d2, float f) { + this.renderEntityAt((TileRepairer) te, d, d1, d2, f); + } +} diff --git a/src/main/java/net/anvilcraft/thaummach/tiles/TileConduitTank.java b/src/main/java/net/anvilcraft/thaummach/tiles/TileConduitTank.java index 19e7489..713b66f 100644 --- a/src/main/java/net/anvilcraft/thaummach/tiles/TileConduitTank.java +++ b/src/main/java/net/anvilcraft/thaummach/tiles/TileConduitTank.java @@ -151,6 +151,9 @@ public class TileConduitTank extends TileEntity implements IConnection { > ent.getVisSuction(new HelperLocation(this)) || this.getTaintSuction((HelperLocation) null) > ent.getTaintSuction(new HelperLocation(this)))) { + this.worldObj.markBlockForUpdate( + this.xCoord, this.yCoord, this.zCoord + ); float[] results = ent.subtractVis(Math.min( this.fillAmount, stackmaxVis - (stackpureVis + stacktaintedVis) diff --git a/src/main/java/net/anvilcraft/thaummach/tiles/TileRepairer.java b/src/main/java/net/anvilcraft/thaummach/tiles/TileRepairer.java new file mode 100644 index 0000000..3b2c462 --- /dev/null +++ b/src/main/java/net/anvilcraft/thaummach/tiles/TileRepairer.java @@ -0,0 +1,448 @@ +package net.anvilcraft.thaummach.tiles; + +import java.util.stream.IntStream; + +import dev.tilera.auracore.api.machine.IUpgradable; +import dev.tilera.auracore.api.machine.TileVisUser; +import dev.tilera.auracore.aura.AuraManager; +import net.anvilcraft.thaummach.GuiID; +import net.anvilcraft.thaummach.ITileGui; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.ISidedInventory; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.network.NetworkManager; +import net.minecraft.network.Packet; +import net.minecraft.network.play.server.S35PacketUpdateTileEntity; +import net.minecraftforge.common.util.ForgeDirection; +import thaumcraft.api.IRepairable; +import thaumcraft.api.aspects.Aspect; +import thaumcraft.api.aspects.AspectList; + +public class TileRepairer extends TileVisUser implements ISidedInventory, IUpgradable, ITileGui { + private ItemStack[] repairerItemStacks = new ItemStack[12]; + public float sucked = 0.0F; + public float currentVis = 0.0F; + public float maxVis = 5.0F; + public int boost = 0; + private byte[] upgrades = new byte[] { -1 }; + public boolean worked; + int boostDelay = 20; + int soundDelay = 0; + + @Override + public GuiID getGuiID() { + return GuiID.REPAIRER; + } + + @Override + public int getSizeInventory() { + return this.repairerItemStacks.length; + } + + @Override + public ItemStack getStackInSlot(int i) { + return this.repairerItemStacks[i]; + } + + @Override + public ItemStack decrStackSize(int i, int j) { + if (this.repairerItemStacks[i] != null) { + ItemStack itemstack1; + if (this.repairerItemStacks[i].stackSize <= j) { + itemstack1 = this.repairerItemStacks[i]; + this.repairerItemStacks[i] = null; + return itemstack1; + } else { + itemstack1 = this.repairerItemStacks[i].splitStack(j); + if (this.repairerItemStacks[i].stackSize == 0) { + this.repairerItemStacks[i] = null; + } + + return itemstack1; + } + } else { + return null; + } + } + + @Override + public void setInventorySlotContents(int i, ItemStack itemstack) { + this.repairerItemStacks[i] = itemstack; + if (itemstack != null && itemstack.stackSize > this.getInventoryStackLimit()) { + itemstack.stackSize = this.getInventoryStackLimit(); + } + } + + @Override + public String getInventoryName() { + return "Thaumic Repairer"; + } + + @Override + public boolean hasCustomInventoryName() { + return true; + } + + @Override + public void readFromNBT(NBTTagCompound nbttagcompound) { + super.readFromNBT(nbttagcompound); + NBTTagList nbttaglist = nbttagcompound.getTagList("Items", 10); + this.repairerItemStacks = new ItemStack[this.getSizeInventory()]; + + for (int i = 0; i < nbttaglist.tagCount(); ++i) { + NBTTagCompound nbttagcompound1 + = (NBTTagCompound) nbttaglist.getCompoundTagAt(i); + byte byte0 = nbttagcompound1.getByte("SlotDuplicator"); + if (byte0 >= 0 && byte0 < this.repairerItemStacks.length) { + this.repairerItemStacks[byte0] + = ItemStack.loadItemStackFromNBT(nbttagcompound1); + } + } + + this.upgrades = nbttagcompound.getByteArray("upgrades"); + this.currentVis = nbttagcompound.getFloat("currentVis"); + this.maxVis = nbttagcompound.getFloat("maxVis"); + } + + @Override + public void writeToNBT(NBTTagCompound nbttagcompound) { + super.writeToNBT(nbttagcompound); + nbttagcompound.setByteArray("upgrades", this.upgrades); + nbttagcompound.setFloat("currentVis", this.currentVis); + nbttagcompound.setFloat("maxVis", this.maxVis); + NBTTagList nbttaglist = new NBTTagList(); + + for (int i = 0; i < this.repairerItemStacks.length; ++i) { + if (this.repairerItemStacks[i] != null) { + NBTTagCompound nbttagcompound1 = new NBTTagCompound(); + nbttagcompound1.setByte("SlotDuplicator", (byte) i); + this.repairerItemStacks[i].writeToNBT(nbttagcompound1); + nbttaglist.appendTag(nbttagcompound1); + } + } + + nbttagcompound.setTag("Items", nbttaglist); + } + + @Override + public int getInventoryStackLimit() { + return 64; + } + + public int getBoostScaled() { + return Math.round(0.1F + (float) this.boost / 2.0F) * 6; + } + + @Override + public void updateEntity() { + super.updateEntity(); + this.worked = false; + if (!super.worldObj.isRemote) { + boolean flag1 = false; + + for (int a = 0; a < 6; ++a) { + boolean isVisRepair = false; + + try { + isVisRepair + = this.repairerItemStacks[a].getItem() instanceof IRepairable; + } catch (Exception var6) {} + + if (this.repairerItemStacks[a] != null + && this.repairerItemStacks[a].isItemDamaged() + && this.repairerItemStacks[a].getItemDamage() > 0 + && (this.repairerItemStacks[a].getItem().isRepairable() || isVisRepair + )) { + float ra = 1.0f; + + ra *= this.hasUpgrade((byte) 1) ? 0.8F : 1.0F; + if (this.repairerItemStacks[a].isItemEnchanted()) { + ra *= 1.5F; + } + + if (this.currentVis >= ra) { + this.worldObj.markBlockForUpdate( + this.xCoord, this.yCoord, this.zCoord + ); + this.currentVis -= ra; + flag1 = true; + this.repairerItemStacks[a].setItemDamage( + this.repairerItemStacks[a].getItemDamage() - 1 + ); + this.worked = true; + if (!this.hasUpgrade((byte) -1)) { + // TODO: FX + //switch (super.worldObj.rand.nextInt(4)) { + // case 0: + // ThaumCraftCore.createSmallGreenFlameFX( + // super.worldObj, + // (float) super.xCoord + 0.25F, + // (float) super.yCoord + 1.15F, + // (float) super.zCoord + 0.25F + // ); + // break; + // case 1: + // ThaumCraftCore.createSmallGreenFlameFX( + // super.worldObj, + // (float) super.xCoord + 0.25F, + // (float) super.yCoord + 1.15F, + // (float) super.zCoord + 0.75F + // ); + // break; + // case 2: + // ThaumCraftCore.createSmallGreenFlameFX( + // super.worldObj, + // (float) super.xCoord + 0.75F, + // (float) super.yCoord + 1.15F, + // (float) super.zCoord + 0.25F + // ); + // break; + // case 3: + // ThaumCraftCore.createSmallGreenFlameFX( + // super.worldObj, + // (float) super.xCoord + 0.75F, + // (float) super.yCoord + 1.15F, + // (float) super.zCoord + 0.75F + // ); + //} + } + } + } + + if (this.repairerItemStacks[a] != null + && !this.repairerItemStacks[a].isItemDamaged()) { + this.moveRepairedItem(a); + } + } + + float suckLimit = 0.5F + 0.05F * (float) this.boost + + (this.hasUpgrade((byte) 0) ? 0.5F : 0.0F); + + for (int i = 0; i < 6; ++i) { + if (this.repairerItemStacks[i] != null) { + if (this.currentVis + suckLimit <= this.maxVis) { + this.currentVis += this.getAvailablePureVis(suckLimit); + } + break; + } + } + + if (flag1 && this.soundDelay <= 0) { + this.soundDelay = 50; + super.worldObj.playSoundEffect( + (double) ((float) super.xCoord + 0.5F), + (double) ((float) super.yCoord + 0.5F), + (double) ((float) super.zCoord + 0.5F), + "thaummach:tinkering", + 0.5F, + 1.0F + ); + + AuraManager.addFluxToClosest( + this.worldObj, + this.xCoord, + this.yCoord, + this.zCoord, + new AspectList().add(Aspect.TAINT, 1) + ); + } + + if (this.soundDelay > 0) { + --this.soundDelay; + } + + // TODO: magic boost + //if (this.boostDelay <= 0 || this.boostDelay == 10) { + // auraX = super.xCoord >> 4; + // auraZ = super.zCoord >> 4; + // ac = (SIAuraChunk) mod_ThaumCraft.AuraHM.get(Arrays.asList( + // auraX, auraZ, ThaumCraftCore.getDimension(super.worldObj) + // )); + // if (ac != null && this.boost < 10 && ac.boost > 0) { + // ++this.boost; + // --ac.boost; + // } + //} + // + //if (this.boostDelay <= 0) { + // if (this.boost > 0) { + // --this.boost; + // } + + // this.boostDelay = 20; + //} else { + // --this.boostDelay; + //} + } + } + + private void moveRepairedItem(int stack) { + ItemStack itemstack = new ItemStack( + this.repairerItemStacks[stack].getItem(), + 1, + this.repairerItemStacks[stack].getItemDamage() + ); + + for (int j = 6; j < 12; ++j) { + if (this.repairerItemStacks[j] == null) { + this.repairerItemStacks[j] = itemstack.copy(); + this.repairerItemStacks[j].setTagCompound( + this.repairerItemStacks[stack].getTagCompound() + ); + --this.repairerItemStacks[stack].stackSize; + if (this.repairerItemStacks[stack].stackSize <= 0) { + this.repairerItemStacks[stack] = null; + } + break; + } + } + } + + // public int getStartInventorySide(int side) { + // return side != 0 && side != 1 ? 6 : 0; + // } + // + // public int getSizeInventorySide(int side) { + // return 6; + // } + + @Override + public boolean isUseableByPlayer(EntityPlayer entityplayer) { + return true; + } + + @Override + public boolean getConnectable(ForgeDirection face) { + return true; + } + + @Override + public boolean canAcceptUpgrade(byte upgrade) { + if (upgrade != 0 && upgrade != 1) { + return false; + } else { + return !this.hasUpgrade(upgrade); + } + } + + @Override + public int getUpgradeLimit() { + return 1; + } + + @Override + public byte[] getUpgrades() { + return this.upgrades; + } + + @Override + public boolean hasUpgrade(byte upgrade) { + if (this.upgrades.length < 1) { + return false; + } else { + for (int a = 0; a < this.getUpgradeLimit(); ++a) { + if (this.upgrades[a] == upgrade) { + return true; + } + } + + return false; + } + } + + @Override + public boolean setUpgrade(byte upgrade) { + for (int a = 0; a < this.getUpgradeLimit(); ++a) { + if (this.upgrades[a] < 0 && this.canAcceptUpgrade(upgrade)) { + this.upgrades[a] = upgrade; + return true; + } + } + + return false; + } + + @Override + public boolean clearUpgrade(int index) { + if (this.upgrades[index] >= 0) { + this.upgrades[index] = -1; + return true; + } else { + return false; + } + } + + @Override + public ItemStack getStackInSlotOnClosing(int var1) { + if (this.repairerItemStacks[var1] != null) { + ItemStack var2 = this.repairerItemStacks[var1]; + this.repairerItemStacks[var1] = null; + return var2; + } else { + return null; + } + } + + @Override + public void openInventory() {} + + @Override + public void closeInventory() {} + + @Override + public boolean isItemValidForSlot(int slot, ItemStack stack) { + // TODO: WTF + return true; + } + + @Override + public int[] getAccessibleSlotsFromSide(int side) { + // output for top/bottom, else input + int offset = side == 0 || side == 1 ? 6 : 0; + + return IntStream.range(offset, 6 + offset).toArray(); + } + + @Override + public boolean canInsertItem(int slot, ItemStack stack, int side) { + return this.isItemValidForSlot(slot, stack); + } + + @Override + public boolean canExtractItem(int slot, ItemStack stack, int side) { + ItemStack curStack = this.repairerItemStacks[slot]; + + return curStack != null && curStack.isItemEqual(stack) + && curStack.stackSize - stack.stackSize > 0; + } + + @Override + public Packet getDescriptionPacket() { + NBTTagCompound nbt = new NBTTagCompound(); + + nbt.setFloat("sucked", this.sucked); + nbt.setFloat("currentVis", this.currentVis); + nbt.setFloat("maxVis", this.maxVis); + nbt.setInteger("boost", this.boost); + nbt.setByteArray("upgrades", this.upgrades); + nbt.setBoolean("worked", this.worked); + + return new S35PacketUpdateTileEntity( + this.xCoord, this.yCoord, this.zCoord, this.getBlockMetadata(), nbt + ); + } + + @Override + public void onDataPacket(NetworkManager net, S35PacketUpdateTileEntity pkt) { + NBTTagCompound nbt = pkt.func_148857_g(); + + this.sucked = nbt.getFloat("sucked"); + this.currentVis = nbt.getFloat("currentVis"); + this.maxVis = nbt.getFloat("maxVis"); + this.boost = nbt.getInteger("boost"); + this.upgrades = nbt.getByteArray("upgrades"); + this.worked = nbt.getBoolean("worked"); + } +} diff --git a/src/main/java/net/anvilcraft/thaummach/utils/UtilsFX.java b/src/main/java/net/anvilcraft/thaummach/utils/UtilsFX.java index 560e87e..75e8090 100644 --- a/src/main/java/net/anvilcraft/thaummach/utils/UtilsFX.java +++ b/src/main/java/net/anvilcraft/thaummach/utils/UtilsFX.java @@ -1,7 +1,9 @@ package net.anvilcraft.thaummach.utils; import dev.tilera.auracore.client.FXSparkle; +import net.anvilcraft.thaummach.TMItems; import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.inventory.GuiContainer; import net.minecraft.client.renderer.Tessellator; import net.minecraft.world.World; import thaumcraft.client.fx.particles.FXWisp; @@ -272,4 +274,17 @@ public class UtilsFX { tes.draw(); } + + /** + * Draws an upgrade into the GuiContainer. + */ + public static void + renderUpgradeIntoGUI(GuiContainer gui, int upgrade, int x, int y) { + if (upgrade < 0) + return; + + gui.drawTexturedModelRectFromIcon( + x, y, TMItems.upgrade.getIconFromDamage(upgrade), 16, 16 + ); + } } diff --git a/src/main/resources/assets/thaummach/sounds.json b/src/main/resources/assets/thaummach/sounds.json index e9a2f84..97a99d3 100644 --- a/src/main/resources/assets/thaummach/sounds.json +++ b/src/main/resources/assets/thaummach/sounds.json @@ -44,6 +44,15 @@ } ] }, + "tinkering": { + "category": "block", + "sounds": [ + { + "name": "tinkering", + "stream": false + } + ] + }, "upgrade": { "category": "master", "sounds": [ diff --git a/src/main/resources/assets/thaummach/sounds/tinkering.ogg b/src/main/resources/assets/thaummach/sounds/tinkering.ogg new file mode 100644 index 0000000000000000000000000000000000000000..7a46fd4228ae023d050b4faee94b09015334deec GIT binary patch literal 22483 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/thaummach/textures/guis/repairer.png b/src/main/resources/assets/thaummach/textures/guis/repairer.png new file mode 100644 index 0000000000000000000000000000000000000000..308ed1bf86f513d5225ac33136c06eedd5fb59c5 GIT binary patch literal 3750 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/thaummach/textures/models/gear.png b/src/main/resources/assets/thaummach/textures/models/gear.png new file mode 100644 index 0000000000000000000000000000000000000000..fc6effae9d9ef93ec72dd0cf975fc38b60c95a03 GIT binary patch literal 866 zcmV-o1D*VdP)O7i5IVWa6nC;k8<=pja#_%vdg$>h0}K+4_7wj~qihd! zl}aUL>v8VrYPG6zxt!YVb|$04dK`T5o7r$7tS4H9d*D0uj2xv!9*;*e$!4=Lp^s~Kg@*FJzP^ltB-}hB^zbSZMYTIGf$KhWh4Vg6EduZWVJ7*I zaYx&|(AOGBI9sNLt4pw2txUp+e7FG=1-5*+0qlJ_V37|ufJtFKk!iuB8uWeNOoWtz zPO_gvJ*wSxcW6RfC=`AU9sv7E_Q$omLNhQEP()Fs%IQb;<7HgCvjGxTfp{s;;@Vx| zbGmV=AsHNIw6j01-8ll(u!NK|9?1lD_Q$om;&mFn3`m>Cc430pKe^{$0oqoUr~(NE`t8mro>n>xA`ZLgE0(_aP7t2vUp?lBm{&bsu^8k+qoztu6A)xjAtQ2quYh2(73=b20YtfASbu(%MH{hh_?a^aZmfX(`H sD%{&YYh?aCm^HGe;a31&0mu}806PfhuI>V3I{*Lx07*qoM6N<$g7`w5mjD0& literal 0 HcmV?d00001