Main readme updated, documentation updated, Makefiles updated. Experimental features snapshot. 1.14: Crafting table item rendering added. Recipe collision resolver added. Lang files updated.

This commit is contained in:
stfwi 2019-09-17 17:56:08 +02:00
parent bc76fed9d6
commit 03957b423a
52 changed files with 893 additions and 267 deletions

View file

@ -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

View file

@ -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).

View file

@ -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()

View file

@ -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<IRecipe> matching_recipes = new ArrayList<IRecipe>();
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<IRecipe> matching_recipes = new ArrayList<IRecipe>();
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<ItemStack> stacks;
protected final CraftingHistory history = new CraftingHistory();
protected boolean has_recipe_collision_ = false;
public BTileEntity()
{ stacks = NonNullList.<ItemStack>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<ItemStack> 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(); }
}
}

View file

@ -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({

View file

@ -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<BlockDecorCraftingTable.BTileEntity>
{
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<BlockDecorCraftingTable.BTileEntity.NUM_OF_CRAFTING_SLOTS; ++i) {
final ItemStack stack = te.getStackInSlot(BlockDecorCraftingTable.BTileEntity.CRAFTING_SLOTS_BEGIN+i);
if(stack.isEmpty()) continue;
boolean isblock = (stack.getItem() instanceof ItemBlock);
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.translate(x+0.5+ox, y+0.5+oy, z+0.5+oz);
GlStateManager.rotate((float)90, 1, 0, 0);
GlStateManager.rotate((float)ry, 0, 0, 1);
GlStateManager.translate(rndo, rndo, 0);
GlStateManager.scale(scaler, scaler, scaler);
Minecraft.getMinecraft().getRenderItem().renderItem(stack, 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());
}
}
}
}
}

View file

@ -37,6 +37,10 @@ public class RecipeCondModSpecific implements IConditionFactory
public BooleanSupplier parse(JsonContext context, JsonObject json) {
if(ModConfig.isWithoutRecipes()) return exclude();
try {
final JsonPrimitive experimental = json.getAsJsonPrimitive("experimental");
if((experimental!=null) && (experimental.getAsBoolean())) {
if(!ModConfig.zmisc.with_experimental) return exclude();
}
final IForgeRegistry<Block> block_registry = ForgeRegistries.BLOCKS;
final IForgeRegistry<Item> item_registry = ForgeRegistries.ITEMS;
final JsonArray items = json.getAsJsonArray("required");

View file

@ -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": {

View file

@ -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
}
}

View file

@ -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
}
}

View file

@ -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
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 27 KiB

Before After
Before After

View file

@ -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

View file

@ -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([

View file

@ -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

View file

@ -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.

View file

@ -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());
}
}

View file

@ -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<Block> event)
@ -104,6 +98,32 @@ public class ModEngineersDecor
@SubscribeEvent
public static void onRegisterContainerTypes(final RegistryEvent.Register<ContainerType<?>> 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());
}
}
}
//

View file

@ -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<ItemStack> 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<Block, BlockState> builder)
{ super.fillStateContainer(builder); builder.add(WATERLOGGED); }
}
}

View file

@ -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;

View file

@ -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<ICraftingRecipe> 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<ICraftingRecipe> 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<ICraftingRecipe> 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<ICraftingRecipe> 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) {
if(usable_recipes.get(i) == currently_used) {
if(++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<ItemStack> 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<ItemStack> 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);

View file

@ -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<Block, BlockState> 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<Block, BlockState> builder)
{ super.fillStateContainer(builder); builder.add(WATERLOGGED); }
}
}

View file

@ -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<Block, BlockState> 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<Block, BlockState> builder)
{ super.fillStateContainer(builder); builder.add(WATERLOGGED); }
}
}

View file

@ -73,7 +73,7 @@ public class BlockDecorDropper extends BlockDecorDirected
@Override
protected void fillStateContainer(StateContainer.Builder<Block, BlockState> builder)
{ builder.add(FACING, OPEN); }
{ super.fillStateContainer(builder); builder.add(OPEN); }
@Override
@Nullable

View file

@ -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)

View file

@ -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); }
}

View file

@ -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")

View file

@ -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<Block, BlockState> 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

View file

@ -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<VoxelShape>(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<Block, BlockState> 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)
{

View file

@ -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)

View file

@ -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<Block, BlockState> 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

View file

@ -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<Block, BlockState> 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

View file

@ -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)

View file

@ -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<Block, BlockState> 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;

View file

@ -71,7 +71,7 @@ public class BlockDecorWasteIncinerator extends BlockDecor
@Override
protected void fillStateContainer(StateContainer.Builder<Block, BlockState> builder)
{ builder.add(LIT); }
{ super.fillStateContainer(builder); builder.add(LIT); }
@Override
@Nullable

View file

@ -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<Block, BlockState> builder)
{ super.fillStateContainer(builder); builder.add(WATERLOGGED); }
}

View file

@ -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<String> excludes_ = new ArrayList<String>();
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]);
}
}
}
}

View file

@ -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<BlockDecorCraftingTable.BTileEntity>
{
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());
}
}
}
}
}

View file

@ -32,9 +32,10 @@ public class OptionalRecipeCondition implements ICondition
private final List<ResourceLocation> all_required;
private final List<ResourceLocation> any_missing;
private final @Nullable ResourceLocation result;
private final boolean experimental;
public OptionalRecipeCondition(ResourceLocation result, List<ResourceLocation> required, List<ResourceLocation> missing)
{ all_required = required; any_missing = missing; this.result = result; }
public OptionalRecipeCondition(ResourceLocation result, List<ResourceLocation> required, List<ResourceLocation> 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> block_registry = ForgeRegistries.BLOCKS;
final IForgeRegistry<Item> item_registry = ForgeRegistries.ITEMS;
if(result != null) {
@ -103,6 +106,7 @@ public class OptionalRecipeCondition implements ICondition
List<ResourceLocation> required = new ArrayList<>();
List<ResourceLocation> 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);
}
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 27 KiB

Before After
Before After

View file

@ -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
}
}

View file

@ -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
}
}

View file

@ -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
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 165 KiB

View file

Before

Width:  |  Height:  |  Size: 85 KiB

After

Width:  |  Height:  |  Size: 85 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 128 KiB

After

Width:  |  Height:  |  Size: 128 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 410 KiB

After

Width:  |  Height:  |  Size: 410 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 222 KiB

After

Width:  |  Height:  |  Size: 222 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 226 KiB

After

Width:  |  Height:  |  Size: 226 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 242 KiB

After

Width:  |  Height:  |  Size: 242 KiB

Before After
Before After

View file

@ -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)

168
readme.md
View file

@ -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.