diff --git a/1.12/Makefile b/1.12/Makefile index 8818ab3..4530a2e 100644 --- a/1.12/Makefile +++ b/1.12/Makefile @@ -28,7 +28,7 @@ wildcardr=$(foreach d,$(wildcard $1*),$(call wildcardr,$d/,$2) $(filter $(subst # # Targets # -.PHONY: default mod init clean clean-all mrproper all run install sanatize dist-check dist start-server port-languages +.PHONY: default mod init clean clean-all mrproper all run install sanatize dist-check dist dist-files start-server port-languages default: mod @@ -94,12 +94,14 @@ dist-check: @echo "[1.12] Running dist checks ..." @djs tasks.js dist-check -dist: sanatize dist-check clean-all init mod +dist-files: clean-all init mod @echo "[1.12] Distribution files ..." @mkdir -p dist @cp build/libs/$(MOD_JAR_PREFIX)* dist/ @djs tasks.js dist +dist: sanatize dist-check dist-files + port-languages: @echo "[1.12] Porting language files to 1.14 ..." @djs tasks.js port-languages diff --git a/1.12/readme.md b/1.12/readme.md index f1124bf..b73abfe 100644 --- a/1.12/readme.md +++ b/1.12/readme.md @@ -10,7 +10,11 @@ Mod sources for Minecraft version 1.12.2. ---- ## Version history - ~ v1.0.12-b2 [A] Lang files updated. + ~ v1.0.12-b2 [A] Crafting Table: Added recipe collision resolver, + also applies to crafting history refabrication. + [A] Crafting Table: Added rendering of placed items + on the top surface of the table. + [M] Lang files updated. - v1.0.12-b1 [A] Mineal Smelter non-experimental now. [M] Window submodels stripped (reopened issue #19, thx overchoice). diff --git a/1.12/src/main/java/wile/engineersdecor/ModContent.java b/1.12/src/main/java/wile/engineersdecor/ModContent.java index b955ceb..e608fe9 100644 --- a/1.12/src/main/java/wile/engineersdecor/ModContent.java +++ b/1.12/src/main/java/wile/engineersdecor/ModContent.java @@ -25,6 +25,7 @@ import net.minecraft.util.ResourceLocation; import net.minecraft.client.renderer.block.model.ModelResourceLocation; import net.minecraftforge.client.model.ModelLoader; import net.minecraftforge.event.RegistryEvent; +import net.minecraftforge.fml.client.registry.ClientRegistry; import net.minecraftforge.fml.common.Loader; import net.minecraftforge.fml.common.registry.GameRegistry; import net.minecraftforge.fml.relauncher.Side; @@ -595,6 +596,11 @@ public class ModContent for(Item e:registeredItems) { if(e instanceof ItemDecor) ((ItemDecor)e).initModel(); } + if(!ModConfig.optout.without_tesrs) { + if(!ModConfig.isOptedOut(TREATED_WOOD_CRAFTING_TABLE)) { + ClientRegistry.bindTileEntitySpecialRenderer(BlockDecorCraftingTable.BTileEntity.class, new ModTesrs.TesrDecorCraftingTable()); + } + } } // Invoked from CommonProxy.registerItems() diff --git a/1.12/src/main/java/wile/engineersdecor/blocks/BlockDecorCraftingTable.java b/1.12/src/main/java/wile/engineersdecor/blocks/BlockDecorCraftingTable.java index 6d1bc89..1de8749 100644 --- a/1.12/src/main/java/wile/engineersdecor/blocks/BlockDecorCraftingTable.java +++ b/1.12/src/main/java/wile/engineersdecor/blocks/BlockDecorCraftingTable.java @@ -9,24 +9,29 @@ */ package wile.engineersdecor.blocks; +import net.minecraft.network.NetworkManager; +import net.minecraft.network.play.server.SPacketUpdateTileEntity; import wile.engineersdecor.ModEngineersDecor; import wile.engineersdecor.detail.Networking; +import net.minecraft.world.World; +import net.minecraft.world.Explosion; import net.minecraft.block.Block; import net.minecraft.block.SoundType; import net.minecraft.block.material.Material; import net.minecraft.block.state.IBlockState; -import net.minecraft.world.World; -import net.minecraft.world.Explosion; +import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.entity.item.EntityItem; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.InventoryPlayer; import net.minecraft.inventory.*; +import net.minecraft.init.Items; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; -import net.minecraft.init.Items; +import net.minecraft.item.crafting.CraftingManager; import net.minecraft.item.crafting.IRecipe; import net.minecraft.item.crafting.Ingredient; +import net.minecraft.network.play.server.SPacketSetSlot; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.*; @@ -342,12 +347,13 @@ public class BlockDecorCraftingTable extends BlockDecorDirected protected static final int BUTTON_NEXT = 0; protected static final int BUTTON_PREV = 1; protected static final int BUTTON_CLEAR_GRID = 2; - protected static final int BUTTON_FROM_STORAGE = 3; - protected static final int BUTTON_TO_STORAGE = 4; - protected static final int BUTTON_FROM_PLAYER = 5; - protected static final int BUTTON_TO_PLAYER = 6; - protected static final int ACTION_PLACE_CURRENT_HISTORY_SEL = 7; - protected static final int ACTION_PLACE_SHIFTCLICKED_STACK = 8; + protected static final int BUTTON_NEXT_COLLISION_RECIPE = 3; + protected static final int BUTTON_FROM_STORAGE = 4; + protected static final int BUTTON_TO_STORAGE = 5; + protected static final int BUTTON_FROM_PLAYER = 6; + protected static final int BUTTON_TO_PLAYER = 7; + protected static final int ACTION_PLACE_CURRENT_HISTORY_SEL = 8; + protected static final int ACTION_PLACE_SHIFTCLICKED_STACK = 9; protected static final ResourceLocation BACKGROUND = new ResourceLocation(ModEngineersDecor.MODID, "textures/gui/treated_wood_crafting_table.png"); protected final BTileEntity te; @@ -369,6 +375,7 @@ public class BlockDecorCraftingTable extends BlockDecorDirected buttons.add(addButton(new GuiButtonImage(BUTTON_NEXT, x0+158,y0+44, 12,12, 194,44, 12, BACKGROUND))); buttons.add(addButton(new GuiButtonImage(BUTTON_PREV, x0+158,y0+30, 12,12, 180,30, 12, BACKGROUND))); buttons.add(addButton(new GuiButtonImage(BUTTON_CLEAR_GRID, x0+158,y0+58, 12,12, 194,8, 12, BACKGROUND))); + buttons.add(addButton(new GuiButtonImage(BUTTON_NEXT_COLLISION_RECIPE, x0+132,y0+18, 20,10, 183,95, 12, BACKGROUND))); if(with_assist_quickmove_buttons) { buttons.add(addButton(new GuiButtonImage(BUTTON_FROM_STORAGE, x0+49, y0+34, 9,17, 219,34, 17, BACKGROUND))); buttons.add(addButton(new GuiButtonImage(BUTTON_TO_STORAGE, x0+49, y0+52, 9,17, 208,16, 17, BACKGROUND))); @@ -381,6 +388,10 @@ public class BlockDecorCraftingTable extends BlockDecorDirected @Override public void drawScreen(int mouseX, int mouseY, float partialTicks) { + if(with_assist) { + buttons.get(BUTTON_NEXT_COLLISION_RECIPE).visible = te.has_recipe_collision(); + buttons.get(BUTTON_NEXT_COLLISION_RECIPE).enabled = te.has_recipe_collision(); + } drawDefaultBackground(); super.drawScreen(mouseX, mouseY, partialTicks); renderHoveredToolTip(mouseX, mouseY); @@ -476,7 +487,8 @@ public class BlockDecorCraftingTable extends BlockDecorDirected case BUTTON_TO_STORAGE: case BUTTON_FROM_PLAYER: case BUTTON_TO_PLAYER: - case ACTION_PLACE_CURRENT_HISTORY_SEL: { + case ACTION_PLACE_CURRENT_HISTORY_SEL: + case BUTTON_NEXT_COLLISION_RECIPE: { NBTTagCompound nbt = new NBTTagCompound(); nbt.setInteger("action", button.id); Networking.PacketTileNotify.sendToServer(te, nbt); @@ -615,8 +627,32 @@ public class BlockDecorCraftingTable extends BlockDecorDirected @Override public void onCraftMatrixChanged(IInventory inv) { + if(world.isRemote) return; try { - slotChangedCraftingGrid(world, player, craftMatrix, craftResult); + InventoryCrafting grid = craftMatrix; + InventoryCraftResult result = craftResult; + EntityPlayerMP pl = (EntityPlayerMP)player; + ItemStack stack = ItemStack.EMPTY; + List matching_recipes = new ArrayList(); + final IRecipe current_recipe = result.getRecipeUsed(); + final ItemStack current_recipe_stack = result.getStackInSlot(0); + IRecipe current_recipe_matching = null; + for(IRecipe r:CraftingManager.REGISTRY) { + if((r==null) || (!r.matches(grid, world))) continue; + if((!r.isDynamic()) && (world.getGameRules().getBoolean("doLimitedCrafting")) && (!pl.getRecipeBook().isUnlocked(r))) continue; + matching_recipes.add(r); + ItemStack recipe_result_stack = r.getCraftingResult(grid); + if((r==current_recipe) || (recipe_result_stack.isItemEqual(current_recipe_stack))) current_recipe_matching = r; + } + te.has_recipe_collision_ = (matching_recipes.size() > 1); + if(matching_recipes.size() > 0) { + if(current_recipe_matching==null) current_recipe_matching = matching_recipes.get(0); + result.setRecipeUsed(current_recipe_matching); + stack = current_recipe_matching.getCraftingResult(grid); + } + result.setInventorySlotContents(0, stack); + pl.connection.sendPacket(new SPacketSetSlot(this.windowId, 0, stack)); + te.syncProperties(player); } catch(Throwable exc) { ModEngineersDecor.logger.error("Recipe failed:", exc); } @@ -676,6 +712,31 @@ public class BlockDecorCraftingTable extends BlockDecorDirected public void setCraftingMatrixSlot(int slot_index, ItemStack stack) { craftMatrix.setInventorySlotContents(slot_index, stack.copy()); } + + public void select_next_collision_recipe(IInventory inv, EntityPlayer player) + { + if(world.isRemote) return; + try { + EntityPlayerMP pl = (EntityPlayerMP) player; + List matching_recipes = new ArrayList(); + final IRecipe current_recipe = craftResult.getRecipeUsed(); + final ItemStack current_recipe_stack = craftResult.getStackInSlot(0); + int next_recipe_index = 0; + for(IRecipe r:CraftingManager.REGISTRY) { + if((r==null) || (!r.matches(craftMatrix, world))) continue; + if((!r.isDynamic()) && (world.getGameRules().getBoolean("doLimitedCrafting")) && (!pl.getRecipeBook().isUnlocked(r))) continue; + matching_recipes.add(r); + ItemStack recipe_result_stack = r.getCraftingResult(craftMatrix); + if((r==current_recipe) || (recipe_result_stack.isItemEqual(current_recipe_stack))) next_recipe_index = matching_recipes.size(); + } + IRecipe next_recipe = matching_recipes.get((next_recipe_index >= matching_recipes.size()) ? 0 : next_recipe_index); + craftResult.setInventorySlotContents(0, next_recipe.getCraftingResult(craftMatrix)); + craftResult.setRecipeUsed(next_recipe); + onCraftMatrixChanged(inv); + } catch(Throwable exc) { + ModEngineersDecor.logger.error("Recipe failed:", exc); + } + } } //-------------------------------------------------------------------------------------------------------------------- @@ -741,6 +802,7 @@ public class BlockDecorCraftingTable extends BlockDecorDirected public static final int NUM_OF_SLOTS = NUM_OF_CRAFTING_SLOTS+NUM_OF_STORAGE_SLOTS; protected NonNullList stacks; protected final CraftingHistory history = new CraftingHistory(); + protected boolean has_recipe_collision_ = false; public BTileEntity() { stacks = NonNullList.withSize(NUM_OF_SLOTS, ItemStack.EMPTY); } @@ -764,6 +826,9 @@ public class BlockDecorCraftingTable extends BlockDecorDirected // private aux methods --------------------------------------------------------------------- + private boolean has_recipe_collision() + { return has_recipe_collision_; } + private boolean itemstack_recipe_match(ItemStack grid_stack, ItemStack history_stack) { if(history.current_recipe()!=null) { @@ -948,7 +1013,7 @@ public class BlockDecorCraftingTable extends BlockDecorDirected } enum EnumRefabPlacement { UNCHANGED, INCOMPLETE, PLACED } - private EnumRefabPlacement place_refab_stacks(IInventory inventory, final int slot_begin, final int slot_end) + private EnumRefabPlacement place_refab_stacks(IInventory inventory, final int slot_begin, final int slot_end, @Nullable EntityPlayer player) { List to_fill = crafting_slot_stacks_to_add(); boolean slots_changed = false; @@ -978,6 +1043,9 @@ public class BlockDecorCraftingTable extends BlockDecorDirected if(!slots_updated) break; } } + if((history.current_recipe() != null) && (player!=null) && (player.openContainer instanceof BContainer)) { + ((BContainer)player.openContainer).craftResult.setRecipeUsed(history.current_recipe()); + } if(!slots_changed) { return EnumRefabPlacement.UNCHANGED; } else if(missing_item) { @@ -1094,25 +1162,25 @@ public class BlockDecorCraftingTable extends BlockDecorDirected if(clear_grid_to_player(player)) { te_changed = true; player_inventory_changed = true; } } break; case BGui.BUTTON_FROM_STORAGE: { - EnumRefabPlacement from_storage = place_refab_stacks(this, STORAGE_SLOTS_BEGIN, STORAGE_SLOTS_BEGIN + NUM_OF_STORAGE_SLOTS); + EnumRefabPlacement from_storage = place_refab_stacks(this, STORAGE_SLOTS_BEGIN, STORAGE_SLOTS_BEGIN + NUM_OF_STORAGE_SLOTS, player); if(from_storage != EnumRefabPlacement.UNCHANGED) te_changed = true; } break; case BGui.BUTTON_FROM_PLAYER: { - EnumRefabPlacement from_player_inv = place_refab_stacks(player.inventory, 9, 36); + EnumRefabPlacement from_player_inv = place_refab_stacks(player.inventory, 9, 36, player); if(from_player_inv != EnumRefabPlacement.UNCHANGED) { te_changed = true; player_inventory_changed = true; } if(from_player_inv != EnumRefabPlacement.PLACED) { - EnumRefabPlacement from_hotbar = place_refab_stacks(player.inventory, 0, 9); + EnumRefabPlacement from_hotbar = place_refab_stacks(player.inventory, 0, 9, player); if(from_hotbar != EnumRefabPlacement.UNCHANGED) { te_changed = true; player_inventory_changed = true; } } } break; case BGui.ACTION_PLACE_CURRENT_HISTORY_SEL: { - EnumRefabPlacement from_storage = place_refab_stacks(this, STORAGE_SLOTS_BEGIN, STORAGE_SLOTS_BEGIN + NUM_OF_STORAGE_SLOTS); + EnumRefabPlacement from_storage = place_refab_stacks(this, STORAGE_SLOTS_BEGIN, STORAGE_SLOTS_BEGIN + NUM_OF_STORAGE_SLOTS, player); if(from_storage != EnumRefabPlacement.UNCHANGED) te_changed = true; if(from_storage != EnumRefabPlacement.PLACED) { - EnumRefabPlacement from_player_inv = place_refab_stacks(player.inventory, 9, 36); + EnumRefabPlacement from_player_inv = place_refab_stacks(player.inventory, 9, 36, player); if(from_player_inv != EnumRefabPlacement.UNCHANGED) { te_changed = true; player_inventory_changed = true; } if(from_player_inv != EnumRefabPlacement.PLACED) { - EnumRefabPlacement from_hotbar = place_refab_stacks(player.inventory, 0, 9); + EnumRefabPlacement from_hotbar = place_refab_stacks(player.inventory, 0, 9, player); if(from_hotbar != EnumRefabPlacement.UNCHANGED) { te_changed = true; player_inventory_changed = true; } } } @@ -1132,6 +1200,11 @@ public class BlockDecorCraftingTable extends BlockDecorDirected if(stat != EnumRefabPlacement.UNCHANGED) { player_inventory_changed = true; te_changed = true; } } } break; + case BGui.BUTTON_NEXT_COLLISION_RECIPE: { + if(player.openContainer instanceof BContainer) { + ((BContainer)player.openContainer).select_next_collision_recipe(this, player); + } + } break; } } if(te_changed) markDirty(); @@ -1146,6 +1219,7 @@ public class BlockDecorCraftingTable extends BlockDecorDirected public void onServerPacketReceived(NBTTagCompound nbt) { if(nbt.hasKey("historydata")) history.read(nbt.getCompoundTag("historydata")); + if(nbt.hasKey("hascollision")) has_recipe_collision_ = nbt.getBoolean("hascollision"); } private void syncHistory(EntityPlayer player) @@ -1155,6 +1229,15 @@ public class BlockDecorCraftingTable extends BlockDecorDirected history.write(history_nbt); NBTTagCompound rnbt = new NBTTagCompound(); rnbt.setTag("historydata", history_nbt); + rnbt.setBoolean("hascollision", has_recipe_collision_); + Networking.PacketTileNotify.sendToPlayer(player, this, rnbt); + } + + private void syncProperties(EntityPlayer player) + { + if(!with_assist) return; + NBTTagCompound rnbt = new NBTTagCompound(); + rnbt.setBoolean("hascollision", has_recipe_collision_); Networking.PacketTileNotify.sendToPlayer(player, this, rnbt); } @@ -1173,9 +1256,26 @@ public class BlockDecorCraftingTable extends BlockDecorDirected { super.writeToNBT(nbt); writenbt(nbt); return nbt; } @Override - public NBTTagCompound getUpdateTag() + public NBTTagCompound getUpdateTag() // on server { NBTTagCompound nbt = new NBTTagCompound(); super.writeToNBT(nbt); writenbt(nbt); return nbt; } + @Override + public void onDataPacket(NetworkManager net, SPacketUpdateTileEntity pkt) // on client + { super.readFromNBT(pkt.getNbtCompound()); readnbt(pkt.getNbtCompound()); super.onDataPacket(net, pkt); } + + @Override + public SPacketUpdateTileEntity getUpdatePacket() // on server + { return new SPacketUpdateTileEntity(pos, 1, getUpdateTag()); } + + @Override + public void handleUpdateTag(NBTTagCompound tag) // on client + { readFromNBT(tag); } + + @Override + @SideOnly(Side.CLIENT) + public double getMaxRenderDistanceSquared() + { return 400; } + // IWorldNamable --------------------------------------------------------------------------- @Override @@ -1256,7 +1356,6 @@ public class BlockDecorCraftingTable extends BlockDecorDirected @Override public void clear() { stacks.clear(); } - } } diff --git a/1.12/src/main/java/wile/engineersdecor/detail/ModConfig.java b/1.12/src/main/java/wile/engineersdecor/detail/ModConfig.java index c89380f..a1c49b8 100644 --- a/1.12/src/main/java/wile/engineersdecor/detail/ModConfig.java +++ b/1.12/src/main/java/wile/engineersdecor/detail/ModConfig.java @@ -191,6 +191,10 @@ public class ModConfig @Config.Comment({"Disable CTRL-SHIFT item tooltip display."}) @Config.Name("Without tooltips") public boolean without_tooltips = false; + + @Config.Comment({"Disable all tile entity special renderers."}) + @Config.Name("Without TESRs") + public boolean without_tesrs = false; } @Config.Comment({ diff --git a/1.12/src/main/java/wile/engineersdecor/detail/ModTesrs.java b/1.12/src/main/java/wile/engineersdecor/detail/ModTesrs.java new file mode 100644 index 0000000..e040887 --- /dev/null +++ b/1.12/src/main/java/wile/engineersdecor/detail/ModTesrs.java @@ -0,0 +1,85 @@ +/* + * @file ModTesrs.java + * @author Stefan Wilhelm (wile) + * @copyright (C) 2018 Stefan Wilhelm + * @license MIT (see https://opensource.org/licenses/MIT) + * + * Yet unstructured initial experiments with TESRs. + * May be structured after I know what I am doing there. + */ +package wile.engineersdecor.detail; + +import wile.engineersdecor.ModEngineersDecor; +import wile.engineersdecor.blocks.BlockDecorCraftingTable; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.block.model.ItemCameraTransforms.TransformType; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.RenderHelper; +import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer; +import net.minecraft.item.ItemBlock; +import net.minecraft.item.ItemStack; +import net.minecraft.util.math.MathHelper; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +public class ModTesrs +{ + //-------------------------------------------------------------------------------------------------------------------- + // Crafting table + //-------------------------------------------------------------------------------------------------------------------- + + @SideOnly(Side.CLIENT) + public static class TesrDecorCraftingTable extends TileEntitySpecialRenderer + { + private static int tesr_error_counter = 4; + private static double scaler = 0.10; + private static double gap = 0.19; + private static double yrotations[] = {0, 90, 180, 270}; // [hdirection] S-W-N-E + private static double offsets[][][] = { // [hdirection][slotindex][xz] + { {-1,-1},{+0,-1},{+1,-1}, {-1,+0},{+0,+0},{+1,+0}, {-1,+1},{+0,+1},{+1,+1} }, // S + { {+1,-1},{+1,+0},{+1,+1}, {+0,-1},{+0,+0},{+0,+1}, {-1,-1},{-1,+0},{-1,+1} }, // W + { {+1,+1},{+0,+1},{-1,+1}, {+1,+0},{+0,+0},{-1,+0}, {+1,-1},{+0,-1},{-1,-1} }, // N + { {-1,+1},{-1,+0},{-1,-1}, {+0,+1},{+0,+0},{+0,-1}, {+1,+1},{+1,+0},{+1,-1} }, // E + }; + + @Override + public void render(final BlockDecorCraftingTable.BTileEntity te, final double x, final double y, final double z, final float partialTicks, final int destroyStage, final float alpha) + { + if(tesr_error_counter<=0) return; + try { + int di = MathHelper.clamp(te.getWorld().getBlockState(te.getPos()).getValue(BlockDecorCraftingTable.FACING).getHorizontalIndex(), 0, 3); + long posrnd = te.getPos().toLong(); + posrnd = (posrnd>>16)^(posrnd<<1); + for(int i=0; i block_registry = ForgeRegistries.BLOCKS; final IForgeRegistry item_registry = ForgeRegistries.ITEMS; final JsonArray items = json.getAsJsonArray("required"); diff --git a/1.12/src/main/resources/assets/engineersdecor/models/block/device/small_tree_cutter_model.json b/1.12/src/main/resources/assets/engineersdecor/models/block/device/small_tree_cutter_model.json index 79ef38f..4a59c10 100644 --- a/1.12/src/main/resources/assets/engineersdecor/models/block/device/small_tree_cutter_model.json +++ b/1.12/src/main/resources/assets/engineersdecor/models/block/device/small_tree_cutter_model.json @@ -199,11 +199,16 @@ "display": { "thirdperson_righthand": { "rotation": [85, 3, -10], - "translation": [1.75, -0.75, -2.25], + "translation": [0.75, 0.25, 0.5], "scale": [0.35, 0.35, 0.35] }, + "firstperson_righthand": { + "rotation": [18, 22, 0], + "translation": [1.25, 0, 0], + "scale": [0.4, 0.4, 0.4] + }, "ground": { - "translation": [0, -0.75, 0], + "translation": [0, -1.25, 0], "scale": [0.2, 0.2, 0.2] }, "gui": { diff --git a/1.12/src/main/resources/assets/engineersdecor/recipes/testing/collision_test1_diorite.json b/1.12/src/main/resources/assets/engineersdecor/recipes/testing/collision_test1_diorite.json new file mode 100644 index 0000000..2597836 --- /dev/null +++ b/1.12/src/main/resources/assets/engineersdecor/recipes/testing/collision_test1_diorite.json @@ -0,0 +1,22 @@ +{ + "conditions": [ + { + "type": "engineersdecor:grc", + "experimental": true + } + ], + "type": "minecraft:crafting_shaped", + "pattern": [ + "DDD", + " D ", + " D " + ], + "key": { + "D": { "item": "minecraft:stone", "data":3 } + }, + "result": { + "item": "minecraft:stone", + "data": 0, + "count": 1 + } +} diff --git a/1.12/src/main/resources/assets/engineersdecor/recipes/testing/collision_test2_diorite.json b/1.12/src/main/resources/assets/engineersdecor/recipes/testing/collision_test2_diorite.json new file mode 100644 index 0000000..8eaa485 --- /dev/null +++ b/1.12/src/main/resources/assets/engineersdecor/recipes/testing/collision_test2_diorite.json @@ -0,0 +1,22 @@ +{ + "conditions": [ + { + "type": "engineersdecor:grc", + "experimental": true + } + ], + "type": "minecraft:crafting_shaped", + "pattern": [ + "DDD", + " D ", + " D " + ], + "key": { + "D": { "item": "minecraft:stone", "data":3 } + }, + "result": { + "item": "minecraft:stone", + "data": 1, + "count": 1 + } +} diff --git a/1.12/src/main/resources/assets/engineersdecor/recipes/testing/collision_test3_diorite.json b/1.12/src/main/resources/assets/engineersdecor/recipes/testing/collision_test3_diorite.json new file mode 100644 index 0000000..a700163 --- /dev/null +++ b/1.12/src/main/resources/assets/engineersdecor/recipes/testing/collision_test3_diorite.json @@ -0,0 +1,22 @@ +{ + "conditions": [ + { + "type": "engineersdecor:grc", + "experimental": true + } + ], + "type": "minecraft:crafting_shaped", + "pattern": [ + "DDD", + " D ", + " D " + ], + "key": { + "D": { "item": "minecraft:stone", "data":3 } + }, + "result": { + "item": "minecraft:stone", + "data": 5, + "count": 1 + } +} diff --git a/1.12/src/main/resources/assets/engineersdecor/textures/gui/treated_wood_crafting_table.png b/1.12/src/main/resources/assets/engineersdecor/textures/gui/treated_wood_crafting_table.png index bc26abf..c6c18dc 100644 Binary files a/1.12/src/main/resources/assets/engineersdecor/textures/gui/treated_wood_crafting_table.png and b/1.12/src/main/resources/assets/engineersdecor/textures/gui/treated_wood_crafting_table.png differ diff --git a/1.14/Makefile b/1.14/Makefile index 6a275f5..9251e35 100644 --- a/1.14/Makefile +++ b/1.14/Makefile @@ -72,12 +72,14 @@ dist-check: @echo "[1.14] Running dist checks ..." @djs tasks.js dist-check -dist: sanatize dist-check clean-all init mod +dist-files: clean-all init mod @echo "[1.14] Distribution files ..." @mkdir -p dist @cp build/libs/$(MOD_JAR_PREFIX)* dist/ @djs tasks.js dist +dist: sanatize dist-check dist-files + assets: @echo "[1.14] Running asset generators ..." @djs tasks.js create-slab-assets diff --git a/1.14/build.gradle b/1.14/build.gradle index 0f376da..885f8f9 100644 --- a/1.14/build.gradle +++ b/1.14/build.gradle @@ -19,21 +19,12 @@ version = "${version_engineersdecor}" group = "wile.engineersdecor" archivesBaseName = "engineersdecor-${version_minecraft}" -def signing = { -> +def signingData = { -> def sp = new Properties() if(file("signing.properties").exists()) file("signing.properties").withInputStream { sp.load(it) } return sp }() -def git_version = { -> - def stdout = new ByteArrayOutputStream() - exec { - commandLine 'git', 'log', '-1', '--format=%h' - standardOutput = stdout - } - return stdout.toString().trim() -}() - repositories { maven { name = "Progwml6 maven"; url = "https://dvs1.progwml6.com/files/maven/" } // JEI files maven { name = "ModMaven"; url = "modmaven.k-4u.nl" } // JEI files, fallback @@ -83,6 +74,11 @@ dependencies { runtimeOnly fg.deobf("mezz.jei:jei-${version_jei}") } +processResources { + outputs.upToDateWhen { false } // thx to @tterrag for this hint + doLast { file("${sourceSets.main.output.resourcesDir}/.gitversion").text = 'git log "-1" "--format=%h"'.execute().in.text.trim() } +} + jar { manifest { attributes([ diff --git a/1.14/gradle.properties b/1.14/gradle.properties index 7d0644d..f51882d 100644 --- a/1.14/gradle.properties +++ b/1.14/gradle.properties @@ -5,4 +5,4 @@ version_minecraft=1.14.4 version_forge_minecraft=1.14.4-28.0.105 version_fml_mappings=20190719-1.14.3 version_jei=1.14.4:6.0.0.10 -version_engineersdecor=1.0.12-b2 +version_engineersdecor=1.0.12-b3 diff --git a/1.14/readme.md b/1.14/readme.md index cd609d5..7a1055e 100644 --- a/1.14/readme.md +++ b/1.14/readme.md @@ -1,7 +1,7 @@ -## Engineer's Decor (MC1.14.3) +## Engineer's Decor (MC1.14.4) -Mod sources for Minecraft version 1.14.3. +Mod sources for Minecraft version 1.14.4. - Description, credits, and features: Please see the readme in the repository root. @@ -11,6 +11,12 @@ Mod sources for Minecraft version 1.14.3. ## Version history + ~ v1.0.12-b3 [A] Crafting Table: Added recipe collision resolver, + also applies to crafting history refabrication. + [A] Crafting Table: Added rendering of placed items + on the top surface of the table. + [A] Waterlogging of non-full-blocks added. + - v1.0.12-b2 [U] Updated to Forge 1.14.4-28.0.105/20190719-1.14.3. [A] Small Solar Panel added. [M] Items fall through the Steel Floor Grating like in 1.12.2 version. diff --git a/1.14/src/main/java/wile/engineersdecor/ModContent.java b/1.14/src/main/java/wile/engineersdecor/ModContent.java index d84de10..33262c7 100644 --- a/1.14/src/main/java/wile/engineersdecor/ModContent.java +++ b/1.14/src/main/java/wile/engineersdecor/ModContent.java @@ -12,6 +12,7 @@ */ package wile.engineersdecor; +import net.minecraftforge.fml.client.registry.ClientRegistry; import org.apache.commons.lang3.ArrayUtils; import wile.engineersdecor.blocks.*; import wile.engineersdecor.detail.ModAuxiliaries; @@ -32,6 +33,8 @@ import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; import net.minecraftforge.event.RegistryEvent; +import wile.engineersdecor.detail.ModTesrs; + import java.util.ArrayList; import java.util.List; import java.util.Collections; @@ -40,12 +43,11 @@ import javax.annotation.Nonnull; @SuppressWarnings("unused") public class ModContent { - //-------------------------------------------------------------------------------------------------------------------- // Blocks //-------------------------------------------------------------------------------------------------------------------- - public static final BlockDecorFull CLINKER_BRICK_BLOCK = (BlockDecorFull)(new BlockDecorFull( + public static final BlockDecor CLINKER_BRICK_BLOCK = (BlockDecor)(new BlockDecor( BlockDecor.CFG_DEFAULT, Block.Properties.create(Material.ROCK, MaterialColor.STONE).hardnessAndResistance(3f, 50f).sound(SoundType.STONE) )).setRegistryName(new ResourceLocation(ModEngineersDecor.MODID, "clinker_brick_block")); @@ -68,7 +70,7 @@ public class ModContent // ------------------------------------------------------------------------------------------------------------------- - public static final BlockDecorFull CLINKER_BRICK_STAINED_BLOCK = (BlockDecorFull)(new BlockDecorFull( + public static final BlockDecor CLINKER_BRICK_STAINED_BLOCK = (BlockDecor)(new BlockDecor( BlockDecor.CFG_DEFAULT, Block.Properties.create(Material.ROCK, MaterialColor.STONE).hardnessAndResistance(3f, 50f).sound(SoundType.STONE) )).setRegistryName(new ResourceLocation(ModEngineersDecor.MODID, "clinker_brick_stained_block")); @@ -86,7 +88,7 @@ public class ModContent // ------------------------------------------------------------------------------------------------------------------- - public static final BlockDecorFull SLAG_BRICK_BLOCK = (BlockDecorFull)(new BlockDecorFull( + public static final BlockDecor SLAG_BRICK_BLOCK = (BlockDecor)(new BlockDecor( BlockDecor.CFG_DEFAULT, Block.Properties.create(Material.ROCK, MaterialColor.STONE).hardnessAndResistance(3f, 50f).sound(SoundType.STONE) )).setRegistryName(new ResourceLocation(ModEngineersDecor.MODID, "slag_brick_block")); @@ -109,7 +111,7 @@ public class ModContent // ------------------------------------------------------------------------------------------------------------------- - public static final BlockDecorFull REBAR_CONCRETE_BLOCK = (BlockDecorFull)(new BlockDecorFull( + public static final BlockDecor REBAR_CONCRETE_BLOCK = (BlockDecor)(new BlockDecor( BlockDecor.CFG_DEFAULT, Block.Properties.create(Material.ROCK, MaterialColor.STONE).hardnessAndResistance(5f, 2000f).sound(SoundType.STONE) )).setRegistryName(new ResourceLocation(ModEngineersDecor.MODID, "rebar_concrete")); @@ -131,13 +133,13 @@ public class ModContent )).setRegistryName(new ResourceLocation(ModEngineersDecor.MODID, "rebar_concrete_wall")); public static final BlockDecorHalfSlab HALFSLAB_REBARCONCRETE = (BlockDecorHalfSlab)(new BlockDecorHalfSlab( - BlockDecor.CFG_DEFAULT, + BlockDecor.CFG_CUTOUT, Block.Properties.create(Material.ROCK, MaterialColor.STONE).hardnessAndResistance(5f, 2000f).sound(SoundType.STONE) )).setRegistryName(new ResourceLocation(ModEngineersDecor.MODID, "halfslab_rebar_concrete")); // ------------------------------------------------------------------------------------------------------------------- - public static final BlockDecorFull REBAR_CONCRETE_TILE = (BlockDecorFull)(new BlockDecorFull( + public static final BlockDecor REBAR_CONCRETE_TILE = (BlockDecor)(new BlockDecor( BlockDecor.CFG_DEFAULT, Block.Properties.create(Material.ROCK, MaterialColor.STONE).hardnessAndResistance(5f, 2000f).sound(SoundType.STONE) )).setRegistryName(new ResourceLocation(ModEngineersDecor.MODID, "rebar_concrete_tile")); @@ -184,7 +186,7 @@ public class ModContent // ------------------------------------------------------------------------------------------------------------------- - public static final BlockDecor TREATED_WOOD_TABLE = (BlockDecor)(new BlockDecor( + public static final BlockDecor.WaterLoggable TREATED_WOOD_TABLE = (BlockDecor.WaterLoggable)(new BlockDecor.WaterLoggable( BlockDecor.CFG_CUTOUT, Block.Properties.create(Material.WOOD, MaterialColor.WOOD).hardnessAndResistance(2f, 15f).sound(SoundType.WOOD), ModAuxiliaries.getPixeledAABB(1,0,1, 15,15.9,15) @@ -196,25 +198,25 @@ public class ModContent ModAuxiliaries.getPixeledAABB(4.1,0,4.1, 11.8,8.8,11.8) )).setRegistryName(new ResourceLocation(ModEngineersDecor.MODID, "treated_wood_stool")); - public static final BlockDecor TREATED_WOOD_SIDE_TABLE = (BlockDecor)(new BlockDecor( + public static final BlockDecor.WaterLoggable TREATED_WOOD_SIDE_TABLE = (BlockDecor.WaterLoggable)(new BlockDecor.WaterLoggable( BlockDecor.CFG_CUTOUT|BlockDecor.CFG_HORIZIONTAL|BlockDecor.CFG_LOOK_PLACEMENT, Block.Properties.create(Material.WOOD, MaterialColor.WOOD).hardnessAndResistance(2f, 15f).sound(SoundType.WOOD), ModAuxiliaries.getPixeledAABB(2,0,2, 14,15.9,14) )).setRegistryName(new ResourceLocation(ModEngineersDecor.MODID, "treated_wood_side_table")); - public static final BlockDecorDirected TREATED_WOOD_WINDOWSILL = (BlockDecorDirected)(new BlockDecorDirected( + public static final BlockDecorDirected.WaterLoggable TREATED_WOOD_WINDOWSILL = (BlockDecorDirected.WaterLoggable)(new BlockDecorDirected.WaterLoggable( BlockDecor.CFG_CUTOUT|BlockDecor.CFG_HORIZIONTAL|BlockDecor.CFG_FACING_PLACEMENT, Block.Properties.create(Material.WOOD, MaterialColor.WOOD).hardnessAndResistance(2f, 15f).sound(SoundType.WOOD), ModAuxiliaries.getPixeledAABB(0.5,15,10.5, 15.5,16,16) )).setRegistryName(new ResourceLocation(ModEngineersDecor.MODID, "treated_wood_windowsill")); - public static final BlockDecorDirected INSET_LIGHT_IRON = (BlockDecorDirected)(new BlockDecorDirected( + public static final BlockDecorDirected.WaterLoggable INSET_LIGHT_IRON = (BlockDecorDirected.WaterLoggable)(new BlockDecorDirected.WaterLoggable( BlockDecor.CFG_CUTOUT|BlockDecor.CFG_OPPOSITE_PLACEMENT, Block.Properties.create(Material.IRON, MaterialColor.IRON).hardnessAndResistance(2f, 15f).sound(SoundType.METAL).lightValue(15), ModAuxiliaries.getPixeledAABB(5.2,5.2,15.7, 10.8,10.8,16.0) )).setRegistryName(new ResourceLocation(ModEngineersDecor.MODID, "iron_inset_light")); - public static final BlockDecor STEEL_TABLE = (BlockDecor)(new BlockDecor( + public static final BlockDecor.WaterLoggable STEEL_TABLE = (BlockDecor.WaterLoggable)(new BlockDecor.WaterLoggable( BlockDecor.CFG_CUTOUT|BlockDecor.CFG_HORIZIONTAL|BlockDecor.CFG_LOOK_PLACEMENT, Block.Properties.create(Material.WOOD, MaterialColor.WOOD).hardnessAndResistance(2f, 15f).sound(SoundType.WOOD), ModAuxiliaries.getPixeledAABB(0,0,0, 16,16,16) @@ -292,43 +294,42 @@ public class ModContent // ------------------------------------------------------------------------------------------------------------------- - public static final BlockDecorDirected SIGN_MODLOGO = (BlockDecorDirected)(new BlockDecorDirected( + public static final BlockDecorDirected.WaterLoggable SIGN_MODLOGO = (BlockDecorDirected.WaterLoggable)(new BlockDecorDirected.WaterLoggable( BlockDecor.CFG_CUTOUT|BlockDecor.CFG_FACING_PLACEMENT|BlockDecor.CFG_HORIZIONTAL, Block.Properties.create(Material.WOOD, MaterialColor.WOOD).hardnessAndResistance(1f, 1000f).sound(SoundType.WOOD).lightValue(1), ModAuxiliaries.getPixeledAABB(0,0,15.6, 16,16,16.0) )).setRegistryName(new ResourceLocation(ModEngineersDecor.MODID, "sign_decor")); - public static final BlockDecorDirected SIGN_HOTWIRE = (BlockDecorDirected)(new BlockDecorDirected( + public static final BlockDecorDirected.WaterLoggable SIGN_HOTWIRE = (BlockDecorDirected.WaterLoggable)(new BlockDecorDirected.WaterLoggable( BlockDecor.CFG_CUTOUT|BlockDecor.CFG_FACING_PLACEMENT|BlockDecor.CFG_HORIZIONTAL, Block.Properties.create(Material.WOOD, MaterialColor.WOOD).hardnessAndResistance(1f, 1f).sound(SoundType.WOOD), ModAuxiliaries.getPixeledAABB(2,2,15.6, 14,14,16) )).setRegistryName(new ResourceLocation(ModEngineersDecor.MODID, "sign_hotwire")); - public static final BlockDecorDirected SIGN_DANGER = (BlockDecorDirected)(new BlockDecorDirected( + public static final BlockDecorDirected.WaterLoggable SIGN_DANGER = (BlockDecorDirected.WaterLoggable)(new BlockDecorDirected.WaterLoggable( BlockDecor.CFG_CUTOUT|BlockDecor.CFG_FACING_PLACEMENT|BlockDecor.CFG_HORIZIONTAL, Block.Properties.create(Material.WOOD, MaterialColor.WOOD).hardnessAndResistance(1f, 1f).sound(SoundType.WOOD), ModAuxiliaries.getPixeledAABB(2,2,15.6, 14,14,16) )).setRegistryName(new ResourceLocation(ModEngineersDecor.MODID, "sign_danger")); - public static final BlockDecorDirected SIGN_DEFENSE = (BlockDecorDirected)(new BlockDecorDirected( + public static final BlockDecorDirected.WaterLoggable SIGN_DEFENSE = (BlockDecorDirected.WaterLoggable)(new BlockDecorDirected.WaterLoggable( BlockDecor.CFG_CUTOUT|BlockDecor.CFG_FACING_PLACEMENT|BlockDecor.CFG_HORIZIONTAL, Block.Properties.create(Material.WOOD, MaterialColor.WOOD).hardnessAndResistance(1f, 1f).sound(SoundType.WOOD), ModAuxiliaries.getPixeledAABB(2,2,15.6, 14,14,16) )).setRegistryName(new ResourceLocation(ModEngineersDecor.MODID, "sign_defense")); - public static final BlockDecorDirected SIGN_FACTORY_AREA = (BlockDecorDirected)(new BlockDecorDirected( + public static final BlockDecorDirected.WaterLoggable SIGN_FACTORY_AREA = (BlockDecorDirected.WaterLoggable)(new BlockDecorDirected.WaterLoggable( BlockDecor.CFG_CUTOUT|BlockDecor.CFG_FACING_PLACEMENT|BlockDecor.CFG_HORIZIONTAL, Block.Properties.create(Material.WOOD, MaterialColor.WOOD).hardnessAndResistance(1f, 1f).sound(SoundType.WOOD), ModAuxiliaries.getPixeledAABB(2,2,15.6, 14,14,16) )).setRegistryName(new ResourceLocation(ModEngineersDecor.MODID, "sign_factoryarea")); - public static final BlockDecorDirected SIGN_EXIT = (BlockDecorDirected)(new BlockDecorDirected( + public static final BlockDecorDirected.WaterLoggable SIGN_EXIT = (BlockDecorDirected.WaterLoggable)(new BlockDecorDirected.WaterLoggable( BlockDecor.CFG_CUTOUT|BlockDecor.CFG_FACING_PLACEMENT|BlockDecor.CFG_HORIZIONTAL, Block.Properties.create(Material.WOOD, MaterialColor.WOOD).hardnessAndResistance(1f, 1f).sound(SoundType.WOOD), ModAuxiliaries.getPixeledAABB(3,7,15.6, 13,13,16) )).setRegistryName(new ResourceLocation(ModEngineersDecor.MODID, "sign_exit")); - // ------------------------------------------------------------------------------------------------------------------- public static final BlockDecorCraftingTable TREATED_WOOD_CRAFTING_TABLE = (BlockDecorCraftingTable)(new BlockDecorCraftingTable( @@ -410,32 +411,32 @@ public class ModContent )).setRegistryName(new ResourceLocation(ModEngineersDecor.MODID, "halfslab_concrete")); public static final BlockDecorHalfSlab HALFSLAB_TREATEDWOOD = (BlockDecorHalfSlab)(new BlockDecorHalfSlab( - BlockDecor.CFG_CUTOUT, + BlockDecor.CFG_CUTOUT|BlockDecor.CFG_HARD_IE_DEPENDENT, Block.Properties.create(Material.WOOD, MaterialColor.WOOD).hardnessAndResistance(1f, 4f).sound(SoundType.WOOD) )).setRegistryName(new ResourceLocation(ModEngineersDecor.MODID, "halfslab_treated_wood")); public static final BlockDecorHalfSlab HALFSLAB_SHEETMETALIRON = (BlockDecorHalfSlab)(new BlockDecorHalfSlab( - BlockDecor.CFG_CUTOUT, + BlockDecor.CFG_CUTOUT|BlockDecor.CFG_HARD_IE_DEPENDENT, Block.Properties.create(Material.IRON, MaterialColor.IRON).hardnessAndResistance(1f, 10f).sound(SoundType.METAL) )).setRegistryName(new ResourceLocation(ModEngineersDecor.MODID, "halfslab_sheetmetal_iron")); public static final BlockDecorHalfSlab HALFSLAB_SHEETMETALSTEEL = (BlockDecorHalfSlab)(new BlockDecorHalfSlab( - BlockDecor.CFG_CUTOUT, + BlockDecor.CFG_CUTOUT|BlockDecor.CFG_HARD_IE_DEPENDENT, Block.Properties.create(Material.IRON, MaterialColor.IRON).hardnessAndResistance(1f, 10f).sound(SoundType.METAL) )).setRegistryName(new ResourceLocation(ModEngineersDecor.MODID, "halfslab_sheetmetal_steel")); public static final BlockDecorHalfSlab HALFSLAB_SHEETMETALCOPPER = (BlockDecorHalfSlab)(new BlockDecorHalfSlab( - BlockDecor.CFG_CUTOUT, + BlockDecor.CFG_CUTOUT|BlockDecor.CFG_HARD_IE_DEPENDENT, Block.Properties.create(Material.IRON, MaterialColor.IRON).hardnessAndResistance(1f, 10f).sound(SoundType.METAL) )).setRegistryName(new ResourceLocation(ModEngineersDecor.MODID, "halfslab_sheetmetal_copper")); public static final BlockDecorHalfSlab HALFSLAB_SHEETMETALGOLD = (BlockDecorHalfSlab)(new BlockDecorHalfSlab( - BlockDecor.CFG_CUTOUT, + BlockDecor.CFG_CUTOUT|BlockDecor.CFG_HARD_IE_DEPENDENT, Block.Properties.create(Material.IRON, MaterialColor.IRON).hardnessAndResistance(1f, 10f).sound(SoundType.METAL) )).setRegistryName(new ResourceLocation(ModEngineersDecor.MODID, "halfslab_sheetmetal_gold")); public static final BlockDecorHalfSlab HALFSLAB_SHEETMETALALUMINIUM = (BlockDecorHalfSlab)(new BlockDecorHalfSlab( - BlockDecor.CFG_CUTOUT, + BlockDecor.CFG_CUTOUT|BlockDecor.CFG_HARD_IE_DEPENDENT, Block.Properties.create(Material.IRON, MaterialColor.IRON).hardnessAndResistance(1f, 10f).sound(SoundType.METAL) )).setRegistryName(new ResourceLocation(ModEngineersDecor.MODID, "halfslab_sheetmetal_aluminum")); @@ -701,4 +702,9 @@ public class ModContent ScreenManager.registerFactory(CT_WASTE_INCINERATOR, BlockDecorWasteIncinerator.BGui::new); } + @OnlyIn(Dist.CLIENT) + public static final void registerTileEntityRenderers(final FMLClientSetupEvent event) + { + ClientRegistry.bindTileEntitySpecialRenderer(BlockDecorCraftingTable.BTileEntity.class, new ModTesrs.TesrDecorCraftingTable()); + } } diff --git a/1.14/src/main/java/wile/engineersdecor/ModEngineersDecor.java b/1.14/src/main/java/wile/engineersdecor/ModEngineersDecor.java index f494ea6..fd7efdc 100644 --- a/1.14/src/main/java/wile/engineersdecor/ModEngineersDecor.java +++ b/1.14/src/main/java/wile/engineersdecor/ModEngineersDecor.java @@ -1,16 +1,15 @@ package wile.engineersdecor; import wile.engineersdecor.detail.ModConfig; -import wile.engineersdecor.detail.OptionalRecipeCondition; import wile.engineersdecor.detail.Networking; import wile.engineersdecor.blocks.*; +import wile.engineersdecor.detail.OptionalRecipeCondition.Serializer; import net.minecraft.client.Minecraft; import net.minecraft.entity.EntityType; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.inventory.container.ContainerType; import net.minecraft.item.ItemGroup; import net.minecraft.tileentity.TileEntityType; -import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; import net.minecraft.block.Block; import net.minecraft.item.Item; @@ -33,7 +32,6 @@ import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import wile.engineersdecor.detail.OptionalRecipeCondition.Serializer; import javax.annotation.Nullable; @@ -70,7 +68,7 @@ public class ModEngineersDecor } private void onClientSetup(final FMLClientSetupEvent event) - { ModContent.registerContainerGuis(event); } + { ModContent.registerContainerGuis(event); ModContent.registerTileEntityRenderers(event); } private void onSendImc(final InterModEnqueueEvent event) {} @@ -78,12 +76,8 @@ public class ModEngineersDecor private void onRecvImc(final InterModProcessEvent event) {} - @SubscribeEvent - public void onServerStarting(FMLServerStartingEvent event) - {} - @Mod.EventBusSubscriber(bus=Mod.EventBusSubscriber.Bus.MOD) - public static class RegistryEvents + public static class ForgeEvents { @SubscribeEvent public static void onBlocksRegistry(final RegistryEvent.Register event) @@ -104,6 +98,32 @@ public class ModEngineersDecor @SubscribeEvent public static void onRegisterContainerTypes(final RegistryEvent.Register> event) { ModContent.registerContainers(event); } + + // @SubscribeEvent + public static void onServerStarting(FMLServerStartingEvent event) + {} + + // @SubscribeEvent + public static void onConfigLoad(net.minecraftforge.fml.config.ModConfig.Loading configEvent) + { + try { + ModEngineersDecor.logger().info("Loaded config file {}", configEvent.getConfig().getFileName()); + ModConfig.apply(); + } catch(Throwable e) { + ModEngineersDecor.logger().error("Failed to load config: " + e.getMessage()); + } + } + + @SubscribeEvent + public static void onConfigFileChange(net.minecraftforge.fml.config.ModConfig.ConfigReloading configEvent) + { + try { + ModEngineersDecor.logger().info("Config file changed {}", configEvent.getConfig().getFileName()); + ModConfig.apply(); + } catch(Throwable e) { + ModEngineersDecor.logger().error("Failed to load changed config: " + e.getMessage()); + } + } } // diff --git a/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecor.java b/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecor.java index 0374051..af1fbf4 100644 --- a/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecor.java +++ b/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecor.java @@ -12,10 +12,16 @@ */ package wile.engineersdecor.blocks; +import net.minecraft.block.IWaterLoggable; +import net.minecraft.state.StateContainer; import wile.engineersdecor.detail.ModAuxiliaries; +import net.minecraft.state.BooleanProperty; +import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.entity.item.ItemEntity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.fluid.IFluidState; +import net.minecraft.fluid.Fluids; +import net.minecraft.world.IWorld; import net.minecraft.world.Explosion; import net.minecraft.world.World; import net.minecraft.util.math.AxisAlignedBB; @@ -26,6 +32,7 @@ import net.minecraft.util.math.shapes.VoxelShapes; import net.minecraft.block.Block; import net.minecraft.block.material.PushReaction; import net.minecraft.block.BlockState; +import net.minecraft.item.BlockItemUseContext; import net.minecraft.item.ItemStack; import net.minecraft.world.IBlockReader; import net.minecraft.world.storage.loot.LootContext; @@ -54,18 +61,20 @@ public class BlockDecor extends Block implements IDecorBlock public static final long CFG_REDSTONE_CONTROLLED = 0x0000000000020000L; // Denotes if a component has somehow a redstone control input public static final long CFG_ANALOG = 0x0000000000040000L; // Denotes if a component has analog behaviour public static final long CFG_HARD_IE_DEPENDENT = 0x8000000000000000L; // The block is implicitly opt'ed out if IE is not installed + public static final long CFG_WATERLOGGABLE = 0x4000000000000000L; // The derived block extends IWaterLoggable + public static final BooleanProperty WATERLOGGED = BlockStateProperties.WATERLOGGED; public final long config; public final VoxelShape vshape; - public BlockDecor(long config, Block.Properties properties) - { this(config, properties, ModAuxiliaries.getPixeledAABB(0, 0, 0, 16, 16,16 )); } + public BlockDecor(long conf, Block.Properties properties) + { this(conf, properties, ModAuxiliaries.getPixeledAABB(0, 0, 0, 16, 16,16 )); } - public BlockDecor(long config, Block.Properties properties, AxisAlignedBB aabb) - { super(properties); this.config = config; this.vshape = VoxelShapes.create(aabb); } + public BlockDecor(long conf, Block.Properties properties, AxisAlignedBB aabb) + { super(properties); config = conf; vshape = VoxelShapes.create(aabb); } - public BlockDecor(long config, Block.Properties properties, VoxelShape voxel_shape) - { super(properties); this.config = config; this.vshape = voxel_shape; } + public BlockDecor(long conf, Block.Properties properties, VoxelShape voxel_shape) + { super(properties); config = conf; vshape = voxel_shape; } @Override @OnlyIn(Dist.CLIENT) @@ -87,6 +96,18 @@ public class BlockDecor extends Block implements IDecorBlock public VoxelShape getCollisionShape(BlockState state, IBlockReader world, BlockPos pos, ISelectionContext selectionContext) { return vshape; } + @Override + @Nullable + public BlockState getStateForPlacement(BlockItemUseContext context) + { + BlockState state = super.getStateForPlacement(context); + if((config & CFG_WATERLOGGABLE)!=0) { + IFluidState fs = context.getWorld().getFluidState(context.getPos()); + state = state.with(WATERLOGGED,fs.getFluid()==Fluids.WATER); + } + return state; + } + @Override public boolean canSpawnInBlock() { return false; } @@ -130,4 +151,52 @@ public class BlockDecor extends Block implements IDecorBlock public List getDrops(BlockState state, LootContext.Builder builder) { return Collections.singletonList(ItemStack.EMPTY); } // { return Collections.singletonList(new ItemStack(this.asItem())); } // + @Override + public boolean propagatesSkylightDown(BlockState state, IBlockReader reader, BlockPos pos) + { + if((config & CFG_WATERLOGGABLE)!=0) { + if(state.get(WATERLOGGED)) return false; + } + return super.propagatesSkylightDown(state, reader, pos); + } + + @Override + @SuppressWarnings("deprecation") + public IFluidState getFluidState(BlockState state) + { + if((config & CFG_WATERLOGGABLE)!=0) { + return state.get(WATERLOGGED) ? Fluids.WATER.getStillFluidState(false) : super.getFluidState(state); + } + return super.getFluidState(state); + } + + @Override + @SuppressWarnings("deprecation") + public BlockState updatePostPlacement(BlockState state, Direction facing, BlockState facingState, IWorld world, BlockPos pos, BlockPos facingPos) + { + if((config & CFG_WATERLOGGABLE)!=0) { + if(state.get(WATERLOGGED)) world.getPendingFluidTicks().scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickRate(world)); + } + return state; + } + + /** + * Water loggable version of the basic block. + */ + public static class WaterLoggable extends BlockDecor implements IWaterLoggable + { + public WaterLoggable(long config, Block.Properties properties) + { super(config|CFG_WATERLOGGABLE, properties); } + + public WaterLoggable(long config, Block.Properties properties, AxisAlignedBB aabb) + { super(config|CFG_WATERLOGGABLE, properties, aabb); } + + public WaterLoggable(long config, Block.Properties properties, VoxelShape voxel_shape) + { super(config|CFG_WATERLOGGABLE, properties, voxel_shape); } + + @Override + protected void fillStateContainer(StateContainer.Builder builder) + { super.fillStateContainer(builder); builder.add(WATERLOGGED); } + } + } diff --git a/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorChair.java b/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorChair.java index c5d39bf..597cdd1 100644 --- a/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorChair.java +++ b/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorChair.java @@ -28,7 +28,7 @@ import java.util.List; import java.util.Random; -public class BlockDecorChair extends BlockDecorDirected +public class BlockDecorChair extends BlockDecorDirected.WaterLoggable { private static boolean sitting_enabled = true; private static double sitting_probability = 0.1; diff --git a/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorCraftingTable.java b/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorCraftingTable.java index 0d28e3a..cc86b26 100644 --- a/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorCraftingTable.java +++ b/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorCraftingTable.java @@ -11,16 +11,10 @@ package wile.engineersdecor.blocks; import wile.engineersdecor.ModContent; import wile.engineersdecor.ModEngineersDecor; import wile.engineersdecor.detail.Networking; -import net.minecraft.client.gui.screen.inventory.ContainerScreen; -import net.minecraft.client.gui.widget.button.ImageButton; import net.minecraft.inventory.container.*; -import net.minecraft.item.Items; -import net.minecraft.item.crafting.ICraftingRecipe; -import net.minecraft.item.crafting.IRecipeType; -import net.minecraft.item.crafting.Ingredient; import net.minecraft.network.play.server.SSetSlotPacket; -import net.minecraft.util.math.BlockRayTraceResult; -import net.minecraft.util.text.StringTextComponent; +import net.minecraft.network.NetworkManager; +import net.minecraft.network.play.server.SUpdateTileEntityPacket; import net.minecraft.world.*; import net.minecraft.block.Block; import net.minecraft.block.BlockState; @@ -31,7 +25,11 @@ import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.ServerPlayerEntity; import net.minecraft.entity.player.PlayerInventory; import net.minecraft.item.Item; +import net.minecraft.item.Items; import net.minecraft.item.ItemStack; +import net.minecraft.item.crafting.ICraftingRecipe; +import net.minecraft.item.crafting.IRecipeType; +import net.minecraft.item.crafting.Ingredient; import net.minecraft.item.crafting.IRecipe; import net.minecraft.inventory.*; import net.minecraft.nbt.CompoundNBT; @@ -40,8 +38,12 @@ import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; import net.minecraft.util.text.ITextComponent; -import net.minecraft.client.gui.widget.button.Button; +import net.minecraft.util.math.BlockRayTraceResult; +import net.minecraft.util.text.StringTextComponent; import net.minecraft.client.renderer.RenderHelper; +import net.minecraft.client.gui.screen.inventory.ContainerScreen; +import net.minecraft.client.gui.widget.button.ImageButton; +import net.minecraft.client.gui.widget.button.Button; import net.minecraftforge.fml.network.NetworkHooks; import net.minecraftforge.common.util.FakePlayer; import net.minecraftforge.registries.ForgeRegistries; @@ -51,9 +53,10 @@ import com.mojang.blaze3d.platform.GlStateManager; import com.google.common.collect.ImmutableList; import javax.annotation.Nullable; import java.util.*; +import java.util.stream.Collectors; -public class BlockDecorCraftingTable extends BlockDecorDirected +public class BlockDecorCraftingTable extends BlockDecorDirected.WaterLoggable { public static boolean with_assist = true; public static boolean with_assist_direct_history_refab = false; @@ -68,7 +71,7 @@ public class BlockDecorCraftingTable extends BlockDecorDirected } public BlockDecorCraftingTable(long config, Block.Properties builder, final AxisAlignedBB unrotatedAABB) - { super(config, builder, unrotatedAABB); } + { super(config|CFG_WATERLOGGABLE, builder, unrotatedAABB); } @Override public boolean hasTileEntity(BlockState state) @@ -168,20 +171,33 @@ public class BlockDecorCraftingTable extends BlockDecorDirected // TileEntity ------------------------------------------------------------------------------ @Override - public void read(CompoundNBT compound) - { super.read(compound); readnbt(compound); } + public void read(CompoundNBT nbt) + { super.read(nbt); readnbt(nbt); } @Override - public CompoundNBT write(CompoundNBT compound) - { super.write(compound); writenbt(compound); return compound; } + public CompoundNBT write(CompoundNBT nbt) + { super.write(nbt); writenbt(nbt); return nbt; } @Override public CompoundNBT getUpdateTag() { CompoundNBT nbt = super.getUpdateTag(); writenbt(nbt); return nbt; } @Override - public void onLoad() - {} + @Nullable + public SUpdateTileEntityPacket getUpdatePacket() + { return new SUpdateTileEntityPacket(pos, 1, getUpdateTag()); } + + @Override + public void onDataPacket(NetworkManager net, SUpdateTileEntityPacket pkt) // on client + { super.read(pkt.getNbtCompound()); readnbt(pkt.getNbtCompound()); super.onDataPacket(net, pkt); } + + @Override + public void handleUpdateTag(CompoundNBT tag) // on client + { read(tag); } + + @OnlyIn(Dist.CLIENT) + public double getMaxRenderDistanceSquared() + { return 400; } // INameable --------------------------------------------------------------------------- @@ -251,7 +267,13 @@ public class BlockDecorCraftingTable extends BlockDecorDirected @Override public void closeInventory(PlayerEntity player) - { this.markDirty(); } + { + markDirty(); + if(world instanceof World) { + BlockState state = world.getBlockState(pos); + world.notifyBlockUpdate(pos, state, state, 1|2); + } + } @Override public boolean isItemValidForSlot(int index, ItemStack stack) @@ -356,6 +378,7 @@ public class BlockDecorCraftingTable extends BlockDecorDirected private final CraftingHistory history_; private final BInventoryCrafting matrix_; private final CraftResultInventory result_; + private boolean has_recipe_collision_; public BContainer(int cid, PlayerInventory pinv) { this(cid, pinv, new Inventory(BTileEntity.NUM_OF_SLOTS), IWorldPosCallable.DUMMY); } @@ -423,15 +446,22 @@ public class BlockDecorCraftingTable extends BlockDecorDirected //craft(windowId, world, player_, matrix_, result_); ServerPlayerEntity player = (ServerPlayerEntity) player_; ItemStack stack = ItemStack.EMPTY; - Optional optional = world.getServer().getRecipeManager().getRecipe(IRecipeType.CRAFTING, matrix_, world); - if(optional.isPresent()) { - ICraftingRecipe icraftingrecipe = optional.get(); - if(result_.canUseRecipe(world, player, icraftingrecipe)) { - stack = icraftingrecipe.getCraftingResult(matrix_); + List recipes = world.getServer().getRecipeManager().getRecipes(IRecipeType.CRAFTING, matrix_, world); + has_recipe_collision_ = false; + if(recipes.size() > 0) { + ICraftingRecipe recipe = recipes.get(0); + IRecipe currently_used = result_.getRecipeUsed(); + has_recipe_collision_ = (recipes.size() > 1); + if((recipes.size() > 1) && (currently_used instanceof ICraftingRecipe) && (recipes.contains(currently_used))) { + recipe = (ICraftingRecipe)currently_used; + } + if(result_.canUseRecipe(world, player, recipe)) { + stack = recipe.getCraftingResult(matrix_); } } result_.setInventorySlotContents(0, stack); player.connection.sendPacket(new SSetSlotPacket(windowId, 0, stack)); + syncProperties(player); } catch(Throwable exc) { ModEngineersDecor.logger().error("Recipe failed:", exc); } @@ -492,6 +522,39 @@ public class BlockDecorCraftingTable extends BlockDecorDirected // private aux methods --------------------------------------------------------------------- + public boolean has_recipe_collision() + { return has_recipe_collision_; } + + public void select_next_collision_recipe(IInventory inv) + { + wpc_.consume((world,pos)->{ + if(world.isRemote) return; + try { + ServerPlayerEntity player = (ServerPlayerEntity) player_; + final List matching_recipes = world.getServer().getRecipeManager().getRecipes(IRecipeType.CRAFTING, matrix_, world); + if(matching_recipes.size() < 2) return; // nothing to change + IRecipe currently_used = result_.getRecipeUsed(); + List usable_recipes = matching_recipes.stream() + .filter((r)->result_.canUseRecipe(world,player,r)) + .sorted((a,b)->Integer.compare(a.getId().hashCode(), b.getId().hashCode())) + .collect(Collectors.toList()); + for(int i=0; i= usable_recipes.size()) i=0; + currently_used = usable_recipes.get(i); + ItemStack stack = ((ICraftingRecipe)currently_used).getCraftingResult(matrix_); + result_.setInventorySlotContents(0, stack); + result_.setRecipeUsed(currently_used); + break; + } + } + onCraftMatrixChanged(inv); + } catch(Throwable exc) { + ModEngineersDecor.logger().error("Recipe failed:", exc); + } + }); + } + private boolean itemstack_recipe_match(ItemStack grid_stack, ItemStack history_stack) { if(history_.current_recipe()!=null) { @@ -680,6 +743,7 @@ public class BlockDecorCraftingTable extends BlockDecorDirected private EnumRefabPlacement place_refab_stacks(IInventory inventory, final int slot_begin, final int slot_end) { List to_fill = crafting_slot_stacks_to_add(); + if(history_.current_recipe() != null) result_.setRecipeUsed(history_.current_recipe()); boolean slots_changed = false; boolean missing_item = false; int num_slots_placed = 0; @@ -719,6 +783,7 @@ public class BlockDecorCraftingTable extends BlockDecorDirected private EnumRefabPlacement distribute_stack(IInventory inventory, final int slotno) { List to_refab = crafting_slot_stacks_to_add(); + if(history_.current_recipe() != null) result_.setRecipeUsed(history_.current_recipe()); ItemStack to_distribute = inventory.getStackInSlot(slotno).copy(); if(to_distribute.isEmpty()) return EnumRefabPlacement.UNCHANGED; int matching_grid_stack_sizes[] = {-1,-1,-1,-1,-1,-1,-1,-1,-1}; @@ -796,9 +861,8 @@ public class BlockDecorCraftingTable extends BlockDecorDirected public void onServerPacketReceived(int windowId, CompoundNBT nbt) { - if(nbt.contains("history")) { - history_.read(nbt.getCompound("history")); - } + if(nbt.contains("history")) history_.read(nbt.getCompound("history")); + if(nbt.contains("hascollision")) has_recipe_collision_ = nbt.getBoolean("hascollision"); } public void onClientPacketReceived(int windowId, PlayerEntity player, CompoundNBT nbt) @@ -871,6 +935,9 @@ public class BlockDecorCraftingTable extends BlockDecorDirected if(stat != EnumRefabPlacement.UNCHANGED) { player_inventory_changed = true; changed = true; } } } break; + case BGui.BUTTON_NEXT_COLLISION_RECIPE: { + select_next_collision_recipe(inventory_); + } break; } } if(changed) inventory_.markDirty(); @@ -895,6 +962,14 @@ public class BlockDecorCraftingTable extends BlockDecorDirected } final CompoundNBT nbt = new CompoundNBT(); nbt.put("history", hist_nbt); + nbt.putBoolean("hascollision", has_recipe_collision_); + Networking.PacketContainerSyncServerToClient.sendToPlayer(player, windowId, nbt); + } + + private void syncProperties(PlayerEntity player) + { + final CompoundNBT nbt = new CompoundNBT(); + nbt.putBoolean("hascollision", has_recipe_collision_); Networking.PacketContainerSyncServerToClient.sendToPlayer(player, windowId, nbt); } } @@ -913,6 +988,7 @@ public class BlockDecorCraftingTable extends BlockDecorDirected protected static final String BUTTON_TO_STORAGE = "to-storage"; protected static final String BUTTON_FROM_PLAYER = "from-player"; protected static final String BUTTON_TO_PLAYER = "to-player"; + protected static final String BUTTON_NEXT_COLLISION_RECIPE = "next-recipe"; protected static final String ACTION_PLACE_CURRENT_HISTORY_SEL = "place-refab"; protected static final String ACTION_PLACE_SHIFTCLICKED_STACK = "place-stack"; protected static final ResourceLocation BACKGROUND = new ResourceLocation(ModEngineersDecor.MODID, "textures/gui/treated_wood_crafting_table.png"); @@ -936,6 +1012,7 @@ public class BlockDecorCraftingTable extends BlockDecorDirected buttons.add(addButton(new ImageButton(x0+158,y0+44, 12,12, 194,44, 12, BACKGROUND, (bt)->action(BUTTON_NEXT)))); buttons.add(addButton(new ImageButton(x0+158,y0+30, 12,12, 180,30, 12, BACKGROUND, (bt)->action(BUTTON_PREV)))); buttons.add(addButton(new ImageButton(x0+158,y0+58, 12,12, 194,8, 12, BACKGROUND, (bt)->action(BUTTON_CLEAR_GRID)))); + buttons.add(addButton(new ImageButton(x0+132,y0+18, 20,10, 183,95, 12, BACKGROUND, (bt)->action(BUTTON_NEXT_COLLISION_RECIPE)))); if(with_assist_quickmove_buttons) { buttons.add(addButton(new ImageButton(x0+49, y0+34, 9,17, 219,34, 17, BACKGROUND, (bt)->action(BUTTON_FROM_STORAGE)))); buttons.add(addButton(new ImageButton(x0+49, y0+52, 9,17, 208,16, 17, BACKGROUND, (bt)->action(BUTTON_TO_STORAGE)))); @@ -948,6 +1025,11 @@ public class BlockDecorCraftingTable extends BlockDecorDirected @Override public void render(int mouseX, int mouseY, float partialTicks) { + if(with_assist) { + boolean is_collision = getContainer().has_recipe_collision(); + buttons.get(3).visible = is_collision; + buttons.get(3).active = is_collision; + } renderBackground(); super.render(mouseX, mouseY, partialTicks); renderHoveredToolTip(mouseX, mouseY); diff --git a/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorDirected.java b/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorDirected.java index 792240f..e9083c9 100644 --- a/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorDirected.java +++ b/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorDirected.java @@ -8,6 +8,7 @@ */ package wile.engineersdecor.blocks; +import net.minecraft.block.IWaterLoggable; import wile.engineersdecor.detail.ModAuxiliaries; import net.minecraft.entity.EntityType; import net.minecraft.state.StateContainer; @@ -77,7 +78,7 @@ public class BlockDecorDirected extends BlockDecor @Override protected void fillStateContainer(StateContainer.Builder builder) - { builder.add(FACING); } + { super.fillStateContainer(builder); builder.add(FACING); } @Override @Nullable @@ -98,7 +99,20 @@ public class BlockDecorDirected extends BlockDecor } if((config & CFG_OPPOSITE_PLACEMENT)!=0) facing = facing.getOpposite(); if(((config & CFG_FLIP_PLACEMENT_SHIFTCLICK) != 0) && (context.getPlayer().isSneaking())) facing = facing.getOpposite(); - return getDefaultState().with(FACING, facing); + return super.getStateForPlacement(context).with(FACING, facing); + } + + /** + * Water loggable version of directed blocks. + */ + public static class WaterLoggable extends BlockDecorDirected implements IWaterLoggable + { + public WaterLoggable(long config, Block.Properties properties, AxisAlignedBB aabb) + { super(config|CFG_WATERLOGGABLE, properties, aabb); } + + @Override + protected void fillStateContainer(StateContainer.Builder builder) + { super.fillStateContainer(builder); builder.add(WATERLOGGED); } } } diff --git a/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorDirectedHorizontal.java b/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorDirectedHorizontal.java index 9773cf6..4f4f98c 100644 --- a/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorDirectedHorizontal.java +++ b/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorDirectedHorizontal.java @@ -10,6 +10,7 @@ package wile.engineersdecor.blocks; import net.minecraft.block.HorizontalBlock; +import net.minecraft.block.IWaterLoggable; import net.minecraft.util.Mirror; import net.minecraft.util.Rotation; import net.minecraft.entity.EntityType; @@ -80,7 +81,7 @@ public class BlockDecorDirectedHorizontal extends BlockDecor @Override protected void fillStateContainer(StateContainer.Builder builder) - { builder.add(HORIZONTAL_FACING); } + { super.fillStateContainer(builder); builder.add(HORIZONTAL_FACING); } @Override @Nullable @@ -96,7 +97,7 @@ public class BlockDecorDirectedHorizontal extends BlockDecor } if((config & CFG_OPPOSITE_PLACEMENT)!=0) facing = facing.getOpposite(); if(((config & CFG_FLIP_PLACEMENT_SHIFTCLICK) != 0) && (context.getPlayer().isSneaking())) facing = facing.getOpposite(); - return getDefaultState().with(HORIZONTAL_FACING, facing); + return super.getStateForPlacement(context).with(HORIZONTAL_FACING, facing); } @Override @@ -109,4 +110,17 @@ public class BlockDecorDirectedHorizontal extends BlockDecor public BlockState mirror(BlockState state, Mirror mirrorIn) { return state.rotate(mirrorIn.toRotation(state.get(HORIZONTAL_FACING))); } + /** + * Water loggable version of directed blocks. + */ + public static class WaterLoggable extends BlockDecorDirectedHorizontal implements IWaterLoggable + { + public WaterLoggable(long config, Block.Properties properties, AxisAlignedBB aabb) + { super(config|CFG_WATERLOGGABLE, properties, aabb); } + + @Override + protected void fillStateContainer(StateContainer.Builder builder) + { super.fillStateContainer(builder); builder.add(WATERLOGGED); } + } + } diff --git a/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorDropper.java b/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorDropper.java index 18167a1..c5311bb 100644 --- a/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorDropper.java +++ b/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorDropper.java @@ -73,7 +73,7 @@ public class BlockDecorDropper extends BlockDecorDirected @Override protected void fillStateContainer(StateContainer.Builder builder) - { builder.add(FACING, OPEN); } + { super.fillStateContainer(builder); builder.add(OPEN); } @Override @Nullable diff --git a/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorFloorGrating.java b/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorFloorGrating.java index 1b48b01..7b6db1f 100644 --- a/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorFloorGrating.java +++ b/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorFloorGrating.java @@ -22,10 +22,10 @@ import net.minecraft.world.IBlockReader; import net.minecraft.world.World; -public class BlockDecorFloorGrating extends BlockDecor +public class BlockDecorFloorGrating extends BlockDecor.WaterLoggable { public BlockDecorFloorGrating(long config, Block.Properties builder, final AxisAlignedBB unrotatedAABB) - { super(config, builder); } + { super(config|CFG_WATERLOGGABLE, builder); } @Override public boolean propagatesSkylightDown(BlockState state, IBlockReader reader, BlockPos pos) diff --git a/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorFull.java b/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorFull.java deleted file mode 100644 index e0716f4..0000000 --- a/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorFull.java +++ /dev/null @@ -1,18 +0,0 @@ -/* - * @file BlockDecorFull.java - * @author Stefan Wilhelm (wile) - * @copyright (C) 2019 Stefan Wilhelm - * @license MIT (see https://opensource.org/licenses/MIT) - * - * Full block characteristics class. Explicitly overrides some - * `Block` methods to return faster due to exclusive block properties. - */ -package wile.engineersdecor.blocks; - -import net.minecraft.block.Block; - -public class BlockDecorFull extends BlockDecor -{ - public BlockDecorFull(long config, Block.Properties properties) - { super(config, properties); } -} diff --git a/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorFurnace.java b/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorFurnace.java index 9d7254a..1e7cddb 100644 --- a/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorFurnace.java +++ b/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorFurnace.java @@ -84,7 +84,7 @@ public class BlockDecorFurnace extends BlockDecorDirected @Override @Nullable public BlockState getStateForPlacement(BlockItemUseContext context) - { return getDefaultState().with(FACING, context.getPlacementHorizontalFacing().getOpposite()).with(LIT, false); } + { return super.getStateForPlacement(context).with(FACING, context.getPlacementHorizontalFacing().getOpposite()).with(LIT, false); } @Override @SuppressWarnings("deprecation") diff --git a/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorHalfSlab.java b/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorHalfSlab.java index 9230a86..83997c6 100644 --- a/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorHalfSlab.java +++ b/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorHalfSlab.java @@ -38,7 +38,7 @@ import java.util.Collections; import java.util.List; -public class BlockDecorHalfSlab extends BlockDecor +public class BlockDecorHalfSlab extends BlockDecor implements IWaterLoggable { public static final IntegerProperty PARTS = IntegerProperty.create("parts", 0, 14); @@ -61,12 +61,10 @@ public class BlockDecorHalfSlab extends BlockDecor VoxelShapes.create(new AxisAlignedBB(0,0,0,1,1,1)) // <- with 4bit fill }; - protected static final int num_slabs_contained_in_parts_[] = { - 1,2,3,4,5,6,7,8,7,6,5,4,3,2,1 ,0x1 // <- with 4bit fill - }; + protected static final int num_slabs_contained_in_parts_[] = { 1,2,3,4,5,6,7,8,7,6,5,4,3,2,1 ,0x1 }; // <- with 4bit fill public BlockDecorHalfSlab(long config, Block.Properties builder) - { super(config, builder); } + { super(config|CFG_WATERLOGGABLE, builder); } protected boolean is_cube(BlockState state) { return state.get(PARTS) == 0x07; } @@ -105,7 +103,7 @@ public class BlockDecorHalfSlab extends BlockDecor @Override protected void fillStateContainer(StateContainer.Builder builder) - { builder.add(PARTS); } + { super.fillStateContainer(builder); builder.add(PARTS, WATERLOGGED); } @Override @Nullable @@ -113,7 +111,7 @@ public class BlockDecorHalfSlab extends BlockDecor { final Direction facing = context.getFace(); double y = context.getHitVec().getY(); - return getDefaultState().with(PARTS, ((facing==Direction.UP) || ((facing!=Direction.DOWN) && (y < 0.6))) ? 0 : 14); + return super.getStateForPlacement(context).with(PARTS, ((facing==Direction.UP) || ((facing!=Direction.DOWN) && (y < 0.6))) ? 0 : 14); } @Override diff --git a/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorHorizontalSupport.java b/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorHorizontalSupport.java index 87d093c..c940c1b 100644 --- a/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorHorizontalSupport.java +++ b/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorHorizontalSupport.java @@ -9,6 +9,7 @@ */ package wile.engineersdecor.blocks; +import net.minecraft.block.IWaterLoggable; import wile.engineersdecor.ModContent; import wile.engineersdecor.detail.ModAuxiliaries; import net.minecraft.entity.EntityType; @@ -35,7 +36,7 @@ import java.util.ArrayList; import java.util.Arrays; -public class BlockDecorHorizontalSupport extends BlockDecor +public class BlockDecorHorizontalSupport extends BlockDecor implements IWaterLoggable { public static final BooleanProperty EASTWEST = BooleanProperty.create("eastwest"); public static final BooleanProperty LEFTBEAM = BooleanProperty.create("leftbeam"); @@ -45,7 +46,7 @@ public class BlockDecorHorizontalSupport extends BlockDecor public BlockDecorHorizontalSupport(long config, Block.Properties builder, final AxisAlignedBB unrotatedAABB) { - super(config|CFG_HORIZIONTAL, builder); + super(config|CFG_HORIZIONTAL|CFG_WATERLOGGABLE, builder); AABBs = new ArrayList(Arrays.asList( // Effective bounding box VoxelShapes.create(ModAuxiliaries.getRotatedAABB(unrotatedAABB.grow(2.0/16, 0, 0), Direction.NORTH, true)), @@ -80,12 +81,12 @@ public class BlockDecorHorizontalSupport extends BlockDecor @Override protected void fillStateContainer(StateContainer.Builder builder) - { builder.add(EASTWEST, RIGHTBEAM, LEFTBEAM, DOWNCONNECT); } + { super.fillStateContainer(builder); builder.add(EASTWEST, RIGHTBEAM, LEFTBEAM, DOWNCONNECT, WATERLOGGED); } @Override @Nullable public BlockState getStateForPlacement(BlockItemUseContext context) - { return temp_block_update_until_better(getDefaultState().with(EASTWEST, context.getPlacementHorizontalFacing().getAxis()==Direction.Axis.X), context.getWorld(), context.getPos()); } + { return temp_block_update_until_better(super.getStateForPlacement(context).with(EASTWEST, context.getPlacementHorizontalFacing().getAxis()==Direction.Axis.X), context.getWorld(), context.getPos()); } private BlockState temp_block_update_until_better(BlockState state, IWorld world, BlockPos pos) { diff --git a/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorMineralSmelter.java b/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorMineralSmelter.java index d7733dd..a8567c4 100644 --- a/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorMineralSmelter.java +++ b/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorMineralSmelter.java @@ -70,7 +70,6 @@ public class BlockDecorMineralSmelter extends BlockDecorDirectedHorizontal public BlockState getStateForPlacement(BlockItemUseContext context) { return super.getStateForPlacement(context).with(PHASE, 0); } - @Override @SuppressWarnings("deprecation") public boolean hasComparatorInputOverride(BlockState state) diff --git a/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorPipeValve.java b/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorPipeValve.java index 3c12253..b751872 100644 --- a/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorPipeValve.java +++ b/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorPipeValve.java @@ -9,6 +9,7 @@ */ package wile.engineersdecor.blocks; +import net.minecraft.block.IWaterLoggable; import wile.engineersdecor.ModContent; import wile.engineersdecor.ModEngineersDecor; import net.minecraft.state.BooleanProperty; @@ -36,7 +37,7 @@ import net.minecraft.util.math.BlockPos; import javax.annotation.Nullable; -public class BlockDecorPipeValve extends BlockDecorDirected +public class BlockDecorPipeValve extends BlockDecorDirected implements IWaterLoggable { public static final BooleanProperty RS_CN_N = BooleanProperty.create("rs_n"); public static final BooleanProperty RS_CN_S = BooleanProperty.create("rs_s"); @@ -53,7 +54,7 @@ public class BlockDecorPipeValve extends BlockDecorDirected } public BlockDecorPipeValve(long config, Block.Properties builder, final AxisAlignedBB unrotatedAABB) - { super(config, builder, unrotatedAABB); } + { super(config|CFG_WATERLOGGABLE, builder, unrotatedAABB); } private BlockState get_rsconnector_state(BlockState state, IWorld world, BlockPos pos, @Nullable BlockPos fromPos) { @@ -88,7 +89,7 @@ public class BlockDecorPipeValve extends BlockDecorDirected @Override protected void fillStateContainer(StateContainer.Builder builder) - { builder.add(FACING, RS_CN_N, RS_CN_S, RS_CN_E, RS_CN_W, RS_CN_U, RS_CN_D); } + { super.fillStateContainer(builder); builder.add(RS_CN_N, RS_CN_S, RS_CN_E, RS_CN_W, RS_CN_U, RS_CN_D, WATERLOGGED); } @Override @Nullable diff --git a/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorSlab.java b/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorSlab.java index ecd0084..d4d0728 100644 --- a/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorSlab.java +++ b/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorSlab.java @@ -51,7 +51,7 @@ public class BlockDecorSlab extends BlockDecor { return state.get(PARTS) >= 2; } public BlockDecorSlab(long config, Block.Properties builder) - { super(config, builder); } + { super(config|CFG_WATERLOGGABLE, builder); } @Override @OnlyIn(Dist.CLIENT) @@ -87,7 +87,7 @@ public class BlockDecorSlab extends BlockDecor @Override protected void fillStateContainer(StateContainer.Builder builder) - { builder.add(PARTS, TEXTURE_VARIANT); } + { super.fillStateContainer(builder); builder.add(PARTS, TEXTURE_VARIANT, WATERLOGGED); } @Override @Nullable @@ -96,7 +96,7 @@ public class BlockDecorSlab extends BlockDecor final Direction facing = context.getFace(); double y = context.getHitVec().getY(); int rnd = MathHelper.clamp((int)(MathHelper.getPositionRandom(context.getPos()) % 4), 0, 3); - return getDefaultState().with(PARTS, ((facing==Direction.UP) || ((facing!=Direction.DOWN) && (y < 0.6))) ? 0 : 1).with(TEXTURE_VARIANT, rnd); + return super.getStateForPlacement(context).with(PARTS, ((facing==Direction.UP) || ((facing!=Direction.DOWN) && (y < 0.6))) ? 0 : 1).with(TEXTURE_VARIANT, rnd); } @Override diff --git a/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorSolarPanel.java b/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorSolarPanel.java index 3106f67..d3b1870 100644 --- a/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorSolarPanel.java +++ b/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorSolarPanel.java @@ -46,7 +46,7 @@ public class BlockDecorSolarPanel extends BlockDecor @Override @Nullable public BlockState getStateForPlacement(BlockItemUseContext context) - { return getDefaultState(); } + { return super.getStateForPlacement(context); } @Override public boolean hasTileEntity(BlockState state) diff --git a/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorStraightPole.java b/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorStraightPole.java index 57c25f5..1e70a64 100644 --- a/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorStraightPole.java +++ b/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorStraightPole.java @@ -10,7 +10,10 @@ package wile.engineersdecor.blocks; import net.minecraft.block.Block; import net.minecraft.block.BlockState; +import net.minecraft.block.IWaterLoggable; +import net.minecraft.fluid.Fluids; import net.minecraft.item.BlockItemUseContext; +import net.minecraft.state.StateContainer; import net.minecraft.world.World; import net.minecraft.util.Direction; import net.minecraft.util.math.AxisAlignedBB; @@ -18,22 +21,27 @@ import net.minecraft.util.math.BlockPos; import javax.annotation.Nullable; -public class BlockDecorStraightPole extends BlockDecorDirected +public class BlockDecorStraightPole extends BlockDecorDirected implements IWaterLoggable { public BlockDecorStraightPole(long config, Block.Properties builder, final AxisAlignedBB unrotatedAABB) - { super(config, builder, unrotatedAABB); } + { super(config|CFG_WATERLOGGABLE, builder, unrotatedAABB); } + + @Override + protected void fillStateContainer(StateContainer.Builder builder) + { super.fillStateContainer(builder); builder.add(WATERLOGGED); } @Override @Nullable public BlockState getStateForPlacement(BlockItemUseContext context) { Direction facing = context.getFace(); - BlockState state = getDefaultState().with(FACING, facing); + final boolean waterlogged = context.getWorld().getFluidState(context.getPos()).getFluid()==Fluids.WATER; + BlockState state = super.getStateForPlacement(context).with(FACING, facing).with(WATERLOGGED, waterlogged); if((config & CFG_FLIP_PLACEMENT_IF_SAME) != 0) { World world = context.getWorld(); BlockPos pos = context.getPos(); if(world.getBlockState(pos.offset(facing.getOpposite())).getBlock() instanceof BlockDecorStraightPole) { - state = state.with(FACING, state.get(FACING).getOpposite()); + state = state.with(FACING, state.get(FACING).getOpposite()).with(WATERLOGGED, waterlogged); } } return state; diff --git a/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorWasteIncinerator.java b/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorWasteIncinerator.java index 74fad14..e5793d9 100644 --- a/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorWasteIncinerator.java +++ b/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorWasteIncinerator.java @@ -71,7 +71,7 @@ public class BlockDecorWasteIncinerator extends BlockDecor @Override protected void fillStateContainer(StateContainer.Builder builder) - { builder.add(LIT); } + { super.fillStateContainer(builder); builder.add(LIT); } @Override @Nullable diff --git a/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorWindow.java b/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorWindow.java index 0ffe709..f670831 100644 --- a/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorWindow.java +++ b/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorWindow.java @@ -10,15 +10,17 @@ package wile.engineersdecor.blocks; import net.minecraft.block.Block; import net.minecraft.block.BlockState; +import net.minecraft.block.IWaterLoggable; +import net.minecraft.state.StateContainer; import net.minecraft.util.BlockRenderLayer; import net.minecraft.util.math.AxisAlignedBB; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; -public class BlockDecorWindow extends BlockDecorDirected +public class BlockDecorWindow extends BlockDecorDirected implements IWaterLoggable { public BlockDecorWindow(long config, Block.Properties builder, final AxisAlignedBB unrotatedAABB) - { super(config, builder, unrotatedAABB); } + { super(config|CFG_WATERLOGGABLE, builder, unrotatedAABB); } @Override @OnlyIn(Dist.CLIENT) @@ -29,4 +31,8 @@ public class BlockDecorWindow extends BlockDecorDirected @OnlyIn(Dist.CLIENT) public boolean canRenderInLayer(BlockState state, BlockRenderLayer layer) { return (layer==BlockRenderLayer.CUTOUT) || (layer==BlockRenderLayer.TRANSLUCENT); } + + @Override + protected void fillStateContainer(StateContainer.Builder builder) + { super.fillStateContainer(builder); builder.add(WATERLOGGED); } } diff --git a/1.14/src/main/java/wile/engineersdecor/detail/ModConfig.java b/1.14/src/main/java/wile/engineersdecor/detail/ModConfig.java index 1f20253..9da05b9 100644 --- a/1.14/src/main/java/wile/engineersdecor/detail/ModConfig.java +++ b/1.14/src/main/java/wile/engineersdecor/detail/ModConfig.java @@ -11,13 +11,12 @@ package wile.engineersdecor.detail; import wile.engineersdecor.ModContent; import wile.engineersdecor.ModEngineersDecor; +import wile.engineersdecor.blocks.*; +import wile.engineersdecor.blocks.BlockDecorSolarPanel.BTileEntity; import net.minecraft.block.Block; import net.minecraft.item.Item; import net.minecraftforge.common.ForgeConfigSpec; -import net.minecraftforge.eventbus.api.SubscribeEvent; import org.apache.commons.lang3.tuple.Pair; -import wile.engineersdecor.blocks.*; -import wile.engineersdecor.blocks.BlockDecorSolarPanel.BTileEntity; import javax.annotation.Nullable; import java.util.ArrayList; @@ -45,14 +44,6 @@ public class ModConfig CLIENT = client_.getLeft(); } - @SubscribeEvent - public static void onLoad(final net.minecraftforge.fml.config.ModConfig.Loading configEvent) - { apply(); ModEngineersDecor.logger().info("Loaded config file {}", configEvent.getConfig().getFileName()); } - - @SubscribeEvent - public static void onFileChange(final net.minecraftforge.fml.config.ModConfig.ConfigReloading configEvent) - { ModEngineersDecor.logger().info("Config file changed {}", configEvent.getConfig().getFileName()); } - //-------------------------------------------------------------------------------------------------------------------- public static class ClientConfig @@ -465,6 +456,9 @@ public class ModConfig return false; } + public static boolean withExperimental() + { return with_experimental_features_; } + //-------------------------------------------------------------------------------------------------------------------- // Cache //-------------------------------------------------------------------------------------------------------------------- @@ -472,6 +466,7 @@ public class ModConfig private static final ArrayList excludes_ = new ArrayList(); public static boolean without_crafting_table = false; public static boolean immersiveengineering_installed = false; + private static boolean with_experimental_features_ = false; public static final void apply() { @@ -484,10 +479,14 @@ public class ModConfig BlockDecorSolarPanel.BTileEntity.on_config(COMMON.small_solar_panel_peak_production.get()); without_crafting_table = isOptedOut(ModContent.TREATED_WOOD_CRAFTING_TABLE); immersiveengineering_installed = ModAuxiliaries.isModLoaded("immersiveengineering"); + with_experimental_features_ = COMMON.with_experimental.get(); + if(with_experimental_features_) { + ModEngineersDecor.logger().info("Config: EXPERIMENTAL FEATURES ENABLED."); + } { String inc = COMMON.pattern_includes.get().toLowerCase().replaceAll(ModEngineersDecor.MODID+":", "").replaceAll("[^*_,a-z0-9]", ""); if(COMMON.pattern_includes.get() != inc) COMMON.pattern_includes.set(inc); - if(!inc.isEmpty()) ModEngineersDecor.logger().info("Pattern includes: '" + inc + "'"); + if(!inc.isEmpty()) ModEngineersDecor.logger().info("Config pattern includes: '" + inc + "'"); String[] incl = inc.split(","); includes_.clear(); for(int i=0; i< incl.length; ++i) { @@ -497,7 +496,7 @@ public class ModConfig } { String exc = COMMON.pattern_includes.get().toLowerCase().replaceAll(ModEngineersDecor.MODID+":", "").replaceAll("[^*_,a-z0-9]", ""); - if(!exc.isEmpty()) ModEngineersDecor.logger().info("Pattern excludes: '" + exc + "'"); + if(!exc.isEmpty()) ModEngineersDecor.logger().info("Config pattern excludes: '" + exc + "'"); String[] excl = exc.split(","); excludes_.clear(); for(int i=0; i< excl.length; ++i) { @@ -505,8 +504,5 @@ public class ModConfig if(!excl[i].isEmpty()) excludes_.add(excl[i]); } } - - } - } diff --git a/1.14/src/main/java/wile/engineersdecor/detail/ModTesrs.java b/1.14/src/main/java/wile/engineersdecor/detail/ModTesrs.java new file mode 100644 index 0000000..274bf6a --- /dev/null +++ b/1.14/src/main/java/wile/engineersdecor/detail/ModTesrs.java @@ -0,0 +1,84 @@ +/* + * @file ModTesrs.java + * @author Stefan Wilhelm (wile) + * @copyright (C) 2018 Stefan Wilhelm + * @license MIT (see https://opensource.org/licenses/MIT) + * + * Yet unstructured initial experiments with TESRs. + * May be structured after I know what I am doing there. + */ +package wile.engineersdecor.detail; + +import wile.engineersdecor.ModEngineersDecor; +import wile.engineersdecor.blocks.BlockDecorCraftingTable; +import net.minecraft.client.renderer.tileentity.TileEntityRenderer; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.RenderHelper; +import net.minecraft.item.ItemStack; +import net.minecraft.util.math.MathHelper; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import com.mojang.blaze3d.platform.GlStateManager; + + +public class ModTesrs +{ + //-------------------------------------------------------------------------------------------------------------------- + // Crafting table + //-------------------------------------------------------------------------------------------------------------------- + + @OnlyIn(Dist.CLIENT) + public static class TesrDecorCraftingTable extends TileEntityRenderer + { + private static int tesr_error_counter = 4; + private static double scaler = 0.10; + private static double gap = 0.19; + private static double yrotations[] = {0, 90, 180, 270}; // [hdirection] S-W-N-E + private static double offsets[][][] = { // [hdirection][slotindex][xz] + { {-1,-1},{+0,-1},{+1,-1}, {-1,+0},{+0,+0},{+1,+0}, {-1,+1},{+0,+1},{+1,+1} }, // S + { {+1,-1},{+1,+0},{+1,+1}, {+0,-1},{+0,+0},{+0,+1}, {-1,-1},{-1,+0},{-1,+1} }, // W + { {+1,+1},{+0,+1},{-1,+1}, {+1,+0},{+0,+0},{-1,+0}, {+1,-1},{+0,-1},{-1,-1} }, // N + { {-1,+1},{-1,+0},{-1,-1}, {+0,+1},{+0,+0},{+0,-1}, {+1,+1},{+1,+0},{+1,-1} }, // E + }; + + @Override + @SuppressWarnings("deprecation") + public void render(final BlockDecorCraftingTable.BTileEntity te, double x, double y, double z, float partialTicks, int destroyStage) + { + if(tesr_error_counter<=0) return; + try { + int di = MathHelper.clamp(te.getWorld().getBlockState(te.getPos()).get(BlockDecorCraftingTable.FACING).getHorizontalIndex(), 0, 3); + long posrnd = te.getPos().toLong(); + posrnd = (posrnd>>16)^(posrnd<<1); + for(int i=0; i<9; ++i) { + final ItemStack stack = te.getStackInSlot(i); + if(stack.isEmpty()) continue; + double prnd = ((double)(((Integer.rotateRight(stack.getItem().hashCode()^(int)posrnd,(stack.getCount()+i)&31)))&1023))/1024.0; + double rndo = gap * ((prnd*0.1)-0.05); + double ox = gap * offsets[di][i][0], oz = gap * offsets[di][i][1]; + double oy = 0.5; + double ry = ((yrotations[di]+180) + ((prnd*60)-30)) % 360; + if(stack.isEmpty()) return; + GlStateManager.pushMatrix(); + GlStateManager.disableLighting(); + RenderHelper.enableStandardItemLighting(); + GlStateManager.translated(x+0.5+ox, y+0.5+oy, z+0.5+oz); + GlStateManager.rotated(90, 1, 0, 0); + GlStateManager.rotated(ry, 0, 0, 1); + GlStateManager.translated(rndo, rndo, 0); + GlStateManager.scaled(scaler, scaler, scaler); + Minecraft.getInstance().getItemRenderer().renderItem(stack, net.minecraft.client.renderer.model.ItemCameraTransforms.TransformType.FIXED); + RenderHelper.disableStandardItemLighting(); + GlStateManager.enableLighting(); + GlStateManager.popMatrix(); + } + } catch(Throwable e) { + if(--tesr_error_counter<=0) { + ModEngineersDecor.logger().error("TESR was disabled because broken, exception was: " + e.getMessage()); + ModEngineersDecor.logger().error(e.getStackTrace()); + } + } + } + } + +} diff --git a/1.14/src/main/java/wile/engineersdecor/detail/OptionalRecipeCondition.java b/1.14/src/main/java/wile/engineersdecor/detail/OptionalRecipeCondition.java index 348dfcd..c13f213 100644 --- a/1.14/src/main/java/wile/engineersdecor/detail/OptionalRecipeCondition.java +++ b/1.14/src/main/java/wile/engineersdecor/detail/OptionalRecipeCondition.java @@ -32,9 +32,10 @@ public class OptionalRecipeCondition implements ICondition private final List all_required; private final List any_missing; private final @Nullable ResourceLocation result; + private final boolean experimental; - public OptionalRecipeCondition(ResourceLocation result, List required, List missing) - { all_required = required; any_missing = missing; this.result = result; } + public OptionalRecipeCondition(ResourceLocation result, List required, List missing, boolean isexperimental) + { all_required = required; any_missing = missing; this.result = result; experimental=isexperimental; } @Override public ResourceLocation getID() @@ -49,12 +50,14 @@ public class OptionalRecipeCondition implements ICondition sb.delete(sb.length()-1, sb.length()).append("], any-missing: ["); for(ResourceLocation e:any_missing) sb.append(e.toString()).append(","); sb.delete(sb.length()-1, sb.length()).append("]"); + if(experimental) sb.append(" EXPERIMENTAL"); return sb.toString(); } @Override public boolean test() { + if((experimental) && (!ModConfig.withExperimental())) return false; final IForgeRegistry block_registry = ForgeRegistries.BLOCKS; final IForgeRegistry item_registry = ForgeRegistries.ITEMS; if(result != null) { @@ -103,6 +106,7 @@ public class OptionalRecipeCondition implements ICondition List required = new ArrayList<>(); List missing = new ArrayList<>(); ResourceLocation result = null; + boolean experimental = false; if(json.has("result")) result = new ResourceLocation(json.get("result").getAsString()); if(json.has("required")) { for(JsonElement e:JSONUtils.getJsonArray(json, "required")) required.add(new ResourceLocation(e.getAsString())); @@ -110,7 +114,8 @@ public class OptionalRecipeCondition implements ICondition if(json.has("missing")) { for(JsonElement e:JSONUtils.getJsonArray(json, "missing")) missing.add(new ResourceLocation(e.getAsString())); } - return new OptionalRecipeCondition(result, required, missing); + if(json.has("experimental")) experimental = json.get("experimental").getAsBoolean(); + return new OptionalRecipeCondition(result, required, missing, experimental); } } } diff --git a/1.14/src/main/resources/assets/engineersdecor/textures/gui/treated_wood_crafting_table.png b/1.14/src/main/resources/assets/engineersdecor/textures/gui/treated_wood_crafting_table.png index bc26abf..c6c18dc 100644 Binary files a/1.14/src/main/resources/assets/engineersdecor/textures/gui/treated_wood_crafting_table.png and b/1.14/src/main/resources/assets/engineersdecor/textures/gui/treated_wood_crafting_table.png differ diff --git a/1.14/src/main/resources/data/engineersdecor/recipes/testing/collision_test1_diorite.json b/1.14/src/main/resources/data/engineersdecor/recipes/testing/collision_test1_diorite.json new file mode 100644 index 0000000..138ffb8 --- /dev/null +++ b/1.14/src/main/resources/data/engineersdecor/recipes/testing/collision_test1_diorite.json @@ -0,0 +1,21 @@ +{ + "conditions": [ + { + "type": "engineersdecor:optional", + "experimental": true + } + ], + "type": "minecraft:crafting_shaped", + "pattern": [ + "DDD", + " D ", + " D " + ], + "key": { + "D": { "item": "minecraft:diorite" } + }, + "result": { + "item": "minecraft:stone", + "count": 1 + } +} diff --git a/1.14/src/main/resources/data/engineersdecor/recipes/testing/collision_test2_diorite.json b/1.14/src/main/resources/data/engineersdecor/recipes/testing/collision_test2_diorite.json new file mode 100644 index 0000000..a2ba7c7 --- /dev/null +++ b/1.14/src/main/resources/data/engineersdecor/recipes/testing/collision_test2_diorite.json @@ -0,0 +1,21 @@ +{ + "conditions": [ + { + "type": "engineersdecor:optional", + "experimental": true + } + ], + "type": "minecraft:crafting_shaped", + "pattern": [ + "DDD", + " D ", + " D " + ], + "key": { + "D": { "item": "minecraft:diorite" } + }, + "result": { + "item": "minecraft:granite", + "count": 1 + } +} diff --git a/1.14/src/main/resources/data/engineersdecor/recipes/testing/collision_test3_diorite.json b/1.14/src/main/resources/data/engineersdecor/recipes/testing/collision_test3_diorite.json new file mode 100644 index 0000000..a8cc4b3 --- /dev/null +++ b/1.14/src/main/resources/data/engineersdecor/recipes/testing/collision_test3_diorite.json @@ -0,0 +1,21 @@ +{ + "conditions": [ + { + "type": "engineersdecor:optional", + "experimental": true + } + ], + "type": "minecraft:crafting_shaped", + "pattern": [ + "DDD", + " D ", + " D " + ], + "key": { + "D": { "item": "minecraft:diorite" } + }, + "result": { + "item": "minecraft:andesite", + "count": 1 + } +} diff --git a/documentation/engineers-decor-crafting-table-items.png b/documentation/engineers-decor-crafting-table-items.png new file mode 100644 index 0000000..f6da094 Binary files /dev/null and b/documentation/engineers-decor-crafting-table-items.png differ diff --git a/documentation/factory-dropper-directional.png b/documentation/engineers-decor-factory-dropper-directional.png similarity index 100% rename from documentation/factory-dropper-directional.png rename to documentation/engineers-decor-factory-dropper-directional.png diff --git a/documentation/factory-dropper-gui.png b/documentation/engineers-decor-factory-dropper-gui.png similarity index 100% rename from documentation/factory-dropper-gui.png rename to documentation/engineers-decor-factory-dropper-gui.png diff --git a/documentation/factory-dropper-metal-press-compression.png b/documentation/engineers-decor-factory-dropper-metal-press-compression.png similarity index 100% rename from documentation/factory-dropper-metal-press-compression.png rename to documentation/engineers-decor-factory-dropper-metal-press-compression.png diff --git a/documentation/small-mineral-smelter-vanilla-automated.png b/documentation/engineers-decor-small-mineral-smelter-vanilla-automated.png similarity index 100% rename from documentation/small-mineral-smelter-vanilla-automated.png rename to documentation/engineers-decor-small-mineral-smelter-vanilla-automated.png diff --git a/documentation/small-solar-panel.png b/documentation/engineers-decor-small-solar-panel.png similarity index 100% rename from documentation/small-solar-panel.png rename to documentation/engineers-decor-small-solar-panel.png diff --git a/documentation/small-tree-cutter.png b/documentation/engineers-decor-small-tree-cutter.png similarity index 100% rename from documentation/small-tree-cutter.png rename to documentation/engineers-decor-small-tree-cutter.png diff --git a/documentation/readme.md b/documentation/readme.md index 2045340..06d746e 100644 --- a/documentation/readme.md +++ b/documentation/readme.md @@ -3,6 +3,7 @@ ![](engineers-decor-v103-summary.png) ![](engineers-decor-v104a-craftinggui.png) +![](engineers-decor-crafting-table-items.png) ![](engineers-decor-v103-labfurnacegui.png) ![](engineers-decor-v103-labfurnace-electrical-speedup.png) ![](engineers-decor-v100a-concrete-stuff.png) @@ -18,8 +19,8 @@ ![](engineers-decor-v106a-wasteincinerator-gui.png) ![](engineers-decor-v104a-redstone-valves.png) ![](engineers-decor-v106a-factorydropper.png) -![](factory-dropper-gui.png) -![](factory-dropper-metal-press-compression.png) -![](small-mineral-smelter-vanilla-automated.png) -![](small-solar-panel.png) -![](small-tree-cutter.png) +![](engineers-decor-factory-dropper-gui.png) +![](engineers-decor-factory-dropper-metal-press-compression.png) +![](engineers-decor-small-mineral-smelter-vanilla-automated.png) +![](engineers-decor-small-solar-panel.png) +![](engineers-decor-small-tree-cutter.png) diff --git a/readme.md b/readme.md index a0f69d9..3e66384 100644 --- a/readme.md +++ b/readme.md @@ -22,136 +22,134 @@ Main distribution channel for this mod is CurseForge: The mod has its focus decorative blocks and devices helping you to build nice looking manufacturing contraptions. Current feature set: -- *Treated wood crafting table*: 3x3 crafting table with IE style GUI and a model +- *Treated Wood Crafting Table*: 3x3 crafting table with IE style GUI and a model fitting better in the engineer's workshop. Keeps its inventory, has eight additional - storage slots on the left side of the crafting grid. Crafted 2x2 with three - treated wood planks and one vanilla crafting table. + storage slots on the left side of the crafting grid. Crafting history for fast + refabrication of previous recipes. Providesa a recipe collision resolver (selection + button for ambiguous recipes). Quick-move buttons (opt-in) to from/to storage or + player inventory. Smart shift-click placement (balanced placing of items in the + crafting grid). Shows the placed items on the top of the table. -- *Small laboratory furnace*: Solid fuel consuming, updraught. Slightly hotter and +- *Small Laboratory Furnace*: Solid fuel consuming, updraught. Slightly hotter and better isolated than a cobblestone furnace, therefore more efficient. Has internal hopper FiFos for input, output, and fuel (two stacks each). Two auxilliary slots - (storage tray). Keeps inventory when relocated. Crafted with one cobblestone - furnace, one hopper, and seven metal plates. + (storage tray). Keeps inventory when relocated. Can be boosted with RF power when + a IE heater is placed in the furnace. -- *Small electrical furnace*: Pass-through electrical furnace. Can pull items out - input side inventories, inserts items into inventories at the output side. Internal - fifo slots. Automatically bypasses items that cannot be cooked or smelted. Electrical - RF/FE power can be applied on all sides. Items can be inserted or drawn from all - sides (e.g. with filtered hopper or whatever). Fits ideally into a conveyor belt - line/lane. Consumption and efficiency tunable via config. +- *Small Electrical Furnace*: Pass-through electrical furnace. Can pull items out of + inventories at the input side, inserts items into inventories at the output side. + Internal fifo slots. Automatically bypasses items that cannot be cooked or smelted. + Electrical RF/FE power can be applied on all sides. Items can be inserted or drawn + from all sides (e.g. with filtered hopper or whatever). Fits ideally into a conveyor + belt line/lane. Consumption and efficiency tunable via config. -- *Factory dropper*: Dropper with GUI configurable drop force, direction, stack size, +- *Factory Dropper*: Dropper with GUI configurable drop force, direction, stack size, trigger cool-down delay, and trigger logic. Three trigger slots ("filter slots") can be used as internal trigger. They emit an internal signal if their item is found in in the dropper inventory (also at least the stack size of a trigger slot). Internal triggers can be easily combined with the external redstone signal trigger using logical *AND* or *OR* gates. If internal triggers match, the dropper will spit out - exactly the stacks in these slots. That allows to drop e.g. always nine lapis, - redstone, nuggets, etc on a conveyor to feed a compression metal press - instantly + exactly the stacks in these slots. That allows to drop e.g. always nine Lapis, + Redstone, nuggets, etc on a conveyor to feed a compression metal press - instantly and automatically after nine of these items have been inserted into the dropper. + Provides redstone pulse mode (drop like a vanilla dropper) or continuous mode + (continue dropping as long as the redstone signal is on). -- *Small waste incinerator*: Buffered and delayed item disposal device. 16 fifo +- *Small Waste Incinerator*: Buffered and delayed item disposal device. 16 fifo slots are filled when new items are pushed in from any side. A GUI allows to take out accidentally trashed items or put in items to get rid of. When the fifo is full, the oldest stack will be disposed. The processing speed can be increased by connecting electrical RF/FE power. -- *Clinker bricks*: Slightly darker and more colorful version of the vanilla brick +- *Clinker Bricks*: Slightly darker and more colorful version of the vanilla brick block. Eight position dependent texture variations are implemented to make the wall look more "alive". Crafted 3x3 with a brick block in the centre and any combination of bricks and nether bricks around (actually, anything where the - ore dictionary says it's a "brick ingot"). Higher explosion resistance than the - vanilla bricks. Also available as stairs and wall, crafted as usual. There - is a reverse recipe to get three clinker brick blocks back from stairs or walls. + ore dictionary says it's a "brick ingot" - useful for bigger industrial buildings + where clay is a rare resource). Higher explosion resistance than the vanilla + bricks. Also available as stairs and wall, crafted as usual. There is a reverse + recipe to get three clinker brick blocks back from stairs or walls. There are + also *Stained Clinker Bricks* (crafted Dirt and Clinkers), which can be mixed + in Clinker walls for more variations. -- *Slag bricks*: Gray-brownish brick, also eight texture variations. Crafted 3x3 +- *Slag Bricks*: Gray-brownish brick, also eight texture variations. Crafted 3x3 from slag in the centre and any kind of bricks ("brick ingot") around. Has a higher explosion resistance than bricks. Also available as stairs and wall, also with reverse recipes. -- Rebar (steel) reinforced concrete: Expensive but creeper-proof. Crafted 3x3 from - four concrete blocks and five steel rods. Texture design oriented at the IE concrete, - slightly darker, eight (position dependent) random texture variations with rust - traces. Also creaftable in form of *stairs* and *walls*. Like the IE contrete *tiles*, - you can craft rebar concrete tiles with corresponding stairs. Reverse recipes - available for all blocks crafted from rebar concrete. +- *Rebar Concrete*: Steel reinforced concrete. Expensive, creeper-proof. + Texture design oriented at the IE concrete, slightly darker, eight (position + dependent) random texture variations with rust traces. Also creaftable in form + of *stairs* and *walls*. Like the IE contrete *tiles*, you can craft rebar + concrete tiles with corresponding stairs. Reverse recipes available for all + blocks crafted from rebar concrete. -- Concrete wall: Solid concrete wall (not the vanilla wall design), crafted 3x3 - from six IE concrete blocks (normal wall recipe). +- *Concrete Wall*: Solid concrete wall (not the vanilla wall design). -- *Treated wood ladder*: Crafted 3x3 with the known ladder pattern, items are - treated wood sticks. Climbing is faster if looking up/down and not sneaking. +- *Treated Wood Ladder*: Stylish ladder, climbing is faster if looking up/down and not + sneaking (but not OP-fast). -- *Metal rung ladder*: Industrial wall-fixed ladder with horizontal bent rods. - Crafted 3x3 with five iron or steel rods in a "U" pattern. Climbing is faster - if looking up/down and not sneaking. +- *Metal Rung Ladder*: Industrial wall-fixed ladder with horizontal bent rods. Climbing + is faster if looking up/down and not sneaking. -- *Staggered metal steps*: Industrial wall-fixed sparse ladder with steps in a - zip pattern. Crafted 3x3 with six iron or steel rods in a zip pattern. Climbing - is faster when looking up/down and not sneaking. +- *Staggered Metal Steps*: Industrial wall-fixed sparse ladder with steps in a zip pattern. + Climbing is faster when looking up/down and not sneaking. -- *Panzer glass*: Reinforced, dark gray tinted glass block. Explosion-proof. - Faint structural lines are visible, multiple texture variations for seemless - look. Crafted 3x3 with four metal rods, four glass blocks, and one diamond. +- *Panzer Glass*: Reinforced, dark gray tinted glass block. Explosion-proof. Faint + structural lines are visible, multiple texture variations for seemless look. -- *Treated wood table*: Four leg table made out of treated wood. Crafted 3x3 - with three treated wood slabs and four treated wood poles. Guess the pattern. +- *Treated Wood Table*: Four leg table made out of treated wood. -- *Treated wood stool*: Simple small stool fitting to the table. Crafted 3x3 - with three treated wood slabs and one treated wood pole. +- *Treated Wood Stool*: Simple small stool fitting to the table. You can sit on it, and + also mobs will occationally do that (only mobs which actually can sit). -- *Treated wood pole*: Pole fragment that can be placed in all directions. It - does intentionally not connect to posts, fences, etc - just a straigt pole. - Can be used e.g. for structural support or wire relay post, where the height - of the IE wire posts does not match. +- *Treated Wood Pole*: Pole fragment that can be placed in all directions. It does + intentionally not connect to posts, fences, etc - just a straigt pole. Can be used e.g. + for structural support or wire relay post, where the height of the IE wire posts does + not match. -- *Thin and thick steel support poles*: Hollow steel pole fragments, can be - placed in all directions. Also with head/food end components. Thin poles crafted - 3x3 from three steel ingots (output 12), thick poles crafted 3x3 from six thin - steel poles. +- *Thin and thick Steel Support Poles*: Hollow steel pole fragments, can be placed in all + directions. Also with head/food end components. -- *Double-T steel support*: Horizontal top-aligned support beam, placed in the - direction you look. Auto connects to adjacent beams if facing towards them. Auto - connects to steel poles underneath. Crafted 3x3 from thin steel poles in a T-shape - (output: 6 beams). +- *Double-T Steel Support*: Horizontal top-aligned support beam, placed in the direction + you look. Auto connects to adjacent beams if facing towards them. Auto connects to steel + poles underneath. Note: When sneaking you can pass underneath it, not all mobs sneak. -- *Inset spot light*: Small metal framed glowstone based light source for ceiling, - wall, or floor. Light level like a torch. Thin, hence not blocking the way. - Allows illuminating places where electrical light installations are problematic. +- *Inset Spot Light*: Small metal framed glowstone based light source for ceiling, wall, + or floor. Light level like a torch. Thin, hence not blocking the way. Allows illuminating + places where electrical light installations are problematic. -- *Industrial signs*: "Danger", "Electrical Hazard", "Exit", etc. +- *Industrial Signs*: "Danger", "Electrical Hazard", "Exit", etc. Makes a factory looking + more alive. -- *Slab slices*: Decorative stackable thin slabs made of of IE metal sheets, - concretes, treated wood. Useful e.g. for roofs or ramps. Left-clicking with - the same slab type in your hand while looking up/down removes slices again. - Crafted 3x3 from four slabs. +- *Slab Slices*: Decorative stackable thin slabs made of of IE metal sheets, concretes, + treated wood. Useful e.g. for roofs or ramps. Left-clicking with the same slab type in + your hand while looking up/down removes slices again. -- *Fluid pipe check valve*: Check valve: IE fluid pipe styled straight valve that - conducts fluids only in one direction. Crafted from 3x3 from three fluid pipes. - Supports IE pressurized fluid transfer. +- *Fluid Pipe Check Valve*: IE fluid pipe styled straight valve that conducts fluids only + in one direction. Crafted from 3x3 from three fluid pipes. Supports IE pressurized fluid + transfer. -- *Redstone controlled valves*: Conduct only in one direction, on-off - variant (open on redstone power) and analog variant (closed at power 0, linear - flow slope, fully open at power 15). Support IE pressurized fluid transfer. +- *Redstone Controlled Valves*: Conduct only in one direction, on-off variant (open on redstone + power) and analog variant (closed at power 0, linear flow slope, fully open at power 15). + Support IE pressurized fluid transfer. -- *Passive fluid accumulator*: Block with one output and five input sides, that - draws fluids out of adjacent tanks when a pump drains fluid from the output port. - Implicit round-robin balanced drain from adjacent blocks. Random initial fluid - drip-in to allow pumps to detect that fluids can be drained. The accumulator - has a vacuum suction delay. +- *Passive Fluid Accumulator*: Block with one output and five input sides, that draws fluids + out of adjacent tanks when a pump drains fluid from the output port. Implicit round-robin + balanced drain from adjacent blocks. Random initial fluid drip-in to allow pumps to detect + that fluids can be drained. The accumulator has a vacuum suction delay. -- *Small Solar Panel*: Produces a small amount of RF power, comparable to a - IE thermal peltier generator over one day cycle. No power at night, reduced - power when raining. The power curve during day time is non-linear. Useful - for electrical lighting of remote places. +- *Small Solar Panel*: Produces a small amount of RF power, comparable to a IE thermal + peltier generator over one day cycle. No power at night, reduced power when raining. The + power curve during day time is non-linear. Useful for electrical lighting of remote places. -- *Small Tree Cutter*: A slab sized device that chops a tree in front of it. - Needs by default about one minute, with RF power less than 10 seconds. Useful - to build a contraptive automated tree farm. +- *Small Tree Cutter*: A slab sized device that chops a tree in front of it. Needs by default + about one minute, with RF power less than 10 seconds. Useful to build a contraptive automated + tree farm. -- *Small Mineral Smelter*: Device that slowly converts most stones or sands to - magma blocks and finally to lava. Needs a lot of power. When the lava is cooled - down in the smelter by removing the RF power, obsidian is generated. +- *Small Mineral Smelter*: Device that slowly converts most stones or sands to magma blocks and + finally to lava. Needs a lot of power. When the lava is cooled down in the smelter by removing + the RF power, obsidian is generated. More to come slowly but steadily.