Packing Up, Part II

- Toolboxes keep nbt on pickup
- Toolbox radial menu supports mouse wheel
- Added Dispose-all buttons
- Synced slots detach when moving stacks back into the toolbox
- Fixed missing data on client on login
This commit is contained in:
simibubi 2021-09-16 20:14:38 +02:00
parent 896ab01644
commit 4dc3629f5d
30 changed files with 554 additions and 113 deletions

View file

@ -427,19 +427,19 @@ a3a11524cd3515fc01d905767b4b7ea782adaf03 assets/create/blockstates/yellow_seat.j
7f39521b211441f5c3e06d60c5978cebe16cacfb assets/create/blockstates/zinc_block.json
b7181bcd8182b2f17088e5aa881f374c9c65470c assets/create/blockstates/zinc_ore.json
337227971382d97fbaa69170e0b6bcc621bdc494 assets/create/lang/en_ud.json
307e88153d5288781e906e566f73ccd59fbcd945 assets/create/lang/en_us.json
5268c9117961dabecdae27b3190d02a8c0ea1077 assets/create/lang/unfinished/de_de.json
2e2002aefd045f492b7232884bd63c7a68d41480 assets/create/lang/unfinished/es_es.json
78836cc1527a95e7e40bc7f50faa95f8cdf5cd9d assets/create/lang/unfinished/fr_fr.json
b83a58ff24f2eca59c628c9a49e286d2feeece35 assets/create/lang/unfinished/it_it.json
5e3e878fe3fd58ba7911877609bf4f0be5a7c71d assets/create/lang/unfinished/ja_jp.json
ff6560eef8744197ab55334392df0a91898d80b2 assets/create/lang/unfinished/ko_kr.json
d0637cc0fa640b328dcdbaf74ae6967a7e15b980 assets/create/lang/unfinished/nl_nl.json
a23c910164b9d295f7c1f5a5e4d9a08094f1f00c assets/create/lang/unfinished/pl_pl.json
bb56417e9607b45350f329f865d2caa7038ebcec assets/create/lang/unfinished/pt_br.json
b643778faf6706b85ad567066de7176272df73d9 assets/create/lang/unfinished/ru_ru.json
45f4a765689a28da8fa267c2845fcf59135c6034 assets/create/lang/unfinished/zh_cn.json
3ac73d1173b450a4fa4eb5622b903cf4b52fbd0b assets/create/lang/unfinished/zh_tw.json
4da832d10fb5bacf10c564bc4f828cdc6592d56c assets/create/lang/en_us.json
31064dd15c813975de6dbe771a94b2fff87d7c84 assets/create/lang/unfinished/de_de.json
785119499208f5a35c4f77a1d189ac78394a133a assets/create/lang/unfinished/es_es.json
7fb3d9f560b08e7d7e4b0e51f7f789ac2eeb3af8 assets/create/lang/unfinished/fr_fr.json
e418df14fbcd15e4b87024dbe4bda97ef1544f47 assets/create/lang/unfinished/it_it.json
95d0baec2d79b914b3aecbfdc6dde970722c552c assets/create/lang/unfinished/ja_jp.json
4fa09f736a742db2d843b0880edc5d607f28d80e assets/create/lang/unfinished/ko_kr.json
757ac709807bdb1322da17f27e0853de552638d1 assets/create/lang/unfinished/nl_nl.json
9b5bc245e4795d86eb27fa35670cd4f261c07576 assets/create/lang/unfinished/pl_pl.json
aaa1e873003b446858fc8bae839db4d0b293472e assets/create/lang/unfinished/pt_br.json
9745c2d6a2e8fc50648399785eb10cc8b125bd1d assets/create/lang/unfinished/ru_ru.json
b04454180b5b4af323009e33c3ba5b163b4e63c1 assets/create/lang/unfinished/zh_cn.json
ce4759ba4aa4ec9e0c24242796ac04b43f4b9a04 assets/create/lang/unfinished/zh_tw.json
487a511a01b2a4531fb672f917922312db78f958 assets/create/models/block/acacia_window.json
b48060cba1a382f373a05bf0039054053eccf076 assets/create/models/block/acacia_window_pane_noside.json
3066db1bf03cffa1a9c7fbacf47ae586632f4eb3 assets/create/models/block/acacia_window_pane_noside_alt.json

View file

