From 915abca4fa2ca3f6514448e15b9d4e88ec046339 Mon Sep 17 00:00:00 2001 From: stfwi Date: Thu, 25 Feb 2021 17:06:12 +0100 Subject: [PATCH] Crafting Table output slot sync reworked. Shingle Roof Wire Conduit added. --- gradle.properties | 2 +- meta/update.json | 5 +- readme.md | 3 + .../java/wile/engineersdecor/ModContent.java | 17 + .../blocks/EdCraftingTable.java | 219 +++++--- .../dark_shingle_roof_wireconduit.json | 44 ++ .../assets/engineersdecor/lang/en_us.json | 7 +- .../assets/engineersdecor/lang/ru_ru.json | 6 +- .../assets/engineersdecor/lang/zh_cn.json | 7 +- .../dark_shingle_roof_wireconduit_model.json | 479 ++++++++++++++++++ .../item/dark_shingle_roof_wireconduit.json | 1 + .../blocks/dark_shingle_roof_wireconduit.json | 21 + 12 files changed, 739 insertions(+), 72 deletions(-) create mode 100644 src/main/resources/assets/engineersdecor/blockstates/dark_shingle_roof_wireconduit.json create mode 100644 src/main/resources/assets/engineersdecor/models/block/roof/dark_shingle_roof_wireconduit_model.json create mode 100644 src/main/resources/assets/engineersdecor/models/item/dark_shingle_roof_wireconduit.json create mode 100644 src/main/resources/data/engineersdecor/loot_tables/blocks/dark_shingle_roof_wireconduit.json diff --git a/gradle.properties b/gradle.properties index 90198f8..1d08100 100644 --- a/gradle.properties +++ b/gradle.properties @@ -5,4 +5,4 @@ version_minecraft=1.16.4 version_forge_minecraft=1.16.4-35.1.10 version_fml_mappings=20201028-1.16.3 version_jei=1.16.4:7.6.1.63 -version_engineersdecor=1.1.8-b2 +version_engineersdecor=1.1.8 diff --git a/meta/update.json b/meta/update.json index c40f45e..2221abd 100644 --- a/meta/update.json +++ b/meta/update.json @@ -1,6 +1,7 @@ { "homepage": "https://www.curseforge.com/minecraft/mc-mods/engineers-decor/", "1.16.4": { + "1.1.8": "[F] Crafting Table Output slot sync rework (issue #138).\n[A] Dark Shingle Roof Wire Conduit added (CFR#347).", "1.1.8-b2": "[F] Fixed Iron Hatch isLadder bug (thx jerryw09).\n[F] Fixed Block Placer block placing pre-conditions (issue #160, ty XFactHD).\n[F] Added explicit scheduled Crafting Table client sync.\n[F] Fixed directional waterloggable block default state forwarding (issue #162, ty b52src).", "1.1.8-b1": "[F] Fluid Funnel waterlogged fluid picking fixed (issue #158, thx ZoMadeStuff).\n[F] Roof rendering fixes (issues #153/#159, thx Salamance73/Murph).\n[A] Recessed Clinkers, Vertically Slit Clinkers, and Structured Vertical Clinker Slab added.", "1.1.7": "[M] 1.16.5 support.\n[F] Fixed Labeled Crate include (issue #157, ty NillerMedDild).", @@ -27,7 +28,7 @@ "1.1.2-b1": "[U] Ported to MC1.16.2." }, "promos": { - "1.16.4-recommended": "1.1.7", - "1.16.4-latest": "1.1.8-b2" + "1.16.4-recommended": "1.1.8", + "1.16.4-latest": "1.1.8" } } \ No newline at end of file diff --git a/readme.md b/readme.md index b094566..6e2475f 100644 --- a/readme.md +++ b/readme.md @@ -11,6 +11,9 @@ Mod sources for Minecraft version 1.16.x. ## Version history + - v1.1.8 [F] Crafting Table Output slot sync rework (issue #138). + [A] Dark Shingle Roof Wire Conduit added (CFR#347). + - v1.1.8-b2 [F] Fixed Iron Hatch isLadder bug (thx jerryw09). [F] Fixed Block Placer block placing pre-conditions (issue #160, ty XFactHD). [F] Added explicit scheduled Crafting Table client sync. diff --git a/src/main/java/wile/engineersdecor/ModContent.java b/src/main/java/wile/engineersdecor/ModContent.java index 34bb6b0..af1806b 100644 --- a/src/main/java/wile/engineersdecor/ModContent.java +++ b/src/main/java/wile/engineersdecor/ModContent.java @@ -15,6 +15,7 @@ package wile.engineersdecor; import net.minecraft.block.BlockState; import net.minecraft.util.SoundEvents; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.shapes.IBooleanFunction; import net.minecraft.world.IBlockReader; import net.minecraft.block.material.MaterialColor; import net.minecraft.block.Block; @@ -277,6 +278,21 @@ public class ModContent VoxelShapes.create(Auxiliaries.getPixeledAABB(5, 0, 5, 11, 16, 11)) )).setRegistryName(new ResourceLocation(MODID, "dark_shingle_roof_chimneytrunk")); + public static final EdChimneyTrunkBlock DARK_CERAMIC_SHINGLE_ROOF_WIRECONDUIT = (EdChimneyTrunkBlock)(new EdChimneyTrunkBlock( + DecorBlock.CFG_CUTOUT, + Block.Properties.create(Material.ROCK, MaterialColor.STONE).hardnessAndResistance(2f, 15f).sound(SoundType.STONE).notSolid().variableOpacity().setAllowsSpawn(ModContent::disallowSpawn), + VoxelShapes.combineAndSimplify( + VoxelShapes.create(Auxiliaries.getPixeledAABB(3, 0, 3, 13, 13, 13)), + VoxelShapes.create(Auxiliaries.getPixeledAABB(5, 13, 5, 11, 16, 11)), + IBooleanFunction.OR + ), + VoxelShapes.combineAndSimplify( + VoxelShapes.create(Auxiliaries.getPixeledAABB(5, 0, 5, 11, 15, 11)), + VoxelShapes.create(Auxiliaries.getPixeledAABB(7, 15, 7, 9, 16, 9)), + IBooleanFunction.OR + ) + )).setRegistryName(new ResourceLocation(MODID, "dark_shingle_roof_wireconduit")); + public static final EdChimneyBlock DARK_CERAMIC_SHINGLE_ROOF_CHIMNEY = (EdChimneyBlock)(new EdChimneyBlock( DecorBlock.CFG_CUTOUT|DecorBlock.CFG_AI_PASSABLE, Block.Properties.create(Material.ROCK, MaterialColor.STONE).hardnessAndResistance(5f, 2000f).sound(SoundType.STONE).variableOpacity().setAllowsSpawn(ModContent::disallowSpawn), @@ -1047,6 +1063,7 @@ public class ModContent DARK_CERAMIC_SHINGLE_ROOF_METALIZED, DARK_CERAMIC_SHINGLE_ROOF_SKYLIGHT, DARK_CERAMIC_SHINGLE_ROOF_CHIMNEYTRUNK, + DARK_CERAMIC_SHINGLE_ROOF_WIRECONDUIT, DARK_CERAMIC_SHINGLE_ROOF_BLOCK, DARK_CERAMIC_SHINGLE_ROOF_SLAB, HALFSLAB_DARK_CERAMIC_SHINGLE_ROOF, diff --git a/src/main/java/wile/engineersdecor/blocks/EdCraftingTable.java b/src/main/java/wile/engineersdecor/blocks/EdCraftingTable.java index 4c159c4..325dde8 100644 --- a/src/main/java/wile/engineersdecor/blocks/EdCraftingTable.java +++ b/src/main/java/wile/engineersdecor/blocks/EdCraftingTable.java @@ -9,7 +9,6 @@ package wile.engineersdecor.blocks; import net.minecraft.inventory.container.*; -import net.minecraft.network.play.server.SSetSlotPacket; import net.minecraft.network.NetworkManager; import net.minecraft.network.play.server.SUpdateTileEntityPacket; import net.minecraft.world.*; @@ -177,7 +176,8 @@ public class EdCraftingTable { public static final int NUM_OF_STORAGE_SLOTS = 18; public static final int NUM_OF_STORAGE_ROWS = 2; - public static final int NUM_OF_SLOTS = 9+NUM_OF_STORAGE_SLOTS; + public static final int NUM_OF_SLOTS = 9+NUM_OF_STORAGE_SLOTS+1; + public static final int CRAFTING_RESULT_SLOT = NUM_OF_SLOTS-1; protected Inventories.StorageInventory inventory_; protected CompoundNBT history = new CompoundNBT(); @@ -289,7 +289,7 @@ public class EdCraftingTable final Block crafting_table_block = getBlockState().getBlock(); if(!(crafting_table_block instanceof CraftingTableBlock)) return; if(world.getPendingBlockTicks().isTickScheduled(getPos(), crafting_table_block)) return; - world.getPendingBlockTicks().scheduleTick(getPos(), crafting_table_block, 20, TickPriority.LOW); + world.getPendingBlockTicks().scheduleTick(getPos(), crafting_table_block, 10, TickPriority.LOW); } } @@ -322,6 +322,7 @@ public class EdCraftingTable private final CraftingHistory history_; private final CraftingTableGrid matrix_; private final CraftResultInventory result_; + private final CraftingOutputSlot crafting_output_slot_; private boolean has_recipe_collision_; private boolean crafting_matrix_changed_now_; private final InventoryRange crafting_grid_range_; @@ -330,6 +331,7 @@ public class EdCraftingTable private final InventoryRange player_storage_range_; private final InventoryRange player_hotbar_range_; private final InventoryRange player_inventory_range_; + private final @Nullable CraftingTableTileEntity te_; public CraftingTableContainer(int cid, PlayerInventory pinv) { this(cid, pinv, new Inventory(CraftingTableTileEntity.NUM_OF_SLOTS), IWorldPosCallable.DUMMY); } @@ -340,20 +342,24 @@ public class EdCraftingTable wpc_ = wpc; player_ = pinv.player; inventory_ = block_inventory; + inventory_.openInventory(player_); World world = player_.world; - if(world.isRemote && (inventory_ instanceof CraftingTableTileEntity)) world = ((CraftingTableTileEntity)inventory_).getWorld(); - history_ = new CraftingHistory(world); - result_ = new CraftResultInventory(); - matrix_ = new CraftingTableGrid(this, block_inventory); - matrix_.openInventory(player_); - crafting_result_range_= new InventoryRange(result_, 0, 1, 1); - crafting_grid_range_ = new InventoryRange(matrix_, 0, 9, 3); + if((inventory_ instanceof StorageInventory) && ((((StorageInventory)inventory_).getTileEntity()) instanceof CraftingTableTileEntity)) { + te_ = (CraftingTableTileEntity)(((StorageInventory)inventory_).getTileEntity()); + } else { + te_ = null; + } + crafting_grid_range_ = new InventoryRange(inventory_, 0, 9, 3); block_storage_range_ = new InventoryRange(inventory_, CRAFTING_SLOTS_SIZE, NUM_OF_STORAGE_SLOTS, NUM_OF_STORAGE_ROWS); + crafting_result_range_= new InventoryRange(inventory_, CraftingTableTileEntity.CRAFTING_RESULT_SLOT, 1, 1); player_storage_range_ = InventoryRange.fromPlayerStorage(player_); player_hotbar_range_ = InventoryRange.fromPlayerHotbar(player_); player_inventory_range_= InventoryRange.fromPlayerInventory(player_); + matrix_ = new CraftingTableGrid(this, inventory_); + result_ = new CraftOutputInventory(crafting_result_range_); + history_ = new CraftingHistory(world); // container slotId 0 === crafting output - addSlot(new CraftingOutputSlot(this, pinv.player, matrix_, result_, 0, 118, 27)); + addSlot(crafting_output_slot_=(new CraftingOutputSlot(this, pinv.player, matrix_, result_, 0, 118, 27))); ArrayList> slotpositions = new ArrayList>(); slotpositions.add(new Tuple<>(118, 27)); // container slotId 1..9 === TE slots 0..8 @@ -381,23 +387,25 @@ public class EdCraftingTable addSlot(new Slot(inventory_, 9+x+y*9, 8+x*18, 65+y*18)); } } - if((!player_.world.isRemote) && (inventory_ instanceof CraftingTableTileEntity)) { - history_.read(((CraftingTableTileEntity)inventory_).history.copy()); + if((!player_.world.isRemote()) && (te_ != null)) { + history_.read(te_.history.copy()); } CRAFTING_SLOT_COORDINATES = ImmutableList.copyOf(slotpositions); - onCraftMatrixChanged(matrix_); + onCraftMatrixChanged(); } @Override public boolean canInteractWith(PlayerEntity player) { return inventory_.isUsableByPlayer(player); } + public void onCraftMatrixChanged() + { onCraftMatrixChanged(matrix_); } + @Override public void onCraftMatrixChanged(IInventory inv) { - detectAndSendChanges(); wpc_.consume((world,pos)->{ - if(world.isRemote) return; + if(world.isRemote()) return; try { crafting_matrix_changed_now_ = true; ServerPlayerEntity player = (ServerPlayerEntity) player_; @@ -412,12 +420,12 @@ public class EdCraftingTable recipe = (ICraftingRecipe)currently_used; } if(result_.canUseRecipe(world, player, recipe)) { + detectAndSendChanges(); stack = recipe.getCraftingResult(matrix_); } } result_.setInventorySlotContents(0, stack); - player.connection.sendPacket(new SSetSlotPacket(windowId, 0, stack)); - sync(); + detectAndSendChanges(); } catch(Throwable exc) { ModEngineersDecor.logger().error("Recipe failed:", exc); } @@ -426,18 +434,7 @@ public class EdCraftingTable @Override public void onContainerClosed(PlayerEntity player) - { - matrix_.closeInventory(player); - result_.clear(); - result_.closeInventory(player); - if(player!=null) { - for(Slot e:player.container.inventorySlots) { - if(e instanceof CraftingResultSlot) { - ((CraftingResultSlot)e).putStack(ItemStack.EMPTY); - } - } - } - } + { inventory_.closeInventory(player); } @Override public boolean canMergeSlot(ItemStack stack, Slot slot) @@ -507,6 +504,7 @@ public class EdCraftingTable } if(nbt.contains("inventory")) { Inventories.readNbtStacks(nbt, "inventory", inventory_); + this.onCraftMatrixChanged(matrix_); } } @@ -642,7 +640,7 @@ public class EdCraftingTable if(changed) inventory_.markDirty(); if(player_inventory_changed) player.inventory.markDirty(); if(changed || player_inventory_changed) { - this.onCraftMatrixChanged(inventory_); + this.onCraftMatrixChanged(); this.detectAndSendChanges(); } } @@ -652,18 +650,19 @@ public class EdCraftingTable private void sync() { - if(!with_assist) return; this.wpc_.consume((world,pos)->{ if(world.isRemote()) return; - CompoundNBT hist_nbt = history_.write(); + inventory_.markDirty(); final CompoundNBT nbt = new CompoundNBT(); - if((inventory_ instanceof CraftingTableTileEntity)) { - ((CraftingTableTileEntity)inventory_).history = hist_nbt.copy(); - inventory_.markDirty(); - nbt.put("inventory", ((CraftingTableTileEntity)inventory_).mainInventory().save(false)); + if(te_ != null) nbt.put("inventory", te_.mainInventory().save(false)); + if(with_assist) { + CompoundNBT hist_nbt = history_.write(); + if(te_ != null) { + te_.history = hist_nbt.copy(); + } + nbt.put("history", hist_nbt); + nbt.putBoolean("hascollision", has_recipe_collision_); } - nbt.put("history", hist_nbt); - nbt.putBoolean("hascollision", has_recipe_collision_); Networking.PacketContainerSyncServerToClient.sendToListeners(world, this, nbt); }); } @@ -696,7 +695,7 @@ public class EdCraftingTable break; } } - onCraftMatrixChanged(inv); + onCraftMatrixChanged(); } catch(Throwable exc) { ModEngineersDecor.logger().error("Recipe failed:", exc); } @@ -807,7 +806,7 @@ public class EdCraftingTable } } if(recipe != null) { - onCraftMatrixChanged(inventory_); + onCraftMatrixChanged(); } } @@ -1089,9 +1088,9 @@ public class EdCraftingTable if(!slot.getStack().isEmpty()) { renderTooltip(mx, slot.getStack(), mouseX, mouseY); return; } if(with_assist) { int hist_index = -1; - if(slot instanceof CraftingResultSlot) { + if(slot instanceof CraftingOutputSlot) { hist_index = 0; - } else if(slot.inventory instanceof CraftingInventory) { + } else if(slot.inventory instanceof CraftOutputInventory) { hist_index = slot.getSlotIndex() + 1; } if((hist_index < 0) || (hist_index >= history_slot_tooltip.length)) return; @@ -1183,7 +1182,7 @@ public class EdCraftingTable { tooltip.resetTimer(); if(type == ClickType.PICKUP) { - boolean place_refab = (slot instanceof CraftingResultSlot) && (!slot.getHasStack()); + boolean place_refab = (slot instanceof CraftingOutputSlot) && (!slot.getHasStack()); if(place_refab && with_assist_direct_history_refab) on_history_item_placement(); // place before crafting -> direct item pick super.handleMouseClick(slot, slotId, mouseButton, type); if(place_refab && (!with_assist_direct_history_refab)) on_history_item_placement(); // place after crafting -> confirmation first @@ -1237,7 +1236,7 @@ public class EdCraftingTable { tooltip.resetTimer(); final Slot resultSlot = this.getSlotUnderMouse(); - if((!with_crafting_slot_mouse_scrolling) || (!(resultSlot instanceof CraftingResultSlot))) { + if((!with_crafting_slot_mouse_scrolling) || (!(resultSlot instanceof CraftingOutputSlot))) { return this.getEventListenerForPos(mouseX, mouseY).filter((evl) -> { return evl.mouseScrolled(mouseX, mouseY, wheel_inc); }).isPresent(); @@ -1268,7 +1267,7 @@ public class EdCraftingTable { if((getContainer().history().current().isEmpty())) return; final Slot resultSlot = this.getSlotUnderMouse(); // double check - if(!(resultSlot instanceof CraftingResultSlot)) return; + if(!(resultSlot instanceof CraftingOutputSlot)) return; action(CraftingTableContainer.ACTION_PLACE_CURRENT_HISTORY_SEL); } } @@ -1488,20 +1487,91 @@ public class EdCraftingTable } } - // Crafting slot of the container ------------------------------------------------------------------------------------ - public static class CraftingOutputSlot extends CraftingResultSlot + // Crafting Result Inventory of the container ------------------------------------------------------------------------ + public static class CraftOutputInventory extends CraftResultInventory implements IInventory, IRecipeHolder + { + private final IInventory result_inv_; + private IRecipe recipe_used_; + + public CraftOutputInventory(IInventory inventory) + { result_inv_ = inventory; } + + public int getSizeInventory() + { return 1; } + + public boolean isEmpty() + { return result_inv_.getStackInSlot(0).isEmpty(); } + + public ItemStack getStackInSlot(int index) + { return result_inv_.getStackInSlot(0); } + + public ItemStack decrStackSize(int index, int count) + { return result_inv_.removeStackFromSlot(0); } + + public ItemStack removeStackFromSlot(int index) + { return result_inv_.removeStackFromSlot(0); } + + public void setInventorySlotContents(int index, ItemStack stack) + { result_inv_.setInventorySlotContents(0, stack); } + + public void markDirty() + { result_inv_.markDirty(); } + + public boolean isUsableByPlayer(PlayerEntity player) + { return true; } + + public void clear() + { result_inv_.setInventorySlotContents(0, ItemStack.EMPTY); } + + public void setRecipeUsed(@Nullable IRecipe recipe) + { recipe_used_ = recipe; } + + @Nullable + public IRecipe getRecipeUsed() + { return recipe_used_; } + } + + // Crafting output slot of the container ----------------------------------------------------------------------------- + // Has to be re-implemented because CraftingResultSlot is not synchronsized for detectAndSendChanges(). + public static class CraftingOutputSlot extends Slot { private final CraftingTableContainer container; private final PlayerEntity player; + private final CraftingInventory craftMatrix; + private int amountCrafted; - public CraftingOutputSlot(CraftingTableContainer container, PlayerEntity player, CraftingInventory craftingInventory, IInventory inventoryIn, int slotIndex, int xPosition, int yPosition) - { super(player, craftingInventory, inventoryIn, slotIndex, xPosition, yPosition); this.container = container; this.player=player; } + public CraftingOutputSlot(CraftingTableContainer container, PlayerEntity player, CraftingInventory craftingInventory, IInventory resultInventory, int slotIndex, int xPosition, int yPosition) + { + super(resultInventory, slotIndex, xPosition, yPosition); + this.craftMatrix = craftingInventory; + this.container = container; + this.player = player; + } + + @Override + public boolean isItemValid(ItemStack stack) + { return false; } + + @Override + public ItemStack decrStackSize(int amount) + { + if(getHasStack()) amountCrafted += Math.min(amount, getStack().getCount()); + return super.decrStackSize(amount); + } + + @Override + protected void onCrafting(ItemStack stack, int amount) + { amountCrafted += amount; onCrafting(stack); } + + @Override + protected void onSwapCraft(int numItemsCrafted) + { amountCrafted += numItemsCrafted; } @Override protected void onCrafting(ItemStack stack) { if((with_assist) && ((player.world!=null) && (!(player.world.isRemote()))) && (!stack.isEmpty())) { - final IRecipe recipe = ((CraftResultInventory)this.inventory).getRecipeUsed(); + final IRecipe recipe = ((CraftOutputInventory)this.inventory).getRecipeUsed(); final ArrayList grid = new ArrayList(); grid.add(stack); for(int i = 0; i<9; ++i) grid.add(container.inventory_.getStackInSlot(i)); @@ -1510,15 +1580,43 @@ public class EdCraftingTable container.history().reset_current(); } } - super.onCrafting(stack); + // Normal crafting result slot behaviour + if(amountCrafted > 0) { + stack.onCrafting(this.player.world, this.player, this.amountCrafted); + net.minecraftforge.fml.hooks.BasicEventHooks.firePlayerCraftingEvent(this.player, stack, this.craftMatrix); + } + if(inventory instanceof IRecipeHolder) { + ((IRecipeHolder)inventory).onCrafting(player); + } + amountCrafted = 0; } @Override - public ItemStack onTake(PlayerEntity player, ItemStack stack) - { - final ItemStack result_stack = super.onTake(player, stack); - container.sync(); - return result_stack; + public ItemStack onTake(PlayerEntity taking_player, ItemStack stack) { + onCrafting(stack); + net.minecraftforge.common.ForgeHooks.setCraftingPlayer(taking_player); + NonNullList stacks = taking_player.world.getRecipeManager().getRecipeNonNull(IRecipeType.CRAFTING, craftMatrix, taking_player.world); + net.minecraftforge.common.ForgeHooks.setCraftingPlayer(null); + for(int i=0; i