mirror of
https://github.com/Creators-of-Create/Create.git
synced 2024-12-29 08:27:03 +01:00
Mechanical Arm Implementation
- The arm blockitem can now be used to select inputs & outputs - Arms now transfer items between inputs and outputs - Arm support for Belts, Depots and Funnels - Some safety checks in net code - Minor refactor to NBTHelper
This commit is contained in:
parent
5411bc3565
commit
f820e2be27
44 changed files with 1104 additions and 129 deletions
|
@ -29,7 +29,7 @@ public class AllBlockPartials {
|
||||||
private static List<AllBlockPartials> all = new ArrayList<>();
|
private static List<AllBlockPartials> all = new ArrayList<>();
|
||||||
|
|
||||||
public static final AllBlockPartials
|
public static final AllBlockPartials
|
||||||
SCHEMATICANNON_CONNECTOR = get("schematicannon/connector"),
|
SCHEMATICANNON_CONNECTOR = get("schematicannon/connector"),
|
||||||
SCHEMATICANNON_PIPE = get("schematicannon/pipe"),
|
SCHEMATICANNON_PIPE = get("schematicannon/pipe"),
|
||||||
|
|
||||||
SHAFTLESS_COGWHEEL = get("cogwheel_shaftless"),
|
SHAFTLESS_COGWHEEL = get("cogwheel_shaftless"),
|
||||||
|
@ -92,6 +92,11 @@ public class AllBlockPartials {
|
||||||
ARM_CLAW_BASE = get("mechanical_arm/claw_base"),
|
ARM_CLAW_BASE = get("mechanical_arm/claw_base"),
|
||||||
ARM_CLAW_GRIP = get("mechanical_arm/claw_grip"),
|
ARM_CLAW_GRIP = get("mechanical_arm/claw_grip"),
|
||||||
|
|
||||||
|
FLAG_SHORT_IN = get("mechanical_arm/flag/short_in"),
|
||||||
|
FLAG_SHORT_OUT = get("mechanical_arm/flag/short_out"),
|
||||||
|
FLAG_LONG_IN = get("mechanical_arm/flag/long_in"),
|
||||||
|
FLAG_LONG_OUT = get("mechanical_arm/flag/long_out"),
|
||||||
|
|
||||||
MECHANICAL_PUMP_ARROW = get("mechanical_pump/arrow"),
|
MECHANICAL_PUMP_ARROW = get("mechanical_pump/arrow"),
|
||||||
MECHANICAL_PUMP_COG = get("mechanical_pump/cog"),
|
MECHANICAL_PUMP_COG = get("mechanical_pump/cog"),
|
||||||
FLUID_PIPE_CASING = get("fluid_pipe/casing");
|
FLUID_PIPE_CASING = get("fluid_pipe/casing");
|
||||||
|
|
|
@ -96,6 +96,7 @@ import com.simibubi.create.content.logistics.block.funnel.VerticalFunnelGenerato
|
||||||
import com.simibubi.create.content.logistics.block.inventories.AdjustableCrateBlock;
|
import com.simibubi.create.content.logistics.block.inventories.AdjustableCrateBlock;
|
||||||
import com.simibubi.create.content.logistics.block.inventories.CreativeCrateBlock;
|
import com.simibubi.create.content.logistics.block.inventories.CreativeCrateBlock;
|
||||||
import com.simibubi.create.content.logistics.block.mechanicalArm.ArmBlock;
|
import com.simibubi.create.content.logistics.block.mechanicalArm.ArmBlock;
|
||||||
|
import com.simibubi.create.content.logistics.block.mechanicalArm.ArmItem;
|
||||||
import com.simibubi.create.content.logistics.block.packager.PackagerBlock;
|
import com.simibubi.create.content.logistics.block.packager.PackagerBlock;
|
||||||
import com.simibubi.create.content.logistics.block.realityFunnel.BeltFunnelBlock;
|
import com.simibubi.create.content.logistics.block.realityFunnel.BeltFunnelBlock;
|
||||||
import com.simibubi.create.content.logistics.block.realityFunnel.BeltFunnelGenerator;
|
import com.simibubi.create.content.logistics.block.realityFunnel.BeltFunnelGenerator;
|
||||||
|
@ -781,7 +782,7 @@ public class AllBlocks {
|
||||||
.initialProperties(SharedProperties::softMetal)
|
.initialProperties(SharedProperties::softMetal)
|
||||||
.blockstate((c, p) -> p.simpleBlock(c.getEntry(), AssetLookup.partialBaseModel(c, p)))
|
.blockstate((c, p) -> p.simpleBlock(c.getEntry(), AssetLookup.partialBaseModel(c, p)))
|
||||||
.transform(StressConfigDefaults.setImpact(8.0))
|
.transform(StressConfigDefaults.setImpact(8.0))
|
||||||
.item()
|
.item(ArmItem::new)
|
||||||
.transform(customItemModel())
|
.transform(customItemModel())
|
||||||
.register();
|
.register();
|
||||||
|
|
||||||
|
|
|
@ -109,7 +109,6 @@ public class ClientEvents {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
double delta = event.getScrollDelta();
|
double delta = event.getScrollDelta();
|
||||||
|
|
||||||
boolean cancelled = CreateClient.schematicHandler.mouseScrolled(delta)
|
boolean cancelled = CreateClient.schematicHandler.mouseScrolled(delta)
|
||||||
|| CreateClient.schematicAndQuillHandler.mouseScrolled(delta) || FilteringHandler.onScroll(delta)
|
|| CreateClient.schematicAndQuillHandler.mouseScrolled(delta) || FilteringHandler.onScroll(delta)
|
||||||
|| ScrollValueHandler.onScroll(delta);
|
|| ScrollValueHandler.onScroll(delta);
|
||||||
|
|
|
@ -14,6 +14,7 @@ import com.simibubi.create.content.curiosities.tools.ExtendoGripRenderHandler;
|
||||||
import com.simibubi.create.content.curiosities.zapper.ZapperRenderHandler;
|
import com.simibubi.create.content.curiosities.zapper.ZapperRenderHandler;
|
||||||
import com.simibubi.create.content.curiosities.zapper.blockzapper.BlockzapperRenderHandler;
|
import com.simibubi.create.content.curiosities.zapper.blockzapper.BlockzapperRenderHandler;
|
||||||
import com.simibubi.create.content.curiosities.zapper.terrainzapper.WorldshaperRenderHandler;
|
import com.simibubi.create.content.curiosities.zapper.terrainzapper.WorldshaperRenderHandler;
|
||||||
|
import com.simibubi.create.content.logistics.block.mechanicalArm.ArmInteractionPointHandler;
|
||||||
import com.simibubi.create.content.schematics.ClientSchematicLoader;
|
import com.simibubi.create.content.schematics.ClientSchematicLoader;
|
||||||
import com.simibubi.create.content.schematics.client.SchematicAndQuillHandler;
|
import com.simibubi.create.content.schematics.client.SchematicAndQuillHandler;
|
||||||
import com.simibubi.create.content.schematics.client.SchematicHandler;
|
import com.simibubi.create.content.schematics.client.SchematicHandler;
|
||||||
|
@ -109,6 +110,7 @@ public class CreateClient {
|
||||||
KineticDebugger.tick();
|
KineticDebugger.tick();
|
||||||
ZapperRenderHandler.tick();
|
ZapperRenderHandler.tick();
|
||||||
ExtendoGripRenderHandler.tick();
|
ExtendoGripRenderHandler.tick();
|
||||||
|
ArmInteractionPointHandler.tick();
|
||||||
outliner.tickOutlines();
|
outliner.tickOutlines();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -76,7 +76,7 @@ public class CuckooClockRenderer extends KineticTileEntityRenderer {
|
||||||
.renderInto(ms, vb);
|
.renderInto(ms, vb);
|
||||||
|
|
||||||
// Figure
|
// Figure
|
||||||
if (clock.animationType != null) {
|
if (clock.animationType != Animation.NONE) {
|
||||||
offset = -(angle / 135) * 1 / 2f + 10 / 16f;
|
offset = -(angle / 135) * 1 / 2f + 10 / 16f;
|
||||||
SuperByteBuffer figure =
|
SuperByteBuffer figure =
|
||||||
(clock.animationType == Animation.PIG ? AllBlockPartials.CUCKOO_PIG : AllBlockPartials.CUCKOO_CREEPER)
|
(clock.animationType == Animation.PIG ? AllBlockPartials.CUCKOO_PIG : AllBlockPartials.CUCKOO_CREEPER)
|
||||||
|
|
|
@ -32,17 +32,18 @@ public class CuckooClockTileEntity extends KineticTileEntity {
|
||||||
private boolean sendAnimationUpdate;
|
private boolean sendAnimationUpdate;
|
||||||
|
|
||||||
enum Animation {
|
enum Animation {
|
||||||
PIG, CREEPER, SURPRISE;
|
PIG, CREEPER, SURPRISE, NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CuckooClockTileEntity(TileEntityType<? extends CuckooClockTileEntity> type) {
|
public CuckooClockTileEntity(TileEntityType<? extends CuckooClockTileEntity> type) {
|
||||||
super(type);
|
super(type);
|
||||||
|
animationType = Animation.NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompoundNBT writeToClient(CompoundNBT compound) {
|
public CompoundNBT writeToClient(CompoundNBT compound) {
|
||||||
if (sendAnimationUpdate)
|
if (sendAnimationUpdate)
|
||||||
compound.putString("Animation", animationType == null ? "none" : NBTHelper.writeEnum(animationType));
|
NBTHelper.writeEnum(compound, "Animation", animationType);
|
||||||
sendAnimationUpdate = false;
|
sendAnimationUpdate = false;
|
||||||
return super.writeToClient(compound);
|
return super.writeToClient(compound);
|
||||||
}
|
}
|
||||||
|
@ -50,11 +51,7 @@ public class CuckooClockTileEntity extends KineticTileEntity {
|
||||||
@Override
|
@Override
|
||||||
public void readClientUpdate(CompoundNBT tag) {
|
public void readClientUpdate(CompoundNBT tag) {
|
||||||
if (tag.contains("Animation")) {
|
if (tag.contains("Animation")) {
|
||||||
String string = tag.getString("Animation");
|
animationType = NBTHelper.readEnum(tag, "Animation", Animation.class);
|
||||||
if ("none".equals(string))
|
|
||||||
animationType = null;
|
|
||||||
else
|
|
||||||
animationType = NBTHelper.readEnum(string, Animation.class);
|
|
||||||
animationProgress.lastValue = 0;
|
animationProgress.lastValue = 0;
|
||||||
animationProgress.value = 0;
|
animationProgress.value = 0;
|
||||||
}
|
}
|
||||||
|
@ -72,7 +69,7 @@ public class CuckooClockTileEntity extends KineticTileEntity {
|
||||||
int minutes = (dayTime % 1000) * 60 / 1000;
|
int minutes = (dayTime % 1000) * 60 / 1000;
|
||||||
|
|
||||||
if (!world.isRemote) {
|
if (!world.isRemote) {
|
||||||
if (animationType == null) {
|
if (animationType == Animation.NONE) {
|
||||||
if (hours == 12 && minutes < 5)
|
if (hours == 12 && minutes < 5)
|
||||||
startAnimation(Animation.PIG);
|
startAnimation(Animation.PIG);
|
||||||
if (hours == 18 && minutes < 36 && minutes > 31)
|
if (hours == 18 && minutes < 36 && minutes > 31)
|
||||||
|
@ -81,13 +78,13 @@ public class CuckooClockTileEntity extends KineticTileEntity {
|
||||||
float value = animationProgress.value;
|
float value = animationProgress.value;
|
||||||
animationProgress.set(value + 1);
|
animationProgress.set(value + 1);
|
||||||
if (value > 100)
|
if (value > 100)
|
||||||
animationType = null;
|
animationType = Animation.NONE;
|
||||||
|
|
||||||
if (animationType == Animation.SURPRISE && animationProgress.value == 50) {
|
if (animationType == Animation.SURPRISE && animationProgress.value == 50) {
|
||||||
Vec3d center = VecHelper.getCenterOf(pos);
|
Vec3d center = VecHelper.getCenterOf(pos);
|
||||||
world.destroyBlock(pos, false);
|
world.destroyBlock(pos, false);
|
||||||
world.createExplosion(null, CUCKOO_SURPRISE, center.x, center.y, center.z, 3, false,
|
world.createExplosion(null, CUCKOO_SURPRISE, center.x, center.y, center.z, 3, false,
|
||||||
Explosion.Mode.BREAK);
|
Explosion.Mode.BREAK);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -96,7 +93,7 @@ public class CuckooClockTileEntity extends KineticTileEntity {
|
||||||
if (world.isRemote) {
|
if (world.isRemote) {
|
||||||
moveHands(hours, minutes);
|
moveHands(hours, minutes);
|
||||||
|
|
||||||
if (animationType == null) {
|
if (animationType == Animation.NONE) {
|
||||||
if (AnimationTickHolder.ticks % 32 == 0)
|
if (AnimationTickHolder.ticks % 32 == 0)
|
||||||
playSound(SoundEvents.BLOCK_NOTE_BLOCK_HAT, 1 / 16f, 2f);
|
playSound(SoundEvents.BLOCK_NOTE_BLOCK_HAT, 1 / 16f, 2f);
|
||||||
else if (AnimationTickHolder.ticks % 16 == 0)
|
else if (AnimationTickHolder.ticks % 16 == 0)
|
||||||
|
|
|
@ -162,7 +162,7 @@ public class DeployerMovementBehaviour extends MovementBehaviour {
|
||||||
}
|
}
|
||||||
|
|
||||||
private Mode getMode(MovementContext context) {
|
private Mode getMode(MovementContext context) {
|
||||||
return NBTHelper.readEnum(context.tileData.getString("Mode"), Mode.class);
|
return NBTHelper.readEnum(context.tileData, "Mode", Mode.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -160,7 +160,7 @@ public class DeployerRenderer extends SafeTileEntityRenderer<DeployerTileEntity>
|
||||||
IVertexBuilder builder = buffer.getBuffer(RenderType.getSolid());
|
IVertexBuilder builder = buffer.getBuffer(RenderType.getSolid());
|
||||||
BlockState blockState = context.state;
|
BlockState blockState = context.state;
|
||||||
BlockPos pos = BlockPos.ZERO;
|
BlockPos pos = BlockPos.ZERO;
|
||||||
Mode mode = NBTHelper.readEnum(context.tileData.getString("Mode"), Mode.class);
|
Mode mode = NBTHelper.readEnum(context.tileData, "Mode", Mode.class);
|
||||||
World world = context.world;
|
World world = context.world;
|
||||||
AllBlockPartials handPose =
|
AllBlockPartials handPose =
|
||||||
mode == Mode.PUNCH ? AllBlockPartials.DEPLOYER_HAND_PUNCHING : AllBlockPartials.DEPLOYER_HAND_POINTING;
|
mode == Mode.PUNCH ? AllBlockPartials.DEPLOYER_HAND_PUNCHING : AllBlockPartials.DEPLOYER_HAND_POINTING;
|
||||||
|
|
|
@ -333,8 +333,8 @@ public class DeployerTileEntity extends KineticTileEntity {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void read(CompoundNBT compound) {
|
public void read(CompoundNBT compound) {
|
||||||
state = NBTHelper.readEnum(compound.getString("State"), State.class);
|
state = NBTHelper.readEnum(compound, "State", State.class);
|
||||||
mode = NBTHelper.readEnum(compound.getString("Mode"), Mode.class);
|
mode = NBTHelper.readEnum(compound, "Mode", Mode.class);
|
||||||
timer = compound.getInt("Timer");
|
timer = compound.getInt("Timer");
|
||||||
deferredInventoryList = compound.getList("Inventory", NBT.TAG_COMPOUND);
|
deferredInventoryList = compound.getList("Inventory", NBT.TAG_COMPOUND);
|
||||||
overflowItems = NBTHelper.readItemList(compound.getList("Overflow", NBT.TAG_COMPOUND));
|
overflowItems = NBTHelper.readItemList(compound.getList("Overflow", NBT.TAG_COMPOUND));
|
||||||
|
@ -345,8 +345,8 @@ public class DeployerTileEntity extends KineticTileEntity {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompoundNBT write(CompoundNBT compound) {
|
public CompoundNBT write(CompoundNBT compound) {
|
||||||
compound.putString("Mode", NBTHelper.writeEnum(mode));
|
NBTHelper.writeEnum(compound, "Mode", mode);
|
||||||
compound.putString("State", NBTHelper.writeEnum(state));
|
NBTHelper.writeEnum(compound, "State", state);
|
||||||
compound.putInt("Timer", timer);
|
compound.putInt("Timer", timer);
|
||||||
if (player != null) {
|
if (player != null) {
|
||||||
compound.put("HeldItem", player.getHeldItemMainhand().serializeNBT());
|
compound.put("HeldItem", player.getHeldItemMainhand().serializeNBT());
|
||||||
|
|
|
@ -24,6 +24,8 @@ public class CancelPlayerFallPacket extends SimplePacketBase {
|
||||||
public void handle(Supplier<Context> context) {
|
public void handle(Supplier<Context> context) {
|
||||||
context.get().enqueueWork(() -> {
|
context.get().enqueueWork(() -> {
|
||||||
ServerPlayerEntity sender = context.get().getSender();
|
ServerPlayerEntity sender = context.get().getSender();
|
||||||
|
if (sender == null)
|
||||||
|
return;
|
||||||
sender.handleFallDamage(sender.fallDistance, 1.0F);
|
sender.handleFallDamage(sender.fallDistance, 1.0F);
|
||||||
sender.fallDistance = 0;
|
sender.fallDistance = 0;
|
||||||
sender.onGround = true;
|
sender.onGround = true;
|
||||||
|
|
|
@ -98,14 +98,14 @@ public class ClockworkContraption extends Contraption {
|
||||||
CompoundNBT tag = super.writeNBT();
|
CompoundNBT tag = super.writeNBT();
|
||||||
tag.putInt("facing", facing.getIndex());
|
tag.putInt("facing", facing.getIndex());
|
||||||
tag.putInt("offset", offset);
|
tag.putInt("offset", offset);
|
||||||
tag.putString("HandType", NBTHelper.writeEnum(handType));
|
NBTHelper.writeEnum(tag, "HandType", handType);
|
||||||
return tag;
|
return tag;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void readNBT(World world, CompoundNBT tag) {
|
public void readNBT(World world, CompoundNBT tag) {
|
||||||
facing = Direction.byIndex(tag.getInt("Facing"));
|
facing = Direction.byIndex(tag.getInt("Facing"));
|
||||||
handType = NBTHelper.readEnum(tag.getString("HandType"), HandType.class);
|
handType = NBTHelper.readEnum(tag, "HandType", HandType.class);
|
||||||
offset = tag.getInt("offset");
|
offset = tag.getInt("offset");
|
||||||
super.readNBT(world, tag);
|
super.readNBT(world, tag);
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,13 +80,13 @@ public class MountedContraption extends Contraption {
|
||||||
@Override
|
@Override
|
||||||
public CompoundNBT writeNBT() {
|
public CompoundNBT writeNBT() {
|
||||||
CompoundNBT writeNBT = super.writeNBT();
|
CompoundNBT writeNBT = super.writeNBT();
|
||||||
writeNBT.putString("RotationMode", NBTHelper.writeEnum(rotationMode));
|
NBTHelper.writeEnum(writeNBT, "RotationMode", rotationMode);
|
||||||
return writeNBT;
|
return writeNBT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void readNBT(World world, CompoundNBT nbt) {
|
public void readNBT(World world, CompoundNBT nbt) {
|
||||||
rotationMode = NBTHelper.readEnum(nbt.getString("RotationMode"), CartMovementMode.class);
|
rotationMode = NBTHelper.readEnum(nbt, "RotationMode", CartMovementMode.class);
|
||||||
super.readNBT(world, nbt);
|
super.readNBT(world, nbt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -88,16 +88,16 @@ public class Instruction {
|
||||||
|
|
||||||
CompoundNBT serialize() {
|
CompoundNBT serialize() {
|
||||||
CompoundNBT tag = new CompoundNBT();
|
CompoundNBT tag = new CompoundNBT();
|
||||||
tag.putString("Type", NBTHelper.writeEnum(instruction));
|
NBTHelper.writeEnum(tag, "Type", instruction);
|
||||||
tag.putString("Modifier", NBTHelper.writeEnum(speedModifier));
|
NBTHelper.writeEnum(tag, "Modifier", speedModifier);
|
||||||
tag.putInt("Value", value);
|
tag.putInt("Value", value);
|
||||||
return tag;
|
return tag;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Instruction deserialize(CompoundNBT tag) {
|
static Instruction deserialize(CompoundNBT tag) {
|
||||||
Instruction instruction =
|
Instruction instruction =
|
||||||
new Instruction(NBTHelper.readEnum(tag.getString("Type"), SequencerInstructions.class));
|
new Instruction(NBTHelper.readEnum(tag, "Type", SequencerInstructions.class));
|
||||||
instruction.speedModifier = NBTHelper.readEnum(tag.getString("Modifier"), InstructionSpeedModifiers.class);
|
instruction.speedModifier = NBTHelper.readEnum(tag, "Modifier", InstructionSpeedModifiers.class);
|
||||||
instruction.value = tag.getInt("Value");
|
instruction.value = tag.getInt("Value");
|
||||||
return instruction;
|
return instruction;
|
||||||
}
|
}
|
||||||
|
|
|
@ -352,8 +352,8 @@ public class BeltInventory {
|
||||||
}
|
}
|
||||||
|
|
||||||
public TransportedItemStack getStackAtOffset(int offset) {
|
public TransportedItemStack getStackAtOffset(int offset) {
|
||||||
float min = offset + .5f - (SEGMENT_WINDOW / 2);
|
float min = offset;
|
||||||
float max = offset + .5f + (SEGMENT_WINDOW / 2);
|
float max = offset + 1;
|
||||||
for (TransportedItemStack stack : items) {
|
for (TransportedItemStack stack : items) {
|
||||||
if (stack.beltPosition > max)
|
if (stack.beltPosition > max)
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -57,6 +57,8 @@ public class ExtendoGripInteractionPacket extends SimplePacketBase {
|
||||||
.enqueueWork(() -> {
|
.enqueueWork(() -> {
|
||||||
ServerPlayerEntity sender = context.get()
|
ServerPlayerEntity sender = context.get()
|
||||||
.getSender();
|
.getSender();
|
||||||
|
if (sender == null)
|
||||||
|
return;
|
||||||
Entity entityByID = sender.getServerWorld()
|
Entity entityByID = sender.getServerWorld()
|
||||||
.getEntityByID(target);
|
.getEntityByID(target);
|
||||||
if (entityByID != null && ExtendoGripItem.isHoldingExtendoGrip(sender)) {
|
if (entityByID != null && ExtendoGripItem.isHoldingExtendoGrip(sender)) {
|
||||||
|
|
|
@ -351,17 +351,16 @@ public class BlockzapperItem extends ZapperItem {
|
||||||
.contains(component.name()))
|
.contains(component.name()))
|
||||||
stack.getOrCreateTag()
|
stack.getOrCreateTag()
|
||||||
.putString(component.name(), ComponentTier.None.name());
|
.putString(component.name(), ComponentTier.None.name());
|
||||||
return NBTHelper.readEnum(stack.getTag()
|
return NBTHelper.readEnum(stack.getTag(), component.name(), ComponentTier.class);
|
||||||
.getString(component.name()), ComponentTier.class);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setTier(Components component, ComponentTier tier, ItemStack stack) {
|
public static void setTier(Components component, ComponentTier tier, ItemStack stack) {
|
||||||
stack.getOrCreateTag()
|
NBTHelper.writeEnum(stack.getOrCreateTag(), component.name(), tier);
|
||||||
.putString(component.name(), NBTHelper.writeEnum(tier));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static enum ComponentTier {
|
public static enum ComponentTier {
|
||||||
None(TextFormatting.DARK_GRAY), Brass(TextFormatting.GOLD), Chromatic(TextFormatting.LIGHT_PURPLE);
|
None(TextFormatting.DARK_GRAY), Brass(TextFormatting.GOLD), Chromatic(TextFormatting.LIGHT_PURPLE);
|
||||||
|
|
||||||
public TextFormatting color;
|
public TextFormatting color;
|
||||||
|
|
||||||
private ComponentTier(TextFormatting color) {
|
private ComponentTier(TextFormatting color) {
|
||||||
|
|
|
@ -53,7 +53,7 @@ public class WorldshaperItem extends ZapperItem {
|
||||||
@Override
|
@Override
|
||||||
protected boolean canActivateWithoutSelectedBlock(ItemStack stack) {
|
protected boolean canActivateWithoutSelectedBlock(ItemStack stack) {
|
||||||
CompoundNBT tag = stack.getOrCreateTag();
|
CompoundNBT tag = stack.getOrCreateTag();
|
||||||
TerrainTools tool = NBTHelper.readEnum(tag.getString("Tool"), TerrainTools.class);
|
TerrainTools tool = NBTHelper.readEnum(tag, "Tool", TerrainTools.class);
|
||||||
return !tool.requiresSelectedBlock();
|
return !tool.requiresSelectedBlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,11 +65,11 @@ public class WorldshaperItem extends ZapperItem {
|
||||||
List<BlockPos> affectedPositions = new ArrayList<>();
|
List<BlockPos> affectedPositions = new ArrayList<>();
|
||||||
|
|
||||||
CompoundNBT tag = stack.getOrCreateTag();
|
CompoundNBT tag = stack.getOrCreateTag();
|
||||||
Brush brush = NBTHelper.readEnum(tag.getString("Brush"), TerrainBrushes.class)
|
Brush brush = NBTHelper.readEnum(tag, "Brush", TerrainBrushes.class)
|
||||||
.get();
|
.get();
|
||||||
BlockPos params = NBTUtil.readBlockPos(tag.getCompound("BrushParams"));
|
BlockPos params = NBTUtil.readBlockPos(tag.getCompound("BrushParams"));
|
||||||
PlacementOptions option = NBTHelper.readEnum(tag.getString("Placement"), PlacementOptions.class);
|
PlacementOptions option = NBTHelper.readEnum(tag, "Placement", PlacementOptions.class);
|
||||||
TerrainTools tool = NBTHelper.readEnum(tag.getString("Tool"), TerrainTools.class);
|
TerrainTools tool = NBTHelper.readEnum(tag, "Tool", TerrainTools.class);
|
||||||
|
|
||||||
brush.set(params.getX(), params.getY(), params.getZ());
|
brush.set(params.getX(), params.getY(), params.getZ());
|
||||||
targetPos = targetPos.add(brush.getOffset(player.getLookVec(), raytrace.getFace(), option));
|
targetPos = targetPos.add(brush.getOffset(player.getLookVec(), raytrace.getFace(), option));
|
||||||
|
|
|
@ -69,9 +69,9 @@ public class WorldshaperRenderHandler {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Brush brush = NBTHelper.readEnum(tag.getString("Brush"), TerrainBrushes.class)
|
Brush brush = NBTHelper.readEnum(tag, "Brush", TerrainBrushes.class)
|
||||||
.get();
|
.get();
|
||||||
PlacementOptions placement = NBTHelper.readEnum(tag.getString("Placement"), PlacementOptions.class);
|
PlacementOptions placement = NBTHelper.readEnum(tag, "Placement", PlacementOptions.class);
|
||||||
BlockPos params = NBTUtil.readBlockPos(tag.getCompound("BrushParams"));
|
BlockPos params = NBTUtil.readBlockPos(tag.getCompound("BrushParams"));
|
||||||
brush.set(params.getX(), params.getY(), params.getZ());
|
brush.set(params.getX(), params.getY(), params.getZ());
|
||||||
renderedShape = brush.getIncludedPositions();
|
renderedShape = brush.getIncludedPositions();
|
||||||
|
|
|
@ -53,9 +53,12 @@ public class WorldshaperScreen extends ZapperScreen {
|
||||||
|
|
||||||
brushLabel = new Label(i + 58, j + 28, "").withShadow();
|
brushLabel = new Label(i + 58, j + 28, "").withShadow();
|
||||||
brushInput = new SelectionScrollInput(i + 55, j + 25, 78, 14).forOptions(brushOptions)
|
brushInput = new SelectionScrollInput(i + 55, j + 25, 78, 14).forOptions(brushOptions)
|
||||||
.titled(Lang.translate("gui.terrainzapper.brush")).writingTo(brushLabel).calling(this::brushChanged);
|
.titled(Lang.translate("gui.terrainzapper.brush"))
|
||||||
|
.writingTo(brushLabel)
|
||||||
|
.calling(this::brushChanged);
|
||||||
if (nbt.contains("Brush"))
|
if (nbt.contains("Brush"))
|
||||||
brushInput.setState(NBTHelper.readEnum(nbt.getString("Brush"), TerrainBrushes.class).ordinal());
|
brushInput.setState(NBTHelper.readEnum(nbt, "Brush", TerrainBrushes.class)
|
||||||
|
.ordinal());
|
||||||
|
|
||||||
widgets.add(brushLabel);
|
widgets.add(brushLabel);
|
||||||
widgets.add(brushInput);
|
widgets.add(brushInput);
|
||||||
|
@ -66,11 +69,13 @@ public class WorldshaperScreen extends ZapperScreen {
|
||||||
for (int id = 0; id < toolValues.length; id++) {
|
for (int id = 0; id < toolValues.length; id++) {
|
||||||
TerrainTools tool = toolValues[id];
|
TerrainTools tool = toolValues[id];
|
||||||
toolButtons.add(new IconButton(i + 8 + id * 18, j + 76, tool.icon));
|
toolButtons.add(new IconButton(i + 8 + id * 18, j + 76, tool.icon));
|
||||||
toolButtons.get(id).setToolTip(Lang.translate("gui.terrainzapper.tool." + tool.translationKey));
|
toolButtons.get(id)
|
||||||
|
.setToolTip(Lang.translate("gui.terrainzapper.tool." + tool.translationKey));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nbt.contains("Tool"))
|
if (nbt.contains("Tool"))
|
||||||
toolButtons.get(NBTHelper.readEnum(nbt.getString("Tool"), TerrainTools.class).ordinal()).active = false;
|
toolButtons.get(NBTHelper.readEnum(nbt, "Tool", TerrainTools.class)
|
||||||
|
.ordinal()).active = false;
|
||||||
widgets.addAll(toolButtons);
|
widgets.addAll(toolButtons);
|
||||||
|
|
||||||
placementButtons = new Vector<>(3);
|
placementButtons = new Vector<>(3);
|
||||||
|
@ -78,21 +83,25 @@ public class WorldshaperScreen extends ZapperScreen {
|
||||||
for (int id = 0; id < placementValues.length; id++) {
|
for (int id = 0; id < placementValues.length; id++) {
|
||||||
PlacementOptions option = placementValues[id];
|
PlacementOptions option = placementValues[id];
|
||||||
placementButtons.add(new IconButton(i + 147 + id * 18, j + 76, option.icon));
|
placementButtons.add(new IconButton(i + 147 + id * 18, j + 76, option.icon));
|
||||||
placementButtons.get(id).setToolTip(Lang.translate("gui.terrainzapper.placement." + option.translationKey));
|
placementButtons.get(id)
|
||||||
|
.setToolTip(Lang.translate("gui.terrainzapper.placement." + option.translationKey));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nbt.contains("Placement"))
|
if (nbt.contains("Placement"))
|
||||||
placementButtons
|
placementButtons.get(NBTHelper.readEnum(nbt, "Placement", PlacementOptions.class)
|
||||||
.get(NBTHelper.readEnum(nbt.getString("Placement"), PlacementOptions.class).ordinal()).active =
|
.ordinal()).active = false;
|
||||||
false;
|
|
||||||
widgets.addAll(placementButtons);
|
widgets.addAll(placementButtons);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void initBrushParams() {
|
public void initBrushParams() {
|
||||||
if (brushParams != null) {
|
if (brushParams != null) {
|
||||||
nbt.put("BrushParams", NBTUtil.writeBlockPos(new BlockPos(brushParams.get(0).getState(),
|
nbt.put("BrushParams", NBTUtil.writeBlockPos(new BlockPos(brushParams.get(0)
|
||||||
brushParams.get(1).getState(), brushParams.get(2).getState())));
|
.getState(),
|
||||||
|
brushParams.get(1)
|
||||||
|
.getState(),
|
||||||
|
brushParams.get(2)
|
||||||
|
.getState())));
|
||||||
|
|
||||||
widgets.removeAll(brushParamLabels);
|
widgets.removeAll(brushParamLabels);
|
||||||
widgets.removeAll(brushParams);
|
widgets.removeAll(brushParams);
|
||||||
|
@ -109,10 +118,12 @@ public class WorldshaperScreen extends ZapperScreen {
|
||||||
brushParamLabels.add(label);
|
brushParamLabels.add(label);
|
||||||
int indexFinal = index;
|
int indexFinal = index;
|
||||||
ScrollInput input = new ScrollInput(i + 55 + 18 * index, j + 43, 14, 14)
|
ScrollInput input = new ScrollInput(i + 55 + 18 * index, j + 43, 14, 14)
|
||||||
.withRange(currentBrush.getMin(index), currentBrush.getMax(index) + 1).writingTo(label)
|
.withRange(currentBrush.getMin(index), currentBrush.getMax(index) + 1)
|
||||||
.titled(currentBrush.getParamLabel(index)).calling(state -> {
|
.writingTo(label)
|
||||||
label.x = i + 62 + 18 * indexFinal - font.getStringWidth(label.text) / 2;
|
.titled(currentBrush.getParamLabel(index))
|
||||||
});
|
.calling(state -> {
|
||||||
|
label.x = i + 62 + 18 * indexFinal - font.getStringWidth(label.text) / 2;
|
||||||
|
});
|
||||||
input.setState(params[index]);
|
input.setState(params[index]);
|
||||||
input.onChanged();
|
input.onChanged();
|
||||||
if (index >= currentBrush.amtParams) {
|
if (index >= currentBrush.amtParams) {
|
||||||
|
@ -140,7 +151,8 @@ public class WorldshaperScreen extends ZapperScreen {
|
||||||
if (placementButton.isHovered()) {
|
if (placementButton.isHovered()) {
|
||||||
placementButtons.forEach(b -> b.active = true);
|
placementButtons.forEach(b -> b.active = true);
|
||||||
placementButton.active = false;
|
placementButton.active = false;
|
||||||
placementButton.playDownSound(Minecraft.getInstance().getSoundHandler());
|
placementButton.playDownSound(Minecraft.getInstance()
|
||||||
|
.getSoundHandler());
|
||||||
nbt.putString("Placement", PlacementOptions.values()[placementButtons.indexOf(placementButton)].name());
|
nbt.putString("Placement", PlacementOptions.values()[placementButtons.indexOf(placementButton)].name());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -149,7 +161,8 @@ public class WorldshaperScreen extends ZapperScreen {
|
||||||
if (toolButton.isHovered()) {
|
if (toolButton.isHovered()) {
|
||||||
toolButtons.forEach(b -> b.active = true);
|
toolButtons.forEach(b -> b.active = true);
|
||||||
toolButton.active = false;
|
toolButton.active = false;
|
||||||
toolButton.playDownSound(Minecraft.getInstance().getSoundHandler());
|
toolButton.playDownSound(Minecraft.getInstance()
|
||||||
|
.getSoundHandler());
|
||||||
nbt.putString("Tool", TerrainTools.values()[toolButtons.indexOf(toolButton)].name());
|
nbt.putString("Tool", TerrainTools.values()[toolButtons.indexOf(toolButton)].name());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -173,9 +186,13 @@ public class WorldshaperScreen extends ZapperScreen {
|
||||||
@Override
|
@Override
|
||||||
protected void writeAdditionalOptions(CompoundNBT nbt) {
|
protected void writeAdditionalOptions(CompoundNBT nbt) {
|
||||||
super.writeAdditionalOptions(nbt);
|
super.writeAdditionalOptions(nbt);
|
||||||
nbt.putString("Brush", NBTHelper.writeEnum(TerrainBrushes.values()[brushInput.getState()]));
|
NBTHelper.writeEnum(nbt, "Brush", TerrainBrushes.values()[brushInput.getState()]);
|
||||||
nbt.put("BrushParams", NBTUtil.writeBlockPos(new BlockPos(brushParams.get(0).getState(),
|
nbt.put("BrushParams", NBTUtil.writeBlockPos(new BlockPos(brushParams.get(0)
|
||||||
brushParams.get(1).getState(), brushParams.get(2).getState())));
|
.getState(),
|
||||||
|
brushParams.get(1)
|
||||||
|
.getState(),
|
||||||
|
brushParams.get(2)
|
||||||
|
.getState())));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,12 +39,12 @@ public class DepotRenderer extends SafeTileEntityRenderer<DepotTileEntity> {
|
||||||
msr.nudge(0);
|
msr.nudge(0);
|
||||||
float offset = MathHelper.lerp(partialTicks, transported.prevBeltPosition, transported.beltPosition);
|
float offset = MathHelper.lerp(partialTicks, transported.prevBeltPosition, transported.beltPosition);
|
||||||
float sideOffset = MathHelper.lerp(partialTicks, transported.prevSideOffset, transported.sideOffset);
|
float sideOffset = MathHelper.lerp(partialTicks, transported.prevSideOffset, transported.sideOffset);
|
||||||
Vec3d offsetVec = new Vec3d(transported.insertedFrom.getOpposite()
|
|
||||||
.getDirectionVec()).scale(.5f - offset);
|
|
||||||
ms.translate(offsetVec.x, offsetVec.y, offsetVec.z);
|
|
||||||
|
|
||||||
if (transported.insertedFrom.getAxis()
|
if (transported.insertedFrom.getAxis()
|
||||||
.isHorizontal()) {
|
.isHorizontal()) {
|
||||||
|
Vec3d offsetVec = new Vec3d(transported.insertedFrom.getOpposite()
|
||||||
|
.getDirectionVec()).scale(.5f - offset);
|
||||||
|
ms.translate(offsetVec.x, offsetVec.y, offsetVec.z);
|
||||||
boolean alongX = transported.insertedFrom.rotateY()
|
boolean alongX = transported.insertedFrom.rotateY()
|
||||||
.getAxis() == Axis.X;
|
.getAxis() == Axis.X;
|
||||||
if (!alongX)
|
if (!alongX)
|
||||||
|
|
|
@ -84,6 +84,13 @@ public class DepotTileEntity extends SmartTileEntity {
|
||||||
if (heldItem.locked != wasLocked || !previousItem.equals(heldItem.stack, false))
|
if (heldItem.locked != wasLocked || !previousItem.equals(heldItem.stack, false))
|
||||||
sendData();
|
sendData();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void remove() {
|
||||||
|
super.remove();
|
||||||
|
if (lazyItemHandler != null)
|
||||||
|
lazyItemHandler.invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompoundNBT write(CompoundNBT compound) {
|
public CompoundNBT write(CompoundNBT compound) {
|
||||||
|
|
|
@ -0,0 +1,77 @@
|
||||||
|
package com.simibubi.create.content.logistics.block.mechanicalArm;
|
||||||
|
|
||||||
|
import com.simibubi.create.foundation.utility.AngleHelper;
|
||||||
|
import com.simibubi.create.foundation.utility.VecHelper;
|
||||||
|
|
||||||
|
import net.minecraft.util.Direction;
|
||||||
|
import net.minecraft.util.Direction.Axis;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.util.math.MathHelper;
|
||||||
|
import net.minecraft.util.math.Vec3d;
|
||||||
|
|
||||||
|
public class ArmAngleTarget {
|
||||||
|
|
||||||
|
static ArmAngleTarget NO_TARGET = new ArmAngleTarget();
|
||||||
|
|
||||||
|
float baseAngle;
|
||||||
|
float lowerArmAngle;
|
||||||
|
float upperArmAngle;
|
||||||
|
float headAngle;
|
||||||
|
|
||||||
|
private ArmAngleTarget() {
|
||||||
|
lowerArmAngle = 155;
|
||||||
|
upperArmAngle = 60;
|
||||||
|
headAngle = -15;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArmAngleTarget(BlockPos armPos, Vec3d pointTarget, Direction clawFacing) {
|
||||||
|
Vec3d target = pointTarget;
|
||||||
|
Vec3d origin = VecHelper.getCenterOf(armPos)
|
||||||
|
.add(0, 4 / 16f, 0);
|
||||||
|
Vec3d clawTarget = target;
|
||||||
|
target = target.add(new Vec3d(clawFacing.getOpposite()
|
||||||
|
.getDirectionVec()).scale(.5f));
|
||||||
|
|
||||||
|
Vec3d diff = target.subtract(origin);
|
||||||
|
float horizontalDistance = (float) diff.mul(1, 0, 1)
|
||||||
|
.length();
|
||||||
|
|
||||||
|
float baseAngle = AngleHelper.deg(MathHelper.atan2(diff.x, diff.z)) + 180;
|
||||||
|
float alphaOffset = AngleHelper.deg(MathHelper.atan2(diff.y, horizontalDistance));
|
||||||
|
|
||||||
|
float a = 18 / 16f; // lower arm length
|
||||||
|
float a2 = a * a;
|
||||||
|
float b = 17 / 16f; // upper arm length
|
||||||
|
float b2 = b * b;
|
||||||
|
float diffLength =
|
||||||
|
MathHelper.clamp(MathHelper.sqrt(diff.y * diff.y + horizontalDistance * horizontalDistance), 1 / 8f, a + b);
|
||||||
|
float diffLength2 = diffLength * diffLength;
|
||||||
|
|
||||||
|
float alphaRatio = (-b2 + a2 + diffLength2) / (2 * a * diffLength);
|
||||||
|
float alpha = AngleHelper.deg(Math.acos(alphaRatio)) + alphaOffset;
|
||||||
|
float betaRatio = (-diffLength2 + a2 + b2) / (2 * b * a);
|
||||||
|
float beta = AngleHelper.deg(Math.acos(betaRatio));
|
||||||
|
|
||||||
|
if (Float.isNaN(alpha))
|
||||||
|
alpha = 0;
|
||||||
|
if (Float.isNaN(beta))
|
||||||
|
beta = 0;
|
||||||
|
|
||||||
|
Vec3d headPos = new Vec3d(0, 0, 0);
|
||||||
|
headPos = VecHelper.rotate(headPos.add(0, b, 0), beta + 180, Axis.X);
|
||||||
|
headPos = VecHelper.rotate(headPos.add(0, a, 0), alpha - 90, Axis.X);
|
||||||
|
headPos = VecHelper.rotate(headPos, baseAngle, Axis.Y);
|
||||||
|
headPos = headPos.add(origin);
|
||||||
|
Vec3d headDiff = clawTarget.subtract(headPos);
|
||||||
|
float horizontalHeadDistance = (float) headDiff.mul(1, 0, 1)
|
||||||
|
.length();
|
||||||
|
float headAngle =
|
||||||
|
(float) (alpha + beta + 135 - AngleHelper.deg(MathHelper.atan2(headDiff.y, horizontalHeadDistance)));
|
||||||
|
|
||||||
|
this.lowerArmAngle = alpha;
|
||||||
|
this.upperArmAngle = beta;
|
||||||
|
this.headAngle = -headAngle;
|
||||||
|
this.baseAngle = baseAngle;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -6,18 +6,13 @@ import com.simibubi.create.content.contraptions.base.KineticBlock;
|
||||||
import com.simibubi.create.foundation.block.ITE;
|
import com.simibubi.create.foundation.block.ITE;
|
||||||
|
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
|
||||||
import net.minecraft.tileentity.TileEntity;
|
import net.minecraft.tileentity.TileEntity;
|
||||||
import net.minecraft.util.ActionResultType;
|
|
||||||
import net.minecraft.util.Direction.Axis;
|
import net.minecraft.util.Direction.Axis;
|
||||||
import net.minecraft.util.Hand;
|
|
||||||
import net.minecraft.util.math.BlockPos;
|
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.ISelectionContext;
|
||||||
import net.minecraft.util.math.shapes.VoxelShape;
|
import net.minecraft.util.math.shapes.VoxelShape;
|
||||||
import net.minecraft.world.IBlockReader;
|
import net.minecraft.world.IBlockReader;
|
||||||
import net.minecraft.world.IWorldReader;
|
import net.minecraft.world.IWorldReader;
|
||||||
import net.minecraft.world.World;
|
|
||||||
|
|
||||||
public class ArmBlock extends KineticBlock implements ITE<ArmTileEntity> {
|
public class ArmBlock extends KineticBlock implements ITE<ArmTileEntity> {
|
||||||
|
|
||||||
|
@ -30,14 +25,6 @@ public class ArmBlock extends KineticBlock implements ITE<ArmTileEntity> {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public ActionResultType onUse(BlockState p_225533_1_, World p_225533_2_, BlockPos p_225533_3_,
|
|
||||||
PlayerEntity p_225533_4_, Hand p_225533_5_, BlockRayTraceResult p_225533_6_) {
|
|
||||||
withTileEntityDo(p_225533_2_, p_225533_3_, ArmTileEntity::toggleRave);
|
|
||||||
return ActionResultType.SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public VoxelShape getShape(BlockState p_220053_1_, IBlockReader p_220053_2_, BlockPos p_220053_3_,
|
public VoxelShape getShape(BlockState p_220053_1_, IBlockReader p_220053_2_, BlockPos p_220053_3_,
|
||||||
ISelectionContext p_220053_4_) {
|
ISelectionContext p_220053_4_) {
|
||||||
|
|
|
@ -0,0 +1,234 @@
|
||||||
|
package com.simibubi.create.content.logistics.block.mechanicalArm;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||||
|
import com.simibubi.create.AllBlockPartials;
|
||||||
|
import com.simibubi.create.AllBlocks;
|
||||||
|
import com.simibubi.create.content.logistics.block.realityFunnel.RealityFunnelBlock;
|
||||||
|
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
|
||||||
|
import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringBehaviour;
|
||||||
|
import com.simibubi.create.foundation.tileEntity.behaviour.inventory.InsertingBehaviour;
|
||||||
|
import com.simibubi.create.foundation.utility.NBTHelper;
|
||||||
|
import com.simibubi.create.foundation.utility.VecHelper;
|
||||||
|
|
||||||
|
import net.minecraft.block.BlockState;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.nbt.CompoundNBT;
|
||||||
|
import net.minecraft.nbt.NBTUtil;
|
||||||
|
import net.minecraft.tileentity.TileEntity;
|
||||||
|
import net.minecraft.util.Direction;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.util.math.Vec3d;
|
||||||
|
import net.minecraft.world.IBlockReader;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
|
import net.minecraftforge.common.util.LazyOptional;
|
||||||
|
import net.minecraftforge.items.CapabilityItemHandler;
|
||||||
|
import net.minecraftforge.items.IItemHandler;
|
||||||
|
import net.minecraftforge.items.ItemHandlerHelper;
|
||||||
|
|
||||||
|
public abstract class ArmInteractionPoint {
|
||||||
|
|
||||||
|
static enum Mode {
|
||||||
|
DEPOSIT, TAKE
|
||||||
|
}
|
||||||
|
|
||||||
|
BlockPos pos;
|
||||||
|
BlockState state;
|
||||||
|
Mode mode;
|
||||||
|
|
||||||
|
private LazyOptional<IItemHandler> cachedHandler;
|
||||||
|
private ArmAngleTarget cachedAngles;
|
||||||
|
|
||||||
|
public ArmInteractionPoint() {
|
||||||
|
cachedHandler = LazyOptional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnlyIn(Dist.CLIENT)
|
||||||
|
void transformFlag(MatrixStack stack) {}
|
||||||
|
|
||||||
|
AllBlockPartials getFlagType() {
|
||||||
|
return mode == Mode.TAKE ? AllBlockPartials.FLAG_LONG_OUT : AllBlockPartials.FLAG_LONG_IN;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cycleMode() {
|
||||||
|
mode = mode == Mode.DEPOSIT ? Mode.TAKE : Mode.DEPOSIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec3d getInteractionPositionVector() {
|
||||||
|
return VecHelper.getCenterOf(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
Direction getInteractionDirection() {
|
||||||
|
return Direction.DOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract boolean isValid(BlockState state);
|
||||||
|
|
||||||
|
static boolean isInteractable(BlockState state) {
|
||||||
|
return AllBlocks.DEPOT.has(state) || AllBlocks.BELT.has(state) || AllBlocks.CHUTE.has(state)
|
||||||
|
|| AllBlocks.REALITY_FUNNEL.has(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
ArmAngleTarget getTargetAngles(BlockPos armPos) {
|
||||||
|
if (cachedAngles == null)
|
||||||
|
cachedAngles = new ArmAngleTarget(armPos, getInteractionPositionVector(), getInteractionDirection());
|
||||||
|
return cachedAngles;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
IItemHandler getHandler(World world) {
|
||||||
|
if (!cachedHandler.isPresent()) {
|
||||||
|
TileEntity te = world.getTileEntity(pos);
|
||||||
|
if (te == null)
|
||||||
|
return null;
|
||||||
|
cachedHandler = te.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, Direction.UP);
|
||||||
|
}
|
||||||
|
return cachedHandler.orElse(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
ItemStack insert(World world, ItemStack stack, boolean simulate) {
|
||||||
|
IItemHandler handler = getHandler(world);
|
||||||
|
if (handler == null)
|
||||||
|
return stack;
|
||||||
|
return ItemHandlerHelper.insertItem(handler, stack, simulate);
|
||||||
|
}
|
||||||
|
|
||||||
|
ItemStack extract(World world, int slot, int amount, boolean simulate) {
|
||||||
|
IItemHandler handler = getHandler(world);
|
||||||
|
if (handler == null)
|
||||||
|
return ItemStack.EMPTY;
|
||||||
|
return handler.extractItem(slot, amount, simulate);
|
||||||
|
}
|
||||||
|
|
||||||
|
ItemStack extract(World world, int slot, boolean simulate) {
|
||||||
|
return extract(world, slot, 64, simulate);
|
||||||
|
}
|
||||||
|
|
||||||
|
int getSlotCount(World world) {
|
||||||
|
IItemHandler handler = getHandler(world);
|
||||||
|
if (handler == null)
|
||||||
|
return 0;
|
||||||
|
return handler.getSlots();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
static ArmInteractionPoint createAt(IBlockReader world, BlockPos pos) {
|
||||||
|
BlockState state = world.getBlockState(pos);
|
||||||
|
ArmInteractionPoint point = null;
|
||||||
|
|
||||||
|
if (AllBlocks.DEPOT.has(state))
|
||||||
|
point = new Depot();
|
||||||
|
if (AllBlocks.BELT.has(state))
|
||||||
|
point = new Belt();
|
||||||
|
if (AllBlocks.CHUTE.has(state))
|
||||||
|
point = new Chute();
|
||||||
|
if (AllBlocks.REALITY_FUNNEL.has(state))
|
||||||
|
point = new Funnel();
|
||||||
|
|
||||||
|
if (point != null) {
|
||||||
|
point.state = state;
|
||||||
|
point.pos = pos;
|
||||||
|
point.mode = Mode.DEPOSIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return point;
|
||||||
|
}
|
||||||
|
|
||||||
|
CompoundNBT serialize() {
|
||||||
|
CompoundNBT nbt = new CompoundNBT();
|
||||||
|
nbt.put("Pos", NBTUtil.writeBlockPos(pos));
|
||||||
|
NBTHelper.writeEnum(nbt, "Mode", mode);
|
||||||
|
return nbt;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ArmInteractionPoint deserialize(IBlockReader world, CompoundNBT nbt) {
|
||||||
|
BlockPos pos = NBTUtil.readBlockPos(nbt.getCompound("Pos"));
|
||||||
|
ArmInteractionPoint interactionPoint = createAt(world, pos);
|
||||||
|
interactionPoint.mode = NBTHelper.readEnum(nbt, "Mode", Mode.class);
|
||||||
|
return interactionPoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
static class Depot extends ArmInteractionPoint {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
Vec3d getInteractionPositionVector() {
|
||||||
|
return new Vec3d(pos).add(.5f, 14 / 16f, .5f);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
boolean isValid(BlockState state) {
|
||||||
|
return AllBlocks.DEPOT.has(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static class Belt extends Depot {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
boolean isValid(BlockState state) {
|
||||||
|
return AllBlocks.BELT.has(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class Chute extends ArmInteractionPoint {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
Vec3d getInteractionPositionVector() {
|
||||||
|
return new Vec3d(pos).add(.5f, 1, .5f);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
boolean isValid(BlockState state) {
|
||||||
|
return AllBlocks.CHUTE.has(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class Funnel extends ArmInteractionPoint {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
Vec3d getInteractionPositionVector() {
|
||||||
|
return VecHelper.getCenterOf(pos)
|
||||||
|
.add(new Vec3d(RealityFunnelBlock.getFunnelFacing(state)
|
||||||
|
.getDirectionVec()).scale(.5f));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
int getSlotCount(World world) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
ItemStack extract(World world, int slot, int amount, boolean simulate) {
|
||||||
|
return ItemStack.EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
Direction getInteractionDirection() {
|
||||||
|
return RealityFunnelBlock.getFunnelFacing(state).getOpposite();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
ItemStack insert(World world, ItemStack stack, boolean simulate) {
|
||||||
|
FilteringBehaviour filtering = TileEntityBehaviour.get(world, pos, FilteringBehaviour.TYPE);
|
||||||
|
InsertingBehaviour inserter = TileEntityBehaviour.get(world, pos, InsertingBehaviour.TYPE);
|
||||||
|
if (inserter == null)
|
||||||
|
return stack;
|
||||||
|
if (filtering != null && !filtering.test(stack))
|
||||||
|
return stack;
|
||||||
|
return inserter.insert(stack, simulate);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
boolean isValid(BlockState state) {
|
||||||
|
return AllBlocks.REALITY_FUNNEL.has(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void cycleMode() {}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,115 @@
|
||||||
|
package com.simibubi.create.content.logistics.block.mechanicalArm;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
|
import com.simibubi.create.AllBlocks;
|
||||||
|
import com.simibubi.create.CreateClient;
|
||||||
|
import com.simibubi.create.content.logistics.block.mechanicalArm.ArmInteractionPoint.Mode;
|
||||||
|
import com.simibubi.create.foundation.networking.AllPackets;
|
||||||
|
|
||||||
|
import net.minecraft.block.BlockState;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.util.ActionResultType;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.util.math.shapes.VoxelShape;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
|
import net.minecraftforge.event.entity.player.PlayerInteractEvent;
|
||||||
|
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||||
|
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
|
||||||
|
|
||||||
|
@EventBusSubscriber(value = Dist.CLIENT)
|
||||||
|
public class ArmInteractionPointHandler {
|
||||||
|
|
||||||
|
static Map<BlockPos, ArmInteractionPoint> currentSelection = new HashMap<>();
|
||||||
|
static ItemStack currentItem;
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public static void rightClickingBlocksSelectsThem(PlayerInteractEvent.RightClickBlock event) {
|
||||||
|
if (currentItem == null)
|
||||||
|
return;
|
||||||
|
BlockPos pos = event.getPos();
|
||||||
|
World world = event.getWorld();
|
||||||
|
if (!world.isRemote)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!currentSelection.containsKey(pos)) {
|
||||||
|
ArmInteractionPoint point = ArmInteractionPoint.createAt(world, pos);
|
||||||
|
if (point == null)
|
||||||
|
return;
|
||||||
|
currentSelection.put(pos, point);
|
||||||
|
}
|
||||||
|
|
||||||
|
currentSelection.get(pos)
|
||||||
|
.cycleMode();
|
||||||
|
event.setCanceled(true);
|
||||||
|
event.setCancellationResult(ActionResultType.SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public static void leftClickingBlocksDeselectsThem(PlayerInteractEvent.LeftClickBlock event) {
|
||||||
|
if (currentItem == null)
|
||||||
|
return;
|
||||||
|
if (!event.getWorld().isRemote)
|
||||||
|
return;
|
||||||
|
BlockPos pos = event.getPos();
|
||||||
|
if (currentSelection.remove(pos) != null) {
|
||||||
|
event.setCanceled(true);
|
||||||
|
event.setCancellationResult(ActionResultType.SUCCESS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void flushSettings(BlockPos pos) {
|
||||||
|
if (currentItem == null)
|
||||||
|
return;
|
||||||
|
AllPackets.channel.sendToServer(new ArmPlacementPacket(currentSelection.values(), pos));
|
||||||
|
currentSelection.clear();
|
||||||
|
currentItem = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void tick() {
|
||||||
|
PlayerEntity player = Minecraft.getInstance().player;
|
||||||
|
World world = Minecraft.getInstance().world;
|
||||||
|
if (player == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ItemStack heldItemMainhand = player.getHeldItemMainhand();
|
||||||
|
if (!AllBlocks.MECHANICAL_ARM.isIn(heldItemMainhand)) {
|
||||||
|
currentItem = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (heldItemMainhand != currentItem) {
|
||||||
|
currentSelection.clear();
|
||||||
|
currentItem = heldItemMainhand;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Iterator<Entry<BlockPos, ArmInteractionPoint>> iterator = currentSelection.entrySet()
|
||||||
|
.iterator(); iterator.hasNext();) {
|
||||||
|
Entry<BlockPos, ArmInteractionPoint> entry = iterator.next();
|
||||||
|
BlockPos pos = entry.getKey();
|
||||||
|
BlockState state = world.getBlockState(pos);
|
||||||
|
ArmInteractionPoint point = entry.getValue();
|
||||||
|
|
||||||
|
if (!point.isValid(state)) {
|
||||||
|
iterator.remove();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
VoxelShape shape = state.getShape(world, pos);
|
||||||
|
if (shape.isEmpty())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int color = point.mode == Mode.DEPOSIT ? 0xffcb74 : 0x4f8a8b;
|
||||||
|
CreateClient.outliner.showAABB(point, shape.getBoundingBox()
|
||||||
|
.offset(pos))
|
||||||
|
.colored(color)
|
||||||
|
.lineWidth(1 / 16f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
package com.simibubi.create.content.logistics.block.mechanicalArm;
|
||||||
|
|
||||||
|
import net.minecraft.block.Block;
|
||||||
|
import net.minecraft.block.BlockState;
|
||||||
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
|
import net.minecraft.item.BlockItem;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.item.ItemUseContext;
|
||||||
|
import net.minecraft.util.ActionResultType;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
|
import net.minecraftforge.fml.DistExecutor;
|
||||||
|
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
|
||||||
|
|
||||||
|
@EventBusSubscriber
|
||||||
|
public class ArmItem extends BlockItem {
|
||||||
|
|
||||||
|
public ArmItem(Block p_i48527_1_, Properties p_i48527_2_) {
|
||||||
|
super(p_i48527_1_, p_i48527_2_);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ActionResultType onItemUse(ItemUseContext ctx) {
|
||||||
|
if (ArmInteractionPoint.isInteractable(ctx.getWorld()
|
||||||
|
.getBlockState(ctx.getPos())))
|
||||||
|
return ActionResultType.SUCCESS;
|
||||||
|
return super.onItemUse(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean onBlockPlaced(BlockPos pos, World world, PlayerEntity p_195943_3_, ItemStack p_195943_4_,
|
||||||
|
BlockState p_195943_5_) {
|
||||||
|
if (world.isRemote)
|
||||||
|
DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> ArmInteractionPointHandler.flushSettings(pos));
|
||||||
|
return super.onBlockPlaced(pos, world, p_195943_3_, p_195943_4_, p_195943_5_);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canPlayerBreakBlockWhileHolding(BlockState state, World p_195938_2_, BlockPos p_195938_3_,
|
||||||
|
PlayerEntity p_195938_4_) {
|
||||||
|
return !ArmInteractionPoint.isInteractable(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,70 @@
|
||||||
|
package com.simibubi.create.content.logistics.block.mechanicalArm;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import com.simibubi.create.foundation.networking.SimplePacketBase;
|
||||||
|
|
||||||
|
import net.minecraft.entity.player.ServerPlayerEntity;
|
||||||
|
import net.minecraft.nbt.CompoundNBT;
|
||||||
|
import net.minecraft.nbt.ListNBT;
|
||||||
|
import net.minecraft.network.PacketBuffer;
|
||||||
|
import net.minecraft.tileentity.TileEntity;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
import net.minecraftforge.common.util.Constants.NBT;
|
||||||
|
import net.minecraftforge.fml.network.NetworkEvent.Context;
|
||||||
|
|
||||||
|
public class ArmPlacementPacket extends SimplePacketBase {
|
||||||
|
|
||||||
|
private Collection<ArmInteractionPoint> points;
|
||||||
|
private ListNBT receivedTag;
|
||||||
|
private BlockPos pos;
|
||||||
|
|
||||||
|
public ArmPlacementPacket(Collection<ArmInteractionPoint> points, BlockPos pos) {
|
||||||
|
this.points = points;
|
||||||
|
this.pos = pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArmPlacementPacket(PacketBuffer buffer) {
|
||||||
|
CompoundNBT nbt = buffer.readCompoundTag();
|
||||||
|
receivedTag = nbt.getList("Points", NBT.TAG_COMPOUND);
|
||||||
|
pos = buffer.readBlockPos();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(PacketBuffer buffer) {
|
||||||
|
CompoundNBT nbt = new CompoundNBT();
|
||||||
|
ListNBT pointsNBT = new ListNBT();
|
||||||
|
points.stream()
|
||||||
|
.map(ArmInteractionPoint::serialize)
|
||||||
|
.forEach(pointsNBT::add);
|
||||||
|
nbt.put("Points", pointsNBT);
|
||||||
|
buffer.writeCompoundTag(nbt);
|
||||||
|
buffer.writeBlockPos(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(Supplier<Context> context) {
|
||||||
|
context.get()
|
||||||
|
.enqueueWork(() -> {
|
||||||
|
ServerPlayerEntity player = context.get()
|
||||||
|
.getSender();
|
||||||
|
if (player == null)
|
||||||
|
return;
|
||||||
|
World world = player.world;
|
||||||
|
if (world == null)
|
||||||
|
return;
|
||||||
|
TileEntity tileEntity = world.getTileEntity(pos);
|
||||||
|
if (tileEntity == null || !(tileEntity instanceof ArmTileEntity))
|
||||||
|
return;
|
||||||
|
|
||||||
|
ArmTileEntity arm = (ArmTileEntity) tileEntity;
|
||||||
|
arm.interactionPointTag = receivedTag;
|
||||||
|
});
|
||||||
|
context.get()
|
||||||
|
.setPacketHandled(true);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -5,17 +5,19 @@ import com.mojang.blaze3d.vertex.IVertexBuilder;
|
||||||
import com.simibubi.create.AllBlockPartials;
|
import com.simibubi.create.AllBlockPartials;
|
||||||
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
|
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
|
||||||
import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer;
|
import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer;
|
||||||
import com.simibubi.create.foundation.utility.AnimationTickHolder;
|
|
||||||
import com.simibubi.create.foundation.utility.ColorHelper;
|
|
||||||
import com.simibubi.create.foundation.utility.Iterate;
|
import com.simibubi.create.foundation.utility.Iterate;
|
||||||
import com.simibubi.create.foundation.utility.MatrixStacker;
|
import com.simibubi.create.foundation.utility.MatrixStacker;
|
||||||
import com.simibubi.create.foundation.utility.SuperByteBuffer;
|
import com.simibubi.create.foundation.utility.SuperByteBuffer;
|
||||||
|
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.renderer.IRenderTypeBuffer;
|
import net.minecraft.client.renderer.IRenderTypeBuffer;
|
||||||
|
import net.minecraft.client.renderer.ItemRenderer;
|
||||||
import net.minecraft.client.renderer.RenderType;
|
import net.minecraft.client.renderer.RenderType;
|
||||||
|
import net.minecraft.client.renderer.model.ItemCameraTransforms.TransformType;
|
||||||
import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher;
|
import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher;
|
||||||
import net.minecraft.util.math.MathHelper;
|
import net.minecraft.item.BlockItem;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
|
||||||
public class ArmRenderer extends KineticTileEntityRenderer {
|
public class ArmRenderer extends KineticTileEntityRenderer {
|
||||||
|
|
||||||
|
@ -24,25 +26,15 @@ public class ArmRenderer extends KineticTileEntityRenderer {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void renderSafe(KineticTileEntity te, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer,
|
protected void renderSafe(KineticTileEntity te, float pt, MatrixStack ms, IRenderTypeBuffer buffer, int light,
|
||||||
int light, int overlay) {
|
int overlay) {
|
||||||
super.renderSafe(te, partialTicks, ms, buffer, light, overlay);
|
super.renderSafe(te, pt, ms, buffer, light, overlay);
|
||||||
|
ArmTileEntity arm = (ArmTileEntity) te;
|
||||||
IVertexBuilder builder = buffer.getBuffer(RenderType.getSolid());
|
IVertexBuilder builder = buffer.getBuffer(RenderType.getSolid());
|
||||||
BlockState blockState = te.getBlockState();
|
BlockState blockState = te.getBlockState();
|
||||||
MatrixStacker msr = MatrixStacker.of(ms);
|
MatrixStacker msr = MatrixStacker.of(ms);
|
||||||
|
|
||||||
float angle = 0;
|
|
||||||
float clawAngle = -25;
|
|
||||||
float otherAngle = 0;
|
|
||||||
int color = 0xFFFFFF;
|
int color = 0xFFFFFF;
|
||||||
|
|
||||||
boolean rave = te instanceof ArmTileEntity && ((ArmTileEntity) te).debugRave;
|
|
||||||
if (rave) {
|
|
||||||
clawAngle = angle = MathHelper.lerp((MathHelper.sin(AnimationTickHolder.getRenderTick() / 2) + 1) / 2, -45, 15);
|
|
||||||
otherAngle = MathHelper.lerp((MathHelper.sin(AnimationTickHolder.getRenderTick() / 4) + 1) / 2, -95, 95);
|
|
||||||
color = ColorHelper.rainbowColor(AnimationTickHolder.ticks * 100);
|
|
||||||
}
|
|
||||||
|
|
||||||
ms.push();
|
ms.push();
|
||||||
|
|
||||||
SuperByteBuffer base = AllBlockPartials.ARM_BASE.renderOn(blockState);
|
SuperByteBuffer base = AllBlockPartials.ARM_BASE.renderOn(blockState);
|
||||||
|
@ -55,33 +47,51 @@ public class ArmRenderer extends KineticTileEntityRenderer {
|
||||||
msr.centre();
|
msr.centre();
|
||||||
|
|
||||||
ms.translate(0, 4 / 16d, 0);
|
ms.translate(0, 4 / 16d, 0);
|
||||||
msr.rotateY(rave ? AnimationTickHolder.getRenderTick() * 10 : 0);
|
msr.rotateY(arm.baseAngle.get(pt));
|
||||||
base.renderInto(ms, builder);
|
base.renderInto(ms, builder);
|
||||||
|
|
||||||
ms.translate(0, 1 / 16d, -2 / 16d);
|
ms.translate(0, 1 / 16d, -2 / 16d);
|
||||||
msr.rotateX(angle);
|
msr.rotateX(arm.lowerArmAngle.get(pt) - 135);
|
||||||
ms.translate(0, -1 / 16d, 0);
|
ms.translate(0, -1 / 16d, 0);
|
||||||
lowerBody.color(color).renderInto(ms, builder);
|
lowerBody.color(color)
|
||||||
|
.renderInto(ms, builder);
|
||||||
|
|
||||||
ms.translate(0, 12 / 16d, 12 / 16d);
|
ms.translate(0, 12 / 16d, 12 / 16d);
|
||||||
msr.rotateX(-otherAngle / 2f);
|
msr.rotateX(arm.upperArmAngle.get(pt) - 90);
|
||||||
upperBody.color(color).renderInto(ms, builder);
|
upperBody.color(color)
|
||||||
|
.renderInto(ms, builder);
|
||||||
|
|
||||||
ms.translate(0, 11 / 16d, -11 / 16d);
|
ms.translate(0, 11 / 16d, -11 / 16d);
|
||||||
msr.rotateX(-angle);
|
msr.rotateX(arm.headAngle.get(pt));
|
||||||
head.renderInto(ms, builder);
|
head.renderInto(ms, builder);
|
||||||
|
|
||||||
ms.translate(0, 0, -4 / 16d);
|
ms.translate(0, 0, -4 / 16d);
|
||||||
claw.renderInto(ms, builder);
|
claw.renderInto(ms, builder);
|
||||||
|
ItemStack item = arm.heldItem;
|
||||||
|
ItemRenderer itemRenderer = Minecraft.getInstance()
|
||||||
|
.getItemRenderer();
|
||||||
|
boolean hasItem = !item.isEmpty();
|
||||||
|
boolean isBlockItem = hasItem && (item.getItem() instanceof BlockItem)
|
||||||
|
&& itemRenderer.getItemModelWithOverrides(item, Minecraft.getInstance().world, null)
|
||||||
|
.isGui3d();
|
||||||
|
|
||||||
for (int flip : Iterate.positiveAndNegative) {
|
for (int flip : Iterate.positiveAndNegative) {
|
||||||
ms.push();
|
ms.push();
|
||||||
ms.translate(0, flip * 3 / 16d, -1 / 16d);
|
ms.translate(0, flip * 3 / 16d, -1 / 16d);
|
||||||
msr.rotateX(flip * clawAngle);
|
msr.rotateX(flip * (hasItem ? isBlockItem ? 0 : -35 : 0));
|
||||||
clawGrip.renderInto(ms, builder);
|
clawGrip.renderInto(ms, builder);
|
||||||
ms.pop();
|
ms.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (hasItem) {
|
||||||
|
float itemScale = isBlockItem ? .5f : .625f;
|
||||||
|
msr.rotateX(90);
|
||||||
|
ms.translate(0, -4 / 16f, 0);
|
||||||
|
ms.scale(itemScale, itemScale, itemScale);
|
||||||
|
itemRenderer
|
||||||
|
.renderItem(item, TransformType.FIXED, light, overlay, ms, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
ms.pop();
|
ms.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,45 +1,297 @@
|
||||||
package com.simibubi.create.content.logistics.block.mechanicalArm;
|
package com.simibubi.create.content.logistics.block.mechanicalArm;
|
||||||
|
|
||||||
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
|
||||||
|
import com.simibubi.create.content.logistics.block.mechanicalArm.ArmInteractionPoint.Mode;
|
||||||
|
import com.simibubi.create.foundation.gui.widgets.InterpolatedAngle;
|
||||||
|
import com.simibubi.create.foundation.utility.AngleHelper;
|
||||||
|
import com.simibubi.create.foundation.utility.NBTHelper;
|
||||||
|
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.nbt.CompoundNBT;
|
import net.minecraft.nbt.CompoundNBT;
|
||||||
|
import net.minecraft.nbt.INBT;
|
||||||
|
import net.minecraft.nbt.ListNBT;
|
||||||
import net.minecraft.tileentity.TileEntityType;
|
import net.minecraft.tileentity.TileEntityType;
|
||||||
|
import net.minecraft.util.math.MathHelper;
|
||||||
|
import net.minecraftforge.common.util.Constants.NBT;
|
||||||
|
|
||||||
public class ArmTileEntity extends KineticTileEntity {
|
public class ArmTileEntity extends KineticTileEntity {
|
||||||
|
|
||||||
boolean debugRave;
|
// Server
|
||||||
|
List<ArmInteractionPoint> inputs;
|
||||||
public ArmTileEntity(TileEntityType<?> typeIn) {
|
List<ArmInteractionPoint> outputs;
|
||||||
super(typeIn);
|
ListNBT interactionPointTag;
|
||||||
}
|
|
||||||
|
// Both
|
||||||
@Override
|
float chasedPointProgress;
|
||||||
public void lazyTick() {
|
int chasedPointIndex;
|
||||||
if (hasWorld())
|
ItemStack heldItem;
|
||||||
if (world.rand.nextInt(100) == 0)
|
Phase phase;
|
||||||
toggleRave();
|
|
||||||
super.lazyTick();
|
// Client
|
||||||
|
ArmAngleTarget previousTarget;
|
||||||
|
InterpolatedAngle lowerArmAngle;
|
||||||
|
InterpolatedAngle upperArmAngle;
|
||||||
|
InterpolatedAngle baseAngle;
|
||||||
|
InterpolatedAngle headAngle;
|
||||||
|
InterpolatedAngle clawAngle;
|
||||||
|
float previousBaseAngle;
|
||||||
|
boolean updateInteractionPoints;
|
||||||
|
|
||||||
|
enum Phase {
|
||||||
|
SEARCH_INPUTS, MOVE_TO_INPUT, SEARCH_OUTPUTS, MOVE_TO_OUTPUT, IDLE
|
||||||
}
|
}
|
||||||
|
|
||||||
public void toggleRave() {
|
public ArmTileEntity(TileEntityType<?> typeIn) {
|
||||||
|
super(typeIn);
|
||||||
|
inputs = new ArrayList<>();
|
||||||
|
outputs = new ArrayList<>();
|
||||||
|
heldItem = ItemStack.EMPTY;
|
||||||
|
phase = Phase.SEARCH_INPUTS;
|
||||||
|
baseAngle = new InterpolatedAngle();
|
||||||
|
lowerArmAngle = new InterpolatedAngle();
|
||||||
|
upperArmAngle = new InterpolatedAngle();
|
||||||
|
headAngle = new InterpolatedAngle();
|
||||||
|
clawAngle = new InterpolatedAngle();
|
||||||
|
previousTarget = ArmAngleTarget.NO_TARGET;
|
||||||
|
previousBaseAngle = previousTarget.baseAngle;
|
||||||
|
updateInteractionPoints = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tick() {
|
||||||
|
super.tick();
|
||||||
|
initInteractionPoints();
|
||||||
|
tickMovementProgress();
|
||||||
|
|
||||||
if (world.isRemote)
|
if (world.isRemote)
|
||||||
return;
|
return;
|
||||||
debugRave = !debugRave;
|
if (chasedPointProgress < 1)
|
||||||
|
return;
|
||||||
|
if (phase == Phase.MOVE_TO_INPUT)
|
||||||
|
collectItem();
|
||||||
|
if (phase == Phase.MOVE_TO_OUTPUT)
|
||||||
|
depositItem();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void lazyTick() {
|
||||||
|
super.lazyTick();
|
||||||
|
|
||||||
|
if (world.isRemote)
|
||||||
|
return;
|
||||||
|
if (chasedPointProgress < .5f)
|
||||||
|
return;
|
||||||
|
if (phase == Phase.SEARCH_INPUTS)
|
||||||
|
searchForItem();
|
||||||
|
if (phase == Phase.SEARCH_OUTPUTS)
|
||||||
|
searchForDestination();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void tickMovementProgress() {
|
||||||
|
chasedPointProgress += Math.min(256, Math.abs(getSpeed())) / 1024f;
|
||||||
|
if (chasedPointProgress > 1)
|
||||||
|
chasedPointProgress = 1;
|
||||||
|
if (!world.isRemote)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ArmInteractionPoint targetedInteractionPoint = getTargetedInteractionPoint();
|
||||||
|
ArmAngleTarget previousTarget = this.previousTarget;
|
||||||
|
ArmAngleTarget target =
|
||||||
|
targetedInteractionPoint == null ? ArmAngleTarget.NO_TARGET : targetedInteractionPoint.getTargetAngles(pos);
|
||||||
|
|
||||||
|
baseAngle.set(AngleHelper.angleLerp(chasedPointProgress, previousBaseAngle,
|
||||||
|
target == ArmAngleTarget.NO_TARGET ? previousBaseAngle : target.baseAngle));
|
||||||
|
|
||||||
|
// Arm's angles first backup to resting position and then continue
|
||||||
|
if (chasedPointProgress < .5f)
|
||||||
|
target = ArmAngleTarget.NO_TARGET;
|
||||||
|
else
|
||||||
|
previousTarget = ArmAngleTarget.NO_TARGET;
|
||||||
|
float progress = chasedPointProgress == 1 ? 1 : (chasedPointProgress % .5f) * 2;
|
||||||
|
|
||||||
|
lowerArmAngle.set(MathHelper.lerp(progress, previousTarget.lowerArmAngle, target.lowerArmAngle));
|
||||||
|
upperArmAngle.set(MathHelper.lerp(progress, previousTarget.upperArmAngle, target.upperArmAngle));
|
||||||
|
headAngle.set(AngleHelper.angleLerp(progress, previousTarget.headAngle, target.headAngle));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private ArmInteractionPoint getTargetedInteractionPoint() {
|
||||||
|
if (chasedPointIndex == -1)
|
||||||
|
return null;
|
||||||
|
if (phase == Phase.MOVE_TO_INPUT && chasedPointIndex < inputs.size())
|
||||||
|
return inputs.get(chasedPointIndex);
|
||||||
|
if (phase == Phase.MOVE_TO_OUTPUT && chasedPointIndex < outputs.size())
|
||||||
|
return outputs.get(chasedPointIndex);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void searchForItem() {
|
||||||
|
for (int index = 0; index < inputs.size(); index++) {
|
||||||
|
ArmInteractionPoint armInteractionPoint = inputs.get(index);
|
||||||
|
for (int i = 0; i < armInteractionPoint.getSlotCount(world); i++) {
|
||||||
|
if (getDistributableAmount(armInteractionPoint, i) == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
phase = Phase.MOVE_TO_INPUT;
|
||||||
|
chasedPointIndex = index;
|
||||||
|
chasedPointProgress = 0;
|
||||||
|
sendData();
|
||||||
|
markDirty();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void searchForDestination() {
|
||||||
|
ItemStack held = heldItem.copy();
|
||||||
|
for (int index = 0; index < outputs.size(); index++) {
|
||||||
|
ArmInteractionPoint armInteractionPoint = outputs.get(index);
|
||||||
|
ItemStack remainder = armInteractionPoint.insert(world, held, true);
|
||||||
|
if (remainder.equals(heldItem, false))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
phase = Phase.MOVE_TO_OUTPUT;
|
||||||
|
chasedPointIndex = index;
|
||||||
|
chasedPointProgress = 0;
|
||||||
|
sendData();
|
||||||
|
markDirty();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int getDistributableAmount(ArmInteractionPoint armInteractionPoint, int i) {
|
||||||
|
ItemStack stack = armInteractionPoint.extract(world, i, true);
|
||||||
|
ItemStack remainder = simulateInsertion(stack);
|
||||||
|
return stack.getCount() - remainder.getCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void depositItem() {
|
||||||
|
ArmInteractionPoint armInteractionPoint = getTargetedInteractionPoint();
|
||||||
|
ItemStack toInsert = heldItem.copy();
|
||||||
|
ItemStack remainder = armInteractionPoint.insert(world, toInsert, false);
|
||||||
|
heldItem = remainder;
|
||||||
|
phase = heldItem.isEmpty() ? Phase.SEARCH_INPUTS : Phase.SEARCH_OUTPUTS;
|
||||||
|
chasedPointProgress = 0;
|
||||||
|
chasedPointIndex = -1;
|
||||||
|
sendData();
|
||||||
|
markDirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void collectItem() {
|
||||||
|
ArmInteractionPoint armInteractionPoint = getTargetedInteractionPoint();
|
||||||
|
for (int i = 0; i < armInteractionPoint.getSlotCount(world); i++) {
|
||||||
|
int amountExtracted = getDistributableAmount(armInteractionPoint, i);
|
||||||
|
if (amountExtracted == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
heldItem = armInteractionPoint.extract(world, i, amountExtracted, false);
|
||||||
|
phase = Phase.SEARCH_OUTPUTS;
|
||||||
|
chasedPointProgress = 0;
|
||||||
|
chasedPointIndex = -1;
|
||||||
|
sendData();
|
||||||
|
markDirty();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
phase = Phase.SEARCH_INPUTS;
|
||||||
|
chasedPointProgress = 0;
|
||||||
|
chasedPointIndex = -1;
|
||||||
|
sendData();
|
||||||
|
markDirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
private ItemStack simulateInsertion(ItemStack stack) {
|
||||||
|
for (ArmInteractionPoint armInteractionPoint : outputs) {
|
||||||
|
stack = armInteractionPoint.insert(world, stack, true);
|
||||||
|
if (stack.isEmpty())
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return stack;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void initInteractionPoints() {
|
||||||
|
if (interactionPointTag == null)
|
||||||
|
return;
|
||||||
|
inputs.clear();
|
||||||
|
outputs.clear();
|
||||||
|
for (INBT inbt : interactionPointTag) {
|
||||||
|
ArmInteractionPoint point = ArmInteractionPoint.deserialize(world, (CompoundNBT) inbt);
|
||||||
|
if (point.mode == Mode.DEPOSIT)
|
||||||
|
outputs.add(point);
|
||||||
|
if (point.mode == Mode.TAKE)
|
||||||
|
inputs.add(point);
|
||||||
|
}
|
||||||
|
interactionPointTag = null;
|
||||||
markDirty();
|
markDirty();
|
||||||
sendData();
|
sendData();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompoundNBT write(CompoundNBT compound) {
|
public CompoundNBT write(CompoundNBT compound) {
|
||||||
super.write(compound);
|
super.write(compound);
|
||||||
compound.putBoolean("DebugRave", debugRave);
|
|
||||||
|
ListNBT pointsNBT = new ListNBT();
|
||||||
|
inputs.stream()
|
||||||
|
.map(ArmInteractionPoint::serialize)
|
||||||
|
.forEach(pointsNBT::add);
|
||||||
|
outputs.stream()
|
||||||
|
.map(ArmInteractionPoint::serialize)
|
||||||
|
.forEach(pointsNBT::add);
|
||||||
|
|
||||||
|
NBTHelper.writeEnum(compound, "Phase", phase);
|
||||||
|
compound.put("InterationPoints", pointsNBT);
|
||||||
|
compound.put("HeldItem", heldItem.serializeNBT());
|
||||||
|
compound.putInt("TargetPointIndex", chasedPointIndex);
|
||||||
|
compound.putFloat("MovementProgress", chasedPointProgress);
|
||||||
return compound;
|
return compound;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CompoundNBT writeToClient(CompoundNBT compound) {
|
||||||
|
super.writeToClient(compound);
|
||||||
|
if (interactionPointTag != null)
|
||||||
|
compound.put("InitialInterationPoints", interactionPointTag);
|
||||||
|
return compound;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void read(CompoundNBT compound) {
|
public void read(CompoundNBT compound) {
|
||||||
super.read(compound);
|
super.read(compound);
|
||||||
debugRave = compound.getBoolean("DebugRave");
|
heldItem = ItemStack.read(compound.getCompound("HeldItem"));
|
||||||
|
phase = NBTHelper.readEnum(compound, "Phase", Phase.class);
|
||||||
|
chasedPointIndex = compound.getInt("TargetPointIndex");
|
||||||
|
chasedPointProgress = compound.getFloat("MovementProgress");
|
||||||
|
|
||||||
|
if (!hasWorld() || !world.isRemote || updateInteractionPoints)
|
||||||
|
interactionPointTag = compound.getList("InterationPoints", NBT.TAG_COMPOUND);
|
||||||
|
updateInteractionPoints = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void readClientUpdate(CompoundNBT tag) {
|
||||||
|
int previousIndex = chasedPointIndex;
|
||||||
|
Phase previousPhase = phase;
|
||||||
|
|
||||||
|
super.readClientUpdate(tag);
|
||||||
|
|
||||||
|
if (previousIndex != chasedPointIndex || (previousPhase != phase)) {
|
||||||
|
ArmInteractionPoint previousPoint = null;
|
||||||
|
if (previousPhase == Phase.MOVE_TO_INPUT && previousIndex < inputs.size())
|
||||||
|
previousPoint = inputs.get(previousIndex);
|
||||||
|
if (previousPhase == Phase.MOVE_TO_OUTPUT && previousIndex < outputs.size())
|
||||||
|
previousPoint = outputs.get(previousIndex);
|
||||||
|
previousTarget = previousPoint == null ? ArmAngleTarget.NO_TARGET : previousPoint.getTargetAngles(pos);
|
||||||
|
if (previousPoint != null)
|
||||||
|
previousBaseAngle = previousPoint.getTargetAngles(pos).baseAngle;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tag.contains("InitialInterationPoints"))
|
||||||
|
interactionPointTag = tag.getList("InitialInterationPoints", NBT.TAG_COMPOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,7 +43,9 @@ public class FilterScreenPacket extends SimplePacketBase {
|
||||||
public void handle(Supplier<Context> context) {
|
public void handle(Supplier<Context> context) {
|
||||||
context.get().enqueueWork(() -> {
|
context.get().enqueueWork(() -> {
|
||||||
ServerPlayerEntity player = context.get().getSender();
|
ServerPlayerEntity player = context.get().getSender();
|
||||||
|
if (player == null)
|
||||||
|
return;
|
||||||
|
|
||||||
if (player.openContainer instanceof AbstractFilterContainer) {
|
if (player.openContainer instanceof AbstractFilterContainer) {
|
||||||
AbstractFilterContainer c = (AbstractFilterContainer) player.openContainer;
|
AbstractFilterContainer c = (AbstractFilterContainer) player.openContainer;
|
||||||
if (option == Option.CLEAR) {
|
if (option == Option.CLEAR) {
|
||||||
|
|
|
@ -49,6 +49,8 @@ public class ConfigureSchematicannonPacket extends SimplePacketBase {
|
||||||
public void handle(Supplier<Context> context) {
|
public void handle(Supplier<Context> context) {
|
||||||
context.get().enqueueWork(() -> {
|
context.get().enqueueWork(() -> {
|
||||||
ServerPlayerEntity player = context.get().getSender();
|
ServerPlayerEntity player = context.get().getSender();
|
||||||
|
if (player == null)
|
||||||
|
return;
|
||||||
World world = player.world;
|
World world = player.world;
|
||||||
if (world == null)
|
if (world == null)
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -32,6 +32,8 @@ public class SchematicPlacePacket extends SimplePacketBase {
|
||||||
public void handle(Supplier<Context> context) {
|
public void handle(Supplier<Context> context) {
|
||||||
context.get().enqueueWork(() -> {
|
context.get().enqueueWork(() -> {
|
||||||
ServerPlayerEntity player = context.get().getSender();
|
ServerPlayerEntity player = context.get().getSender();
|
||||||
|
if (player == null)
|
||||||
|
return;
|
||||||
Template t = SchematicItem.loadSchematic(stack);
|
Template t = SchematicItem.loadSchematic(stack);
|
||||||
PlacementSettings settings = SchematicItem.getSettings(stack);
|
PlacementSettings settings = SchematicItem.getSettings(stack);
|
||||||
settings.setIgnoreEntities(false);
|
settings.setIgnoreEntities(false);
|
||||||
|
|
|
@ -68,6 +68,8 @@ public class SchematicUploadPacket extends SimplePacketBase {
|
||||||
.enqueueWork(() -> {
|
.enqueueWork(() -> {
|
||||||
ServerPlayerEntity player = context.get()
|
ServerPlayerEntity player = context.get()
|
||||||
.getSender();
|
.getSender();
|
||||||
|
if (player == null)
|
||||||
|
return;
|
||||||
if (code == BEGIN) {
|
if (code == BEGIN) {
|
||||||
BlockPos pos = ((SchematicTableContainer) player.openContainer).getTileEntity()
|
BlockPos pos = ((SchematicTableContainer) player.openContainer).getTileEntity()
|
||||||
.getPos();
|
.getPos();
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
package com.simibubi.create.foundation.gui.widgets;
|
||||||
|
|
||||||
|
import com.simibubi.create.foundation.utility.AngleHelper;
|
||||||
|
|
||||||
|
public class InterpolatedAngle extends InterpolatedValue {
|
||||||
|
|
||||||
|
public float get(float partialTicks) {
|
||||||
|
return AngleHelper.angleLerp(partialTicks, lastValue, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -4,6 +4,10 @@ import com.simibubi.create.foundation.utility.AngleHelper;
|
||||||
|
|
||||||
public class InterpolatedChasingAngle extends InterpolatedChasingValue {
|
public class InterpolatedChasingAngle extends InterpolatedChasingValue {
|
||||||
|
|
||||||
|
public float get(float partialTicks) {
|
||||||
|
return AngleHelper.angleLerp(partialTicks, lastValue, value);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected float getCurrentDiff() {
|
protected float getCurrentDiff() {
|
||||||
return AngleHelper.getShortestAngleDiff(value, getTarget());
|
return AngleHelper.getShortestAngleDiff(value, getTarget());
|
||||||
|
|
|
@ -12,6 +12,7 @@ import com.simibubi.create.content.contraptions.relays.advanced.sequencer.Config
|
||||||
import com.simibubi.create.content.curiosities.symmetry.SymmetryEffectPacket;
|
import com.simibubi.create.content.curiosities.symmetry.SymmetryEffectPacket;
|
||||||
import com.simibubi.create.content.curiosities.tools.ExtendoGripInteractionPacket;
|
import com.simibubi.create.content.curiosities.tools.ExtendoGripInteractionPacket;
|
||||||
import com.simibubi.create.content.curiosities.zapper.ZapperBeamPacket;
|
import com.simibubi.create.content.curiosities.zapper.ZapperBeamPacket;
|
||||||
|
import com.simibubi.create.content.logistics.block.mechanicalArm.ArmPlacementPacket;
|
||||||
import com.simibubi.create.content.logistics.item.filter.FilterScreenPacket;
|
import com.simibubi.create.content.logistics.item.filter.FilterScreenPacket;
|
||||||
import com.simibubi.create.content.logistics.packet.ConfigureFlexcratePacket;
|
import com.simibubi.create.content.logistics.packet.ConfigureFlexcratePacket;
|
||||||
import com.simibubi.create.content.logistics.packet.ConfigureStockswitchPacket;
|
import com.simibubi.create.content.logistics.packet.ConfigureStockswitchPacket;
|
||||||
|
@ -44,6 +45,7 @@ public enum AllPackets {
|
||||||
CONFIGURE_SCROLLABLE(ScrollValueUpdatePacket.class, ScrollValueUpdatePacket::new),
|
CONFIGURE_SCROLLABLE(ScrollValueUpdatePacket.class, ScrollValueUpdatePacket::new),
|
||||||
CANCEL_FALL(CancelPlayerFallPacket.class, CancelPlayerFallPacket::new),
|
CANCEL_FALL(CancelPlayerFallPacket.class, CancelPlayerFallPacket::new),
|
||||||
EXTENDO_INTERACT(ExtendoGripInteractionPacket.class, ExtendoGripInteractionPacket::new),
|
EXTENDO_INTERACT(ExtendoGripInteractionPacket.class, ExtendoGripInteractionPacket::new),
|
||||||
|
PLACE_ARM(ArmPlacementPacket.class, ArmPlacementPacket::new),
|
||||||
|
|
||||||
// Server to Client
|
// Server to Client
|
||||||
SYMMETRY_EFFECT(SymmetryEffectPacket.class, SymmetryEffectPacket::new),
|
SYMMETRY_EFFECT(SymmetryEffectPacket.class, SymmetryEffectPacket::new),
|
||||||
|
|
|
@ -40,6 +40,8 @@ public class NbtPacket extends SimplePacketBase {
|
||||||
public void handle(Supplier<Context> context) {
|
public void handle(Supplier<Context> context) {
|
||||||
context.get().enqueueWork(() -> {
|
context.get().enqueueWork(() -> {
|
||||||
ServerPlayerEntity player = context.get().getSender();
|
ServerPlayerEntity player = context.get().getSender();
|
||||||
|
if (player == null)
|
||||||
|
return;
|
||||||
|
|
||||||
if (slot == -1) {
|
if (slot == -1) {
|
||||||
ItemStack heldItem = player.getHeldItem(hand);
|
ItemStack heldItem = player.getHeldItem(hand);
|
||||||
|
|
|
@ -35,6 +35,8 @@ public abstract class TileEntityConfigurationPacket<TE extends SyncedTileEntity>
|
||||||
public void handle(Supplier<Context> context) {
|
public void handle(Supplier<Context> context) {
|
||||||
context.get().enqueueWork(() -> {
|
context.get().enqueueWork(() -> {
|
||||||
ServerPlayerEntity player = context.get().getSender();
|
ServerPlayerEntity player = context.get().getSender();
|
||||||
|
if (player == null)
|
||||||
|
return;
|
||||||
World world = player.world;
|
World world = player.world;
|
||||||
|
|
||||||
if (world == null || world.getTileEntity(pos) == null)
|
if (world == null || world.getTileEntity(pos) == null)
|
||||||
|
|
|
@ -12,8 +12,9 @@ import net.minecraft.util.math.AxisAlignedBB;
|
||||||
|
|
||||||
public class NBTHelper {
|
public class NBTHelper {
|
||||||
|
|
||||||
public static <T extends Enum<?>> T readEnum(String name, Class<T> enumClass) {
|
public static <T extends Enum<?>> T readEnum(CompoundNBT nbt, String key, Class<T> enumClass) {
|
||||||
T[] enumConstants = enumClass.getEnumConstants();
|
T[] enumConstants = enumClass.getEnumConstants();
|
||||||
|
String name = nbt.getString(key);
|
||||||
if (enumConstants == null)
|
if (enumConstants == null)
|
||||||
throw new IllegalArgumentException("Non-Enum class passed to readEnum(): " + enumClass.getName());
|
throw new IllegalArgumentException("Non-Enum class passed to readEnum(): " + enumClass.getName());
|
||||||
for (T t : enumConstants) {
|
for (T t : enumConstants) {
|
||||||
|
@ -22,11 +23,11 @@ public class NBTHelper {
|
||||||
}
|
}
|
||||||
return enumConstants[0];
|
return enumConstants[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T extends Enum<?>> String writeEnum(T enumConstant) {
|
public static <T extends Enum<?>> void writeEnum(CompoundNBT nbt, String key, T enumConstant) {
|
||||||
return enumConstant.name();
|
nbt.putString(key, enumConstant.name());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> ListNBT writeCompoundList(List<T> list, Function<T, CompoundNBT> serializer) {
|
public static <T> ListNBT writeCompoundList(List<T> list, Function<T, CompoundNBT> serializer) {
|
||||||
ListNBT listNBT = new ListNBT();
|
ListNBT listNBT = new ListNBT();
|
||||||
list.forEach(t -> listNBT.add(serializer.apply(t)));
|
list.forEach(t -> listNBT.add(serializer.apply(t)));
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
{
|
||||||
|
"credit": "Made with Blockbench",
|
||||||
|
"parent": "block/block",
|
||||||
|
"textures": {
|
||||||
|
"4": "create:block/marker_flag"
|
||||||
|
},
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"from": [0, 0, 0],
|
||||||
|
"to": [1, 16, 1],
|
||||||
|
"rotation": {"angle": 0, "axis": "y", "origin": [8, -3, 10]},
|
||||||
|
"faces": {
|
||||||
|
"north": {"uv": [1, 0, 2, 16], "texture": "#4"},
|
||||||
|
"east": {"uv": [0, 0, 1, 16], "texture": "#4"},
|
||||||
|
"south": {"uv": [1, 0, 2, 16], "texture": "#4"},
|
||||||
|
"west": {"uv": [0, 0, 1, 16], "texture": "#4"},
|
||||||
|
"up": {"uv": [0, 0, 1, 1], "texture": "#4"},
|
||||||
|
"down": {"uv": [0, 0, 1, 1], "texture": "#4"}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"from": [0.4, 7.5, 1],
|
||||||
|
"to": [0.4, 15.5, 9],
|
||||||
|
"rotation": {"angle": 0, "axis": "y", "origin": [8, -3, 10]},
|
||||||
|
"faces": {
|
||||||
|
"east": {"uv": [16, 0, 8, 8], "texture": "#4", "tintindex": 0},
|
||||||
|
"west": {"uv": [8, 0, 16, 8], "texture": "#4", "tintindex": 0}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
{
|
||||||
|
"credit": "Made with Blockbench",
|
||||||
|
"parent": "block/block",
|
||||||
|
"textures": {
|
||||||
|
"4": "create:block/marker_flag"
|
||||||
|
},
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"from": [0, 0, 0],
|
||||||
|
"to": [1, 16, 1],
|
||||||
|
"rotation": {"angle": 0, "axis": "y", "origin": [8, -3, 10]},
|
||||||
|
"faces": {
|
||||||
|
"north": {"uv": [1, 0, 2, 16], "texture": "#4"},
|
||||||
|
"east": {"uv": [0, 0, 1, 16], "texture": "#4"},
|
||||||
|
"south": {"uv": [1, 0, 2, 16], "texture": "#4"},
|
||||||
|
"west": {"uv": [0, 0, 1, 16], "texture": "#4"},
|
||||||
|
"up": {"uv": [0, 0, 1, 1], "texture": "#4"},
|
||||||
|
"down": {"uv": [0, 0, 1, 1], "texture": "#4"}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"from": [0.4, 7.5, 1],
|
||||||
|
"to": [0.4, 15.5, 9],
|
||||||
|
"rotation": {"angle": 0, "axis": "y", "origin": [8, -3, 10]},
|
||||||
|
"faces": {
|
||||||
|
"east": {"uv": [16, 8, 8, 16], "texture": "#4", "tintindex": 0},
|
||||||
|
"west": {"uv": [8, 8, 16, 16], "texture": "#4", "tintindex": 0}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
{
|
||||||
|
"credit": "Made with Blockbench",
|
||||||
|
"parent": "block/block",
|
||||||
|
"textures": {
|
||||||
|
"4": "create:block/marker_flag"
|
||||||
|
},
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"from": [0, 0, 0],
|
||||||
|
"to": [1, 8, 1],
|
||||||
|
"rotation": {"angle": 0, "axis": "y", "origin": [8, -3, 10]},
|
||||||
|
"faces": {
|
||||||
|
"north": {"uv": [1, 8, 2, 16], "texture": "#4"},
|
||||||
|
"east": {"uv": [0, 0, 1, 8], "texture": "#4"},
|
||||||
|
"south": {"uv": [1, 0, 2, 8], "texture": "#4"},
|
||||||
|
"west": {"uv": [0, 0, 1, 8], "texture": "#4"},
|
||||||
|
"up": {"uv": [0, 0, 1, 1], "texture": "#4"},
|
||||||
|
"down": {"uv": [0, 0, 1, 1], "texture": "#4"}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"from": [0.4, -0.5, 1],
|
||||||
|
"to": [0.4, 7.5, 9],
|
||||||
|
"rotation": {"angle": 0, "axis": "y", "origin": [8, -3, 10]},
|
||||||
|
"faces": {
|
||||||
|
"east": {"uv": [16, 0, 8, 8], "texture": "#4", "tintindex": 0},
|
||||||
|
"west": {"uv": [8, 0, 16, 8], "texture": "#4", "tintindex": 0}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
{
|
||||||
|
"credit": "Made with Blockbench",
|
||||||
|
"parent": "block/block",
|
||||||
|
"textures": {
|
||||||
|
"4": "create:block/marker_flag"
|
||||||
|
},
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"from": [0, 0, 0],
|
||||||
|
"to": [1, 8, 1],
|
||||||
|
"rotation": {"angle": 0, "axis": "y", "origin": [8, -3, 10]},
|
||||||
|
"faces": {
|
||||||
|
"north": {"uv": [1, 8, 2, 16], "texture": "#4"},
|
||||||
|
"east": {"uv": [0, 0, 1, 8], "texture": "#4"},
|
||||||
|
"south": {"uv": [1, 0, 2, 8], "texture": "#4"},
|
||||||
|
"west": {"uv": [0, 0, 1, 8], "texture": "#4"},
|
||||||
|
"up": {"uv": [0, 0, 1, 1], "texture": "#4"},
|
||||||
|
"down": {"uv": [0, 0, 1, 1], "texture": "#4"}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"from": [0.4, -0.5, 1],
|
||||||
|
"to": [0.4, 7.5, 9],
|
||||||
|
"rotation": {"angle": 0, "axis": "y", "origin": [8, -3, 10]},
|
||||||
|
"faces": {
|
||||||
|
"east": {"uv": [16, 8, 8, 16], "texture": "#4", "tintindex": 0},
|
||||||
|
"west": {"uv": [8, 8, 16, 16], "texture": "#4", "tintindex": 0}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
BIN
src/main/resources/assets/create/textures/block/marker_flag.png
Normal file
BIN
src/main/resources/assets/create/textures/block/marker_flag.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 324 B |
Loading…
Reference in a new issue