@ -795,6 +795,8 @@
"create.toolbox.unequip": "Unequip: %1$s",
"create.toolbox.outOfRange": "Toolbox of held item not in Range",
"create.toolbox.detach": "Stop tracking and keep item",
"create.toolbox.depositAll": "Return items to nearby Toolboxes",
"create.toolbox.depositBox": "Return items to Toolbox",
"create.gui.symmetryWand.mirrorType": "Mirror",
"create.gui.symmetryWand.orientation": "Orientation",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 1138",
"_": "Missing Localizations: 1140",
"_": "->------------------------] Game Elements [------------------------<-",
@ -796,6 +796,8 @@
"create.toolbox.unequip": "UNLOCALIZED: Unequip: %1$s",
"create.toolbox.outOfRange": "UNLOCALIZED: Toolbox of held item not in Range",
"create.toolbox.detach": "UNLOCALIZED: Stop tracking and keep item",
"create.toolbox.depositAll": "UNLOCALIZED: Return items to nearby Toolboxes",
"create.toolbox.depositBox": "UNLOCALIZED: Return items to Toolbox",
"create.gui.symmetryWand.mirrorType": "Spiegeln",
"create.gui.symmetryWand.orientation": "Orientierung",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 4",
"_": "Missing Localizations: 6",
"_": "->------------------------] Game Elements [------------------------<-",
@ -796,6 +796,8 @@
"create.toolbox.unequip": "UNLOCALIZED: Unequip: %1$s",
"create.toolbox.outOfRange": "UNLOCALIZED: Toolbox of held item not in Range",
"create.toolbox.detach": "UNLOCALIZED: Stop tracking and keep item",
"create.toolbox.depositAll": "UNLOCALIZED: Return items to nearby Toolboxes",
"create.toolbox.depositBox": "UNLOCALIZED: Return items to Toolbox",
"create.gui.symmetryWand.mirrorType": "Espejado",
"create.gui.symmetryWand.orientation": "Orientación",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 1390",
"_": "Missing Localizations: 1392",
"_": "->------------------------] Game Elements [------------------------<-",
@ -796,6 +796,8 @@
"create.toolbox.unequip": "UNLOCALIZED: Unequip: %1$s",
"create.toolbox.outOfRange": "UNLOCALIZED: Toolbox of held item not in Range",
"create.toolbox.detach": "UNLOCALIZED: Stop tracking and keep item",
"create.toolbox.depositAll": "UNLOCALIZED: Return items to nearby Toolboxes",
"create.toolbox.depositBox": "UNLOCALIZED: Return items to Toolbox",
"create.gui.symmetryWand.mirrorType": "Mirroir",
"create.gui.symmetryWand.orientation": "Orientation",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 918",
"_": "Missing Localizations: 920",
"_": "->------------------------] Game Elements [------------------------<-",
@ -796,6 +796,8 @@
"create.toolbox.unequip": "UNLOCALIZED: Unequip: %1$s",
"create.toolbox.outOfRange": "UNLOCALIZED: Toolbox of held item not in Range",
"create.toolbox.detach": "UNLOCALIZED: Stop tracking and keep item",
"create.toolbox.depositAll": "UNLOCALIZED: Return items to nearby Toolboxes",
"create.toolbox.depositBox": "UNLOCALIZED: Return items to Toolbox",
"create.gui.symmetryWand.mirrorType": "Specchio",
"create.gui.symmetryWand.orientation": "Orientamento",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 13",
"_": "Missing Localizations: 15",
"_": "->------------------------] Game Elements [------------------------<-",
@ -796,6 +796,8 @@
"create.toolbox.unequip": "UNLOCALIZED: Unequip: %1$s",
"create.toolbox.outOfRange": "UNLOCALIZED: Toolbox of held item not in Range",
"create.toolbox.detach": "UNLOCALIZED: Stop tracking and keep item",
"create.toolbox.depositAll": "UNLOCALIZED: Return items to nearby Toolboxes",
"create.toolbox.depositBox": "UNLOCALIZED: Return items to Toolbox",
"create.gui.symmetryWand.mirrorType": "ミラーの種類",
"create.gui.symmetryWand.orientation": "方向",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 28",
"_": "Missing Localizations: 30",
"_": "->------------------------] Game Elements [------------------------<-",
@ -796,6 +796,8 @@
"create.toolbox.unequip": "UNLOCALIZED: Unequip: %1$s",
"create.toolbox.outOfRange": "UNLOCALIZED: Toolbox of held item not in Range",
"create.toolbox.detach": "UNLOCALIZED: Stop tracking and keep item",
"create.toolbox.depositAll": "UNLOCALIZED: Return items to nearby Toolboxes",
"create.toolbox.depositBox": "UNLOCALIZED: Return items to Toolbox",
"create.gui.symmetryWand.mirrorType": "거울의 형태",
"create.gui.symmetryWand.orientation": "거울의 방향",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 1770",
"_": "Missing Localizations: 1772",
"_": "->------------------------] Game Elements [------------------------<-",
@ -796,6 +796,8 @@
"create.toolbox.unequip": "UNLOCALIZED: Unequip: %1$s",
"create.toolbox.outOfRange": "UNLOCALIZED: Toolbox of held item not in Range",
"create.toolbox.detach": "UNLOCALIZED: Stop tracking and keep item",
"create.toolbox.depositAll": "UNLOCALIZED: Return items to nearby Toolboxes",
"create.toolbox.depositBox": "UNLOCALIZED: Return items to Toolbox",
"create.gui.symmetryWand.mirrorType": "Spiegelen",
"create.gui.symmetryWand.orientation": "Orientatie",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 260",
"_": "Missing Localizations: 262",
"_": "->------------------------] Game Elements [------------------------<-",
@ -796,6 +796,8 @@
"create.toolbox.unequip": "UNLOCALIZED: Unequip: %1$s",
"create.toolbox.outOfRange": "UNLOCALIZED: Toolbox of held item not in Range",
"create.toolbox.detach": "UNLOCALIZED: Stop tracking and keep item",
"create.toolbox.depositAll": "UNLOCALIZED: Return items to nearby Toolboxes",
"create.toolbox.depositBox": "UNLOCALIZED: Return items to Toolbox",
"create.gui.symmetryWand.mirrorType": "Odbicie lustrzane",
"create.gui.symmetryWand.orientation": "Orientacja",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 1811",
"_": "Missing Localizations: 1813",
"_": "->------------------------] Game Elements [------------------------<-",
@ -796,6 +796,8 @@
"create.toolbox.unequip": "UNLOCALIZED: Unequip: %1$s",
"create.toolbox.outOfRange": "UNLOCALIZED: Toolbox of held item not in Range",
"create.toolbox.detach": "UNLOCALIZED: Stop tracking and keep item",
"create.toolbox.depositAll": "UNLOCALIZED: Return items to nearby Toolboxes",
"create.toolbox.depositBox": "UNLOCALIZED: Return items to Toolbox",
"create.gui.symmetryWand.mirrorType": "Espelhar",
"create.gui.symmetryWand.orientation": "Orientação",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 9",
"_": "Missing Localizations: 11",
"_": "->------------------------] Game Elements [------------------------<-",
@ -796,6 +796,8 @@
"create.toolbox.unequip": "UNLOCALIZED: Unequip: %1$s",
"create.toolbox.outOfRange": "UNLOCALIZED: Toolbox of held item not in Range",
"create.toolbox.detach": "UNLOCALIZED: Stop tracking and keep item",
"create.toolbox.depositAll": "UNLOCALIZED: Return items to nearby Toolboxes",
"create.toolbox.depositBox": "UNLOCALIZED: Return items to Toolbox",
"create.gui.symmetryWand.mirrorType": "Зеркало",
"create.gui.symmetryWand.orientation": "Ориентация",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 8",
"_": "Missing Localizations: 10",
"_": "->------------------------] Game Elements [------------------------<-",
@ -796,6 +796,8 @@
"create.toolbox.unequip": "UNLOCALIZED: Unequip: %1$s",
"create.toolbox.outOfRange": "UNLOCALIZED: Toolbox of held item not in Range",
"create.toolbox.detach": "UNLOCALIZED: Stop tracking and keep item",
"create.toolbox.depositAll": "UNLOCALIZED: Return items to nearby Toolboxes",
"create.toolbox.depositBox": "UNLOCALIZED: Return items to Toolbox",
"create.gui.symmetryWand.mirrorType": "镜子类型",
"create.gui.symmetryWand.orientation": "方向",

View file

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 23",
"_": "Missing Localizations: 25",
"_": "->------------------------] Game Elements [------------------------<-",
@ -796,6 +796,8 @@
"create.toolbox.unequip": "UNLOCALIZED: Unequip: %1$s",
"create.toolbox.outOfRange": "UNLOCALIZED: Toolbox of held item not in Range",
"create.toolbox.detach": "UNLOCALIZED: Stop tracking and keep item",
"create.toolbox.depositAll": "UNLOCALIZED: Return items to nearby Toolboxes",
"create.toolbox.depositBox": "UNLOCALIZED: Return items to Toolbox",
"create.gui.symmetryWand.mirrorType": "鏡子類型",
"create.gui.symmetryWand.orientation": "方向",

View file

