Crafting Table shift-ctrl tweaks added. Crafting table mouse wheel stack inc/dec added. Lang file en_en updated (issue #76). Fixed tree cutter progress reset (issue #77). Added Solar Panel energy cap export (issue #78). Build system json-lang sanatized added.

This commit is contained in:
stfwi 2020-01-10 07:49:58 +01:00
parent 11e985b8db
commit d4488df2b7
39 changed files with 1339 additions and 569 deletions

View file

@ -68,6 +68,7 @@ sanatize:
@echo "[1.14] Running sanatising tasks ..."
@djs tasks.js trailing-whitespaces
@djs tasks.js tabs-to-spaces
@djs tasks.js lang-json-fixes
@djs tasks.js sync-languages
@djs tasks.js version-check
@djs tasks.js update-json

View file

@ -70,7 +70,7 @@ dependencies {
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() }
doLast { file("${sourceSets.main.output.resourcesDir}/.gitversion-engineersdecor").text = 'git log "-1" "--format=%h"'.execute().in.text.trim() }
}
jar {

View file

@ -2,7 +2,7 @@
org.gradle.daemon=false
org.gradle.jvmargs=-Xmx8G
version_minecraft=1.14.4
version_forge_minecraft=1.14.4-28.1.109
version_forge_minecraft=1.14.4-28.1.111
version_fml_mappings=20190719-1.14.3
version_jei=1.14.4:6.0.0.10
version_engineersdecor=1.0.18-b2
version_engineersdecor=1.0.18-b3

View file

@ -1,6 +1,7 @@
{
"homepage": "https://www.curseforge.com/minecraft/mc-mods/engineers-decor/",
"1.14.4": {
"1.0.18-b3": "[A] Added Treated Wood Crafting table tweaks (ctrl-shift moves all same stacks from the inventory, mouse wheel over crafting slot increases/decreases crafting grid stacks).\n[F] EN Lang file fixed (issue #76, thx Riverstar907).\n[F] Fixed Tree Cutter not respecting power-required config (thx federsavo, issue #77).\n[F] Fixed Small Solar Panel not exposing energy capability (thx MatthiasMann, issue #78).",
"1.0.18-b2": "[F] Fixed JEI integration warning if nothing is opt'ed out (thx @SDUBZ for reporting).\n[M] Lang ru_ru updated (Smollet777).",
"1.0.18-b1": "[U] Updated to Forge 1.14.4-28.1.109/20190719-1.14.3.\n[A] Added opt-out config for the Small Tree Cutter.",
"1.0.17-b3": "[F] Double newline escapes in lang files fixed (\"\\n\" in a tooltip).\n[M] Updated zh_cn lang file (scikirbypoke).",
@ -42,6 +43,6 @@
},
"promos": {
"1.14.4-recommended": "",
"1.14.4-latest": "1.0.18-b2"
"1.14.4-latest": "1.0.18-b3"
}
}

View file

@ -11,6 +11,12 @@ Mod sources for Minecraft version 1.14.4.
## Version history
- v1.0.18-b3 [A] Added Treated Wood Crafting table tweaks (ctrl-shift moves all same stacks from the
inventory, mouse wheel over crafting slot increases/decreases crafting grid stacks).
[F] EN Lang file fixed (issue #76, thx Riverstar907).
[F] Fixed Tree Cutter not respecting power-required config (thx federsavo, issue #77).
[F] Fixed Small Solar Panel not exposing energy capability (thx MatthiasMann, issue #78).
- v1.0.18-b2 [F] Fixed JEI integration warning if nothing is opt'ed out (thx @SDUBZ for reporting).
[M] Lang ru_ru updated (Smollet777).

View file

@ -1,5 +1,7 @@
package wile.engineersdecor;
import net.minecraft.client.util.InputMappings;
import org.lwjgl.glfw.GLFW;
import wile.engineersdecor.detail.ModAuxiliaries;
import wile.engineersdecor.detail.ModConfig;
import wile.engineersdecor.detail.Networking;
@ -33,6 +35,7 @@ import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import javax.annotation.Nullable;
import java.util.Optional;
@Mod("engineersdecor")
@ -146,19 +149,17 @@ public class ModEngineersDecor
default @Nullable PlayerEntity getPlayerClientSide() { return null; }
default @Nullable World getWorldClientSide() { return null; }
default @Nullable Minecraft mc() { return null; }
default Optional<Boolean> isCtrlDown() { return Optional.empty(); }
}
public static final class ClientProxy implements ISidedProxy
{
public @Nullable PlayerEntity getPlayerClientSide() { return Minecraft.getInstance().player; }
public @Nullable World getWorldClientSide() { return Minecraft.getInstance().world; }
public @Nullable Minecraft mc() { return Minecraft.getInstance(); }
public Optional<Boolean> isCtrlDown() { return Optional.of(ModAuxiliaries.isCtrlDown()); }
}
public static final class ServerProxy implements ISidedProxy
{
public @Nullable PlayerEntity getPlayerClientSide() { return null; }
public @Nullable World getWorldClientSide() { return null; }
public @Nullable Minecraft mc() { return null; }
}
{}
//
// Item group / creative tab

View file

@ -10,6 +10,7 @@ package wile.engineersdecor.blocks;
import wile.engineersdecor.ModContent;
import wile.engineersdecor.ModEngineersDecor;
import wile.engineersdecor.detail.ModAuxiliaries;
import wile.engineersdecor.detail.Networking;
import net.minecraft.inventory.container.*;
import net.minecraft.network.play.server.SSetSlotPacket;
@ -61,12 +62,15 @@ public class BlockDecorCraftingTable extends BlockDecorDirected.WaterLoggable
public static boolean with_assist = true;
public static boolean with_assist_direct_history_refab = false;
public static boolean with_assist_quickmove_buttons = false;
public static boolean with_crafting_slot_mouse_scrolling = true;
public static final void on_config(boolean without_crafting_assist, boolean with_assist_immediate_history_refab, boolean with_quickmove_buttons)
public static final void on_config(boolean without_crafting_assist, boolean with_assist_immediate_history_refab,
boolean with_quickmove_buttons, boolean without_crafting_slot_mouse_scrolling)
{
with_assist = !without_crafting_assist;
with_assist_direct_history_refab = with_assist_immediate_history_refab;
with_assist_quickmove_buttons = with_quickmove_buttons;
with_crafting_slot_mouse_scrolling = !without_crafting_slot_mouse_scrolling;
CraftingHistory.max_history_size(32);
}
@ -295,6 +299,8 @@ public class BlockDecorCraftingTable extends BlockDecorDirected.WaterLoggable
public static class BContainer extends Container implements Networking.INetworkSynchronisableContainer
{
public enum PlacementResult { UNCHANGED, INCOMPLETE, PLACED }
// Crafting slot of container --------------------------------------------------------------------------------------
public static class BSlotCrafting extends CraftingResultSlot
{
@ -368,6 +374,13 @@ public class BlockDecorCraftingTable extends BlockDecorDirected.WaterLoggable
}
}
private static class SlotRange
{
public final IInventory inventory;
public int start_slot, end_slot;
public SlotRange(IInventory inv, int start, int end) { inventory=inv; start_slot=start; end_slot=end; }
}
//------------------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------------
public static final int CRAFTING_SLOTS_BEGIN = 0;
@ -576,7 +589,7 @@ public class BlockDecorCraftingTable extends BlockDecorDirected.WaterLoggable
return false;
}
private List<ItemStack> crafting_slot_stacks_to_add()
private List<ItemStack> refab_crafting_stacks()
{
final ArrayList<ItemStack> slots = new ArrayList<ItemStack>();
final List<ItemStack> tocraft = history_.current();
@ -618,30 +631,46 @@ public class BlockDecorCraftingTable extends BlockDecorDirected.WaterLoggable
return slots;
}
private List<ItemStack> incr_crafting_grid_stacks(int count)
{
final ArrayList<ItemStack> stacks = new ArrayList<ItemStack>();
for(int i=0; i<9; ++i) {
final ItemStack palced = inventory_.getStackInSlot(i+CRAFTING_SLOTS_BEGIN).copy();
if(!palced.isEmpty()) palced.setCount(count);
stacks.add(palced);
}
return stacks;
}
/**
* Moves as much items from the stack to the slots in range [first_slot, last_slot] of the inventory,
* filling up existing stacks first, then (player inventory only) checks appropriate empty slots next
* to stacks that have that item already, and last uses any empty slot that can be found.
* Returns the stack that is still remaining in the referenced `stack`.
*/
private ItemStack move_stack_to_inventory(final ItemStack stack_to_move, IInventory inventory, final int slot_begin, final int slot_end, boolean only_fillup)
private ItemStack move_stack_to_inventory(final ItemStack stack_to_move, SlotRange range, boolean only_fillup, int limit)
{
final IInventory inventory = range.inventory;
final int slot_begin = range.start_slot;
final int slot_end = range.end_slot;
final ItemStack mvstack = stack_to_move.copy();
if((mvstack.isEmpty()) || (slot_begin < 0) || (slot_end > inventory.getSizeInventory())) return mvstack;
int limit_left = (limit>0) ? (Math.min(limit, mvstack.getMaxStackSize())) : (mvstack.getMaxStackSize());
// first iteration: fillup existing stacks
for(int i = slot_begin; i < slot_end; ++i) {
final ItemStack stack = inventory.getStackInSlot(i);
if((stack.isEmpty()) || (!stack.isItemEqual(mvstack))) continue;
int nmax = stack.getMaxStackSize() - stack.getCount();
int nmax = Math.min(limit_left, stack.getMaxStackSize() - stack.getCount());
if(mvstack.getCount() <= nmax) {
stack.setCount(stack.getCount()+mvstack.getCount());
mvstack.setCount(0);
inventory.setInventorySlotContents(i, stack);
return mvstack;
} else {
stack.setCount(stack.getMaxStackSize());
stack.grow(nmax);
mvstack.shrink(nmax);
inventory.setInventorySlotContents(i, stack);
limit_left -= nmax;
}
}
if(only_fillup) return mvstack;
@ -651,8 +680,11 @@ public class BlockDecorCraftingTable extends BlockDecorDirected.WaterLoggable
final ItemStack stack = inventory.getStackInSlot(i);
if(!stack.isEmpty()) continue;
if((!inventory.getStackInSlot(i+1).isItemEqual(mvstack)) && (!inventory.getStackInSlot(i-1).isItemEqual(mvstack))) continue;
inventory.setInventorySlotContents(i, mvstack.copy());
mvstack.setCount(0);
int nmax = Math.min(limit_left, mvstack.getCount());
ItemStack placed = mvstack.copy();
placed.setCount(nmax);
mvstack.shrink(nmax);
inventory.setInventorySlotContents(i, placed);
return mvstack;
}
}
@ -660,8 +692,11 @@ public class BlockDecorCraftingTable extends BlockDecorDirected.WaterLoggable
for(int i = slot_begin; i < slot_end; ++i) {
final ItemStack stack = inventory.getStackInSlot(i);
if(!stack.isEmpty()) continue;
inventory.setInventorySlotContents(i, mvstack.copy());
mvstack.setCount(0);
int nmax = Math.min(limit_left, mvstack.getCount());
ItemStack placed = mvstack.copy();
placed.setCount(nmax);
mvstack.shrink(nmax);
inventory.setInventorySlotContents(i, placed);
return mvstack;
}
return mvstack;
@ -671,8 +706,11 @@ public class BlockDecorCraftingTable extends BlockDecorDirected.WaterLoggable
* Moves as much items from the slots in range [first_slot, last_slot] of the inventory into a new stack.
* Implicitly shrinks the inventory stacks and the `request_stack`.
*/
private ItemStack move_stack_from_inventory(IInventory inventory, final ItemStack request_stack, final int slot_begin, final int slot_end)
private ItemStack move_stack_from_inventory(SlotRange range, final ItemStack request_stack)
{
final IInventory inventory = range.inventory;
final int slot_begin = range.start_slot;
final int slot_end = range.end_slot;
ItemStack fetched_stack = request_stack.copy();
fetched_stack.setCount(0);
int n_left = request_stack.getCount();
@ -687,8 +725,8 @@ public class BlockDecorCraftingTable extends BlockDecorDirected.WaterLoggable
// the user has to place this item manually.
if(stack.hasTag()) {
final CompoundNBT nbt = stack.getTag();
int n = stack.getTag().size();
if((n > 0) && (stack.getTag().contains("Damage"))) --n;
int n = nbt.size();
if((n > 0) && (nbt.contains("Damage"))) --n;
if(n > 0) continue;
}
fetched_stack = stack.copy(); // copy exact stack with nbt and tool damage, otherwise we have an automagical repair of items.
@ -720,7 +758,7 @@ public class BlockDecorCraftingTable extends BlockDecorDirected.WaterLoggable
for(int grid_i = CRAFTING_SLOTS_BEGIN; grid_i < (CRAFTING_SLOTS_BEGIN+NUM_OF_CRAFTING_SLOTS); ++grid_i) {
ItemStack stack = inventory_.getStackInSlot(grid_i);
if(stack.isEmpty()) continue;
ItemStack remaining = move_stack_to_inventory(stack, inventory_, STORAGE_SLOTS_BEGIN, STORAGE_SLOTS_BEGIN+NUM_OF_STORAGE_SLOTS, false);
ItemStack remaining = move_stack_to_inventory(stack, new SlotRange(inventory_, STORAGE_SLOTS_BEGIN, STORAGE_SLOTS_BEGIN+NUM_OF_STORAGE_SLOTS), false, 0);
inventory_.setInventorySlotContents(grid_i, remaining);
changed = true;
}
@ -733,63 +771,68 @@ public class BlockDecorCraftingTable extends BlockDecorDirected.WaterLoggable
for(int grid_i = CRAFTING_SLOTS_BEGIN; grid_i < (CRAFTING_SLOTS_BEGIN+NUM_OF_CRAFTING_SLOTS); ++grid_i) {
ItemStack remaining = inventory_.getStackInSlot(grid_i);
if(remaining.isEmpty()) continue;
remaining = move_stack_to_inventory(remaining, player.inventory,9, 36, true); // prefer filling up inventory stacks
remaining = move_stack_to_inventory(remaining, player.inventory,0, 9, true); // then fill up the hotbar stacks
remaining = move_stack_to_inventory(remaining, player.inventory,9, 36, false); // then allow empty stacks in inventory
remaining = move_stack_to_inventory(remaining, player.inventory,0, 9, false); // then new stacks in the hotbar
remaining = move_stack_to_inventory(remaining, new SlotRange(player.inventory,9, 36), true, 0); // prefer filling up inventory stacks
remaining = move_stack_to_inventory(remaining, new SlotRange(player.inventory,0, 9), true, 0); // then fill up the hotbar stacks
remaining = move_stack_to_inventory(remaining, new SlotRange(player.inventory,9, 36), false, 0); // then allow empty stacks in inventory
remaining = move_stack_to_inventory(remaining, new SlotRange(player.inventory,0, 9), false, 0); // then new stacks in the hotbar
inventory_.setInventorySlotContents(grid_i, remaining);
changed = true;
}
return changed;
}
enum EnumRefabPlacement { UNCHANGED, INCOMPLETE, PLACED }
private EnumRefabPlacement place_refab_stacks(IInventory inventory, final int slot_begin, final int slot_end)
private PlacementResult place_stacks(final SlotRange[] ranges, final List<ItemStack> to_fill)
{
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;
if(!to_fill.isEmpty()) {
for(int it_guard=63; it_guard>=0; --it_guard) {
boolean slots_updated = false;
for(int i = 0; i < 9; ++i) {
final ItemStack req_stack = to_fill.get(i).copy();
if(req_stack.isEmpty()) continue;
req_stack.setCount(1);
to_fill.get(i).shrink(1);
final ItemStack mv_stack = move_stack_from_inventory(inventory, req_stack, slot_begin, slot_end);
if(mv_stack.isEmpty()) { missing_item=true; continue; }
// sizes already checked
ItemStack grid_stack = inventory_.getStackInSlot(i + CRAFTING_SLOTS_BEGIN).copy();
if(grid_stack.isEmpty()) {
grid_stack = mv_stack.copy();
} else {
grid_stack.grow(mv_stack.getCount());
for(SlotRange slot_range: ranges) {
for(int it_guard=63; it_guard>=0; --it_guard) {
boolean slots_updated = false;
for(int i = 0; i < 9; ++i) {
if(to_fill.get(i).isEmpty()) continue;
ItemStack grid_stack = inventory_.getStackInSlot(i + CRAFTING_SLOTS_BEGIN).copy();
if(grid_stack.getCount() >= grid_stack.getMaxStackSize()) continue;
final ItemStack req_stack = to_fill.get(i).copy();
req_stack.setCount(1);
final ItemStack mv_stack = move_stack_from_inventory(slot_range, req_stack);
if(mv_stack.isEmpty()) continue;
to_fill.get(i).shrink(1);
if(grid_stack.isEmpty()) {
grid_stack = mv_stack.copy();
} else {
grid_stack.grow(mv_stack.getCount());
}
inventory_.setInventorySlotContents(i + CRAFTING_SLOTS_BEGIN, grid_stack);
slots_changed = true;
slots_updated = true;
}
inventory_.setInventorySlotContents(i + CRAFTING_SLOTS_BEGIN, grid_stack);
slots_changed = true;
slots_updated = true;
if(!slots_updated) break;
}
if(!slots_updated) break;
}
}
boolean missing_item = false;
for(ItemStack st:to_fill) {
if(!st.isEmpty()) {
missing_item = true;
break;
}
}
if(!slots_changed) {
return EnumRefabPlacement.UNCHANGED;
return PlacementResult.UNCHANGED;
} else if(missing_item) {
return EnumRefabPlacement.INCOMPLETE;
return PlacementResult.INCOMPLETE;
} else {
return EnumRefabPlacement.PLACED;
return PlacementResult.PLACED;
}
}
private EnumRefabPlacement distribute_stack(IInventory inventory, final int slotno)
private PlacementResult distribute_stack(IInventory inventory, final int slotno)
{
List<ItemStack> to_refab = crafting_slot_stacks_to_add();
List<ItemStack> to_refab = refab_crafting_stacks();
if(history_.current_recipe() != null) result_.setRecipeUsed(history_.current_recipe());
ItemStack to_distribute = inventory.getStackInSlot(slotno).copy();
if(to_distribute.isEmpty()) return EnumRefabPlacement.UNCHANGED;
if(to_distribute.isEmpty()) return PlacementResult.UNCHANGED;
int matching_grid_stack_sizes[] = {-1,-1,-1,-1,-1,-1,-1,-1,-1};
int max_matching_stack_size = -1;
int min_matching_stack_size = 65;
@ -816,9 +859,9 @@ public class BlockDecorCraftingTable extends BlockDecorDirected.WaterLoggable
}
}
}
if(min_matching_stack_size < 0) return EnumRefabPlacement.UNCHANGED;
if(min_matching_stack_size < 0) return PlacementResult.UNCHANGED;
final int stack_limit_size = Math.min(to_distribute.getMaxStackSize(), inventory_.getInventoryStackLimit());
if(min_matching_stack_size >= stack_limit_size) return EnumRefabPlacement.UNCHANGED;
if(min_matching_stack_size >= stack_limit_size) return PlacementResult.UNCHANGED;
int n_to_distribute = to_distribute.getCount();
for(int it_guard=63; it_guard>=0; --it_guard) {
if(n_to_distribute <= 0) break;
@ -837,7 +880,7 @@ public class BlockDecorCraftingTable extends BlockDecorDirected.WaterLoggable
}
if(min_matching_stack_size >= stack_limit_size) break; // all full
}
if(n_to_distribute == to_distribute.getCount()) return EnumRefabPlacement.UNCHANGED; // was already full
if(n_to_distribute == to_distribute.getCount()) return PlacementResult.UNCHANGED; // was already full
if(n_to_distribute <= 0) {
inventory.setInventorySlotContents(slotno, ItemStack.EMPTY);
} else {
@ -851,9 +894,30 @@ public class BlockDecorCraftingTable extends BlockDecorDirected.WaterLoggable
grid_stack.setCount(matching_grid_stack_sizes[i]);
inventory_.setInventorySlotContents(i + CRAFTING_SLOTS_BEGIN, grid_stack);
}
return EnumRefabPlacement.PLACED;
return PlacementResult.PLACED;
}
private boolean decrease_grid_stacks(SlotRange[] ranges, int limit)
{
boolean changed = false;
for(int i=0; i<9; ++i) {
ItemStack stack = inventory_.getStackInSlot(i+CRAFTING_SLOTS_BEGIN).copy();
if(stack.isEmpty()) continue;
for(SlotRange range:ranges) {
ItemStack remaining = move_stack_to_inventory(stack, range, false, limit);
if(remaining.getCount() < stack.getCount()) changed = true;
boolean stop = (remaining.getCount() <= Math.max(0, (stack.getCount()-limit)));
stack = remaining;
if(stop) break;
}
inventory_.setInventorySlotContents(i+CRAFTING_SLOTS_BEGIN, stack.isEmpty() ? ItemStack.EMPTY : stack);
}
return changed;
}
private boolean increase_grid_stacks(SlotRange[] ranges, int limit)
{ return place_stacks(ranges, incr_crafting_grid_stacks(limit)) != PlacementResult.UNCHANGED; }
// Container client/server synchronisation --------------------------------------------------
@OnlyIn(Dist.CLIENT)
@ -901,47 +965,118 @@ public class BlockDecorCraftingTable extends BlockDecorDirected.WaterLoggable
if(clear_grid_to_player(player)) { changed = true; player_inventory_changed = true; }
} break;
case BGui.BUTTON_FROM_STORAGE: {
EnumRefabPlacement from_storage = place_refab_stacks(inventory_, STORAGE_SLOTS_BEGIN, STORAGE_SLOTS_BEGIN+NUM_OF_STORAGE_SLOTS);
if(from_storage != EnumRefabPlacement.UNCHANGED) changed = true;
if(place_stacks(new SlotRange[]{
new SlotRange(inventory_, STORAGE_SLOTS_BEGIN, STORAGE_SLOTS_BEGIN+NUM_OF_STORAGE_SLOTS)
}, refab_crafting_stacks()) != PlacementResult.UNCHANGED) {
changed = true;
}
} break;
case BGui.BUTTON_FROM_PLAYER: {
EnumRefabPlacement from_player_inv = place_refab_stacks(player.inventory, 9, 36);
if(from_player_inv != EnumRefabPlacement.UNCHANGED) { changed = true; player_inventory_changed = true; }
if(from_player_inv != EnumRefabPlacement.PLACED) {
EnumRefabPlacement from_hotbar = place_refab_stacks(player.inventory, 0, 9);
if(from_hotbar != EnumRefabPlacement.UNCHANGED) { changed = true; player_inventory_changed = true; }
if(place_stacks(new SlotRange[]{
new SlotRange(player.inventory, 9, 36),
new SlotRange(player.inventory, 0, 9)
}, refab_crafting_stacks()) != PlacementResult.UNCHANGED) {
changed = true; player_inventory_changed = true;
}
} break;
case BGui.ACTION_PLACE_CURRENT_HISTORY_SEL: {
EnumRefabPlacement from_storage = place_refab_stacks(inventory_, STORAGE_SLOTS_BEGIN, STORAGE_SLOTS_BEGIN+NUM_OF_STORAGE_SLOTS);
if(from_storage != EnumRefabPlacement.UNCHANGED) changed = true;
if(from_storage != EnumRefabPlacement.PLACED) {
EnumRefabPlacement from_player_inv = place_refab_stacks(player.inventory, 9, 36);
if(from_player_inv != EnumRefabPlacement.UNCHANGED) { changed = true; player_inventory_changed = true; }
if(from_player_inv != EnumRefabPlacement.PLACED) {
EnumRefabPlacement from_hotbar = place_refab_stacks(player.inventory, 0, 9);
if(from_hotbar != EnumRefabPlacement.UNCHANGED) { changed = true; player_inventory_changed = true; }
}
if(place_stacks(new SlotRange[]{
new SlotRange(player.inventory, 0, 9),
new SlotRange(player.inventory, 9, 36),
new SlotRange(inventory_, STORAGE_SLOTS_BEGIN, STORAGE_SLOTS_BEGIN+NUM_OF_STORAGE_SLOTS)
}, refab_crafting_stacks()) != PlacementResult.UNCHANGED) {
changed = true;
}
} break;
case BGui.ACTION_PLACE_SHIFTCLICKED_STACK: {
final int container_slot_id = nbt.getInt("containerslot");
if((container_slot_id < 10) || (container_slot_id > 53)) break; // out of range
if((container_slot_id < 10) || (container_slot_id > 53)) {
break; // out of range
}
if(container_slot_id >= 46) {
// from storage
final int storage_slot = container_slot_id - 46 + STORAGE_SLOTS_BEGIN;
EnumRefabPlacement stat = distribute_stack(inventory_, storage_slot);
if(stat != EnumRefabPlacement.UNCHANGED) changed = true;
PlacementResult stat = distribute_stack(inventory_, storage_slot);
if(stat != PlacementResult.UNCHANGED) changed = true;
} else {
// from player
int player_slot = (container_slot_id >= 37) ? (container_slot_id-37) : (container_slot_id-10+9);
EnumRefabPlacement stat = distribute_stack(player.inventory, player_slot);
if(stat != EnumRefabPlacement.UNCHANGED) { player_inventory_changed = true; changed = true; }
final ItemStack reference_stack = player.inventory.getStackInSlot(player_slot).copy();
if((!reference_stack.isEmpty()) && (distribute_stack(player.inventory, player_slot) != PlacementResult.UNCHANGED)) {
player_inventory_changed = true;
changed = true;
if(nbt.contains("move-all")) {
for(int i=0; i < player.inventory.getSizeInventory(); ++i) {
final ItemStack stack = player.inventory.getStackInSlot(i);
if(!reference_stack.isItemEqual(stack)) continue;
if(distribute_stack(player.inventory, i) == PlacementResult.UNCHANGED) break; // grid is full
}
}
}
}
} break;
case BGui.ACTION_MOVE_ALL_STACKS: {
final int container_slot_id = nbt.getInt("containerslot");
if((container_slot_id < 1) || (container_slot_id > 53)) {
break; // out of range
} else if(container_slot_id < 10) {
// from crafting grid to player inventory, we clear the grid here as this is most likely
// what is wanted in the end. Saves clicking the other grid stacks.
if(clear_grid_to_player(player)) { changed = true; player_inventory_changed = true; }
if(clear_grid_to_storage(player)) changed = true;
break;
}
IInventory from_inventory;
SlotRange[] to_ranges;
int from_slot;
if(container_slot_id >= 46) {
// from storage to player inventory
from_inventory = inventory_;
from_slot = container_slot_id - 46 + STORAGE_SLOTS_BEGIN;
to_ranges = new SlotRange[] {new SlotRange(player.inventory, 9, 36), new SlotRange(player.inventory, 0, 9)};
} else {
// from player to storage (otherwise ACTION_PLACE_SHIFTCLICKED_STACK would have been used)
from_inventory = player.inventory;
from_slot = (container_slot_id >= 37) ? (container_slot_id-37) : (container_slot_id-10+9);
to_ranges = new SlotRange[] {new SlotRange(inventory_, STORAGE_SLOTS_BEGIN, STORAGE_SLOTS_BEGIN+NUM_OF_STORAGE_SLOTS)};
}
final ItemStack reference_stack = from_inventory.getStackInSlot(from_slot).copy();
if(!reference_stack.isEmpty()) {
boolean abort = false;
for(int i=0; (i < from_inventory.getSizeInventory()) && (!abort); ++i) {
final ItemStack stack = from_inventory.getStackInSlot(i);
if(!reference_stack.isItemEqual(stack)) continue;
ItemStack remaining = from_inventory.getStackInSlot(i);
for(SlotRange range:to_ranges) {
remaining = move_stack_to_inventory(remaining, range, false, 0);
if(!remaining.isEmpty()) {
abort = true; // no space left
break;
} else {
changed = player_inventory_changed = true;
}
}
from_inventory.setInventorySlotContents(i, remaining);
}
}
} break;
case BGui.BUTTON_NEXT_COLLISION_RECIPE: {
select_next_collision_recipe(inventory_);
} break;
case BGui.ACTION_DECREASE_CRAFTING_STACKS: {
changed = player_inventory_changed = decrease_grid_stacks(new SlotRange[]{
new SlotRange(player.inventory, 9, 36),
new SlotRange(player.inventory, 0, 9),
new SlotRange(inventory_, STORAGE_SLOTS_BEGIN, STORAGE_SLOTS_BEGIN+NUM_OF_STORAGE_SLOTS)
}, MathHelper.clamp(nbt.getInt("limit"), 1, 8));
} break;
case BGui.ACTION_INCREASE_CRAFTING_STACKS: {
changed = player_inventory_changed = increase_grid_stacks(new SlotRange[]{
new SlotRange(player.inventory, 9, 36),
new SlotRange(player.inventory, 0, 9),
new SlotRange(inventory_, STORAGE_SLOTS_BEGIN, STORAGE_SLOTS_BEGIN+NUM_OF_STORAGE_SLOTS)
}, MathHelper.clamp(nbt.getInt("limit"), 1, 8));
} break;
}
}
if(changed) inventory_.markDirty();
@ -955,7 +1090,6 @@ public class BlockDecorCraftingTable extends BlockDecorDirected.WaterLoggable
public CraftingHistory history()
{ return history_; }
// todo: somehow hook into the container listeners for syncing all clients having that container open.
private void syncHistory(PlayerEntity player)
{
if((!with_assist) || (player.world.isRemote)) return;
@ -967,7 +1101,7 @@ public class BlockDecorCraftingTable extends BlockDecorDirected.WaterLoggable
final CompoundNBT nbt = new CompoundNBT();
nbt.put("history", hist_nbt);
nbt.putBoolean("hascollision", has_recipe_collision_);
Networking.PacketContainerSyncServerToClient.sendToPlayer(player, windowId, nbt);
Networking.PacketContainerSyncServerToClient.sendToListeners(player.world, this, nbt);
}
private void syncProperties(PlayerEntity player)
@ -995,6 +1129,9 @@ public class BlockDecorCraftingTable extends BlockDecorDirected.WaterLoggable
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 String ACTION_MOVE_ALL_STACKS = "move-stacks";
protected static final String ACTION_INCREASE_CRAFTING_STACKS = "inc-crafting-stacks";
protected static final String ACTION_DECREASE_CRAFTING_STACKS = "dec-crafting-stacks";
protected static final ResourceLocation BACKGROUND = new ResourceLocation(ModEngineersDecor.MODID, "textures/gui/treated_wood_crafting_table.png");
protected final PlayerEntity player;
protected final ArrayList<Button> buttons = new ArrayList<Button>();
@ -1134,29 +1271,74 @@ public class BlockDecorCraftingTable extends BlockDecorDirected.WaterLoggable
if(place_refab && (!with_assist_direct_history_refab)) on_history_item_placement(); // place after crafting -> confirmation first
return;
}
if((type == ClickType.QUICK_MOVE) && (slotId > 9) && (slot.getHasStack())) { // container slots 0..9 are crafting output and grid
if((type == ClickType.QUICK_MOVE) && (slotId > 0) && (slot.getHasStack())) { // container slots 0 is crafting output
if(with_assist) {
List<ItemStack> history = getContainer().history().current();
boolean palce_in_crafting_grid = (!history.isEmpty());
if(!palce_in_crafting_grid) {
for(int i = 0; i < 9; ++i) {
if(!(getContainer().getSlot(i).getStack().isEmpty())) {
palce_in_crafting_grid = true;
break;
boolean palce_in_crafting_grid = false;
if(slotId > 9) { // container slots 1..9 are crafting grid
palce_in_crafting_grid = (!history.isEmpty());
if(!palce_in_crafting_grid) {
for(int i = 0; i < 9; ++i) {
if(!(getContainer().getSlot(i).getStack().isEmpty())) {
palce_in_crafting_grid = true;
break;
}
}
}
}
if(palce_in_crafting_grid) {
// Explicit grid placement.
CompoundNBT nbt = new CompoundNBT();
nbt.putInt("containerslot", slotId);
if(ModAuxiliaries.isCtrlDown()) nbt.putBoolean("move-all", true);
action(ACTION_PLACE_SHIFTCLICKED_STACK, nbt);
return;
} else if(ModAuxiliaries.isCtrlDown()) {
// Move all same items from the inventory of the clicked slot
// (or the crafting grid) to the corresponding target inventory.
CompoundNBT nbt = new CompoundNBT();
nbt.putInt("containerslot", slotId);
action(ACTION_MOVE_ALL_STACKS, nbt);
return;
} else {
// Let the normal slot click handle that.
}
}
}
super.handleMouseClick(slot, slotId, mouseButton, type);
}
@Override
public boolean mouseScrolled(double mouseX, double mouseY, double wheel_inc)
{
final Slot resultSlot = this.getSlotUnderMouse();
if((!with_crafting_slot_mouse_scrolling) || (!(resultSlot instanceof CraftingResultSlot))) {
return this.func_212930_a(mouseX, mouseY).filter((evl) -> {
return evl.mouseScrolled(mouseX, mouseY, wheel_inc);
}).isPresent();
}
int count = resultSlot.getStack().getCount();
int limit = (ModAuxiliaries.isShiftDown() ? 2 : 1) * (ModAuxiliaries.isCtrlDown() ? 4 : 1);
if(wheel_inc > 0.1) {
if(count > 0) {
if((count < resultSlot.getStack().getMaxStackSize()) && (count < resultSlot.getSlotStackLimit())) {
CompoundNBT nbt = new CompoundNBT();
if(limit > 1) nbt.putInt("limit", limit);
action(ACTION_INCREASE_CRAFTING_STACKS, nbt);
}
} else if(!getContainer().history().current().isEmpty()) {
action(ACTION_PLACE_CURRENT_HISTORY_SEL);
}
} else if(wheel_inc < -0.1) {
if(count > 0) {
CompoundNBT nbt = new CompoundNBT();
if(limit > 1) nbt.putInt("limit", limit);
action(ACTION_DECREASE_CRAFTING_STACKS, nbt);
}
}
return true;
}
private void on_history_item_placement()
{
if((getContainer().history().current().isEmpty())) return;

View file

@ -25,6 +25,8 @@ import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraftforge.energy.CapabilityEnergy;
import net.minecraftforge.energy.IEnergyStorage;
import net.minecraftforge.common.capabilities.ICapabilityProvider;
import net.minecraftforge.common.util.LazyOptional;
import javax.annotation.Nullable;
@ -61,7 +63,7 @@ public class BlockDecorSolarPanel extends BlockDecor
// Tile entity
//--------------------------------------------------------------------------------------------------------------------
public static class BTileEntity extends TileEntity implements ITickableTileEntity
public static class BTileEntity extends TileEntity implements ITickableTileEntity, ICapabilityProvider, IEnergyStorage
{
public static final int DEFAULT_PEAK_POWER = 45;
public static final int TICK_INTERVAL = 8;
@ -93,6 +95,51 @@ public class BlockDecorSolarPanel extends BlockDecor
protected void writenbt(CompoundNBT nbt, boolean update_packet)
{ nbt.putInt("energy", accumulated_power_); }
// IEnergyStorage --------------------------------------------------------------------------
@Override
public boolean canExtract()
{ return true; }
@Override
public boolean canReceive()
{ return false; }
@Override
public int getMaxEnergyStored()
{ return max_power_storage_; }
@Override
public int getEnergyStored()
{ return accumulated_power_; }
@Override
public int extractEnergy(int maxExtract, boolean simulate)
{
int p = Math.min(accumulated_power_, maxExtract);
if(!simulate) accumulated_power_ -= p;
return p;
}
@Override
public int receiveEnergy(int maxReceive, boolean simulate)
{ return 0; }
// ICapabilityProvider ---------------------------------------------------------------------
protected LazyOptional<IEnergyStorage> energy_handler_ = LazyOptional.of(() -> (IEnergyStorage)this);
@Override
public <T> LazyOptional<T> getCapability(net.minecraftforge.common.capabilities.Capability<T> capability, @Nullable Direction facing)
{
if(!this.removed && (facing != null)) {
if(capability== CapabilityEnergy.ENERGY) {
return energy_handler_.cast();
}
}
return super.getCapability(capability, facing);
}
// TileEntity ------------------------------------------------------------------------------
@Override

View file

@ -192,6 +192,9 @@ public class BlockDecorTreeCutter extends BlockDecorDirectedHorizontal
--active_timer_;
}
boolean active = (active_timer_ > 0);
if(requires_power && !active) {
proc_time_elapsed_ = Math.max(0, proc_time_elapsed_ - 2*TICK_INTERVAL);
}
if(proc_time_elapsed_ >= cutting_time_needed) {
proc_time_elapsed_ = 0;
TreeCutting.chopTree(world, tree_state, tree_pos, 512, false);

View file

@ -5,8 +5,6 @@
* @license MIT (see https://opensource.org/licenses/MIT)
*
* General commonly used functionality.
*
* @TODO KEYBOARD INPUT
*/
package wile.engineersdecor.detail;
@ -26,6 +24,7 @@ import net.minecraft.util.math.AxisAlignedBB;
import net.minecraftforge.fml.ModList;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import org.apache.logging.log4j.Logger;
import org.lwjgl.glfw.GLFW;
import javax.annotation.Nullable;
import java.io.BufferedReader;
@ -40,6 +39,8 @@ import java.util.stream.Collectors;
public class ModAuxiliaries
{
public static final String MODID = ModEngineersDecor.MODID;
public static final Logger LOGGER = ModEngineersDecor.logger();
public static final ModEngineersDecor.ISidedProxy PROXY = ModEngineersDecor.proxy;
// -------------------------------------------------------------------------------------------------------------------
// Sideness, system/environment, tagging interfaces
@ -53,30 +54,44 @@ public class ModAuxiliaries
public static final boolean isDevelopmentMode()
{ return SharedConstants.developmentMode; }
@OnlyIn(Dist.CLIENT)
public static final boolean isShiftDown()
{
return (InputMappings.isKeyDown(PROXY.mc().mainWindow.getHandle(), GLFW.GLFW_KEY_LEFT_SHIFT) ||
InputMappings.isKeyDown(PROXY.mc().mainWindow.getHandle(), GLFW.GLFW_KEY_RIGHT_SHIFT));
}
@OnlyIn(Dist.CLIENT)
public static final boolean isCtrlDown()
{
return (InputMappings.isKeyDown(PROXY.mc().mainWindow.getHandle(), GLFW.GLFW_KEY_LEFT_CONTROL) ||
InputMappings.isKeyDown(PROXY.mc().mainWindow.getHandle(), GLFW.GLFW_KEY_RIGHT_CONTROL));
}
// -------------------------------------------------------------------------------------------------------------------
// Logging
// -------------------------------------------------------------------------------------------------------------------
public static final void logInfo(final String msg)
{ ModEngineersDecor.logger().info(msg); }
{ LOGGER.info(msg); }
public static final void logWarn(final String msg)
{ ModEngineersDecor.logger().warn(msg); }
{ LOGGER.warn(msg); }
public static final void logError(final String msg)
{ ModEngineersDecor.logger().error(msg); }
{ LOGGER.error(msg); }
// -------------------------------------------------------------------------------------------------------------------
// Localization, text formatting
// -------------------------------------------------------------------------------------------------------------------
/**
* Text localisation wrapper, implicitly prepends `ModEngineersDecor.MODID` to the
* Text localisation wrapper, implicitly prepends `MODID` to the
* translation keys. Forces formatting argument, nullable if no special formatting shall be applied..
*/
public static TranslationTextComponent localizable(String modtrkey, @Nullable TextFormatting color, Object... args)
{
TranslationTextComponent tr = new TranslationTextComponent(ModEngineersDecor.MODID+"."+modtrkey, args);
TranslationTextComponent tr = new TranslationTextComponent(MODID+"."+modtrkey, args);
if(color!=null) tr.getStyle().setColor(color);
return tr;
}
@ -85,7 +100,7 @@ public class ModAuxiliaries
{ return localizable(modtrkey, null); }
public static TranslationTextComponent localizable_block_key(String blocksubkey)
{ return new TranslationTextComponent("block."+ModEngineersDecor.MODID+"."+blocksubkey); }
{ return new TranslationTextComponent("block."+MODID+"."+blocksubkey); }
@OnlyIn(Dist.CLIENT)
public static String localize(String translationKey, Object... args)
@ -134,21 +149,11 @@ public class ModAuxiliaries
{
@OnlyIn(Dist.CLIENT)
public static boolean extendedTipCondition()
{
return (
InputMappings.isKeyDown(ModEngineersDecor.proxy.mc().mainWindow.getHandle(), GLFW.GLFW_KEY_LEFT_SHIFT) ||
InputMappings.isKeyDown(ModEngineersDecor.proxy.mc().mainWindow.getHandle(), GLFW.GLFW_KEY_RIGHT_SHIFT)
);
}
{ return isShiftDown(); }
@OnlyIn(Dist.CLIENT)
public static boolean helpCondition()
{
return extendedTipCondition() && (
InputMappings.isKeyDown(ModEngineersDecor.proxy.mc().mainWindow.getHandle(), GLFW.GLFW_KEY_LEFT_CONTROL) ||
InputMappings.isKeyDown(ModEngineersDecor.proxy.mc().mainWindow.getHandle(), GLFW.GLFW_KEY_RIGHT_CONTROL)
);
}
{ return isShiftDown() && isCtrlDown(); }
/**
* Adds an extended tooltip or help tooltip depending on the key states of CTRL and SHIFT.
@ -177,8 +182,8 @@ public class ModAuxiliaries
return true;
} else if(addAdvancedTooltipHints) {
String s = "";
if(tip_available) s += localize(ModEngineersDecor.MODID + ".tooltip.hint.extended") + (help_available ? " " : "");
if(help_available) s += localize(ModEngineersDecor.MODID + ".tooltip.hint.help");
if(tip_available) s += localize(MODID + ".tooltip.hint.extended") + (help_available ? " " : "");
if(help_available) s += localize(MODID + ".tooltip.hint.help");
tooltip.add(new StringTextComponent(s));
}
return false;
@ -252,7 +257,7 @@ public class ModAuxiliaries
{
try {
// Done during construction to have an exact version in case of a crash while registering.
String version = ModAuxiliaries.loadResourceText("/.gitversion").trim();
String version = ModAuxiliaries.loadResourceText("/.gitversion-" + MODID).trim();
logInfo(mod_name+((version.isEmpty())?(" (dev build)"):(" GIT id #"+version)) + ".");
} catch(Throwable e) {
// (void)e; well, then not. Priority is not to get unneeded crashes because of version logging.

View file

@ -143,6 +143,7 @@ public class ModConfig
public final ForgeConfigSpec.DoubleValue chair_mob_sitting_probability_percent;
public final ForgeConfigSpec.DoubleValue chair_mob_standup_probability_percent;
public final ForgeConfigSpec.BooleanValue with_crafting_quickmove_buttons;
public final ForgeConfigSpec.BooleanValue without_crafting_mouse_scrolling;
public final ForgeConfigSpec.IntValue pipevalve_max_flowrate;
public final ForgeConfigSpec.IntValue pipevalve_redstone_gain;
public final ForgeConfigSpec.IntValue block_breaker_power_consumption;
@ -389,6 +390,10 @@ public class ModConfig
.comment("Enables small quick-move arrows from/to player/block storage. " +
"Makes the UI a bit too busy, therefore disabled by default.")
.define("with_crafting_quickmove_buttons", false);
without_crafting_mouse_scrolling = builder
.translation(ModEngineersDecor.MODID + ".config.without_crafting_mouse_scrolling")
.comment("Disables increasing/decreasing the crafting grid items by scrolling over the crafting result slot.")
.define("without_crafting_mouse_scrolling", false);
pipevalve_max_flowrate = builder
.translation(ModEngineersDecor.MODID + ".config.pipevalve_max_flowrate")
.comment("Defines how many millibuckets can be transferred (per tick) through the valves. " +
@ -598,7 +603,7 @@ public class ModConfig
BlockDecorFurnace.BTileEntity.on_config(COMMON.furnace_smelting_speed_percent.get(), COMMON.furnace_fuel_efficiency_percent.get(), COMMON.furnace_boost_energy_consumption.get());
BlockDecorChair.on_config(COMMON.without_chair_sitting.get(), COMMON.without_mob_chair_sitting.get(), COMMON.chair_mob_sitting_probability_percent.get(), COMMON.chair_mob_standup_probability_percent.get());
BlockDecorLadder.on_config(COMMON.without_ladder_speed_boost.get());
BlockDecorCraftingTable.on_config(COMMON.without_crafting_table_history.get(), false, COMMON.with_crafting_quickmove_buttons.get());
BlockDecorCraftingTable.on_config(COMMON.without_crafting_table_history.get(), false, COMMON.with_crafting_quickmove_buttons.get(), COMMON.without_crafting_mouse_scrolling.get());
BlockDecorPipeValve.on_config(COMMON.pipevalve_max_flowrate.get(), COMMON.pipevalve_redstone_gain.get());
BlockDecorFurnaceElectrical.BTileEntity.on_config(COMMON.e_furnace_speed_percent.get(), COMMON.e_furnace_power_consumption.get(), COMMON.e_furnace_automatic_pulling.get());
BlockDecorSolarPanel.BTileEntity.on_config(COMMON.small_solar_panel_peak_production.get());

View file

@ -204,16 +204,14 @@ public class Networking
DEFAULT_CHANNEL.sendTo(new PacketContainerSyncServerToClient(container.windowId, nbt), ((ServerPlayerEntity)player).connection.netManager, NetworkDirection.PLAY_TO_CLIENT);
}
// Container listners are private, and add/remove listener overriding seems not too nice, as
// removeListner is client only???
//public static <C extends Container & INetworkSynchronisableContainer> void sendToListeners(C container, CompoundNBT nbt)
//{
// for(IContainerListener listener: container.getListeners()) {
// if(!(listener instanceof ServerPlayerEntity)) continue;
// DEFAULT_CHANNEL.sendTo(new PacketContainerSyncServerToClient(container.windowId, nbt), ((ServerPlayerEntity)listener).connection.netManager, NetworkDirection.PLAY_TO_CLIENT);
// }
//}
public static <C extends Container & INetworkSynchronisableContainer>
void sendToListeners(World world, C container, CompoundNBT nbt)
{
for(PlayerEntity player: world.getPlayers()) {
if(player.openContainer.windowId != container.windowId) continue;
sendToPlayer(player, container.windowId, nbt);
}
}
public PacketContainerSyncServerToClient()
{}

View file

@ -8,12 +8,12 @@
*/
package wile.engineersdecor.eapi.jei;
import mezz.jei.api.constants.VanillaRecipeCategoryUid;
import mezz.jei.api.registration.IRecipeTransferRegistration;
import wile.engineersdecor.ModEngineersDecor;
import wile.engineersdecor.blocks.BlockDecorCraftingTable;
import wile.engineersdecor.detail.ModConfig;
import wile.engineersdecor.ModContent;
import mezz.jei.api.constants.VanillaRecipeCategoryUid;
import mezz.jei.api.registration.IRecipeTransferRegistration;
import mezz.jei.api.constants.VanillaTypes;
import mezz.jei.api.runtime.IJeiRuntime;
import net.minecraft.block.Block;

View file

@ -101,8 +101,8 @@
"block.engineersdecor.clinker_brick_stairs.help": "§6Looks slightly darker and more color intensive than the vanilla brick block.",
"block.engineersdecor.clinker_brick_stained_stairs": "Stained Clinker Brick Stairs",
"block.engineersdecor.clinker_brick_stained_stairs.help": "§6Looks slightly darker and more color intensive than the vanilla brick block. Has more visible traces of grime or stain.",
"block.engineersdecor.slag_brick_stairs": "Clinker Brick Stairs",
"block.engineersdecor.slag_brick_stairs.help": "§6Looks slightly darker and more color intensive than the vanilla brick block.",
"block.engineersdecor.slag_brick_stairs": "Slag Brick Stairs",
"block.engineersdecor.slag_brick_stairs.help": "§6Gray-brown brick stairs.",
"block.engineersdecor.rebar_concrete_stairs": "Rebar Concrete Stairs",
"block.engineersdecor.rebar_concrete_stairs.help": "§6Steel reinforced concrete stairs.§r Expensive but Creeper-proof like obsidian.",
"block.engineersdecor.rebar_concrete_tile_stairs": "Rebar Concrete Tile Stairs",
@ -134,7 +134,7 @@
"block.engineersdecor.treated_wood_stool": "Treated Wood Stool",
"block.engineersdecor.treated_wood_stool.help": "§6Robust Wood Stool.§r Indoor and outdoor use.",
"block.engineersdecor.treated_wood_crafting_table": "Treated Wood Crafting Table",
"block.engineersdecor.treated_wood_crafting_table.help": "§6Robust and weather-proof.§r Eight storage slots, keeps inventory, no vanilla recipe book.\n Click up/down arrow buttons for crafting history selection, output slot for item placement, X-button to clear crafting grid and history. Shift-click stack: player-to-storage stack transfer when crafting grid empty, otherwise player-to-grid stack transfer. Automatically distributes the clicked stack.",
"block.engineersdecor.treated_wood_crafting_table.help": "§6Robust and weather-proof.§r Eight storage slots, keeps inventory, no vanilla recipe book.\n Click up/down arrow buttons for crafting history selection, output slot for item placement, X-button to clear crafting grid and history. Shift-click stack: player-to-storage stack transfer when crafting grid empty, otherwise player-to-grid stack transfer. Automatically distributes the clicked stack. Shift-Ctrl-click stack: Move all same stacks. Mouse wheel over crafting slot: Increase/decrease crafting grid items.",
"block.engineersdecor.treated_wood_side_table": "Treated Wood Side Table",
"block.engineersdecor.treated_wood_side_table.help": "§6Needed after the work's done.",
"block.engineersdecor.iron_inset_light": "Inset Light",

View file

@ -48,4 +48,8 @@ tasks["create-half-slab-assets"] = function() {
for(var i in block_data) halfslab_assets.create(block_data[i]);
}
tasks["lang-json-fixes"] = function() {
libtask114.stdtasks["lang-json-fixes"]();
};
libtask.run(tasks, sys.args);