@ -33,10 +33,13 @@ public class RadialToolboxMenu extends AbstractSimiScreen {
private State state;
private int ticksOpen;
private int hoveredSlot;
private boolean scrollMode;
private int scrollSlot = 0;
private List<ToolboxTileEntity> toolboxes;
private ToolboxTileEntity selectedBox;
final int UNEQUIP = -5;
private static final int DEPOSIT = -7;
private static final int UNEQUIP = -5;
public RadialToolboxMenu(List<ToolboxTileEntity> toolboxes, State state) {
this.toolboxes = toolboxes;
@ -47,6 +50,10 @@ public class RadialToolboxMenu extends AbstractSimiScreen {
selectedBox = toolboxes.get(0);
}
public void prevSlot(int slot) {
scrollSlot = slot;
}
@Override
protected void renderWindow(MatrixStack ms, int mouseX, int mouseY, float partialTicks) {
float fade = MathHelper.clamp((ticksOpen + AnimationTickHolder.getPartialTicks()) / 10f, 1 / 512f, 1);
@ -57,11 +64,13 @@ public class RadialToolboxMenu extends AbstractSimiScreen {
float hoveredY = mouseY - window.getGuiScaledHeight() / 2;
float distance = hoveredX * hoveredX + hoveredY * hoveredY;
if (distance > 25 && distance < 20000)
if (distance > 25 && distance < 10000)
hoveredSlot =
(MathHelper.floor((AngleHelper.deg(MathHelper.atan2(hoveredY, hoveredX)) + 360 + 180 - 22.5f)) % 360)
/ 45;
boolean renderCenterSlot = state == State.SELECT_ITEM_UNEQUIP;
if (scrollMode && distance > 150)
scrollMode = false;
if (renderCenterSlot && distance <= 150)
hoveredSlot = UNEQUIP;
@ -86,7 +95,7 @@ public class RadialToolboxMenu extends AbstractSimiScreen {
ms.translate(-0.5, 0.5, 0);
AllIcons.I_DISABLE.draw(ms, this, -9, -9);
ms.translate(0.5, -0.5, 0);
if (hoveredSlot == UNEQUIP) {
if (!scrollMode && hoveredSlot == UNEQUIP) {
AllGuiTextures.TOOLBELT_SLOT_HIGHLIGHT.draw(ms, this, -13, -13);
tip = Lang.translate("toolbox.detach")
.withStyle(TextFormatting.GOLD);
@ -94,6 +103,23 @@ public class RadialToolboxMenu extends AbstractSimiScreen {
ms.popPose();
} else {
if (hoveredX > 60 && hoveredX < 100 && hoveredY > -20 && hoveredY < 20)
hoveredSlot = DEPOSIT;
ms.pushPose();
ms.translate(80 + (-5 * (1 - fade) * (1 - fade)), 0, 0);
AllGuiTextures.TOOLBELT_SLOT.draw(ms, this, -12, -12);
ms.translate(-0.5, 0.5, 0);
AllIcons.I_TOOLBOX.draw(ms, this, -9, -9);
ms.translate(0.5, -0.5, 0);
if (!scrollMode && hoveredSlot == DEPOSIT) {
AllGuiTextures.TOOLBELT_SLOT_HIGHLIGHT.draw(ms, this, -13, -13);
tip = Lang.translate(state == State.SELECT_BOX ? "toolbox.depositAll" : "toolbox.depositBox")
.withStyle(TextFormatting.GOLD);
}
ms.popPose();
for (int slot = 0; slot < 8; slot++) {
ms.pushPose();
MatrixTransformStack.of(ms)
@ -116,7 +142,7 @@ public class RadialToolboxMenu extends AbstractSimiScreen {
.at(3, 3)
.render(ms);
if (slot == hoveredSlot && !empty) {
if (slot == (scrollMode ? scrollSlot : hoveredSlot) && !empty) {
AllGuiTextures.TOOLBELT_SLOT_HIGHLIGHT.draw(ms, this, -1, -1);
tip = stackInSlot.getHoverName();
}
@ -131,7 +157,7 @@ public class RadialToolboxMenu extends AbstractSimiScreen {
.at(3, 3)
.render(ms);
if (slot == hoveredSlot) {
if (slot == (scrollMode ? scrollSlot : hoveredSlot)) {
AllGuiTextures.TOOLBELT_SLOT_HIGHLIGHT.draw(ms, this, -1, -1);
tip = toolboxes.get(slot)
.getDisplayName();
@ -147,8 +173,8 @@ public class RadialToolboxMenu extends AbstractSimiScreen {
if (renderCenterSlot) {
ms.pushPose();
AllGuiTextures.TOOLBELT_SLOT.draw(ms, this, -12, -12);
AllIcons.I_TRASH.draw(ms, this, -9, -9);
if (UNEQUIP == hoveredSlot) {
(scrollMode ? AllIcons.I_REFRESH : AllIcons.I_FLIP).draw(ms, this, -9, -9);
if (!scrollMode && UNEQUIP == hoveredSlot) {
AllGuiTextures.TOOLBELT_SLOT_HIGHLIGHT.draw(ms, this, -13, -13);
tip = Lang.translate("toolbox.unequip", minecraft.player.getMainHandItem()
.getHoverName())
@ -172,7 +198,6 @@ public class RadialToolboxMenu extends AbstractSimiScreen {
int k1 = 16777215;
int k = i1 << 24 & -16777216;
int l = font.width(tip);
// this.drawBackdrop(ms, font, -4, l, 16777215 | k);
font.draw(ms, tip, (float) (-l / 2), -4.0F, k1 | k);
RenderSystem.disableBlend();
ms.popPose();
@ -197,46 +222,103 @@ public class RadialToolboxMenu extends AbstractSimiScreen {
public void removed() {
super.removed();
int selected = (scrollMode ? scrollSlot : hoveredSlot);
if (selected == DEPOSIT) {
if (state == State.DETACH)
return;
else if (state == State.SELECT_BOX)
toolboxes.forEach(te -> AllPackets.channel.sendToServer(new ToolboxDisposeAllPacket(te.getBlockPos())));
else
AllPackets.channel.sendToServer(new ToolboxDisposeAllPacket(selectedBox.getBlockPos()));
return;
}
if (state == State.SELECT_BOX)
return;
if (state == State.DETACH) {
if (hoveredSlot == UNEQUIP)
if (selected == UNEQUIP)
AllPackets.channel.sendToServer(
new ToolboxEquipPacket(null, hoveredSlot, Minecraft.getInstance().player.inventory.selected));
new ToolboxEquipPacket(null, selected, Minecraft.getInstance().player.inventory.selected));
return;
}
if (hoveredSlot == UNEQUIP)
AllPackets.channel.sendToServer(new ToolboxEquipPacket(selectedBox.getBlockPos(), hoveredSlot,
if (selected == UNEQUIP)
AllPackets.channel.sendToServer(new ToolboxEquipPacket(selectedBox.getBlockPos(), selected,
Minecraft.getInstance().player.inventory.selected));
if (hoveredSlot < 0)
if (selected < 0)
return;
ToolboxInventory inv = selectedBox.inventory;
ItemStack stackInSlot = inv.filters.get(hoveredSlot);
ItemStack stackInSlot = inv.filters.get(selected);
if (stackInSlot.isEmpty())
return;
if (inv.getStackInSlot(hoveredSlot * ToolboxInventory.STACKS_PER_COMPARTMENT)
if (inv.getStackInSlot(selected * ToolboxInventory.STACKS_PER_COMPARTMENT)
.isEmpty())
return;
AllPackets.channel.sendToServer(new ToolboxEquipPacket(selectedBox.getBlockPos(), hoveredSlot,
AllPackets.channel.sendToServer(new ToolboxEquipPacket(selectedBox.getBlockPos(), selected,
Minecraft.getInstance().player.inventory.selected));
}
@Override
public boolean mouseClicked(double x, double y, int button) {
if (state == State.SELECT_BOX && hoveredSlot >= 0 && hoveredSlot < toolboxes.size()) {
state = State.SELECT_ITEM;
selectedBox = toolboxes.get(hoveredSlot);
public boolean mouseScrolled(double mouseX, double mouseY, double delta) {
MainWindow window = getMinecraft().getWindow();
double hoveredX = mouseX - window.getGuiScaledWidth() / 2;
double hoveredY = mouseY - window.getGuiScaledHeight() / 2;
double distance = hoveredX * hoveredX + hoveredY * hoveredY;
if (distance <= 150) {
scrollMode = true;
scrollSlot = (((int) (scrollSlot - delta)) + 8) % 8;
for (int i = 0; i < 10; i++) {
if (state == State.SELECT_ITEM || state == State.SELECT_ITEM_UNEQUIP) {
ToolboxInventory inv = selectedBox.inventory;
ItemStack stackInSlot = inv.filters.get(scrollSlot);
if (!stackInSlot.isEmpty()
&& !inv.getStackInSlot(scrollSlot * ToolboxInventory.STACKS_PER_COMPARTMENT)
.isEmpty())
break;
}
if (state == State.SELECT_BOX)
if (scrollSlot < toolboxes.size())
break;
if (state == State.DETACH)
break;
scrollSlot -= MathHelper.sign(delta);
scrollSlot = (scrollSlot + 8) % 8;
}
return true;
}
if (state == State.SELECT_ITEM || state == State.SELECT_ITEM_UNEQUIP) {
if (hoveredSlot == UNEQUIP || hoveredSlot >= 0) {
return super.mouseScrolled(mouseX, mouseY, delta);
}
@Override
public boolean mouseClicked(double x, double y, int button) {
int selected = (scrollMode ? scrollSlot : hoveredSlot);
if (selected == DEPOSIT) {
onClose();
ToolboxHandlerClient.COOLDOWN = 10;
ToolboxHandlerClient.COOLDOWN = 2;
return true;
}
if (state == State.SELECT_BOX && selected >= 0 && selected < toolboxes.size()) {
state = State.SELECT_ITEM;
selectedBox = toolboxes.get(selected);
return true;
}
if (state == State.DETACH || state == State.SELECT_ITEM || state == State.SELECT_ITEM_UNEQUIP) {
if (selected == UNEQUIP || selected >= 0) {
onClose();
ToolboxHandlerClient.COOLDOWN = 2;
return true;
}
}

View file

@ -2,6 +2,9 @@ package com.simibubi.create.content.curiosities.toolbox;
import static net.minecraft.state.properties.BlockStateProperties.WATERLOGGED;
import java.util.Optional;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllShapes;
import com.simibubi.create.AllTileEntities;
import com.simibubi.create.foundation.block.ITE;
@ -17,6 +20,7 @@ import net.minecraft.fluid.FluidState;
import net.minecraft.fluid.Fluids;
import net.minecraft.item.BlockItemUseContext;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.state.StateContainer.Builder;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.ActionResultType;
@ -26,6 +30,7 @@ import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.util.math.shapes.ISelectionContext;
import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.IWorld;
import net.minecraft.world.World;
@ -66,19 +71,44 @@ public class ToolboxBlock extends HorizontalBlock implements IWaterLoggable, ITE
});
}
@Override
public void onRemove(BlockState state, World world, BlockPos pos, BlockState newState, boolean moving) {
if (state.hasTileEntity() && (!state.is(newState.getBlock()) || !newState.hasTileEntity()))
world.removeBlockEntity(pos);
}
@Override
public void attack(BlockState state, World world, BlockPos pos, PlayerEntity player) {
if (player instanceof FakePlayer)
return;
if (world.isClientSide)
return;
withTileEntityDo(world, pos, ToolboxTileEntity::unequipTracked);
if (world instanceof ServerWorld) {
for (ItemStack itemStack : Block.getDrops(state, (ServerWorld) world, pos, world.getBlockEntity(pos)))
player.inventory.placeItemBackInInventory(world, itemStack);
ItemStack cloneItemStack = getCloneItemStack(world, pos, state);
world.destroyBlock(pos, false);
if (world.getBlockState(pos) != state)
player.inventory.placeItemBackInInventory(world, cloneItemStack);
}
}
@Override
public ItemStack getCloneItemStack(IBlockReader world, BlockPos pos, BlockState state) {
ItemStack item = AllBlocks.TOOLBOX.asStack();
Optional<ToolboxTileEntity> tileEntityOptional = getTileEntityOptional(world, pos);
CompoundNBT tag = item.getOrCreateTag();
CompoundNBT inv = tileEntityOptional.map(tb -> tb.inventory.serializeNBT())
.orElse(new CompoundNBT());
tag.put("Inventory", inv);
ITextComponent customName = tileEntityOptional.map(ToolboxTileEntity::getCustomName)
.orElse(null);
if (customName != null)
item.setHoverName(customName);
return item;
}
@Override
public BlockState updateShape(BlockState state, Direction direction, BlockState neighbourState, IWorld world,
BlockPos pos, BlockPos neighbourPos) {

View file

@ -17,7 +17,6 @@ import net.minecraft.nbt.CompoundNBT;
import net.minecraft.network.PacketBuffer;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.BlockPos;
import net.minecraftforge.items.ItemHandlerHelper;
import net.minecraftforge.items.SlotItemHandler;
public class ToolboxContainer extends ContainerBase<ToolboxTileEntity> {
@ -84,15 +83,12 @@ public class ToolboxContainer extends ContainerBase<ToolboxTileEntity> {
ItemStack carried = playerInv.getCarried();
if (type == ClickType.PICKUP && !carried.isEmpty() && !itemInClickedSlot.isEmpty()
&& ItemHandlerHelper.canItemStacksStack(itemInClickedSlot, carried)) {
&& ToolboxInventory.canItemsShareCompartment(itemInClickedSlot, carried)) {
int subIndex = index % STACKS_PER_COMPARTMENT;
if (subIndex != STACKS_PER_COMPARTMENT - 1)
return clicked(index - subIndex + STACKS_PER_COMPARTMENT - 1, flags, type, player);
}
if (type == ClickType.PICKUP && !carried.isEmpty() && itemInClickedSlot.isEmpty())
contentHolder.inventory.filters.set(index / STACKS_PER_COMPARTMENT, carried);
if (type == ClickType.PICKUP && carried.isEmpty() && itemInClickedSlot.isEmpty())
if (!player.level.isClientSide) {
contentHolder.inventory.filters.set(index / STACKS_PER_COMPARTMENT, ItemStack.EMPTY);

View file

@ -0,0 +1,81 @@
package com.simibubi.create.content.curiosities.toolbox;
import java.util.function.Supplier;
import org.apache.commons.lang3.mutable.MutableBoolean;
import com.simibubi.create.foundation.networking.SimplePacketBase;
import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.nbt.NBTUtil;
import net.minecraft.network.PacketBuffer;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.fml.network.NetworkEvent.Context;
import net.minecraftforge.items.ItemHandlerHelper;
public class ToolboxDisposeAllPacket extends SimplePacketBase {
private BlockPos toolboxPos;
public ToolboxDisposeAllPacket(BlockPos toolboxPos) {
this.toolboxPos = toolboxPos;
}
public ToolboxDisposeAllPacket(PacketBuffer buffer) {
toolboxPos = buffer.readBlockPos();
}
@Override
public void write(PacketBuffer buffer) {
buffer.writeBlockPos(toolboxPos);
}
@Override
public void handle(Supplier<Context> context) {
Context ctx = context.get();
ctx.enqueueWork(() -> {
ServerPlayerEntity player = ctx.getSender();
World world = player.level;
TileEntity blockEntity = world.getBlockEntity(toolboxPos);
double maxRange = ToolboxHandler.getMaxRange(player);
if (player.distanceToSqr(toolboxPos.getX() + 0.5, toolboxPos.getY(), toolboxPos.getZ() + 0.5) > maxRange
* maxRange)
return;
if (!(blockEntity instanceof ToolboxTileEntity))
return;
ToolboxTileEntity toolbox = (ToolboxTileEntity) blockEntity;
CompoundNBT compound = player.getPersistentData()
.getCompound("CreateToolboxData");
MutableBoolean sendData = new MutableBoolean(false);
toolbox.inventory.inLimitedMode(inventory -> {
for (int i = 0; i < 36; i++) {
String key = String.valueOf(i);
if (compound.contains(key) && NBTUtil.readBlockPos(compound.getCompound(key)
.getCompound("Pos"))
.equals(toolboxPos)) {
ToolboxHandler.unequip(player, i, true);
sendData.setTrue();
}
ItemStack itemStack = player.inventory.getItem(i);
ItemStack remainder = ItemHandlerHelper.insertItemStacked(toolbox.inventory, itemStack, false);
if (remainder.getCount() != itemStack.getCount())
player.inventory.setItem(i, remainder);
}
});
if (sendData.booleanValue())
ToolboxHandler.syncData(player);
});
ctx.setPacketHandled(true);
}
}

View file

@ -2,8 +2,6 @@ package com.simibubi.create.content.curiosities.toolbox;
import java.util.function.Supplier;
import com.simibubi.create.foundation.networking.AllPackets;
import com.simibubi.create.foundation.networking.ISyncPersistentData;
import com.simibubi.create.foundation.networking.SimplePacketBase;
import net.minecraft.entity.player.ServerPlayerEntity;
@ -15,7 +13,6 @@ import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.fml.network.NetworkEvent.Context;
import net.minecraftforge.fml.network.PacketDistributor;
import net.minecraftforge.items.ItemHandlerHelper;
public class ToolboxEquipPacket extends SimplePacketBase {
@ -54,35 +51,32 @@ public class ToolboxEquipPacket extends SimplePacketBase {
World world = player.level;
if (toolboxPos == null) {
player.getPersistentData()
.getCompound("CreateToolboxData")
.remove(String.valueOf(hotbarSlot));
sendData(player);
ToolboxHandler.unequip(player, hotbarSlot, false);
ToolboxHandler.syncData(player);
return;
}
TileEntity blockEntity = world.getBlockEntity(toolboxPos);
double maxRange = ToolboxHandler.getMaxRange(player);
if (ctx.getSender()
.distanceToSqr(toolboxPos.getX() + 0.5, toolboxPos.getY(),
toolboxPos.getZ() + 0.5) > maxRange * maxRange)
if (player.distanceToSqr(toolboxPos.getX() + 0.5, toolboxPos.getY(), toolboxPos.getZ() + 0.5) > maxRange
* maxRange)
return;
if (!(blockEntity instanceof ToolboxTileEntity))
return;
ToolboxHandler.unequip(player, hotbarSlot);
ToolboxHandler.unequip(player, hotbarSlot, false);
if (slot < 0 || slot >= 8) {
sendData(player);
ToolboxHandler.syncData(player);
return;
}
ToolboxTileEntity toolboxTileEntity = (ToolboxTileEntity) blockEntity;
ItemStack playerStack = player.inventory.getItem(hotbarSlot);
if (!playerStack.isEmpty()
&& !ItemHandlerHelper.canItemStacksStack(playerStack, toolboxTileEntity.inventory.filters.get(slot))) {
if (!playerStack.isEmpty() && !ToolboxInventory.canItemsShareCompartment(playerStack,
toolboxTileEntity.inventory.filters.get(slot))) {
ItemStack remainder =
ItemHandlerHelper.insertItemStacked(toolboxTileEntity.inventory, playerStack, false);
if (!remainder.isEmpty())
@ -103,15 +97,11 @@ public class ToolboxEquipPacket extends SimplePacketBase {
player.getPersistentData()
.put("CreateToolboxData", compound);
sendData(player);
toolboxTileEntity.connectPlayer(slot, player, hotbarSlot);
ToolboxHandler.syncData(player);
});
ctx.setPacketHandled(true);
}
private void sendData(ServerPlayerEntity player) {
AllPackets.channel.send(PacketDistributor.PLAYER.with(() -> player), new ISyncPersistentData.Packet(player));
}
}

View file

@ -4,9 +4,14 @@ import java.util.List;
import java.util.WeakHashMap;
import java.util.stream.Collectors;
import com.simibubi.create.foundation.config.AllConfigs;
import com.simibubi.create.foundation.networking.AllPackets;
import com.simibubi.create.foundation.networking.ISyncPersistentData;
import com.simibubi.create.foundation.utility.WorldAttached;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.nbt.NBTUtil;
import net.minecraft.tileentity.TileEntity;
@ -14,6 +19,8 @@ import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.vector.Vector3d;
import net.minecraft.world.IWorld;
import net.minecraft.world.World;
import net.minecraft.world.server.ServerWorld;
import net.minecraftforge.fml.network.PacketDistributor;
public class ToolboxHandler {
@ -30,6 +37,70 @@ public class ToolboxHandler {
.remove(te.getBlockPos());
}
static int validationTimer = 20;
public static void entityTick(Entity entity, World world) {
if (world.isClientSide)
return;
if (!(world instanceof ServerWorld))
return;
if (!(entity instanceof ServerPlayerEntity))
return;
if (entity.tickCount % validationTimer != 0)
return;
ServerPlayerEntity player = (ServerPlayerEntity) entity;
if (!player.getPersistentData()
.contains("CreateToolboxData"))
return;
boolean sendData = false;
CompoundNBT compound = player.getPersistentData()
.getCompound("CreateToolboxData");
for (int i = 0; i < 9; i++) {
String key = String.valueOf(i);
if (!compound.contains(key))
continue;
CompoundNBT data = compound.getCompound(key);
BlockPos pos = NBTUtil.readBlockPos(data.getCompound("Pos"));
int slot = data.getInt("Slot");
if (!world.isAreaLoaded(pos, 0))
continue;
if (!(world.getBlockState(pos)
.getBlock() instanceof ToolboxBlock)) {
compound.remove(key);
sendData = true;
continue;
}
TileEntity prevBlockEntity = world.getBlockEntity(pos);
if (prevBlockEntity instanceof ToolboxTileEntity)
((ToolboxTileEntity) prevBlockEntity).connectPlayer(slot, player, i);
}
if (sendData)
syncData(player);
}
public static void playerLogin(PlayerEntity player) {
if (!(player instanceof ServerPlayerEntity))
return;
if (player.getPersistentData()
.contains("CreateToolboxData")
&& !player.getPersistentData()
.getCompound("CreateToolboxData")
.isEmpty()) {
syncData(player);
}
}
public static void syncData(PlayerEntity player) {
AllPackets.channel.send(PacketDistributor.PLAYER.with(() -> (ServerPlayerEntity) player),
new ISyncPersistentData.Packet(player));
}
public static List<ToolboxTileEntity> getNearest(IWorld world, PlayerEntity player, int maxAmount) {
Vector3d location = player.position();
double maxRange = getMaxRange(player);
@ -43,7 +114,7 @@ public class ToolboxHandler {
.collect(Collectors.toList());
}
public static void unequip(PlayerEntity player, int hotbarSlot) {
public static void unequip(PlayerEntity player, int hotbarSlot, boolean keepItems) {
CompoundNBT compound = player.getPersistentData()
.getCompound("CreateToolboxData");
World world = player.level;
@ -56,8 +127,10 @@ public class ToolboxHandler {
int prevSlot = prevData.getInt("Slot");
TileEntity prevBlockEntity = world.getBlockEntity(prevPos);
if (prevBlockEntity instanceof ToolboxTileEntity)
((ToolboxTileEntity) prevBlockEntity).unequip(prevSlot, player, hotbarSlot);
if (prevBlockEntity instanceof ToolboxTileEntity) {
ToolboxTileEntity toolbox = (ToolboxTileEntity) prevBlockEntity;
toolbox.unequip(prevSlot, player, hotbarSlot, keepItems || !ToolboxHandler.withinRange(player, toolbox));
}
compound.remove(key);
}
@ -73,7 +146,8 @@ public class ToolboxHandler {
}
public static double getMaxRange(PlayerEntity player) {
return 10;
return AllConfigs.SERVER.curiosities.toolboxRange.get()
.doubleValue();
}
}

View file

@ -60,8 +60,11 @@ public class ToolboxHandlerClient {
if (canReachToolbox) {
TileEntity blockEntity = level.getBlockEntity(pos);
if (blockEntity instanceof ToolboxTileEntity) {
ScreenOpener.open(new RadialToolboxMenu(ImmutableList.of((ToolboxTileEntity) blockEntity),
RadialToolboxMenu.State.SELECT_ITEM_UNEQUIP));
RadialToolboxMenu screen = new RadialToolboxMenu(ImmutableList.of((ToolboxTileEntity) blockEntity),
RadialToolboxMenu.State.SELECT_ITEM_UNEQUIP);
screen.prevSlot(compound.getCompound(slotKey)
.getInt("Slot"));
ScreenOpener.open(screen);
return;
}
}
@ -73,10 +76,6 @@ public class ToolboxHandlerClient {
if (toolboxes.isEmpty())
return;
// ItemStack itemStackFromSlot = player.getItemStackFromSlot(EquipmentSlotType.LEGS);
// if (!AllItems.TOOLBELT.isIn(itemStackFromSlot))
// return;
if (toolboxes.size() == 1)
ScreenOpener.open(new RadialToolboxMenu(toolboxes, RadialToolboxMenu.State.SELECT_ITEM));
else

View file

@ -2,9 +2,11 @@ package com.simibubi.create.content.curiosities.toolbox;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import javax.annotation.Nonnull;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.foundation.utility.NBTHelper;
import net.minecraft.item.ItemStack;
@ -20,15 +22,24 @@ public class ToolboxInventory extends ItemStackHandler {
boolean settling;
private ToolboxTileEntity te;
private boolean limitedMode;
public ToolboxInventory(ToolboxTileEntity te) {
super(8 * STACKS_PER_COMPARTMENT);
this.te = te;
limitedMode = false;
filters = new ArrayList<>();
settling = false;
for (int i = 0; i < 8; i++)
filters.add(ItemStack.EMPTY);
}
public void inLimitedMode(Consumer<ToolboxInventory> action) {
limitedMode = true;
action.accept(this);
limitedMode = false;
}
public void settle(int compartment) {
int totalCount = 0;
boolean valid = true;
@ -50,23 +61,42 @@ public class ToolboxInventory extends ItemStackHandler {
return;
settling = true;
if (!sample.isStackable()) {
for (int i = 0; i < STACKS_PER_COMPARTMENT; i++) {
if (!getStackInSlot(compartment * STACKS_PER_COMPARTMENT + i).isEmpty())
continue;
for (int j = i + 1; j < STACKS_PER_COMPARTMENT; j++) {
ItemStack stackInSlot = getStackInSlot(compartment * STACKS_PER_COMPARTMENT + j);
if (stackInSlot.isEmpty())
continue;
setStackInSlot(compartment * STACKS_PER_COMPARTMENT + i, stackInSlot);
setStackInSlot(compartment * STACKS_PER_COMPARTMENT + j, ItemStack.EMPTY);
break;
}
}
} else {
for (int i = 0; i < STACKS_PER_COMPARTMENT; i++) {
ItemStack copy = totalCount <= 0 ? ItemStack.EMPTY
: ItemHandlerHelper.copyStackWithSize(sample, Math.min(totalCount, sample.getMaxStackSize()));
setStackInSlot(compartment * STACKS_PER_COMPARTMENT + i, copy);
totalCount -= copy.getCount();
}
}
settling = false;
te.sendData();
}
@Override
public boolean isItemValid(int slot, ItemStack stack) {
if (AllBlocks.TOOLBOX.isIn(stack))
return false;
if (slot < 0 || slot >= getSlots())
return false;
int compartment = slot / STACKS_PER_COMPARTMENT;
ItemStack filter = filters.get(compartment);
if (!filter.isEmpty() && ItemHandlerHelper.canItemStacksStack(filter, stack))
if (limitedMode && filter.isEmpty())
return false;
if (filter.isEmpty() || ToolboxInventory.canItemsShareCompartment(filter, stack))
return super.isItemValid(slot, stack);
return false;
}
@ -76,8 +106,24 @@ public class ToolboxInventory extends ItemStackHandler {
super.setStackInSlot(slot, stack);
int compartment = slot / STACKS_PER_COMPARTMENT;
if (!stack.isEmpty() && filters.get(compartment)
.isEmpty())
.isEmpty()) {
filters.set(compartment, ItemHandlerHelper.copyStackWithSize(stack, 1));
te.sendData();
}
}
@Override
public ItemStack insertItem(int slot, ItemStack stack, boolean simulate) {
ItemStack insertItem = super.insertItem(slot, stack, simulate);
if (insertItem.getCount() != stack.getCount()) {
int compartment = slot / STACKS_PER_COMPARTMENT;
if (!stack.isEmpty() && filters.get(compartment)
.isEmpty()) {
filters.set(compartment, ItemHandlerHelper.copyStackWithSize(stack, 1));
te.sendData();
}
}
return insertItem;
}
@Override
@ -128,7 +174,7 @@ public class ToolboxInventory extends ItemStackHandler {
for (int i = STACKS_PER_COMPARTMENT - 1; i >= 0; i--) {
int slot = compartment * STACKS_PER_COMPARTMENT + i;
ItemStack extracted = extractItem(slot, amount, simulate);
ItemStack extracted = extractItem(slot, remaining, simulate);
remaining -= extracted.getCount();
if (!extracted.isEmpty())
lastValid = extracted;
@ -142,4 +188,10 @@ public class ToolboxInventory extends ItemStackHandler {
return ItemHandlerHelper.copyStackWithSize(lastValid, amount - remaining);
}
public static boolean canItemsShareCompartment(ItemStack stack1, ItemStack stack2) {
if (!stack1.isStackable() && !stack2.isStackable() && stack1.isDamageableItem() && stack2.isDamageableItem())
return stack1.getItem() == stack2.getItem();
return ItemHandlerHelper.canItemStacksStack(stack1, stack2);
}
}

View file

@ -14,7 +14,9 @@ import com.simibubi.create.foundation.gui.AllGuiTextures;
import com.simibubi.create.foundation.gui.AllIcons;
import com.simibubi.create.foundation.gui.GuiGameElement;
import com.simibubi.create.foundation.gui.widgets.IconButton;
import com.simibubi.create.foundation.networking.AllPackets;
import com.simibubi.create.foundation.utility.Iterate;
import com.simibubi.create.foundation.utility.Lang;
import net.minecraft.client.renderer.Rectangle2d;
import net.minecraft.entity.player.PlayerInventory;
@ -28,6 +30,7 @@ public class ToolboxScreen extends AbstractSimiContainerScreen<ToolboxContainer>
AllGuiTextures PLAYER = AllGuiTextures.PLAYER_INVENTORY;
protected Slot hoveredToolboxSlot;
private IconButton confirmButton;
private IconButton disposeButton;
private List<Rectangle2d> extraAreas = Collections.emptyList();
@ -42,7 +45,10 @@ public class ToolboxScreen extends AbstractSimiContainerScreen<ToolboxContainer>
widgets.clear();
setWindowSize(BG.width, 256);
confirmButton = new IconButton(getGuiLeft() + BG.width - 23, getGuiTop() + BG.height - 24, AllIcons.I_CONFIRM);
disposeButton = new IconButton(getGuiLeft() + 91, getGuiTop() + 69, AllIcons.I_TOOLBOX);
disposeButton.setToolTip(Lang.translate("toolbox.depositBox"));
widgets.add(confirmButton);
widgets.add(disposeButton);
extraAreas = ImmutableList.of(new Rectangle2d(118, 155, 80, 100), new Rectangle2d(308, 125, 100, 70));
}
@ -125,7 +131,8 @@ public class ToolboxScreen extends AbstractSimiContainerScreen<ToolboxContainer>
for (int offset : Iterate.zeroAndOne) {
ms.pushPose();
ms.translate(0, -offset * 1 / 8f, menu.contentHolder.drawers.getValue(partialTicks) * -.175f * (2 - offset));
ms.translate(0, -offset * 1 / 8f,
menu.contentHolder.drawers.getValue(partialTicks) * -.175f * (2 - offset));
GuiGameElement.of(AllBlockPartials.TOOLBOX_DRAWER)
.render(ms);
ms.popPose();
@ -149,6 +156,10 @@ public class ToolboxScreen extends AbstractSimiContainerScreen<ToolboxContainer>
minecraft.player.closeContainer();
return true;
}
if (disposeButton.isHovered()) {
AllPackets.channel.sendToServer(new ToolboxDisposeAllPacket(menu.contentHolder.getBlockPos()));
return true;
}
}
return mouseClicked;

View file

@ -1,14 +1,14 @@
package com.simibubi.create.content.curiosities.toolbox;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.WeakHashMap;
import com.simibubi.create.foundation.networking.AllPackets;
import com.simibubi.create.foundation.networking.ISyncPersistentData;
import com.simibubi.create.foundation.tileEntity.SmartTileEntity;
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
import com.simibubi.create.foundation.utility.VecHelper;
@ -34,7 +34,6 @@ import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TranslationTextComponent;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.fml.network.PacketDistributor;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.ItemHandlerHelper;
@ -93,6 +92,8 @@ public class ToolboxTileEntity extends SmartTileEntity implements INamedContaine
}
private void tickPlayers() {
boolean update = false;
for (Iterator<Entry<Integer, WeakHashMap<PlayerEntity, Integer>>> toolboxSlots = connectedPlayers.entrySet()
.iterator(); toolboxSlots.hasNext();) {
@ -115,15 +116,14 @@ public class ToolboxTileEntity extends SmartTileEntity implements INamedContaine
ItemStack playerStack = player.inventory.getItem(hotbarSlot);
if (clear
|| !playerStack.isEmpty() && !ItemHandlerHelper.canItemStacksStack(playerStack, referenceItem)) {
if (clear || !playerStack.isEmpty()
&& !ToolboxInventory.canItemsShareCompartment(playerStack, referenceItem)) {
player.getPersistentData()
.getCompound("CreateToolboxData")
.remove(String.valueOf(hotbarSlot));
playerEntries.remove();
if (player instanceof ServerPlayerEntity)
AllPackets.channel.send(PacketDistributor.PLAYER.with(() -> (ServerPlayerEntity) player),
new ISyncPersistentData.Packet(player));
ToolboxHandler.syncData(player);
continue;
}
@ -132,34 +132,99 @@ public class ToolboxTileEntity extends SmartTileEntity implements INamedContaine
if (count < targetAmount) {
int amountToReplenish = targetAmount - count;
if (isOpenInContainer(player)) {
ItemStack extracted = inventory.takeFromCompartment(amountToReplenish, slot, true);
if (!extracted.isEmpty()) {
ToolboxHandler.unequip(player, hotbarSlot, false);
ToolboxHandler.syncData(player);
continue;
}
}
ItemStack extracted = inventory.takeFromCompartment(amountToReplenish, slot, false);
if (!extracted.isEmpty())
if (!extracted.isEmpty()) {
update = true;
player.inventory.setItem(hotbarSlot,
ItemHandlerHelper.copyStackWithSize(extracted, count + extracted.getCount()));
}
}
if (count > targetAmount) {
int amountToDeposit = count - targetAmount;
ItemStack toDistribute = ItemHandlerHelper.copyStackWithSize(playerStack, amountToDeposit);
if (isOpenInContainer(player)) {
int deposited = amountToDeposit - inventory.distributeToCompartment(toDistribute, slot, true)
.getCount();
if (deposited > 0) {
ToolboxHandler.unequip(player, hotbarSlot, true);
ToolboxHandler.syncData(player);
continue;
}
}
int deposited = amountToDeposit - inventory.distributeToCompartment(toDistribute, slot, false)
.getCount();
if (deposited > 0)
if (deposited > 0) {
update = true;
player.inventory.setItem(hotbarSlot,
ItemHandlerHelper.copyStackWithSize(playerStack, count - deposited));
}
}
}
if (clear)
toolboxSlots.remove();
}
if (update)
sendData();
}
public void unequip(int slot, PlayerEntity player, int hotbarSlot) {
private boolean isOpenInContainer(PlayerEntity player) {
return player.containerMenu instanceof ToolboxContainer
&& ((ToolboxContainer) player.containerMenu).contentHolder == this;
}
public void unequipTracked() {
if (level.isClientSide)
return;
Set<ServerPlayerEntity> affected = new HashSet<>();
for (Iterator<Entry<Integer, WeakHashMap<PlayerEntity, Integer>>> toolboxSlots = connectedPlayers.entrySet()
.iterator(); toolboxSlots.hasNext();) {
Entry<Integer, WeakHashMap<PlayerEntity, Integer>> toolboxSlotEntry = toolboxSlots.next();
WeakHashMap<PlayerEntity, Integer> set = toolboxSlotEntry.getValue();
for (Iterator<Entry<PlayerEntity, Integer>> playerEntries = set.entrySet()
.iterator(); playerEntries.hasNext();) {
Entry<PlayerEntity, Integer> playerEntry = playerEntries.next();
PlayerEntity player = playerEntry.getKey();
int hotbarSlot = playerEntry.getValue();
ToolboxHandler.unequip(player, hotbarSlot, false);
if (player instanceof ServerPlayerEntity)
affected.add((ServerPlayerEntity) player);
}
}
for (ServerPlayerEntity player : affected)
ToolboxHandler.syncData(player);
connectedPlayers.clear();
}
public void unequip(int slot, PlayerEntity player, int hotbarSlot, boolean keepItems) {
if (!connectedPlayers.containsKey(slot))
return;
connectedPlayers.get(slot)
.remove(player);
if (!ToolboxHandler.withinRange(player, this))
if (keepItems)
return;
ItemStack playerStack = player.inventory.getItem(hotbarSlot);
@ -220,11 +285,6 @@ public class ToolboxTileEntity extends SmartTileEntity implements INamedContaine
return ToolboxContainer.create(id, inv, this);
}
@Override
public ITextComponent getDisplayName() {
return customName != null ? customName : new TranslationTextComponent("block.create.toolbox");
}
@Override
public void lazyTick() {
updateOpenCount();
@ -272,6 +332,12 @@ public class ToolboxTileEntity extends SmartTileEntity implements INamedContaine
if (level.isClientSide)
return;
WeakHashMap<PlayerEntity, Integer> map = connectedPlayers.computeIfAbsent(slot, WeakHashMap::new);
Integer previous = map.get(player);
if (previous != null) {
if (previous == hotbarSlot)
return;
ToolboxHandler.unequip(player, previous, false);
}
map.put(player, hotbarSlot);
}
@ -283,6 +349,21 @@ public class ToolboxTileEntity extends SmartTileEntity implements INamedContaine
this.customName = customName;
}
@Override
public ITextComponent getDisplayName() {
return customName != null ? customName : new TranslationTextComponent("block.create.toolbox");
}
@Override
public ITextComponent getCustomName() {
return customName;
}
@Override
public boolean hasCustomName() {
return customName != null;
}
@Override
public ITextComponent getName() {
return customName;

View file

@ -8,6 +8,7 @@ import com.simibubi.create.content.contraptions.components.structureMovement.tra
import com.simibubi.create.content.contraptions.fluids.recipe.FluidTransferRecipes;
import com.simibubi.create.content.contraptions.fluids.recipe.PotionMixingRecipeManager;
import com.simibubi.create.content.contraptions.wrench.WrenchItem;
import com.simibubi.create.content.curiosities.toolbox.ToolboxHandler;
import com.simibubi.create.content.curiosities.zapper.ZapperInteractionHandler;
import com.simibubi.create.content.curiosities.zapper.ZapperItem;
import com.simibubi.create.content.logistics.item.LinkedControllerServerHandler;
@ -21,6 +22,7 @@ import com.simibubi.create.foundation.utility.recipe.RecipeFinder;
import net.minecraft.block.BlockState;
import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.fluid.FluidState;
import net.minecraft.item.ItemStack;
@ -39,6 +41,7 @@ import net.minecraftforge.event.entity.EntityJoinWorldEvent;
import net.minecraftforge.event.entity.living.LivingEvent.LivingUpdateEvent;
import net.minecraftforge.event.entity.player.AttackEntityEvent;
import net.minecraftforge.event.entity.player.PlayerEvent;
import net.minecraftforge.event.entity.player.PlayerEvent.PlayerLoggedInEvent;
import net.minecraftforge.event.world.BlockEvent.FluidPlaceBlockEvent;
import net.minecraftforge.event.world.ChunkEvent;
import net.minecraftforge.event.world.WorldEvent;
@ -64,6 +67,12 @@ public class CommonEvents {
CapabilityMinecartController.onChunkUnloaded(event);
}
@SubscribeEvent
public static void playerLoggedIn(PlayerLoggedInEvent event) {
PlayerEntity player = event.getPlayer();
ToolboxHandler.playerLogin(player);
}
@SubscribeEvent
public static void whenFluidsMeet(FluidPlaceBlockEvent event) {
BlockState blockState = event.getOriginalState();
@ -75,7 +84,8 @@ public class CommonEvents {
return;
for (Direction direction : Iterate.directions) {
FluidState metFluidState = fluidState.isSource() ? fluidState : world.getFluidState(pos.relative(direction));
FluidState metFluidState =
fluidState.isSource() ? fluidState : world.getFluidState(pos.relative(direction));
if (!metFluidState.is(FluidTags.WATER))
continue;
BlockState lavaInteraction = AllFluids.getLavaInteraction(metFluidState);
@ -104,6 +114,7 @@ public class CommonEvents {
if (world == null)
return;
ContraptionHandler.entitiesWhoJustDismountedGetSentToTheRightLocation(entityLiving, world);
ToolboxHandler.entityTick(entityLiving, world);
}
@SubscribeEvent

View file

@ -4,6 +4,7 @@ public class CCuriosities extends ConfigBase {
public ConfigInt maxSymmetryWandRange = i(50, 10, "maxSymmetryWandRange", Comments.symmetryRange);
public ConfigInt placementAssistRange = i(12, 3, "placementAssistRange", Comments.placementRange);
public ConfigInt toolboxRange = i(10, 1, "toolboxRange", Comments.toolboxRange);
public ConfigInt airInBacktank = i(900, 1, "airInBacktank", Comments.maxAirInBacktank);
public ConfigInt enchantedBacktankCapacity = i(300, 1, "enchantedBacktankCapacity", Comments.enchantedBacktankCapacity);
@ -25,6 +26,8 @@ public class CCuriosities extends ConfigBase {
"The volume of Air added by each level of the backtanks Capacity Enchantment";
static String placementRange =
"The Maximum Distance a Block placed by Create's placement assist will have to its interaction point.";
static String toolboxRange =
"The Maximum Distance at which a Toolbox can interact with Players' Inventories.";
static String maxExtendoGripActions =
"Amount of free Extendo Grip actions provided by one filled Copper Backtank. Set to 0 makes Extendo Grips unbreakable";
static String maxPotatoCannonShots =

View file

@ -86,6 +86,7 @@ public class AllIcons implements IScreenRenderable {
I_TUNNEL_PREFER_NEAREST = next(),
I_TUNNEL_RANDOMIZE = next(),
I_TUNNEL_SYNCHRONIZE = next(),
I_TOOLBOX = next(),
I_TOOL_MOVE_XZ = newRow(),
I_TOOL_MOVE_Y = next(),

View file

@ -23,6 +23,7 @@ import com.simibubi.create.content.contraptions.fluids.actors.FluidSplashPacket;
import com.simibubi.create.content.contraptions.relays.advanced.sequencer.ConfigureSequencedGearshiftPacket;
import com.simibubi.create.content.curiosities.bell.SoulPulseEffectPacket;
import com.simibubi.create.content.curiosities.symmetry.SymmetryEffectPacket;
import com.simibubi.create.content.curiosities.toolbox.ToolboxDisposeAllPacket;
import com.simibubi.create.content.curiosities.toolbox.ToolboxEquipPacket;
import com.simibubi.create.content.curiosities.tools.BlueprintAssignCompleteRecipePacket;
import com.simibubi.create.content.curiosities.tools.ExtendoGripInteractionPacket;
@ -98,6 +99,7 @@ public enum AllPackets {
SUBMIT_GHOST_ITEM(GhostItemSubmitPacket.class, GhostItemSubmitPacket::new, PLAY_TO_SERVER),
BLUEPRINT_COMPLETE_RECIPE(BlueprintAssignCompleteRecipePacket.class, BlueprintAssignCompleteRecipePacket::new, PLAY_TO_SERVER),
TOOLBOX_EQUIP(ToolboxEquipPacket.class, ToolboxEquipPacket::new, PLAY_TO_SERVER),
TOOLBOX_DISPOSE_ALL(ToolboxDisposeAllPacket.class, ToolboxDisposeAllPacket::new, PLAY_TO_SERVER),
// Server to Client
SYMMETRY_EFFECT(SymmetryEffectPacket.class, SymmetryEffectPacket::new, PLAY_TO_CLIENT),

View file

@ -108,6 +108,8 @@
"create.toolbox.unequip": "Unequip: %1$s",
"create.toolbox.outOfRange": "Toolbox of held item not in Range",
"create.toolbox.detach": "Stop tracking and keep item",
"create.toolbox.depositAll": "Return items to nearby Toolboxes",
"create.toolbox.depositBox": "Return items to Toolbox",
"create.gui.symmetryWand.mirrorType": "Mirror",
"create.gui.symmetryWand.orientation": "Orientation",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB