mirror of
https://github.com/Creators-of-Create/Create.git
synced 2024-11-16 23:11:40 +01:00
Mounted Storage and Contraption Stalling
- Saws are now portable and chop trees while mounted - Portable contraptions can now hold an inventory - Saw, Drill and Harvester now fill a contraptions internal storage before dropping items - Mounted blocks can now hold moving contraptions in place - Saw and Drill now briefly stall contraptions while breaking blocks in front of themselves - Refactored IHaveMovementBehaviour to IPortableBlock and MovementBehaviour - Fixed Harvester blades rotating in the wrong direction sometimes - Shadows on portable contraptions are now a little less aggressive - Added a block for item exchange with storage on contraptions - Fixed link range config registering with wrong id - Added a utility for purposely slowing down animations on the client to match server tps - Smart Tileentities now lazy tick on initialization - Fixed crash when breaking active bearings - Fixed crash when cart assembler fails to assemble a contraption - Fixed goggles having missing textures - Reworked Schematicannon Model - Removed Schematicannon Creatifier from creative tab
This commit is contained in:
parent
45195df7f9
commit
e0b36a79c9
63 changed files with 1725 additions and 555 deletions
|
@ -10,6 +10,7 @@ import com.simibubi.create.modules.IModule;
|
||||||
import com.simibubi.create.modules.contraptions.CasingBlock;
|
import com.simibubi.create.modules.contraptions.CasingBlock;
|
||||||
import com.simibubi.create.modules.contraptions.components.actors.DrillBlock;
|
import com.simibubi.create.modules.contraptions.components.actors.DrillBlock;
|
||||||
import com.simibubi.create.modules.contraptions.components.actors.HarvesterBlock;
|
import com.simibubi.create.modules.contraptions.components.actors.HarvesterBlock;
|
||||||
|
import com.simibubi.create.modules.contraptions.components.actors.PortableStorageInterfaceBlock;
|
||||||
import com.simibubi.create.modules.contraptions.components.clock.CuckooClockBlock;
|
import com.simibubi.create.modules.contraptions.components.clock.CuckooClockBlock;
|
||||||
import com.simibubi.create.modules.contraptions.components.contraptions.bearing.MechanicalBearingBlock;
|
import com.simibubi.create.modules.contraptions.components.contraptions.bearing.MechanicalBearingBlock;
|
||||||
import com.simibubi.create.modules.contraptions.components.contraptions.chassis.LinearChassisBlock;
|
import com.simibubi.create.modules.contraptions.components.contraptions.chassis.LinearChassisBlock;
|
||||||
|
@ -70,8 +71,8 @@ import com.simibubi.create.modules.palettes.CTWindowBlock;
|
||||||
import com.simibubi.create.modules.palettes.GlassPaneBlock;
|
import com.simibubi.create.modules.palettes.GlassPaneBlock;
|
||||||
import com.simibubi.create.modules.palettes.HorizontalCTGlassBlock;
|
import com.simibubi.create.modules.palettes.HorizontalCTGlassBlock;
|
||||||
import com.simibubi.create.modules.palettes.LayeredCTBlock;
|
import com.simibubi.create.modules.palettes.LayeredCTBlock;
|
||||||
import com.simibubi.create.modules.palettes.VerticalCTGlassBlock;
|
|
||||||
import com.simibubi.create.modules.palettes.ScoriaBlock;
|
import com.simibubi.create.modules.palettes.ScoriaBlock;
|
||||||
|
import com.simibubi.create.modules.palettes.VerticalCTGlassBlock;
|
||||||
import com.simibubi.create.modules.schematics.block.CreativeCrateBlock;
|
import com.simibubi.create.modules.schematics.block.CreativeCrateBlock;
|
||||||
import com.simibubi.create.modules.schematics.block.SchematicTableBlock;
|
import com.simibubi.create.modules.schematics.block.SchematicTableBlock;
|
||||||
import com.simibubi.create.modules.schematics.block.SchematicannonBlock;
|
import com.simibubi.create.modules.schematics.block.SchematicannonBlock;
|
||||||
|
@ -129,11 +130,6 @@ public enum AllBlocks {
|
||||||
MECHANICAL_PRESS(new MechanicalPressBlock()),
|
MECHANICAL_PRESS(new MechanicalPressBlock()),
|
||||||
MECHANICAL_MIXER(new MechanicalMixerBlock()),
|
MECHANICAL_MIXER(new MechanicalMixerBlock()),
|
||||||
BASIN(new BasinBlock()),
|
BASIN(new BasinBlock()),
|
||||||
MECHANICAL_CRAFTER(new MechanicalCrafterBlock()),
|
|
||||||
|
|
||||||
FLYWHEEL(new FlywheelBlock()),
|
|
||||||
FURNACE_ENGINE(new FurnaceEngineBlock()),
|
|
||||||
|
|
||||||
SPEED_GAUGE(new GaugeBlock(GaugeBlock.Type.SPEED)),
|
SPEED_GAUGE(new GaugeBlock(GaugeBlock.Type.SPEED)),
|
||||||
STRESS_GAUGE(new GaugeBlock(GaugeBlock.Type.STRESS)),
|
STRESS_GAUGE(new GaugeBlock(GaugeBlock.Type.STRESS)),
|
||||||
|
|
||||||
|
@ -149,6 +145,7 @@ public enum AllBlocks {
|
||||||
SAW(new SawBlock()),
|
SAW(new SawBlock()),
|
||||||
HARVESTER(new HarvesterBlock()),
|
HARVESTER(new HarvesterBlock()),
|
||||||
DEPLOYER(new DeployerBlock()),
|
DEPLOYER(new DeployerBlock()),
|
||||||
|
PORTABLE_STORAGE_INTERFACE(new PortableStorageInterfaceBlock()),
|
||||||
CART_ASSEMBLER(new CartAssemblerBlock()),
|
CART_ASSEMBLER(new CartAssemblerBlock()),
|
||||||
MINECART_ANCHOR(new MinecartAnchorBlock()),
|
MINECART_ANCHOR(new MinecartAnchorBlock()),
|
||||||
ANALOG_LEVER(new AnalogLeverBlock()),
|
ANALOG_LEVER(new AnalogLeverBlock()),
|
||||||
|
@ -157,6 +154,10 @@ public enum AllBlocks {
|
||||||
COPPER_CASING(new CasingBlock("copper_casing")),
|
COPPER_CASING(new CasingBlock("copper_casing")),
|
||||||
BRASS_CASING(new CasingBlock("crafter_top")),
|
BRASS_CASING(new CasingBlock("crafter_top")),
|
||||||
|
|
||||||
|
MECHANICAL_CRAFTER(new MechanicalCrafterBlock()),
|
||||||
|
FLYWHEEL(new FlywheelBlock()),
|
||||||
|
FURNACE_ENGINE(new FurnaceEngineBlock()),
|
||||||
|
|
||||||
__LOGISTICS__(),
|
__LOGISTICS__(),
|
||||||
CONTACT(new ContactBlock()),
|
CONTACT(new ContactBlock()),
|
||||||
REDSTONE_BRIDGE(new RedstoneLinkBlock()),
|
REDSTONE_BRIDGE(new RedstoneLinkBlock()),
|
||||||
|
|
|
@ -8,6 +8,8 @@ import com.simibubi.create.foundation.behaviour.filtering.FilteringCountUpdatePa
|
||||||
import com.simibubi.create.foundation.command.ConfigureConfigPacket;
|
import com.simibubi.create.foundation.command.ConfigureConfigPacket;
|
||||||
import com.simibubi.create.foundation.packet.NbtPacket;
|
import com.simibubi.create.foundation.packet.NbtPacket;
|
||||||
import com.simibubi.create.foundation.packet.SimplePacketBase;
|
import com.simibubi.create.foundation.packet.SimplePacketBase;
|
||||||
|
import com.simibubi.create.foundation.utility.ServerSpeedProvider;
|
||||||
|
import com.simibubi.create.modules.contraptions.components.contraptions.ContraptionStallPacket;
|
||||||
import com.simibubi.create.modules.contraptions.components.contraptions.chassis.ConfigureChassisPacket;
|
import com.simibubi.create.modules.contraptions.components.contraptions.chassis.ConfigureChassisPacket;
|
||||||
import com.simibubi.create.modules.contraptions.components.mixer.ConfigureMixerPacket;
|
import com.simibubi.create.modules.contraptions.components.mixer.ConfigureMixerPacket;
|
||||||
import com.simibubi.create.modules.contraptions.components.motor.ConfigureMotorPacket;
|
import com.simibubi.create.modules.contraptions.components.motor.ConfigureMotorPacket;
|
||||||
|
@ -45,8 +47,10 @@ public enum AllPackets {
|
||||||
|
|
||||||
// Server to Client
|
// Server to Client
|
||||||
SYMMETRY_EFFECT(SymmetryEffectPacket.class, SymmetryEffectPacket::new),
|
SYMMETRY_EFFECT(SymmetryEffectPacket.class, SymmetryEffectPacket::new),
|
||||||
|
SERVER_SPEED(ServerSpeedProvider.Packet.class, ServerSpeedProvider.Packet::new),
|
||||||
BEAM_EFFECT(BlockzapperBeamPacket.class, BlockzapperBeamPacket::new),
|
BEAM_EFFECT(BlockzapperBeamPacket.class, BlockzapperBeamPacket::new),
|
||||||
CONFIGURE_CONFIG(ConfigureConfigPacket.class, ConfigureConfigPacket::new),
|
CONFIGURE_CONFIG(ConfigureConfigPacket.class, ConfigureConfigPacket::new),
|
||||||
|
CONTRAPTION_STALL(ContraptionStallPacket.class, ContraptionStallPacket::new),
|
||||||
|
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
package com.simibubi.create;
|
package com.simibubi.create;
|
||||||
|
|
||||||
import com.simibubi.create.foundation.advancement.AllCriterionTriggers;
|
import com.simibubi.create.foundation.advancement.AllCriterionTriggers;
|
||||||
import com.simibubi.create.foundation.advancement.SandpaperUseTrigger;
|
|
||||||
import net.minecraft.advancements.CriteriaTriggers;
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ public class CLogistics extends ConfigBase {
|
||||||
public ConfigInt extractorDelay = i(20, 10, "extractorDelay", Comments.extractorDelay);
|
public ConfigInt extractorDelay = i(20, 10, "extractorDelay", Comments.extractorDelay);
|
||||||
public ConfigInt extractorInventoryScanDelay = i(40, 10, "extractorInventoryScanDelay", Comments.extractorInventoryScanDelay);
|
public ConfigInt extractorInventoryScanDelay = i(40, 10, "extractorInventoryScanDelay", Comments.extractorInventoryScanDelay);
|
||||||
public ConfigInt extractorAmount = i(16, 1, 64, "extractorAmount", Comments.extractorAmount);
|
public ConfigInt extractorAmount = i(16, 1, 64, "extractorAmount", Comments.extractorAmount);
|
||||||
public ConfigInt linkRange = i(128, 1, "extractorDelay", Comments.linkRange);
|
public ConfigInt linkRange = i(128, 1, "linkRange", Comments.linkRange);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
|
|
|
@ -8,6 +8,10 @@ public class CServer extends ConfigBase {
|
||||||
public ConfigBool enablePalettes = b(true, "enablePalettes");
|
public ConfigBool enablePalettes = b(true, "enablePalettes");
|
||||||
public ConfigBool enableLogistics = b(true, "enableLogistics");
|
public ConfigBool enableLogistics = b(true, "enableLogistics");
|
||||||
|
|
||||||
|
public ConfigGroup infrastructure = group(0, "infrastructure", Comments.infrastructure);
|
||||||
|
public ConfigInt tickrateSyncTimer =
|
||||||
|
i(20, 5, "tickrateSyncTimer", "[in Ticks]", Comments.tickrateSyncTimer, Comments.tickrateSyncTimer2);
|
||||||
|
|
||||||
public CKinetics kinetics = nested(0, CKinetics::new, Comments.kinetics);
|
public CKinetics kinetics = nested(0, CKinetics::new, Comments.kinetics);
|
||||||
public CLogistics logistics = nested(0, CLogistics::new, Comments.logistics);
|
public CLogistics logistics = nested(0, CLogistics::new, Comments.logistics);
|
||||||
public CSchematics schematics = nested(0, CSchematics::new, Comments.schematics);
|
public CSchematics schematics = nested(0, CSchematics::new, Comments.schematics);
|
||||||
|
@ -26,6 +30,10 @@ public class CServer extends ConfigBase {
|
||||||
static String curiosities = "Everything that spins";
|
static String curiosities = "Everything that spins";
|
||||||
static String modules = "Configure which Modules should be accessible in recipes and creative menus.";
|
static String modules = "Configure which Modules should be accessible in recipes and creative menus.";
|
||||||
static String control = "You can try inhibiting related game mechanics for troubleshooting repeated crashes.";
|
static String control = "You can try inhibiting related game mechanics for troubleshooting repeated crashes.";
|
||||||
|
static String infrastructure = "The Backbone of Create";
|
||||||
|
static String tickrateSyncTimer =
|
||||||
|
"The amount of time a server waits before sending out tickrate synchronization packets.";
|
||||||
|
static String tickrateSyncTimer2 = "These packets help animations to be more accurate when tps is below 20.";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,17 +2,13 @@ package com.simibubi.create.foundation.advancement;
|
||||||
|
|
||||||
import com.google.gson.JsonDeserializationContext;
|
import com.google.gson.JsonDeserializationContext;
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
import net.minecraft.advancements.PlayerAdvancements;
|
|
||||||
import net.minecraft.advancements.criterion.CriterionInstance;
|
|
||||||
import net.minecraft.advancements.criterion.ItemPredicate;
|
import net.minecraft.advancements.criterion.ItemPredicate;
|
||||||
import net.minecraft.entity.player.ServerPlayerEntity;
|
import net.minecraft.entity.player.ServerPlayerEntity;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.util.ResourceLocation;
|
import net.minecraft.util.ResourceLocation;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
public class SandpaperUseTrigger extends CriterionTriggerBase<SandpaperUseTrigger.Instance> {
|
public class SandpaperUseTrigger extends CriterionTriggerBase<SandpaperUseTrigger.Instance> {
|
||||||
|
|
|
@ -58,6 +58,7 @@ public abstract class SmartTileEntity extends SyncedTileEntity implements ITicka
|
||||||
|
|
||||||
public void initialize() {
|
public void initialize() {
|
||||||
behaviours.values().forEach(TileEntityBehaviour::initialize);
|
behaviours.values().forEach(TileEntityBehaviour::initialize);
|
||||||
|
lazyTick();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateClient(CompoundNBT compound) {
|
public void updateClient(CompoundNBT compound) {
|
||||||
|
|
|
@ -33,7 +33,7 @@ public class ExtractingBehaviour extends InventoryManagementBehaviour {
|
||||||
super(te, attachments);
|
super(te, attachments);
|
||||||
customAmountFilter = stack -> 64;
|
customAmountFilter = stack -> 64;
|
||||||
customFilter = stack -> true;
|
customFilter = stack -> true;
|
||||||
callback = onExtract;
|
setCallback(onExtract);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ExtractingBehaviour withAmountThreshold(Function<ItemStack, Integer> filter) {
|
public ExtractingBehaviour withAmountThreshold(Function<ItemStack, Integer> filter) {
|
||||||
|
@ -47,11 +47,15 @@ public class ExtractingBehaviour extends InventoryManagementBehaviour {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean extract() {
|
public boolean extract() {
|
||||||
|
return extract(getAmountToExtract());
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getAmountToExtract() {
|
||||||
int amount = -1;
|
int amount = -1;
|
||||||
FilteringBehaviour filter = get(tileEntity, FilteringBehaviour.TYPE);
|
FilteringBehaviour filter = get(tileEntity, FilteringBehaviour.TYPE);
|
||||||
if (filter != null && !filter.anyAmount())
|
if (filter != null && !filter.anyAmount())
|
||||||
amount = filter.getAmount();
|
amount = filter.getAmount();
|
||||||
return extract(amount);
|
return amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean extract(int exactAmount) {
|
public boolean extract(int exactAmount) {
|
||||||
|
@ -60,11 +64,7 @@ public class ExtractingBehaviour extends InventoryManagementBehaviour {
|
||||||
if (AllConfigs.SERVER.control.freezeExtractors.get())
|
if (AllConfigs.SERVER.control.freezeExtractors.get())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
Predicate<ItemStack> test = customFilter;
|
Predicate<ItemStack> test = getFilterTest();
|
||||||
FilteringBehaviour filter = get(tileEntity, FilteringBehaviour.TYPE);
|
|
||||||
if (filter != null)
|
|
||||||
test = customFilter.and(filter::test);
|
|
||||||
|
|
||||||
for (IItemHandler inv : getInventories()) {
|
for (IItemHandler inv : getInventories()) {
|
||||||
ItemStack extract = ItemStack.EMPTY;
|
ItemStack extract = ItemStack.EMPTY;
|
||||||
if (exactAmount != -1)
|
if (exactAmount != -1)
|
||||||
|
@ -81,9 +81,21 @@ public class ExtractingBehaviour extends InventoryManagementBehaviour {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Predicate<ItemStack> getFilterTest() {
|
||||||
|
Predicate<ItemStack> test = customFilter;
|
||||||
|
FilteringBehaviour filter = get(tileEntity, FilteringBehaviour.TYPE);
|
||||||
|
if (filter != null)
|
||||||
|
test = customFilter.and(filter::test);
|
||||||
|
return test;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IBehaviourType<?> getType() {
|
public IBehaviourType<?> getType() {
|
||||||
return TYPE;
|
return TYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setCallback(Consumer<ItemStack> callback) {
|
||||||
|
this.callback = callback;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,8 +13,9 @@ import net.minecraft.util.math.BlockPos;
|
||||||
|
|
||||||
public class SingleTargetAutoExtractingBehaviour extends AutoExtractingBehaviour {
|
public class SingleTargetAutoExtractingBehaviour extends AutoExtractingBehaviour {
|
||||||
|
|
||||||
public static IBehaviourType<SingleTargetAutoExtractingBehaviour> TYPE = new IBehaviourType<SingleTargetAutoExtractingBehaviour>() {
|
public static IBehaviourType<SingleTargetAutoExtractingBehaviour> TYPE =
|
||||||
};
|
new IBehaviourType<SingleTargetAutoExtractingBehaviour>() {
|
||||||
|
};
|
||||||
|
|
||||||
private Supplier<Direction> attachmentDirection;
|
private Supplier<Direction> attachmentDirection;
|
||||||
boolean synced;
|
boolean synced;
|
||||||
|
@ -28,8 +29,8 @@ public class SingleTargetAutoExtractingBehaviour extends AutoExtractingBehaviour
|
||||||
advantageOnNextSync = false;
|
advantageOnNextSync = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SingleTargetAutoExtractingBehaviour dontSynchronize() {
|
public SingleTargetAutoExtractingBehaviour setSynchronized(boolean sync) {
|
||||||
synced = false;
|
synced = sync;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,10 @@ public class AllShapes {
|
||||||
makeCuboidShape(4, 4, 11, 12, 12, 17)), Direction.SOUTH),
|
makeCuboidShape(4, 4, 11, 12, 12, 17)), Direction.SOUTH),
|
||||||
FURNACE_ENGINE = VoxelShaper.forHorizontal(VoxelShapes.or(
|
FURNACE_ENGINE = VoxelShaper.forHorizontal(VoxelShapes.or(
|
||||||
makeCuboidShape(1, 1, 0, 15, 15, 16),
|
makeCuboidShape(1, 1, 0, 15, 15, 16),
|
||||||
makeCuboidShape(0, 0, 9, 16, 16, 14)), Direction.SOUTH)
|
makeCuboidShape(0, 0, 9, 16, 16, 14)), Direction.SOUTH),
|
||||||
|
PORTABLE_STORAGE_INTERFACE = VoxelShaper.forDirectional(VoxelShapes.or(
|
||||||
|
makeCuboidShape(0, 0, 0, 16, 12, 16),
|
||||||
|
makeCuboidShape(3, 12, 3, 13, 16, 13)), Direction.UP)
|
||||||
|
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,9 @@ import java.util.function.Function;
|
||||||
|
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.nbt.CompoundNBT;
|
import net.minecraft.nbt.CompoundNBT;
|
||||||
|
import net.minecraft.nbt.FloatNBT;
|
||||||
import net.minecraft.nbt.ListNBT;
|
import net.minecraft.nbt.ListNBT;
|
||||||
|
import net.minecraft.util.math.AxisAlignedBB;
|
||||||
|
|
||||||
public class NBTHelper {
|
public class NBTHelper {
|
||||||
|
|
||||||
|
@ -44,5 +46,24 @@ public class NBTHelper {
|
||||||
public static List<ItemStack> readItemList(ListNBT stacks) {
|
public static List<ItemStack> readItemList(ListNBT stacks) {
|
||||||
return readCompoundList(stacks, ItemStack::read);
|
return readCompoundList(stacks, ItemStack::read);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static ListNBT writeAABB(AxisAlignedBB bb) {
|
||||||
|
ListNBT bbtag = new ListNBT();
|
||||||
|
bbtag.add(new FloatNBT((float) bb.minX));
|
||||||
|
bbtag.add(new FloatNBT((float) bb.minY));
|
||||||
|
bbtag.add(new FloatNBT((float) bb.minZ));
|
||||||
|
bbtag.add(new FloatNBT((float) bb.maxX));
|
||||||
|
bbtag.add(new FloatNBT((float) bb.maxY));
|
||||||
|
bbtag.add(new FloatNBT((float) bb.maxZ));
|
||||||
|
return bbtag;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static AxisAlignedBB readAABB(ListNBT bbtag) {
|
||||||
|
if (bbtag == null || bbtag.isEmpty())
|
||||||
|
return null;
|
||||||
|
return new AxisAlignedBB(bbtag.getFloat(0), bbtag.getFloat(1), bbtag.getFloat(2), bbtag.getFloat(3),
|
||||||
|
bbtag.getFloat(4), bbtag.getFloat(5));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,83 @@
|
||||||
|
package com.simibubi.create.foundation.utility;
|
||||||
|
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import com.simibubi.create.AllPackets;
|
||||||
|
import com.simibubi.create.config.AllConfigs;
|
||||||
|
import com.simibubi.create.foundation.gui.widgets.InterpolatedChasingValue;
|
||||||
|
import com.simibubi.create.foundation.packet.SimplePacketBase;
|
||||||
|
|
||||||
|
import net.minecraft.network.PacketBuffer;
|
||||||
|
import net.minecraftforge.event.TickEvent;
|
||||||
|
import net.minecraftforge.event.TickEvent.Phase;
|
||||||
|
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||||
|
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
|
||||||
|
import net.minecraftforge.fml.network.NetworkEvent.Context;
|
||||||
|
import net.minecraftforge.fml.network.PacketDistributor;
|
||||||
|
|
||||||
|
@EventBusSubscriber
|
||||||
|
public class ServerSpeedProvider {
|
||||||
|
|
||||||
|
static int clientTimer = 0;
|
||||||
|
static int serverTimer = 0;
|
||||||
|
static boolean initialized = false;
|
||||||
|
static InterpolatedChasingValue modifier = new InterpolatedChasingValue().withSpeed(.25f);
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public static void onServerTick(TickEvent.ServerTickEvent event) {
|
||||||
|
if (event.phase == Phase.START)
|
||||||
|
return;
|
||||||
|
serverTimer++;
|
||||||
|
if (serverTimer > getSyncInterval()) {
|
||||||
|
AllPackets.channel.send(PacketDistributor.ALL.noArg(), new Packet());
|
||||||
|
serverTimer = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Integer getSyncInterval() {
|
||||||
|
return AllConfigs.SERVER.tickrateSyncTimer.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public static void onClientTick(TickEvent.ClientTickEvent event) {
|
||||||
|
if (event.phase == Phase.START)
|
||||||
|
return;
|
||||||
|
modifier.tick();
|
||||||
|
clientTimer++;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float get() {
|
||||||
|
return modifier.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Packet extends SimplePacketBase {
|
||||||
|
|
||||||
|
public Packet() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Packet(PacketBuffer buffer) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(PacketBuffer buffer) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(Supplier<Context> context) {
|
||||||
|
context.get().enqueueWork(() -> {
|
||||||
|
if (!initialized) {
|
||||||
|
initialized = true;
|
||||||
|
clientTimer = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
float target = ((float) getSyncInterval()) / Math.max(clientTimer, 1);
|
||||||
|
modifier.target(target);
|
||||||
|
clientTimer = 0;
|
||||||
|
|
||||||
|
});
|
||||||
|
context.get().setPacketHandled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -23,7 +23,7 @@ import net.minecraft.world.server.ServerWorld;
|
||||||
|
|
||||||
public abstract class BlockBreakingKineticTileEntity extends KineticTileEntity {
|
public abstract class BlockBreakingKineticTileEntity extends KineticTileEntity {
|
||||||
|
|
||||||
private static final AtomicInteger NEXT_BREAKER_ID = new AtomicInteger();
|
public static final AtomicInteger NEXT_BREAKER_ID = new AtomicInteger();
|
||||||
protected int ticksUntilNextProgress;
|
protected int ticksUntilNextProgress;
|
||||||
protected int destroyProgress;
|
protected int destroyProgress;
|
||||||
protected int breakerId = -NEXT_BREAKER_ID.incrementAndGet();
|
protected int breakerId = -NEXT_BREAKER_ID.incrementAndGet();
|
||||||
|
@ -119,6 +119,10 @@ public abstract class BlockBreakingKineticTileEntity extends KineticTileEntity {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean canBreak(BlockState stateToBreak, float blockHardness) {
|
public boolean canBreak(BlockState stateToBreak, float blockHardness) {
|
||||||
|
return isBreakable(stateToBreak, blockHardness);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isBreakable(BlockState stateToBreak, float blockHardness) {
|
||||||
return !(stateToBreak.getMaterial().isLiquid() || stateToBreak.getBlock() instanceof AirBlock
|
return !(stateToBreak.getMaterial().isLiquid() || stateToBreak.getBlock() instanceof AirBlock
|
||||||
|| blockHardness == -1);
|
|| blockHardness == -1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,122 @@
|
||||||
|
package com.simibubi.create.modules.contraptions.components.actors;
|
||||||
|
|
||||||
|
import com.simibubi.create.foundation.utility.BlockHelper;
|
||||||
|
import com.simibubi.create.modules.contraptions.components.contraptions.MovementBehaviour;
|
||||||
|
import com.simibubi.create.modules.contraptions.components.contraptions.MovementContext;
|
||||||
|
|
||||||
|
import net.minecraft.block.BlockState;
|
||||||
|
import net.minecraft.nbt.CompoundNBT;
|
||||||
|
import net.minecraft.nbt.NBTUtil;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.util.math.MathHelper;
|
||||||
|
import net.minecraft.util.math.Vec3d;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
|
public class BlockBreakingMovementBehaviour extends MovementBehaviour {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void startMoving(MovementContext context) {
|
||||||
|
context.data.putInt("BreakerId", -BlockBreakingKineticTileEntity.NEXT_BREAKER_ID.incrementAndGet());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitNewPosition(MovementContext context, BlockPos pos) {
|
||||||
|
World world = context.world;
|
||||||
|
BlockState stateVisited = world.getBlockState(pos);
|
||||||
|
|
||||||
|
if (world.isRemote)
|
||||||
|
return;
|
||||||
|
if (stateVisited.getCollisionShape(world, pos).isEmpty())
|
||||||
|
return;
|
||||||
|
if (stateVisited.getBlockHardness(world, pos) == -1)
|
||||||
|
return;
|
||||||
|
if (!canBreak(stateVisited))
|
||||||
|
return;
|
||||||
|
|
||||||
|
context.data.put("BreakingPos", NBTUtil.writeBlockPos(pos));
|
||||||
|
context.stall = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stopMoving(MovementContext context) {
|
||||||
|
CompoundNBT data = context.data;
|
||||||
|
if (!data.contains("BreakingPos"))
|
||||||
|
return;
|
||||||
|
|
||||||
|
World world = context.world;
|
||||||
|
int id = data.getInt("BreakerId");
|
||||||
|
BlockPos breakingPos = NBTUtil.readBlockPos(data.getCompound("BreakingPos"));
|
||||||
|
|
||||||
|
data.remove("Progress");
|
||||||
|
data.remove("TicksUntilNextProgress");
|
||||||
|
data.remove("BreakingPos");
|
||||||
|
|
||||||
|
context.stall = false;
|
||||||
|
world.sendBlockBreakProgress(id, breakingPos, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tick(MovementContext context) {
|
||||||
|
CompoundNBT data = context.data;
|
||||||
|
if (!data.contains("BreakingPos"))
|
||||||
|
return;
|
||||||
|
if (context.relativeMotion.equals(Vec3d.ZERO)) {
|
||||||
|
context.stall = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ticksUntilNextProgress = data.getInt("TicksUntilNextProgress");
|
||||||
|
if (ticksUntilNextProgress-- > 0) {
|
||||||
|
data.putInt("TicksUntilNextProgress", ticksUntilNextProgress);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
World world = context.world;
|
||||||
|
BlockPos breakingPos = NBTUtil.readBlockPos(data.getCompound("BreakingPos"));
|
||||||
|
int destroyProgress = data.getInt("Progress");
|
||||||
|
int id = data.getInt("BreakerId");
|
||||||
|
BlockState stateToBreak = world.getBlockState(breakingPos);
|
||||||
|
float blockHardness = stateToBreak.getBlockHardness(world, breakingPos);
|
||||||
|
|
||||||
|
if (!BlockBreakingKineticTileEntity.isBreakable(stateToBreak, blockHardness) || !canBreak(stateToBreak)) {
|
||||||
|
if (destroyProgress != 0) {
|
||||||
|
destroyProgress = 0;
|
||||||
|
data.remove("Progress");
|
||||||
|
data.remove("TicksUntilNextProgress");
|
||||||
|
data.remove("BreakingPos");
|
||||||
|
context.stall = false;
|
||||||
|
world.sendBlockBreakProgress(id, breakingPos, -1);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
float breakSpeed = MathHelper.clamp(Math.abs(context.getAnimationSpeed()) / 500f, 1 / 128f, 16f);
|
||||||
|
destroyProgress += MathHelper.clamp((int) (breakSpeed / blockHardness), 1, 10 - destroyProgress);
|
||||||
|
|
||||||
|
if (destroyProgress >= 10) {
|
||||||
|
BlockHelper.destroyBlock(context.world, breakingPos, 1f, stack -> this.dropItem(context, stack));
|
||||||
|
onBlockBroken(context, breakingPos);
|
||||||
|
ticksUntilNextProgress = -1;
|
||||||
|
world.sendBlockBreakProgress(id, breakingPos, -1);
|
||||||
|
data.remove("Progress");
|
||||||
|
data.remove("TicksUntilNextProgress");
|
||||||
|
data.remove("BreakingPos");
|
||||||
|
context.stall = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ticksUntilNextProgress = (int) (blockHardness / breakSpeed);
|
||||||
|
world.sendBlockBreakProgress(id, breakingPos, (int) destroyProgress);
|
||||||
|
data.putInt("TicksUntilNextProgress", ticksUntilNextProgress);
|
||||||
|
data.putInt("Progress", destroyProgress);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean canBreak(BlockState state) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onBlockBroken(MovementContext context, BlockPos pos) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,36 +1,28 @@
|
||||||
package com.simibubi.create.modules.contraptions.components.actors;
|
package com.simibubi.create.modules.contraptions.components.actors;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import com.simibubi.create.foundation.block.IWithTileEntity;
|
import com.simibubi.create.foundation.block.IWithTileEntity;
|
||||||
import com.simibubi.create.foundation.utility.AllShapes;
|
import com.simibubi.create.foundation.utility.AllShapes;
|
||||||
import com.simibubi.create.foundation.utility.SuperByteBuffer;
|
|
||||||
import com.simibubi.create.foundation.utility.VecHelper;
|
|
||||||
import com.simibubi.create.modules.contraptions.base.DirectionalKineticBlock;
|
import com.simibubi.create.modules.contraptions.base.DirectionalKineticBlock;
|
||||||
import com.simibubi.create.modules.contraptions.components.contraptions.IHaveMovementBehavior;
|
import com.simibubi.create.modules.contraptions.components.contraptions.IPortableBlock;
|
||||||
|
import com.simibubi.create.modules.contraptions.components.contraptions.MovementBehaviour;
|
||||||
|
|
||||||
import net.minecraft.block.Block;
|
import net.minecraft.block.Block;
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
import net.minecraft.block.Blocks;
|
import net.minecraft.block.Blocks;
|
||||||
import net.minecraft.block.material.PushReaction;
|
import net.minecraft.block.material.PushReaction;
|
||||||
import net.minecraft.entity.item.ItemEntity;
|
|
||||||
import net.minecraft.item.ItemStack;
|
|
||||||
import net.minecraft.tileentity.TileEntity;
|
import net.minecraft.tileentity.TileEntity;
|
||||||
import net.minecraft.util.Direction;
|
import net.minecraft.util.Direction;
|
||||||
import net.minecraft.util.Direction.Axis;
|
import net.minecraft.util.Direction.Axis;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.util.math.Vec3d;
|
|
||||||
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;
|
import net.minecraft.world.World;
|
||||||
import net.minecraft.world.server.ServerWorld;
|
|
||||||
import net.minecraftforge.api.distmarker.Dist;
|
|
||||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
|
||||||
|
|
||||||
public class DrillBlock extends DirectionalKineticBlock
|
public class DrillBlock extends DirectionalKineticBlock implements IPortableBlock, IWithTileEntity<DrillTileEntity> {
|
||||||
implements IHaveMovementBehavior, IWithTileEntity<DrillTileEntity> {
|
|
||||||
|
public static MovementBehaviour MOVEMENT = new DrillMovementBehaviour();
|
||||||
|
|
||||||
public DrillBlock() {
|
public DrillBlock() {
|
||||||
super(Properties.from(Blocks.IRON_BLOCK));
|
super(Properties.from(Blocks.IRON_BLOCK));
|
||||||
|
@ -76,44 +68,10 @@ public class DrillBlock extends DirectionalKineticBlock
|
||||||
protected boolean hasStaticPart() {
|
protected boolean hasStaticPart() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
@OnlyIn(value = Dist.CLIENT)
|
|
||||||
public SuperByteBuffer renderInContraption(MovementContext context) {
|
|
||||||
return DrillTileEntityRenderer.renderInContraption(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isActive(MovementContext context) {
|
public MovementBehaviour getMovementBehaviour() {
|
||||||
return !VecHelper.isVecPointingTowards(context.relativeMotion, context.state.get(FACING).getOpposite());
|
return MOVEMENT;
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Vec3d getActiveAreaOffset(MovementContext context) {
|
|
||||||
return new Vec3d(context.state.get(FACING).getDirectionVec()).scale(.65f);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void visitNewPosition(MovementContext context, BlockPos pos) {
|
|
||||||
World world = context.world;
|
|
||||||
BlockState stateVisited = world.getBlockState(pos);
|
|
||||||
|
|
||||||
if (world.isRemote)
|
|
||||||
return;
|
|
||||||
if (stateVisited.getCollisionShape(world, pos).isEmpty())
|
|
||||||
return;
|
|
||||||
if (stateVisited.getBlockHardness(world, pos) == -1)
|
|
||||||
return;
|
|
||||||
|
|
||||||
world.playEvent(2001, pos, Block.getStateId(stateVisited));
|
|
||||||
List<ItemStack> drops = Block.getDrops(stateVisited, (ServerWorld) world, pos, null);
|
|
||||||
world.setBlockState(pos, Blocks.AIR.getDefaultState());
|
|
||||||
|
|
||||||
for (ItemStack stack : drops) {
|
|
||||||
ItemEntity itemEntity = new ItemEntity(world, pos.getX() + .5f, pos.getY() + .25f, pos.getZ() + .5f, stack);
|
|
||||||
itemEntity.setMotion(context.motion.add(0, 0.5f, 0).scale(world.rand.nextFloat() * .3f));
|
|
||||||
world.addEntity(itemEntity);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
package com.simibubi.create.modules.contraptions.components.actors;
|
||||||
|
|
||||||
|
import com.simibubi.create.foundation.utility.SuperByteBuffer;
|
||||||
|
import com.simibubi.create.foundation.utility.VecHelper;
|
||||||
|
import com.simibubi.create.modules.contraptions.components.contraptions.MovementContext;
|
||||||
|
|
||||||
|
import net.minecraft.util.math.Vec3d;
|
||||||
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
|
|
||||||
|
public class DrillMovementBehaviour extends BlockBreakingMovementBehaviour {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isActive(MovementContext context) {
|
||||||
|
return !VecHelper.isVecPointingTowards(context.relativeMotion,
|
||||||
|
context.state.get(DrillBlock.FACING).getOpposite());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Vec3d getActiveAreaOffset(MovementContext context) {
|
||||||
|
return new Vec3d(context.state.get(DrillBlock.FACING).getDirectionVec()).scale(.65f);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@OnlyIn(value = Dist.CLIENT)
|
||||||
|
public SuperByteBuffer renderInContraption(MovementContext context) {
|
||||||
|
return DrillTileEntityRenderer.renderInContraption(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -9,7 +9,7 @@ import com.simibubi.create.foundation.utility.VecHelper;
|
||||||
import com.simibubi.create.modules.contraptions.base.IRotate;
|
import com.simibubi.create.modules.contraptions.base.IRotate;
|
||||||
import com.simibubi.create.modules.contraptions.base.KineticTileEntity;
|
import com.simibubi.create.modules.contraptions.base.KineticTileEntity;
|
||||||
import com.simibubi.create.modules.contraptions.base.KineticTileEntityRenderer;
|
import com.simibubi.create.modules.contraptions.base.KineticTileEntityRenderer;
|
||||||
import com.simibubi.create.modules.contraptions.components.contraptions.IHaveMovementBehavior.MovementContext;
|
import com.simibubi.create.modules.contraptions.components.contraptions.MovementContext;
|
||||||
|
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
import net.minecraft.util.Direction.Axis;
|
import net.minecraft.util.Direction.Axis;
|
||||||
|
@ -29,9 +29,10 @@ public class DrillTileEntityRenderer extends KineticTileEntityRenderer {
|
||||||
BlockState state = context.state;
|
BlockState state = context.state;
|
||||||
SuperByteBuffer buffer = getRotatingModel(state);
|
SuperByteBuffer buffer = getRotatingModel(state);
|
||||||
|
|
||||||
float speed = (float) (!VecHelper.isVecPointingTowards(context.relativeMotion, state.get(FACING).getOpposite())
|
float speed = (float) (context.contraption.stalled
|
||||||
? context.getAnimationSpeed()
|
|| !VecHelper.isVecPointingTowards(context.relativeMotion, state.get(FACING).getOpposite())
|
||||||
: 0);
|
? context.getAnimationSpeed()
|
||||||
|
: 0);
|
||||||
Axis axis = ((IRotate) state.getBlock()).getRotationAxis(state);
|
Axis axis = ((IRotate) state.getBlock()).getRotationAxis(state);
|
||||||
float time = AnimationTickHolder.getRenderTick() / 20;
|
float time = AnimationTickHolder.getRenderTick() / 20;
|
||||||
float angle = (float) (((time * speed) % 360) / 180 * (float) Math.PI);
|
float angle = (float) (((time * speed) % 360) / 180 * (float) Math.PI);
|
||||||
|
|
|
@ -1,43 +1,29 @@
|
||||||
package com.simibubi.create.modules.contraptions.components.actors;
|
package com.simibubi.create.modules.contraptions.components.actors;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import com.simibubi.create.AllBlocks;
|
import com.simibubi.create.AllBlocks;
|
||||||
import com.simibubi.create.foundation.utility.AllShapes;
|
import com.simibubi.create.foundation.utility.AllShapes;
|
||||||
import com.simibubi.create.foundation.utility.SuperByteBuffer;
|
import com.simibubi.create.modules.contraptions.components.contraptions.IPortableBlock;
|
||||||
import com.simibubi.create.foundation.utility.VecHelper;
|
import com.simibubi.create.modules.contraptions.components.contraptions.MovementBehaviour;
|
||||||
import com.simibubi.create.modules.contraptions.components.contraptions.IHaveMovementBehavior;
|
|
||||||
|
|
||||||
import net.minecraft.block.Block;
|
import net.minecraft.block.Block;
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
import net.minecraft.block.Blocks;
|
import net.minecraft.block.Blocks;
|
||||||
import net.minecraft.block.CropsBlock;
|
|
||||||
import net.minecraft.block.HorizontalBlock;
|
import net.minecraft.block.HorizontalBlock;
|
||||||
import net.minecraft.block.SugarCaneBlock;
|
|
||||||
import net.minecraft.block.material.PushReaction;
|
import net.minecraft.block.material.PushReaction;
|
||||||
import net.minecraft.entity.item.ItemEntity;
|
|
||||||
import net.minecraft.item.BlockItemUseContext;
|
import net.minecraft.item.BlockItemUseContext;
|
||||||
import net.minecraft.item.ItemStack;
|
|
||||||
import net.minecraft.state.IProperty;
|
|
||||||
import net.minecraft.state.IntegerProperty;
|
|
||||||
import net.minecraft.state.StateContainer.Builder;
|
import net.minecraft.state.StateContainer.Builder;
|
||||||
import net.minecraft.state.properties.BlockStateProperties;
|
|
||||||
import net.minecraft.tileentity.TileEntity;
|
import net.minecraft.tileentity.TileEntity;
|
||||||
import net.minecraft.util.BlockRenderLayer;
|
import net.minecraft.util.BlockRenderLayer;
|
||||||
import net.minecraft.util.Direction;
|
import net.minecraft.util.Direction;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.util.math.Vec3d;
|
|
||||||
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;
|
|
||||||
import net.minecraft.world.server.ServerWorld;
|
|
||||||
import net.minecraftforge.api.distmarker.Dist;
|
|
||||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
|
||||||
import net.minecraftforge.common.IPlantable;
|
|
||||||
|
|
||||||
public class HarvesterBlock extends HorizontalBlock implements IHaveMovementBehavior {
|
public class HarvesterBlock extends HorizontalBlock implements IPortableBlock {
|
||||||
|
|
||||||
|
public static MovementBehaviour MOVEMENT = new HarvesterMovementBehaviour();
|
||||||
|
|
||||||
public HarvesterBlock() {
|
public HarvesterBlock() {
|
||||||
super(Properties.from(Blocks.IRON_BLOCK));
|
super(Properties.from(Blocks.IRON_BLOCK));
|
||||||
|
@ -70,12 +56,6 @@ public class HarvesterBlock extends HorizontalBlock implements IHaveMovementBeha
|
||||||
super.fillStateContainer(builder);
|
super.fillStateContainer(builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
@OnlyIn(value = Dist.CLIENT)
|
|
||||||
public SuperByteBuffer renderInContraption(MovementContext context) {
|
|
||||||
return HarvesterTileEntityRenderer.renderInContraption(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BlockRenderLayer getRenderLayer() {
|
public BlockRenderLayer getRenderLayer() {
|
||||||
return BlockRenderLayer.CUTOUT;
|
return BlockRenderLayer.CUTOUT;
|
||||||
|
@ -94,8 +74,8 @@ public class HarvesterBlock extends HorizontalBlock implements IHaveMovementBeha
|
||||||
if (context.getFace().getAxis().isVertical())
|
if (context.getFace().getAxis().isVertical())
|
||||||
facing = context.getPlacementHorizontalFacing().getOpposite();
|
facing = context.getPlacementHorizontalFacing().getOpposite();
|
||||||
else {
|
else {
|
||||||
BlockState blockState = context.getWorld()
|
BlockState blockState =
|
||||||
.getBlockState(context.getPos().offset(context.getFace().getOpposite()));
|
context.getWorld().getBlockState(context.getPos().offset(context.getFace().getOpposite()));
|
||||||
if (AllBlocks.HARVESTER.typeOf(blockState))
|
if (AllBlocks.HARVESTER.typeOf(blockState))
|
||||||
facing = blockState.get(HORIZONTAL_FACING);
|
facing = blockState.get(HORIZONTAL_FACING);
|
||||||
else
|
else
|
||||||
|
@ -105,118 +85,8 @@ public class HarvesterBlock extends HorizontalBlock implements IHaveMovementBeha
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isActive(MovementContext context) {
|
public MovementBehaviour getMovementBehaviour() {
|
||||||
return !VecHelper.isVecPointingTowards(context.relativeMotion,
|
return MOVEMENT;
|
||||||
context.state.get(HORIZONTAL_FACING).getOpposite());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Vec3d getActiveAreaOffset(MovementContext context) {
|
|
||||||
return new Vec3d(context.state.get(HORIZONTAL_FACING).getDirectionVec()).scale(.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void visitNewPosition(MovementContext context, BlockPos pos) {
|
|
||||||
World world = context.world;
|
|
||||||
BlockState stateVisited = world.getBlockState(pos);
|
|
||||||
boolean notCropButCuttable = false;
|
|
||||||
|
|
||||||
if (world.isRemote)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (stateVisited.getBlock() == Blocks.SUGAR_CANE) {
|
|
||||||
notCropButCuttable = true;
|
|
||||||
pos = pos.up();
|
|
||||||
stateVisited = world.getBlockState(pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isValidCrop(world, pos, stateVisited)) {
|
|
||||||
if (isValidOther(world, pos, stateVisited))
|
|
||||||
notCropButCuttable = true;
|
|
||||||
else
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<ItemStack> drops = Block.getDrops(stateVisited, (ServerWorld) world, pos, null);
|
|
||||||
world.playEvent(2001, pos, Block.getStateId(stateVisited));
|
|
||||||
world.setBlockState(pos, cutCrop(world, pos, stateVisited));
|
|
||||||
|
|
||||||
boolean seedSubtracted = notCropButCuttable;
|
|
||||||
for (ItemStack stack : drops) {
|
|
||||||
if (!seedSubtracted && stack.isItemEqual(new ItemStack(stateVisited.getBlock()))) {
|
|
||||||
stack.shrink(1);
|
|
||||||
seedSubtracted = true;
|
|
||||||
}
|
|
||||||
ItemEntity itemEntity = new ItemEntity(world, pos.getX() + .5f, pos.getY() + .25f, pos.getZ() + .5f, stack);
|
|
||||||
itemEntity.setMotion(context.motion.add(0, 0.5f, 0).scale(world.rand.nextFloat() * .3f));
|
|
||||||
world.addEntity(itemEntity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isValidCrop(World world, BlockPos pos, BlockState state) {
|
|
||||||
if (state.getBlock() instanceof CropsBlock) {
|
|
||||||
CropsBlock crop = (CropsBlock) state.getBlock();
|
|
||||||
if (!crop.isMaxAge(state))
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (state.getCollisionShape(world, pos).isEmpty()) {
|
|
||||||
for (IProperty<?> property : state.getProperties()) {
|
|
||||||
if (!(property instanceof IntegerProperty))
|
|
||||||
continue;
|
|
||||||
if (!property.getName().equals(BlockStateProperties.AGE_0_1.getName()))
|
|
||||||
continue;
|
|
||||||
if (((IntegerProperty) property).getAllowedValues().size() - 1 != state.get((IntegerProperty) property)
|
|
||||||
.intValue())
|
|
||||||
continue;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isValidOther(World world, BlockPos pos, BlockState state) {
|
|
||||||
if (state.getBlock() instanceof CropsBlock)
|
|
||||||
return false;
|
|
||||||
if (state.getBlock() instanceof SugarCaneBlock)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if (state.getCollisionShape(world, pos).isEmpty()) {
|
|
||||||
for (IProperty<?> property : state.getProperties()) {
|
|
||||||
if (!(property instanceof IntegerProperty))
|
|
||||||
continue;
|
|
||||||
if (!property.getName().equals(BlockStateProperties.AGE_0_1.getName()))
|
|
||||||
continue;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state.getBlock() instanceof IPlantable)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private BlockState cutCrop(World world, BlockPos pos, BlockState state) {
|
|
||||||
if (state.getBlock() instanceof CropsBlock) {
|
|
||||||
CropsBlock crop = (CropsBlock) state.getBlock();
|
|
||||||
return crop.withAge(0);
|
|
||||||
}
|
|
||||||
if (state.getBlock() == Blocks.SUGAR_CANE) {
|
|
||||||
return Blocks.AIR.getDefaultState();
|
|
||||||
}
|
|
||||||
if (state.getCollisionShape(world, pos).isEmpty()) {
|
|
||||||
for (IProperty<?> property : state.getProperties()) {
|
|
||||||
if (!(property instanceof IntegerProperty))
|
|
||||||
continue;
|
|
||||||
if (!property.getName().equals(BlockStateProperties.AGE_0_1.getName()))
|
|
||||||
continue;
|
|
||||||
return state.with((IntegerProperty) property, Integer.valueOf(0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Blocks.AIR.getDefaultState();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,148 @@
|
||||||
|
package com.simibubi.create.modules.contraptions.components.actors;
|
||||||
|
|
||||||
|
import static net.minecraft.block.HorizontalBlock.HORIZONTAL_FACING;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.mutable.MutableBoolean;
|
||||||
|
|
||||||
|
import com.simibubi.create.foundation.utility.BlockHelper;
|
||||||
|
import com.simibubi.create.foundation.utility.SuperByteBuffer;
|
||||||
|
import com.simibubi.create.foundation.utility.VecHelper;
|
||||||
|
import com.simibubi.create.modules.contraptions.components.contraptions.MovementBehaviour;
|
||||||
|
import com.simibubi.create.modules.contraptions.components.contraptions.MovementContext;
|
||||||
|
|
||||||
|
import net.minecraft.block.BlockState;
|
||||||
|
import net.minecraft.block.Blocks;
|
||||||
|
import net.minecraft.block.CropsBlock;
|
||||||
|
import net.minecraft.block.SugarCaneBlock;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.state.IProperty;
|
||||||
|
import net.minecraft.state.IntegerProperty;
|
||||||
|
import net.minecraft.state.properties.BlockStateProperties;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.util.math.Vec3d;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
|
import net.minecraftforge.common.IPlantable;
|
||||||
|
|
||||||
|
public class HarvesterMovementBehaviour extends MovementBehaviour {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isActive(MovementContext context) {
|
||||||
|
return !VecHelper.isVecPointingTowards(context.relativeMotion,
|
||||||
|
context.state.get(HORIZONTAL_FACING).getOpposite());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@OnlyIn(value = Dist.CLIENT)
|
||||||
|
public SuperByteBuffer renderInContraption(MovementContext context) {
|
||||||
|
return HarvesterTileEntityRenderer.renderInContraption(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Vec3d getActiveAreaOffset(MovementContext context) {
|
||||||
|
return new Vec3d(context.state.get(HORIZONTAL_FACING).getDirectionVec()).scale(.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitNewPosition(MovementContext context, BlockPos pos) {
|
||||||
|
World world = context.world;
|
||||||
|
BlockState stateVisited = world.getBlockState(pos);
|
||||||
|
boolean notCropButCuttable = false;
|
||||||
|
|
||||||
|
if (world.isRemote)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (stateVisited.getBlock() == Blocks.SUGAR_CANE) {
|
||||||
|
notCropButCuttable = true;
|
||||||
|
pos = pos.up();
|
||||||
|
stateVisited = world.getBlockState(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isValidCrop(world, pos, stateVisited)) {
|
||||||
|
if (isValidOther(world, pos, stateVisited))
|
||||||
|
notCropButCuttable = true;
|
||||||
|
else
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MutableBoolean seedSubtracted = new MutableBoolean(notCropButCuttable);
|
||||||
|
BlockState state = stateVisited;
|
||||||
|
BlockHelper.destroyBlock(world, pos, 1, stack -> {
|
||||||
|
if (!seedSubtracted.getValue() && stack.isItemEqual(new ItemStack(state.getBlock()))) {
|
||||||
|
stack.shrink(1);
|
||||||
|
seedSubtracted.setTrue();
|
||||||
|
}
|
||||||
|
dropItem(context, stack);
|
||||||
|
});
|
||||||
|
|
||||||
|
world.setBlockState(pos, cutCrop(world, pos, stateVisited));
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isValidCrop(World world, BlockPos pos, BlockState state) {
|
||||||
|
if (state.getBlock() instanceof CropsBlock) {
|
||||||
|
CropsBlock crop = (CropsBlock) state.getBlock();
|
||||||
|
if (!crop.isMaxAge(state))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (state.getCollisionShape(world, pos).isEmpty()) {
|
||||||
|
for (IProperty<?> property : state.getProperties()) {
|
||||||
|
if (!(property instanceof IntegerProperty))
|
||||||
|
continue;
|
||||||
|
if (!property.getName().equals(BlockStateProperties.AGE_0_1.getName()))
|
||||||
|
continue;
|
||||||
|
if (((IntegerProperty) property).getAllowedValues().size() - 1 != state.get((IntegerProperty) property)
|
||||||
|
.intValue())
|
||||||
|
continue;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isValidOther(World world, BlockPos pos, BlockState state) {
|
||||||
|
if (state.getBlock() instanceof CropsBlock)
|
||||||
|
return false;
|
||||||
|
if (state.getBlock() instanceof SugarCaneBlock)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (state.getCollisionShape(world, pos).isEmpty()) {
|
||||||
|
for (IProperty<?> property : state.getProperties()) {
|
||||||
|
if (!(property instanceof IntegerProperty))
|
||||||
|
continue;
|
||||||
|
if (!property.getName().equals(BlockStateProperties.AGE_0_1.getName()))
|
||||||
|
continue;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state.getBlock() instanceof IPlantable)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private BlockState cutCrop(World world, BlockPos pos, BlockState state) {
|
||||||
|
if (state.getBlock() instanceof CropsBlock) {
|
||||||
|
CropsBlock crop = (CropsBlock) state.getBlock();
|
||||||
|
return crop.withAge(0);
|
||||||
|
}
|
||||||
|
if (state.getBlock() == Blocks.SUGAR_CANE) {
|
||||||
|
return Blocks.AIR.getDefaultState();
|
||||||
|
}
|
||||||
|
if (state.getCollisionShape(world, pos).isEmpty()) {
|
||||||
|
for (IProperty<?> property : state.getProperties()) {
|
||||||
|
if (!(property instanceof IntegerProperty))
|
||||||
|
continue;
|
||||||
|
if (!property.getName().equals(BlockStateProperties.AGE_0_1.getName()))
|
||||||
|
continue;
|
||||||
|
return state.with((IntegerProperty) property, Integer.valueOf(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Blocks.AIR.getDefaultState();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -7,7 +7,7 @@ import com.simibubi.create.foundation.block.SafeTileEntityRendererFast;
|
||||||
import com.simibubi.create.foundation.utility.AnimationTickHolder;
|
import com.simibubi.create.foundation.utility.AnimationTickHolder;
|
||||||
import com.simibubi.create.foundation.utility.SuperByteBuffer;
|
import com.simibubi.create.foundation.utility.SuperByteBuffer;
|
||||||
import com.simibubi.create.foundation.utility.VecHelper;
|
import com.simibubi.create.foundation.utility.VecHelper;
|
||||||
import com.simibubi.create.modules.contraptions.components.contraptions.IHaveMovementBehavior.MovementContext;
|
import com.simibubi.create.modules.contraptions.components.contraptions.MovementContext;
|
||||||
|
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
import net.minecraft.client.renderer.BufferBuilder;
|
import net.minecraft.client.renderer.BufferBuilder;
|
||||||
|
@ -19,16 +19,18 @@ import net.minecraft.world.World;
|
||||||
public class HarvesterTileEntityRenderer extends SafeTileEntityRendererFast<HarvesterTileEntity> {
|
public class HarvesterTileEntityRenderer extends SafeTileEntityRendererFast<HarvesterTileEntity> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void renderFast(HarvesterTileEntity te, double x, double y, double z, float partialTicks,
|
public void renderFast(HarvesterTileEntity te, double x, double y, double z, float partialTicks, int destroyStage,
|
||||||
int destroyStage, BufferBuilder buffer) {
|
BufferBuilder buffer) {
|
||||||
SuperByteBuffer superBuffer = renderHead(getWorld(), te.getPos(), te.getBlockState(), 0);
|
SuperByteBuffer superBuffer = renderHead(getWorld(), te.getPos(), te.getBlockState(), 0);
|
||||||
superBuffer.translate(x, y, z).renderInto(buffer);
|
superBuffer.translate(x, y, z).renderInto(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SuperByteBuffer renderInContraption(MovementContext context) {
|
public static SuperByteBuffer renderInContraption(MovementContext context) {
|
||||||
BlockState state = context.state;
|
BlockState state = context.state;
|
||||||
float speed = (float) (!VecHelper.isVecPointingTowards(context.relativeMotion, state.get(HORIZONTAL_FACING).getOpposite())
|
Direction facing = state.get(HORIZONTAL_FACING);
|
||||||
? context.getAnimationSpeed() * state.get(HORIZONTAL_FACING).getAxisDirection().getOffset()
|
int offset = facing.getAxisDirection().getOffset() * (facing.getAxis() == Axis.X ? 1 : -1);
|
||||||
|
float speed = (float) (!VecHelper.isVecPointingTowards(context.relativeMotion, facing.getOpposite())
|
||||||
|
? context.getAnimationSpeed() * offset
|
||||||
: 0);
|
: 0);
|
||||||
float time = AnimationTickHolder.getRenderTick() / 20;
|
float time = AnimationTickHolder.getRenderTick() / 20;
|
||||||
float angle = (float) (((time * speed) % 360) / 180 * (float) Math.PI);
|
float angle = (float) (((time * speed) % 360) / 180 * (float) Math.PI);
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
package com.simibubi.create.modules.contraptions.components.actors;
|
||||||
|
|
||||||
|
import com.simibubi.create.foundation.block.ProperDirectionalBlock;
|
||||||
|
import com.simibubi.create.foundation.utility.AllShapes;
|
||||||
|
import com.simibubi.create.modules.contraptions.components.contraptions.IPortableBlock;
|
||||||
|
import com.simibubi.create.modules.contraptions.components.contraptions.MovementBehaviour;
|
||||||
|
|
||||||
|
import net.minecraft.block.BlockState;
|
||||||
|
import net.minecraft.block.Blocks;
|
||||||
|
import net.minecraft.item.BlockItemUseContext;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.util.math.shapes.ISelectionContext;
|
||||||
|
import net.minecraft.util.math.shapes.VoxelShape;
|
||||||
|
import net.minecraft.world.IBlockReader;
|
||||||
|
|
||||||
|
public class PortableStorageInterfaceBlock extends ProperDirectionalBlock implements IPortableBlock {
|
||||||
|
|
||||||
|
public static MovementBehaviour MOVEMENT = new StorageInterfaceMovement();
|
||||||
|
|
||||||
|
public PortableStorageInterfaceBlock() {
|
||||||
|
super(Properties.from(Blocks.ANDESITE));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockState getStateForPlacement(BlockItemUseContext context) {
|
||||||
|
return getDefaultState().with(FACING, context.getNearestLookingDirection().getOpposite());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) {
|
||||||
|
return AllShapes.PORTABLE_STORAGE_INTERFACE.get(state.get(FACING));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MovementBehaviour getMovementBehaviour() {
|
||||||
|
return MOVEMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
package com.simibubi.create.modules.contraptions.components.actors;
|
||||||
|
|
||||||
|
import com.simibubi.create.foundation.utility.BlockHelper;
|
||||||
|
import com.simibubi.create.foundation.utility.TreeCutter;
|
||||||
|
import com.simibubi.create.foundation.utility.TreeCutter.Tree;
|
||||||
|
import com.simibubi.create.foundation.utility.VecHelper;
|
||||||
|
import com.simibubi.create.modules.contraptions.components.contraptions.MovementContext;
|
||||||
|
import com.simibubi.create.modules.contraptions.components.saw.SawBlock;
|
||||||
|
|
||||||
|
import net.minecraft.block.BlockState;
|
||||||
|
import net.minecraft.entity.item.ItemEntity;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.tags.BlockTags;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.util.math.Vec3d;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
import net.minecraftforge.items.ItemHandlerHelper;
|
||||||
|
|
||||||
|
public class SawMovementBehaviour extends BlockBreakingMovementBehaviour {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isActive(MovementContext context) {
|
||||||
|
return SawBlock.isHorizontal(context.state);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Vec3d getActiveAreaOffset(MovementContext context) {
|
||||||
|
return new Vec3d(context.state.get(SawBlock.FACING).getDirectionVec()).scale(.65f);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean canBreak(BlockState state) {
|
||||||
|
return super.canBreak(state) && state.isIn(BlockTags.LOGS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onBlockBroken(MovementContext context, BlockPos pos) {
|
||||||
|
Tree tree = TreeCutter.cutTree(context.world, pos);
|
||||||
|
if (tree != null) {
|
||||||
|
for (BlockPos log : tree.logs)
|
||||||
|
BlockHelper.destroyBlock(context.world, log, 1 / 2f, stack -> dropItemFromCutTree(context, log, stack));
|
||||||
|
for (BlockPos leaf : tree.leaves)
|
||||||
|
BlockHelper.destroyBlock(context.world, leaf, 1 / 8f,
|
||||||
|
stack -> dropItemFromCutTree(context, leaf, stack));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void dropItemFromCutTree(MovementContext context, BlockPos pos, ItemStack stack) {
|
||||||
|
ItemStack remainder = ItemHandlerHelper.insertItem(context.contraption.inventory, stack, false);
|
||||||
|
if (remainder.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
World world = context.world;
|
||||||
|
Vec3d dropPos = VecHelper.getCenterOf(pos);
|
||||||
|
float distance = (float) dropPos.distanceTo(context.position);
|
||||||
|
ItemEntity entity = new ItemEntity(world, dropPos.x, dropPos.y, dropPos.z, remainder);
|
||||||
|
entity.setMotion(context.relativeMotion.scale(distance / 20f));
|
||||||
|
world.addEntity(entity);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,157 @@
|
||||||
|
package com.simibubi.create.modules.contraptions.components.actors;
|
||||||
|
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
import com.simibubi.create.config.AllConfigs;
|
||||||
|
import com.simibubi.create.foundation.behaviour.base.TileEntityBehaviour;
|
||||||
|
import com.simibubi.create.foundation.behaviour.filtering.FilteringBehaviour;
|
||||||
|
import com.simibubi.create.foundation.behaviour.inventory.SingleTargetAutoExtractingBehaviour;
|
||||||
|
import com.simibubi.create.foundation.item.ItemHelper;
|
||||||
|
import com.simibubi.create.foundation.utility.VecHelper;
|
||||||
|
import com.simibubi.create.modules.contraptions.components.contraptions.MovementBehaviour;
|
||||||
|
import com.simibubi.create.modules.contraptions.components.contraptions.MovementContext;
|
||||||
|
import com.simibubi.create.modules.logistics.block.transposer.TransposerBlock;
|
||||||
|
import com.simibubi.create.modules.logistics.block.transposer.TransposerTileEntity;
|
||||||
|
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.nbt.NBTUtil;
|
||||||
|
import net.minecraft.tileentity.TileEntity;
|
||||||
|
import net.minecraft.util.Direction;
|
||||||
|
import net.minecraft.util.Direction.Axis;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.util.math.Vec3d;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
import net.minecraftforge.items.IItemHandlerModifiable;
|
||||||
|
import net.minecraftforge.items.ItemHandlerHelper;
|
||||||
|
|
||||||
|
public class StorageInterfaceMovement extends MovementBehaviour {
|
||||||
|
|
||||||
|
private static final String _exporting_ = "Exporting";
|
||||||
|
private static final String _delay_ = "Delay";
|
||||||
|
private static final String _workingPos_ = "WorkingPos";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Vec3d getActiveAreaOffset(MovementContext context) {
|
||||||
|
return new Vec3d(context.state.get(PortableStorageInterfaceBlock.FACING).getDirectionVec()).scale(.65f);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitNewPosition(MovementContext context, BlockPos pos) {
|
||||||
|
Direction currentFacing = getCurrentFacing(context);
|
||||||
|
TransposerTileEntity transposer = getValidTransposer(context.world, pos, currentFacing.getAxis());
|
||||||
|
if (transposer == null)
|
||||||
|
return;
|
||||||
|
context.data.put(_workingPos_, NBTUtil.writeBlockPos(pos));
|
||||||
|
context.data.putBoolean(_exporting_,
|
||||||
|
TransposerBlock.getBlockFacing(transposer.getBlockState()) != currentFacing);
|
||||||
|
context.stall = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tick(MovementContext context) {
|
||||||
|
if (!context.data.contains(_workingPos_))
|
||||||
|
return;
|
||||||
|
if (context.world.isRemote)
|
||||||
|
return;
|
||||||
|
|
||||||
|
BlockPos pos = NBTUtil.readBlockPos(context.data.getCompound(_workingPos_));
|
||||||
|
TransposerTileEntity transposer = getValidTransposer(context.world, pos, getCurrentFacing(context).getAxis());
|
||||||
|
if (transposer == null) {
|
||||||
|
reset(context);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nextExtract = context.data.getInt(_delay_);
|
||||||
|
if (nextExtract > 0) {
|
||||||
|
nextExtract--;
|
||||||
|
context.data.putInt(_delay_, nextExtract);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean extract = context.data.getBoolean(_exporting_);
|
||||||
|
boolean success = false;
|
||||||
|
IItemHandlerModifiable inv = context.contraption.inventory;
|
||||||
|
SingleTargetAutoExtractingBehaviour extracting =
|
||||||
|
TileEntityBehaviour.get(transposer, SingleTargetAutoExtractingBehaviour.TYPE);
|
||||||
|
FilteringBehaviour filtering = TileEntityBehaviour.get(transposer, FilteringBehaviour.TYPE);
|
||||||
|
|
||||||
|
if (extract) {
|
||||||
|
// Export from Contraption
|
||||||
|
Predicate<ItemStack> test = extracting.getFilterTest();
|
||||||
|
int exactAmount = extracting.getAmountToExtract();
|
||||||
|
ItemStack itemExtracted = ItemStack.EMPTY;
|
||||||
|
if (exactAmount != -1)
|
||||||
|
itemExtracted = ItemHelper.extract(inv, test, exactAmount, false);
|
||||||
|
else
|
||||||
|
itemExtracted = ItemHelper.extract(inv, test, transposer::amountToExtract, false);
|
||||||
|
|
||||||
|
if (!itemExtracted.isEmpty()) {
|
||||||
|
transposer.onExtract(itemExtracted);
|
||||||
|
success = exactAmount == -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// Import to Contraption
|
||||||
|
if (extracting != null) {
|
||||||
|
extracting.setSynchronized(false);
|
||||||
|
extracting.withAdditionalFilter(stack -> {
|
||||||
|
if (filtering.anyAmount())
|
||||||
|
return true;
|
||||||
|
return ItemHandlerHelper.insertItemStacked(inv, stack, true).isEmpty();
|
||||||
|
});
|
||||||
|
|
||||||
|
extracting.withAmountThreshold(stack -> {
|
||||||
|
ItemStack tester = stack.copy();
|
||||||
|
tester.setCount(64);
|
||||||
|
return 64 - ItemHandlerHelper.insertItemStacked(inv, stack, true).getCount();
|
||||||
|
});
|
||||||
|
|
||||||
|
extracting.setCallback(stack -> {
|
||||||
|
ItemHandlerHelper.insertItemStacked(inv, stack, false);
|
||||||
|
});
|
||||||
|
|
||||||
|
success = extracting.extract() && filtering.anyAmount();
|
||||||
|
extracting.setSynchronized(true);
|
||||||
|
transposer.applyFilteringCallbacks();
|
||||||
|
extracting.setCallback(transposer::onExtract);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!success) {
|
||||||
|
reset(context);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
context.data.putInt(_delay_, AllConfigs.SERVER.logistics.extractorDelay.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stopMoving(MovementContext context) {
|
||||||
|
reset(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reset(MovementContext context) {
|
||||||
|
context.data.remove(_workingPos_);
|
||||||
|
context.data.remove(_delay_);
|
||||||
|
context.data.remove(_exporting_);
|
||||||
|
context.stall = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private TransposerTileEntity getValidTransposer(World world, BlockPos pos, Axis validAxis) {
|
||||||
|
TileEntity te = world.getTileEntity(pos);
|
||||||
|
if (!(te instanceof TransposerTileEntity))
|
||||||
|
return null;
|
||||||
|
if (TransposerBlock.getBlockFacing(world.getBlockState(pos)).getAxis() != validAxis)
|
||||||
|
return null;
|
||||||
|
if (world.isBlockPowered(pos))
|
||||||
|
return null;
|
||||||
|
return (TransposerTileEntity) te;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Direction getCurrentFacing(MovementContext context) {
|
||||||
|
Vec3d directionVec = new Vec3d(context.state.get(PortableStorageInterfaceBlock.FACING).getDirectionVec());
|
||||||
|
directionVec = VecHelper.rotate(directionVec, context.rotation.x, context.rotation.y, context.rotation.z);
|
||||||
|
return Direction.getFacingFromVector(directionVec.x, directionVec.y, directionVec.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -4,20 +4,24 @@ import static net.minecraft.state.properties.BlockStateProperties.AXIS;
|
||||||
import static net.minecraft.state.properties.BlockStateProperties.FACING;
|
import static net.minecraft.state.properties.BlockStateProperties.FACING;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.function.BiConsumer;
|
||||||
import java.util.function.BiPredicate;
|
import java.util.function.BiPredicate;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import org.apache.commons.lang3.tuple.MutablePair;
|
import org.apache.commons.lang3.tuple.MutablePair;
|
||||||
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
|
|
||||||
import com.simibubi.create.AllBlocks;
|
import com.simibubi.create.AllBlocks;
|
||||||
import com.simibubi.create.config.AllConfigs;
|
import com.simibubi.create.config.AllConfigs;
|
||||||
import com.simibubi.create.modules.contraptions.components.contraptions.IHaveMovementBehavior.MovementContext;
|
import com.simibubi.create.foundation.utility.NBTHelper;
|
||||||
import com.simibubi.create.modules.contraptions.components.contraptions.bearing.BearingContraption;
|
import com.simibubi.create.modules.contraptions.components.contraptions.bearing.BearingContraption;
|
||||||
import com.simibubi.create.modules.contraptions.components.contraptions.chassis.AbstractChassisBlock;
|
import com.simibubi.create.modules.contraptions.components.contraptions.chassis.AbstractChassisBlock;
|
||||||
import com.simibubi.create.modules.contraptions.components.contraptions.chassis.ChassisTileEntity;
|
import com.simibubi.create.modules.contraptions.components.contraptions.chassis.ChassisTileEntity;
|
||||||
|
@ -27,14 +31,14 @@ import com.simibubi.create.modules.contraptions.components.contraptions.mounted.
|
||||||
import com.simibubi.create.modules.contraptions.components.contraptions.piston.PistonContraption;
|
import com.simibubi.create.modules.contraptions.components.contraptions.piston.PistonContraption;
|
||||||
import com.simibubi.create.modules.contraptions.components.saw.SawBlock;
|
import com.simibubi.create.modules.contraptions.components.saw.SawBlock;
|
||||||
|
|
||||||
|
import net.minecraft.block.Block;
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
import net.minecraft.block.Blocks;
|
import net.minecraft.block.Blocks;
|
||||||
import net.minecraft.block.FallingBlock;
|
import net.minecraft.block.FallingBlock;
|
||||||
import net.minecraft.block.PistonBlock;
|
|
||||||
import net.minecraft.block.ShulkerBoxBlock;
|
import net.minecraft.block.ShulkerBoxBlock;
|
||||||
import net.minecraft.block.SlimeBlock;
|
import net.minecraft.block.SlimeBlock;
|
||||||
|
import net.minecraft.block.material.PushReaction;
|
||||||
import net.minecraft.nbt.CompoundNBT;
|
import net.minecraft.nbt.CompoundNBT;
|
||||||
import net.minecraft.nbt.FloatNBT;
|
|
||||||
import net.minecraft.nbt.ListNBT;
|
import net.minecraft.nbt.ListNBT;
|
||||||
import net.minecraft.nbt.NBTUtil;
|
import net.minecraft.nbt.NBTUtil;
|
||||||
import net.minecraft.state.properties.BlockStateProperties;
|
import net.minecraft.state.properties.BlockStateProperties;
|
||||||
|
@ -44,21 +48,30 @@ import net.minecraft.util.Direction.Axis;
|
||||||
import net.minecraft.util.Direction.AxisDirection;
|
import net.minecraft.util.Direction.AxisDirection;
|
||||||
import net.minecraft.util.math.AxisAlignedBB;
|
import net.minecraft.util.math.AxisAlignedBB;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.util.math.Vec3d;
|
||||||
import net.minecraft.world.IWorld;
|
import net.minecraft.world.IWorld;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
import net.minecraft.world.gen.feature.template.Template.BlockInfo;
|
import net.minecraft.world.gen.feature.template.Template.BlockInfo;
|
||||||
|
import net.minecraftforge.items.IItemHandlerModifiable;
|
||||||
|
import net.minecraftforge.items.wrapper.CombinedInvWrapper;
|
||||||
|
|
||||||
public class Contraption {
|
public class Contraption {
|
||||||
|
|
||||||
public Map<BlockPos, BlockInfo> blocks;
|
public Map<BlockPos, BlockInfo> blocks;
|
||||||
|
public Map<BlockPos, MountedStorage> storage;
|
||||||
public List<MutablePair<BlockInfo, MovementContext>> actors;
|
public List<MutablePair<BlockInfo, MovementContext>> actors;
|
||||||
|
public CombinedInvWrapper inventory;
|
||||||
|
|
||||||
public AxisAlignedBB constructCollisionBox;
|
public AxisAlignedBB constructCollisionBox;
|
||||||
|
public boolean stalled;
|
||||||
|
|
||||||
protected Set<BlockPos> cachedColliders;
|
protected Set<BlockPos> cachedColliders;
|
||||||
protected Direction cachedColliderDirection;
|
protected Direction cachedColliderDirection;
|
||||||
protected BlockPos anchor;
|
protected BlockPos anchor;
|
||||||
|
|
||||||
public Contraption() {
|
public Contraption() {
|
||||||
blocks = new HashMap<>();
|
blocks = new HashMap<>();
|
||||||
|
storage = new HashMap<>();
|
||||||
actors = new ArrayList<>();
|
actors = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,15 +150,22 @@ public class Contraption {
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
for (int limit = 1000; limit > 0; limit--) {
|
for (int limit = 1000; limit > 0; limit--) {
|
||||||
if (frontier.isEmpty())
|
if (frontier.isEmpty()) {
|
||||||
|
onAssembled(world, pos);
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
if (!moveBlock(world, frontier.remove(0), direction, frontier, visited))
|
if (!moveBlock(world, frontier.remove(0), direction, frontier, visited))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void onAssembled(World world, BlockPos pos) {
|
||||||
|
List<IItemHandlerModifiable> list =
|
||||||
|
storage.values().stream().map(MountedStorage::getItemHandler).collect(Collectors.toList());
|
||||||
|
inventory = new CombinedInvWrapper(Arrays.copyOf(list.toArray(), list.size(), IItemHandlerModifiable[].class));
|
||||||
|
}
|
||||||
|
|
||||||
protected boolean addToInitialFrontier(World world, BlockPos pos, Direction direction, List<BlockPos> frontier) {
|
protected boolean addToInitialFrontier(World world, BlockPos pos, Direction direction, List<BlockPos> frontier) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -417,15 +437,16 @@ public class Contraption {
|
||||||
return true;
|
return true;
|
||||||
if (blockState.getBlock() instanceof ShulkerBoxBlock)
|
if (blockState.getBlock() instanceof ShulkerBoxBlock)
|
||||||
return false;
|
return false;
|
||||||
return PistonBlock.canPush(blockState, world, pos, direction, true, direction);
|
return blockState.getPushReaction() != PushReaction.BLOCK;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected BlockInfo capture(World world, BlockPos pos) {
|
protected Pair<BlockInfo, TileEntity> capture(World world, BlockPos pos) {
|
||||||
BlockState blockstate = world.getBlockState(pos);
|
BlockState blockstate = world.getBlockState(pos);
|
||||||
if (AllBlocks.SAW.typeOf(blockstate))
|
if (AllBlocks.SAW.typeOf(blockstate))
|
||||||
blockstate = blockstate.with(SawBlock.RUNNING, true);
|
blockstate = blockstate.with(SawBlock.RUNNING, true);
|
||||||
CompoundNBT compoundnbt = getTileEntityNBT(world, pos);
|
CompoundNBT compoundnbt = getTileEntityNBT(world, pos);
|
||||||
return new BlockInfo(pos, blockstate, compoundnbt);
|
TileEntity tileentity = world.getTileEntity(pos);
|
||||||
|
return Pair.of(new BlockInfo(pos, blockstate, compoundnbt), tileentity);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CompoundNBT getTileEntityNBT(World world, BlockPos pos) {
|
public static CompoundNBT getTileEntityNBT(World world, BlockPos pos) {
|
||||||
|
@ -440,13 +461,20 @@ public class Contraption {
|
||||||
return compoundnbt;
|
return compoundnbt;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void add(BlockPos pos, BlockInfo block) {
|
public void add(BlockPos pos, Pair<BlockInfo, TileEntity> pair) {
|
||||||
|
BlockInfo captured = pair.getKey();
|
||||||
BlockPos localPos = pos.subtract(anchor);
|
BlockPos localPos = pos.subtract(anchor);
|
||||||
BlockInfo blockInfo = new BlockInfo(localPos, block.state, block.nbt);
|
BlockInfo blockInfo = new BlockInfo(localPos, captured.state, captured.nbt);
|
||||||
blocks.put(localPos, blockInfo);
|
|
||||||
if (block.state.getBlock() instanceof IHaveMovementBehavior)
|
if (blocks.put(localPos, blockInfo) != null)
|
||||||
getActors().add(MutablePair.of(blockInfo, null));
|
return;
|
||||||
constructCollisionBox = constructCollisionBox.union(new AxisAlignedBB(localPos));
|
constructCollisionBox = constructCollisionBox.union(new AxisAlignedBB(localPos));
|
||||||
|
|
||||||
|
TileEntity te = pair.getValue();
|
||||||
|
if (te != null && MountedStorage.canUseAsStorage(te))
|
||||||
|
storage.put(localPos, new MountedStorage(te));
|
||||||
|
if (captured.state.getBlock() instanceof IPortableBlock)
|
||||||
|
getActors().add(MutablePair.of(blockInfo, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Contraption fromNBT(World world, CompoundNBT nbt) {
|
public static Contraption fromNBT(World world, CompoundNBT nbt) {
|
||||||
|
@ -463,6 +491,7 @@ public class Contraption {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void readNBT(World world, CompoundNBT nbt) {
|
public void readNBT(World world, CompoundNBT nbt) {
|
||||||
|
blocks.clear();
|
||||||
nbt.getList("Blocks", 10).forEach(c -> {
|
nbt.getList("Blocks", 10).forEach(c -> {
|
||||||
CompoundNBT comp = (CompoundNBT) c;
|
CompoundNBT comp = (CompoundNBT) c;
|
||||||
BlockInfo info = new BlockInfo(NBTUtil.readBlockPos(comp.getCompound("Pos")),
|
BlockInfo info = new BlockInfo(NBTUtil.readBlockPos(comp.getCompound("Pos")),
|
||||||
|
@ -471,23 +500,31 @@ public class Contraption {
|
||||||
blocks.put(info.pos, info);
|
blocks.put(info.pos, info);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
actors.clear();
|
||||||
nbt.getList("Actors", 10).forEach(c -> {
|
nbt.getList("Actors", 10).forEach(c -> {
|
||||||
CompoundNBT comp = (CompoundNBT) c;
|
CompoundNBT comp = (CompoundNBT) c;
|
||||||
BlockInfo info = blocks.get(NBTUtil.readBlockPos(comp.getCompound("Pos")));
|
BlockInfo info = blocks.get(NBTUtil.readBlockPos(comp.getCompound("Pos")));
|
||||||
MovementContext context = MovementContext.readNBT(world, comp);
|
MovementContext context = MovementContext.readNBT(world, comp);
|
||||||
|
context.contraption = this;
|
||||||
getActors().add(MutablePair.of(info, context));
|
getActors().add(MutablePair.of(info, context));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
storage.clear();
|
||||||
|
nbt.getList("Storage", 10).forEach(c -> {
|
||||||
|
CompoundNBT comp = (CompoundNBT) c;
|
||||||
|
storage.put(NBTUtil.readBlockPos(comp.getCompound("Pos")), new MountedStorage(comp.getCompound("Data")));
|
||||||
|
});
|
||||||
|
List<IItemHandlerModifiable> list =
|
||||||
|
storage.values().stream().map(MountedStorage::getItemHandler).collect(Collectors.toList());
|
||||||
|
inventory = new CombinedInvWrapper(Arrays.copyOf(list.toArray(), list.size(), IItemHandlerModifiable[].class));
|
||||||
|
|
||||||
if (nbt.contains("BoundsFront"))
|
if (nbt.contains("BoundsFront"))
|
||||||
constructCollisionBox = readAABB(nbt.getList("BoundsFront", 5));
|
constructCollisionBox = NBTHelper.readAABB(nbt.getList("BoundsFront", 5));
|
||||||
|
|
||||||
|
stalled = nbt.getBoolean("Stalled");
|
||||||
anchor = NBTUtil.readBlockPos(nbt.getCompound("Anchor"));
|
anchor = NBTUtil.readBlockPos(nbt.getCompound("Anchor"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public AxisAlignedBB getCollisionBoxFront() {
|
|
||||||
return constructCollisionBox;
|
|
||||||
}
|
|
||||||
|
|
||||||
public CompoundNBT writeNBT() {
|
public CompoundNBT writeNBT() {
|
||||||
CompoundNBT nbt = new CompoundNBT();
|
CompoundNBT nbt = new CompoundNBT();
|
||||||
|
|
||||||
|
@ -498,14 +535,14 @@ public class Contraption {
|
||||||
if (this instanceof BearingContraption)
|
if (this instanceof BearingContraption)
|
||||||
nbt.putString("Type", "Bearing");
|
nbt.putString("Type", "Bearing");
|
||||||
|
|
||||||
ListNBT blocks = new ListNBT();
|
ListNBT blocksNBT = new ListNBT();
|
||||||
for (BlockInfo block : this.blocks.values()) {
|
for (BlockInfo block : this.blocks.values()) {
|
||||||
CompoundNBT c = new CompoundNBT();
|
CompoundNBT c = new CompoundNBT();
|
||||||
c.put("Block", NBTUtil.writeBlockState(block.state));
|
c.put("Block", NBTUtil.writeBlockState(block.state));
|
||||||
c.put("Pos", NBTUtil.writeBlockPos(block.pos));
|
c.put("Pos", NBTUtil.writeBlockPos(block.pos));
|
||||||
if (block.nbt != null)
|
if (block.nbt != null)
|
||||||
c.put("Data", block.nbt);
|
c.put("Data", block.nbt);
|
||||||
blocks.add(c);
|
blocksNBT.add(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
ListNBT actorsNBT = new ListNBT();
|
ListNBT actorsNBT = new ListNBT();
|
||||||
|
@ -515,41 +552,37 @@ public class Contraption {
|
||||||
actor.right.writeToNBT(compound);
|
actor.right.writeToNBT(compound);
|
||||||
actorsNBT.add(compound);
|
actorsNBT.add(compound);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ListNBT storageNBT = new ListNBT();
|
||||||
|
for (BlockPos pos : storage.keySet()) {
|
||||||
|
CompoundNBT c = new CompoundNBT();
|
||||||
|
MountedStorage mountedStorage = storage.get(pos);
|
||||||
|
if (!mountedStorage.isWorking())
|
||||||
|
continue;
|
||||||
|
c.put("Pos", NBTUtil.writeBlockPos(pos));
|
||||||
|
c.put("Data", mountedStorage.serialize());
|
||||||
|
storageNBT.add(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
nbt.put("Blocks", blocksNBT);
|
||||||
nbt.put("Actors", actorsNBT);
|
nbt.put("Actors", actorsNBT);
|
||||||
|
nbt.put("Storage", storageNBT);
|
||||||
|
nbt.put("Anchor", NBTUtil.writeBlockPos(anchor));
|
||||||
|
nbt.putBoolean("Stalled", stalled);
|
||||||
|
|
||||||
if (constructCollisionBox != null) {
|
if (constructCollisionBox != null) {
|
||||||
ListNBT bb = writeAABB(constructCollisionBox);
|
ListNBT bb = NBTHelper.writeAABB(constructCollisionBox);
|
||||||
nbt.put("BoundsFront", bb);
|
nbt.put("BoundsFront", bb);
|
||||||
}
|
}
|
||||||
nbt.put("Blocks", blocks);
|
|
||||||
nbt.put("Anchor", NBTUtil.writeBlockPos(anchor));
|
|
||||||
return nbt;
|
return nbt;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ListNBT writeAABB(AxisAlignedBB bb) {
|
|
||||||
ListNBT bbtag = new ListNBT();
|
|
||||||
bbtag.add(new FloatNBT((float) bb.minX));
|
|
||||||
bbtag.add(new FloatNBT((float) bb.minY));
|
|
||||||
bbtag.add(new FloatNBT((float) bb.minZ));
|
|
||||||
bbtag.add(new FloatNBT((float) bb.maxX));
|
|
||||||
bbtag.add(new FloatNBT((float) bb.maxY));
|
|
||||||
bbtag.add(new FloatNBT((float) bb.maxZ));
|
|
||||||
return bbtag;
|
|
||||||
}
|
|
||||||
|
|
||||||
public AxisAlignedBB readAABB(ListNBT bbtag) {
|
|
||||||
if (bbtag == null || bbtag.isEmpty())
|
|
||||||
return null;
|
|
||||||
return new AxisAlignedBB(bbtag.getFloat(0), bbtag.getFloat(1), bbtag.getFloat(2), bbtag.getFloat(3),
|
|
||||||
bbtag.getFloat(4), bbtag.getFloat(5));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isFrozen() {
|
public static boolean isFrozen() {
|
||||||
return AllConfigs.SERVER.control.freezePistonConstructs.get();
|
return AllConfigs.SERVER.control.freezePistonConstructs.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void disassemble(IWorld world, BlockPos offset, float yaw, float pitch) {
|
public void disassemble(World world, BlockPos offset, float yaw, float pitch) {
|
||||||
disassemble(world, offset, yaw, pitch, (pos, state) -> false);
|
disassemble(world, offset, yaw, pitch, (pos, state) -> false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -566,8 +599,9 @@ public class Contraption {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void disassemble(IWorld world, BlockPos offset, float yaw, float pitch,
|
public void disassemble(World world, BlockPos offset, float yaw, float pitch,
|
||||||
BiPredicate<BlockPos, BlockState> customPlacement) {
|
BiPredicate<BlockPos, BlockState> customPlacement) {
|
||||||
|
stop(world);
|
||||||
for (BlockInfo block : blocks.values()) {
|
for (BlockInfo block : blocks.values()) {
|
||||||
BlockPos targetPos = block.pos.add(offset);
|
BlockPos targetPos = block.pos.add(offset);
|
||||||
BlockState state = block.state;
|
BlockState state = block.state;
|
||||||
|
@ -589,7 +623,13 @@ public class Contraption {
|
||||||
block.nbt.putInt("y", targetPos.getY());
|
block.nbt.putInt("y", targetPos.getY());
|
||||||
block.nbt.putInt("z", targetPos.getZ());
|
block.nbt.putInt("z", targetPos.getZ());
|
||||||
tileEntity.read(block.nbt);
|
tileEntity.read(block.nbt);
|
||||||
|
if (storage.containsKey(block.pos)) {
|
||||||
|
MountedStorage mountedStorage = storage.get(block.pos);
|
||||||
|
if (mountedStorage.isWorking())
|
||||||
|
mountedStorage.fill(tileEntity);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -597,11 +637,16 @@ public class Contraption {
|
||||||
for (MutablePair<BlockInfo, MovementContext> pair : actors) {
|
for (MutablePair<BlockInfo, MovementContext> pair : actors) {
|
||||||
BlockState blockState = pair.left.state;
|
BlockState blockState = pair.left.state;
|
||||||
MovementContext context = new MovementContext(world, blockState);
|
MovementContext context = new MovementContext(world, blockState);
|
||||||
((IHaveMovementBehavior) blockState.getBlock()).startMoving(context);
|
context.contraption = this;
|
||||||
|
getMovement(blockState).startMoving(context);
|
||||||
pair.setRight(context);
|
pair.setRight(context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public AxisAlignedBB getCollisionBoxFront() {
|
||||||
|
return constructCollisionBox;
|
||||||
|
}
|
||||||
|
|
||||||
public List<MutablePair<BlockInfo, MovementContext>> getActors() {
|
public List<MutablePair<BlockInfo, MovementContext>> getActors() {
|
||||||
return actors;
|
return actors;
|
||||||
}
|
}
|
||||||
|
@ -610,4 +655,26 @@ public class Contraption {
|
||||||
return anchor;
|
return anchor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void stop(World world) {
|
||||||
|
foreachActor(world, (behaviour, ctx) -> {
|
||||||
|
behaviour.stopMoving(ctx);
|
||||||
|
ctx.position = null;
|
||||||
|
ctx.motion = Vec3d.ZERO;
|
||||||
|
ctx.relativeMotion = Vec3d.ZERO;
|
||||||
|
ctx.rotation = Vec3d.ZERO;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void foreachActor(World world, BiConsumer<MovementBehaviour, MovementContext> callBack) {
|
||||||
|
for (MutablePair<BlockInfo, MovementContext> pair : actors)
|
||||||
|
callBack.accept(getMovement(pair.getLeft().state), pair.getRight());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static MovementBehaviour getMovement(BlockState state) {
|
||||||
|
Block block = state.getBlock();
|
||||||
|
if (!(block instanceof IPortableBlock))
|
||||||
|
return null;
|
||||||
|
return ((IPortableBlock) block).getMovementBehaviour();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -3,16 +3,21 @@ package com.simibubi.create.modules.contraptions.components.contraptions;
|
||||||
import org.apache.commons.lang3.tuple.MutablePair;
|
import org.apache.commons.lang3.tuple.MutablePair;
|
||||||
|
|
||||||
import com.simibubi.create.AllEntities;
|
import com.simibubi.create.AllEntities;
|
||||||
|
import com.simibubi.create.AllPackets;
|
||||||
import com.simibubi.create.foundation.utility.VecHelper;
|
import com.simibubi.create.foundation.utility.VecHelper;
|
||||||
import com.simibubi.create.modules.contraptions.components.contraptions.IHaveMovementBehavior.MovementContext;
|
|
||||||
|
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.entity.EntityType;
|
import net.minecraft.entity.EntityType;
|
||||||
import net.minecraft.entity.item.minecart.AbstractMinecartEntity;
|
import net.minecraft.entity.item.minecart.AbstractMinecartEntity;
|
||||||
import net.minecraft.nbt.CompoundNBT;
|
import net.minecraft.nbt.CompoundNBT;
|
||||||
|
import net.minecraft.nbt.ListNBT;
|
||||||
import net.minecraft.nbt.NBTUtil;
|
import net.minecraft.nbt.NBTUtil;
|
||||||
import net.minecraft.network.IPacket;
|
import net.minecraft.network.IPacket;
|
||||||
import net.minecraft.network.PacketBuffer;
|
import net.minecraft.network.PacketBuffer;
|
||||||
|
import net.minecraft.network.datasync.DataParameter;
|
||||||
|
import net.minecraft.network.datasync.DataSerializers;
|
||||||
|
import net.minecraft.network.datasync.EntityDataManager;
|
||||||
import net.minecraft.tileentity.TileEntity;
|
import net.minecraft.tileentity.TileEntity;
|
||||||
import net.minecraft.util.math.AxisAlignedBB;
|
import net.minecraft.util.math.AxisAlignedBB;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
@ -20,8 +25,11 @@ import net.minecraft.util.math.Vec3d;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
import net.minecraft.world.gen.feature.template.Template.BlockInfo;
|
import net.minecraft.world.gen.feature.template.Template.BlockInfo;
|
||||||
import net.minecraft.world.server.ServerWorld;
|
import net.minecraft.world.server.ServerWorld;
|
||||||
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
import net.minecraftforge.fml.common.registry.IEntityAdditionalSpawnData;
|
import net.minecraftforge.fml.common.registry.IEntityAdditionalSpawnData;
|
||||||
import net.minecraftforge.fml.network.NetworkHooks;
|
import net.minecraftforge.fml.network.NetworkHooks;
|
||||||
|
import net.minecraftforge.fml.network.PacketDistributor;
|
||||||
|
|
||||||
public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnData {
|
public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnData {
|
||||||
|
|
||||||
|
@ -29,8 +37,10 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
|
||||||
protected float initialAngle;
|
protected float initialAngle;
|
||||||
protected BlockPos controllerPos;
|
protected BlockPos controllerPos;
|
||||||
protected IControlContraption controllerTE;
|
protected IControlContraption controllerTE;
|
||||||
|
protected Vec3d motionBeforeStall;
|
||||||
|
|
||||||
public float movementSpeedModifier;
|
private static final DataParameter<Boolean> STALLED =
|
||||||
|
EntityDataManager.createKey(ContraptionEntity.class, DataSerializers.BOOLEAN);
|
||||||
|
|
||||||
public float prevYaw;
|
public float prevYaw;
|
||||||
public float prevPitch;
|
public float prevPitch;
|
||||||
|
@ -46,6 +56,7 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
|
||||||
|
|
||||||
public ContraptionEntity(EntityType<?> entityTypeIn, World worldIn) {
|
public ContraptionEntity(EntityType<?> entityTypeIn, World worldIn) {
|
||||||
super(entityTypeIn, worldIn);
|
super(entityTypeIn, worldIn);
|
||||||
|
motionBeforeStall = Vec3d.ZERO;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ContraptionEntity(World world) {
|
protected ContraptionEntity(World world) {
|
||||||
|
@ -59,7 +70,6 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
|
||||||
this.prevYaw = initialAngle;
|
this.prevYaw = initialAngle;
|
||||||
this.yaw = initialAngle;
|
this.yaw = initialAngle;
|
||||||
this.targetYaw = initialAngle;
|
this.targetYaw = initialAngle;
|
||||||
movementSpeedModifier = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T extends TileEntity & IControlContraption> ContraptionEntity controlledBy(T controller) {
|
public <T extends TileEntity & IControlContraption> ContraptionEntity controlledBy(T controller) {
|
||||||
|
@ -70,8 +80,13 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void tick() {
|
public void tick() {
|
||||||
|
if (contraption == null) {
|
||||||
|
remove();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
attachToController();
|
attachToController();
|
||||||
|
|
||||||
Entity e = getRidingEntity();
|
Entity e = getRidingEntity();
|
||||||
if (e != null) {
|
if (e != null) {
|
||||||
Vec3d movementVector = e.getMotion();
|
Vec3d movementVector = e.getMotion();
|
||||||
|
@ -97,7 +112,19 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
|
||||||
pitch = angleLerp(speed, pitch, targetPitch);
|
pitch = angleLerp(speed, pitch, targetPitch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean wasStalled = isStalled();
|
||||||
tickActors(movementVector);
|
tickActors(movementVector);
|
||||||
|
if (isStalled()) {
|
||||||
|
if (!wasStalled)
|
||||||
|
motionBeforeStall = e.getMotion();
|
||||||
|
e.setMotion(0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wasStalled && !isStalled()) {
|
||||||
|
e.setMotion(motionBeforeStall);
|
||||||
|
motionBeforeStall = Vec3d.ZERO;
|
||||||
|
}
|
||||||
|
|
||||||
super.tick();
|
super.tick();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -111,47 +138,62 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
|
||||||
}
|
}
|
||||||
|
|
||||||
public void tickActors(Vec3d movementVector) {
|
public void tickActors(Vec3d movementVector) {
|
||||||
movementSpeedModifier = 1;
|
|
||||||
|
|
||||||
float anglePitch = getPitch(1);
|
float anglePitch = getPitch(1);
|
||||||
float angleYaw = getYaw(1);
|
float angleYaw = getYaw(1);
|
||||||
float angleRoll = getRoll(1);
|
float angleRoll = getRoll(1);
|
||||||
Vec3d rotationVec = new Vec3d(angleRoll, angleYaw, anglePitch);
|
Vec3d rotationVec = new Vec3d(angleRoll, angleYaw, anglePitch);
|
||||||
Vec3d rotationOffset = VecHelper.getCenterOf(BlockPos.ZERO);
|
Vec3d rotationOffset = VecHelper.getCenterOf(BlockPos.ZERO);
|
||||||
|
boolean stalledPreviously = contraption.stalled;
|
||||||
|
|
||||||
|
if (!world.isRemote)
|
||||||
|
contraption.stalled = false;
|
||||||
|
|
||||||
for (MutablePair<BlockInfo, MovementContext> pair : contraption.actors) {
|
for (MutablePair<BlockInfo, MovementContext> pair : contraption.actors) {
|
||||||
MovementContext context = pair.right;
|
MovementContext context = pair.right;
|
||||||
BlockInfo blockInfo = pair.left;
|
BlockInfo blockInfo = pair.left;
|
||||||
IHaveMovementBehavior actor = (IHaveMovementBehavior) blockInfo.state.getBlock();
|
MovementBehaviour actor = Contraption.getMovement(blockInfo.state);
|
||||||
|
|
||||||
Vec3d actorPosition = new Vec3d(blockInfo.pos);
|
Vec3d actorPosition = new Vec3d(blockInfo.pos);
|
||||||
actorPosition = actorPosition.add(actor.getActiveAreaOffset(context));
|
actorPosition = actorPosition.add(actor.getActiveAreaOffset(context));
|
||||||
actorPosition = VecHelper.rotate(actorPosition, angleRoll, angleYaw, anglePitch);
|
actorPosition = VecHelper.rotate(actorPosition, angleRoll, angleYaw, anglePitch);
|
||||||
actorPosition = actorPosition.add(rotationOffset).add(posX, posY, posZ);
|
actorPosition = actorPosition.add(rotationOffset).add(posX, posY, posZ);
|
||||||
|
|
||||||
Vec3d previousPosition = context.position;
|
boolean newPosVisited = context.position == null;
|
||||||
BlockPos gridPosition = new BlockPos(actorPosition);
|
BlockPos gridPosition = new BlockPos(actorPosition);
|
||||||
boolean newPosVisited = true;
|
|
||||||
|
|
||||||
if (previousPosition != null) {
|
if (!stalledPreviously) {
|
||||||
context.motion = actorPosition.subtract(previousPosition);
|
Vec3d previousPosition = context.position;
|
||||||
Vec3d relativeMotion = context.motion;
|
if (previousPosition != null) {
|
||||||
relativeMotion = VecHelper.rotate(relativeMotion, -angleRoll, -angleYaw, -anglePitch);
|
context.motion = actorPosition.subtract(previousPosition);
|
||||||
context.relativeMotion = relativeMotion;
|
Vec3d relativeMotion = context.motion;
|
||||||
newPosVisited = !new BlockPos(previousPosition).equals(gridPosition);
|
relativeMotion = VecHelper.rotate(relativeMotion, -angleRoll, -angleYaw, -anglePitch);
|
||||||
|
context.relativeMotion = relativeMotion;
|
||||||
|
newPosVisited = !new BlockPos(previousPosition).equals(gridPosition);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
context.rotation = rotationVec;
|
context.rotation = rotationVec;
|
||||||
context.position = actorPosition;
|
context.position = actorPosition;
|
||||||
|
|
||||||
if (actor.isActive(context)) {
|
if (actor.isActive(context)) {
|
||||||
if (newPosVisited)
|
if (newPosVisited && !context.stall)
|
||||||
actor.visitNewPosition(context, gridPosition);
|
actor.visitNewPosition(context, gridPosition);
|
||||||
actor.tick(context);
|
actor.tick(context);
|
||||||
|
contraption.stalled |= context.stall;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (movementSpeedModifier > context.movementSpeedModifier)
|
}
|
||||||
movementSpeedModifier = context.movementSpeedModifier;
|
|
||||||
|
if (!world.isRemote) {
|
||||||
|
if (!stalledPreviously && contraption.stalled) {
|
||||||
|
if (controllerTE != null)
|
||||||
|
controllerTE.onStall();
|
||||||
|
AllPackets.channel.send(PacketDistributor.TRACKING_ENTITY.with(() -> this),
|
||||||
|
new ContraptionStallPacket(getEntityId(), posX, posY, posZ, yaw, pitch, roll));
|
||||||
|
}
|
||||||
|
dataManager.set(STALLED, contraption.stalled);
|
||||||
|
} else {
|
||||||
|
contraption.stalled = isStalled();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,6 +213,11 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
|
||||||
getShortestAngleDiff(this.pitch, pitch));
|
getShortestAngleDiff(this.pitch, pitch));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void notifyDataManagerChange(DataParameter<?> key) {
|
||||||
|
super.notifyDataManagerChange(key);
|
||||||
|
}
|
||||||
|
|
||||||
public void rotate(double roll, double yaw, double pitch) {
|
public void rotate(double roll, double yaw, double pitch) {
|
||||||
|
|
||||||
// Collision and stuff
|
// Collision and stuff
|
||||||
|
@ -242,12 +289,16 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void registerData() {
|
protected void registerData() {
|
||||||
|
this.dataManager.register(STALLED, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void readAdditional(CompoundNBT compound) {
|
protected void readAdditional(CompoundNBT compound) {
|
||||||
contraption = Contraption.fromNBT(world, compound.getCompound("Contraption"));
|
contraption = Contraption.fromNBT(world, compound.getCompound("Contraption"));
|
||||||
initialAngle = compound.getFloat("InitialAngle");
|
initialAngle = compound.getFloat("InitialAngle");
|
||||||
|
ListNBT vecNBT = compound.getList("CachedMotion", 6);
|
||||||
|
if (!vecNBT.isEmpty())
|
||||||
|
motionBeforeStall = new Vec3d(vecNBT.getDouble(0), vecNBT.getDouble(1), vecNBT.getDouble(2));
|
||||||
if (compound.contains("Controller"))
|
if (compound.contains("Controller"))
|
||||||
controllerPos = NBTUtil.readBlockPos(compound.getCompound("Controller"));
|
controllerPos = NBTUtil.readBlockPos(compound.getCompound("Controller"));
|
||||||
prevYaw = initialAngle;
|
prevYaw = initialAngle;
|
||||||
|
@ -256,12 +307,14 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
|
||||||
}
|
}
|
||||||
|
|
||||||
public void attachToController() {
|
public void attachToController() {
|
||||||
if (controllerPos != null && controllerTE == null) {
|
if (controllerPos != null && (controllerTE == null || !controllerTE.isValid())) {
|
||||||
if (!world.isBlockPresent(controllerPos))
|
if (!world.isBlockPresent(controllerPos))
|
||||||
return;
|
return;
|
||||||
TileEntity te = world.getTileEntity(controllerPos);
|
TileEntity te = world.getTileEntity(controllerPos);
|
||||||
if (te == null || !(te instanceof IControlContraption))
|
if (te == null || !(te instanceof IControlContraption)) {
|
||||||
remove();
|
remove();
|
||||||
|
return;
|
||||||
|
}
|
||||||
IControlContraption controllerTE = (IControlContraption) te;
|
IControlContraption controllerTE = (IControlContraption) te;
|
||||||
this.controllerTE = controllerTE;
|
this.controllerTE = controllerTE;
|
||||||
controllerTE.attach(this);
|
controllerTE.attach(this);
|
||||||
|
@ -272,6 +325,7 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
|
||||||
protected void writeAdditional(CompoundNBT compound) {
|
protected void writeAdditional(CompoundNBT compound) {
|
||||||
compound.put("Contraption", getContraption().writeNBT());
|
compound.put("Contraption", getContraption().writeNBT());
|
||||||
compound.putFloat("InitialAngle", initialAngle);
|
compound.putFloat("InitialAngle", initialAngle);
|
||||||
|
compound.put("CachedMotion", newDoubleNBTList(motionBeforeStall.x, motionBeforeStall.y, motionBeforeStall.z));
|
||||||
if (controllerPos != null)
|
if (controllerPos != null)
|
||||||
compound.put("Controller", NBTUtil.writeBlockPos(controllerPos));
|
compound.put("Controller", NBTUtil.writeBlockPos(controllerPos));
|
||||||
}
|
}
|
||||||
|
@ -303,4 +357,24 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
|
||||||
return contraption;
|
return contraption;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isStalled() {
|
||||||
|
return dataManager.get(STALLED);
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnlyIn(Dist.CLIENT)
|
||||||
|
static void handleStallPacket(ContraptionStallPacket packet) {
|
||||||
|
Entity entity = Minecraft.getInstance().world.getEntityByID(packet.entityID);
|
||||||
|
if (!(entity instanceof ContraptionEntity))
|
||||||
|
return;
|
||||||
|
ContraptionEntity ce = (ContraptionEntity) entity;
|
||||||
|
if (ce.getRidingEntity() == null) {
|
||||||
|
ce.posX = packet.x;
|
||||||
|
ce.posY = packet.y;
|
||||||
|
ce.posZ = packet.z;
|
||||||
|
}
|
||||||
|
ce.yaw = packet.yaw;
|
||||||
|
ce.pitch = packet.pitch;
|
||||||
|
ce.roll = packet.roll;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,6 @@ import com.simibubi.create.CreateClient;
|
||||||
import com.simibubi.create.foundation.utility.PlacementSimulationWorld;
|
import com.simibubi.create.foundation.utility.PlacementSimulationWorld;
|
||||||
import com.simibubi.create.foundation.utility.SuperByteBuffer;
|
import com.simibubi.create.foundation.utility.SuperByteBuffer;
|
||||||
import com.simibubi.create.foundation.utility.SuperByteBufferCache.Compartment;
|
import com.simibubi.create.foundation.utility.SuperByteBufferCache.Compartment;
|
||||||
import com.simibubi.create.modules.contraptions.components.contraptions.IHaveMovementBehavior.MovementContext;
|
|
||||||
|
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.renderer.BlockModelRenderer;
|
import net.minecraft.client.renderer.BlockModelRenderer;
|
||||||
|
@ -18,7 +17,8 @@ import net.minecraft.client.renderer.BlockRendererDispatcher;
|
||||||
import net.minecraft.client.renderer.BufferBuilder;
|
import net.minecraft.client.renderer.BufferBuilder;
|
||||||
import net.minecraft.client.renderer.model.IBakedModel;
|
import net.minecraft.client.renderer.model.IBakedModel;
|
||||||
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
|
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos.MutableBlockPos;
|
||||||
|
import net.minecraft.world.LightType;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
import net.minecraft.world.gen.feature.template.Template.BlockInfo;
|
import net.minecraft.world.gen.feature.template.Template.BlockInfo;
|
||||||
import net.minecraftforge.client.model.data.EmptyModelData;
|
import net.minecraftforge.client.model.data.EmptyModelData;
|
||||||
|
@ -31,7 +31,7 @@ public class ContraptionRenderer {
|
||||||
public static void render(World world, Contraption c, Consumer<SuperByteBuffer> transform, BufferBuilder buffer) {
|
public static void render(World world, Contraption c, Consumer<SuperByteBuffer> transform, BufferBuilder buffer) {
|
||||||
SuperByteBuffer contraptionBuffer = CreateClient.bufferCache.get(CONTRAPTION, c, () -> renderContraption(c));
|
SuperByteBuffer contraptionBuffer = CreateClient.bufferCache.get(CONTRAPTION, c, () -> renderContraption(c));
|
||||||
transform.accept(contraptionBuffer);
|
transform.accept(contraptionBuffer);
|
||||||
contraptionBuffer.light((lx, ly, lz) -> world.getCombinedLight(new BlockPos(lx, ly, lz), 0)).renderInto(buffer);
|
contraptionBuffer.light((lx, ly, lz) -> getLight(world, lx, ly, lz)).renderInto(buffer);
|
||||||
renderActors(world, c, transform, buffer);
|
renderActors(world, c, transform, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,8 +69,7 @@ public class ContraptionRenderer {
|
||||||
context.world = world;
|
context.world = world;
|
||||||
|
|
||||||
BlockInfo blockInfo = actor.getLeft();
|
BlockInfo blockInfo = actor.getLeft();
|
||||||
IHaveMovementBehavior block = (IHaveMovementBehavior) blockInfo.state.getBlock();
|
SuperByteBuffer render = Contraption.getMovement(blockInfo.state).renderInContraption(context);
|
||||||
SuperByteBuffer render = block.renderInContraption(context);
|
|
||||||
if (render == null)
|
if (render == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -80,8 +79,24 @@ public class ContraptionRenderer {
|
||||||
|
|
||||||
render.translate(posX, posY, posZ);
|
render.translate(posX, posY, posZ);
|
||||||
transform.accept(render);
|
transform.accept(render);
|
||||||
render.light((lx, ly, lz) -> world.getCombinedLight(new BlockPos(lx, ly, lz), 0)).renderInto(buffer);
|
render.light((lx, ly, lz) -> getLight(world, lx, ly, lz)).renderInto(buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static int getLight(World world, float lx, float ly, float lz) {
|
||||||
|
MutableBlockPos pos = new MutableBlockPos();
|
||||||
|
float sky = 0, block = 0;
|
||||||
|
float offset = 1 / 8f;
|
||||||
|
|
||||||
|
for (float zOffset = offset; zOffset >= -offset; zOffset -= 2 * offset)
|
||||||
|
for (float yOffset = offset; yOffset >= -offset; yOffset -= 2 * offset)
|
||||||
|
for (float xOffset = offset; xOffset >= -offset; xOffset -= 2 * offset) {
|
||||||
|
pos.setPos(lx + xOffset, ly + yOffset, lz + zOffset);
|
||||||
|
sky += world.getLightFor(LightType.SKY, pos) / 8f;
|
||||||
|
block += world.getLightFor(LightType.BLOCK, pos) / 8f;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ((int) sky) << 20 | ((int) block) << 4;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,60 @@
|
||||||
|
package com.simibubi.create.modules.contraptions.components.contraptions;
|
||||||
|
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import com.simibubi.create.foundation.packet.SimplePacketBase;
|
||||||
|
|
||||||
|
import net.minecraft.network.PacketBuffer;
|
||||||
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
|
import net.minecraftforge.fml.DistExecutor;
|
||||||
|
import net.minecraftforge.fml.network.NetworkEvent.Context;
|
||||||
|
|
||||||
|
public class ContraptionStallPacket extends SimplePacketBase {
|
||||||
|
|
||||||
|
int entityID;
|
||||||
|
float x;
|
||||||
|
float y;
|
||||||
|
float z;
|
||||||
|
float yaw;
|
||||||
|
float pitch;
|
||||||
|
float roll;
|
||||||
|
|
||||||
|
public ContraptionStallPacket(int entityID, double posX, double posY, double posZ, float yaw, float pitch, float roll) {
|
||||||
|
this.entityID = entityID;
|
||||||
|
this.x = (float) posX;
|
||||||
|
this.y = (float) posY;
|
||||||
|
this.z = (float) posZ;
|
||||||
|
this.yaw = yaw;
|
||||||
|
this.pitch = pitch;
|
||||||
|
this.roll = roll;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ContraptionStallPacket(PacketBuffer buffer) {
|
||||||
|
entityID = buffer.readInt();
|
||||||
|
x = buffer.readFloat();
|
||||||
|
y = buffer.readFloat();
|
||||||
|
z = buffer.readFloat();
|
||||||
|
yaw = buffer.readFloat();
|
||||||
|
pitch = buffer.readFloat();
|
||||||
|
roll = buffer.readFloat();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(PacketBuffer buffer) {
|
||||||
|
buffer.writeInt(entityID);
|
||||||
|
writeAll(buffer, x, y, z, yaw, pitch, roll);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(Supplier<Context> context) {
|
||||||
|
context.get().enqueueWork(
|
||||||
|
() -> DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> ContraptionEntity.handleStallPacket(this)));
|
||||||
|
context.get().setPacketHandled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writeAll(PacketBuffer buffer, float... floats) {
|
||||||
|
for (float f : floats)
|
||||||
|
buffer.writeFloat(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -4,4 +4,9 @@ public interface IControlContraption {
|
||||||
|
|
||||||
public void attach(ContraptionEntity contraption);
|
public void attach(ContraptionEntity contraption);
|
||||||
|
|
||||||
|
default void onStall() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isValid();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,99 +0,0 @@
|
||||||
package com.simibubi.create.modules.contraptions.components.contraptions;
|
|
||||||
|
|
||||||
import com.simibubi.create.foundation.utility.SuperByteBuffer;
|
|
||||||
import com.simibubi.create.foundation.utility.VecHelper;
|
|
||||||
|
|
||||||
import net.minecraft.block.BlockState;
|
|
||||||
import net.minecraft.nbt.CompoundNBT;
|
|
||||||
import net.minecraft.nbt.NBTUtil;
|
|
||||||
import net.minecraft.util.math.BlockPos;
|
|
||||||
import net.minecraft.util.math.Vec3d;
|
|
||||||
import net.minecraft.world.World;
|
|
||||||
import net.minecraftforge.api.distmarker.Dist;
|
|
||||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
|
||||||
import net.minecraftforge.common.util.Constants.NBT;
|
|
||||||
|
|
||||||
public interface IHaveMovementBehavior {
|
|
||||||
|
|
||||||
public class MovementContext {
|
|
||||||
|
|
||||||
public Vec3d position;
|
|
||||||
public Vec3d motion;
|
|
||||||
public Vec3d relativeMotion;
|
|
||||||
public Vec3d rotation;
|
|
||||||
public World world;
|
|
||||||
public BlockState state;
|
|
||||||
|
|
||||||
public float movementSpeedModifier;
|
|
||||||
public CompoundNBT data;
|
|
||||||
|
|
||||||
public MovementContext(World world, BlockState state) {
|
|
||||||
this.world = world;
|
|
||||||
this.state = state;
|
|
||||||
|
|
||||||
motion = Vec3d.ZERO;
|
|
||||||
relativeMotion = Vec3d.ZERO;
|
|
||||||
rotation = Vec3d.ZERO;
|
|
||||||
position = null;
|
|
||||||
data = new CompoundNBT();
|
|
||||||
movementSpeedModifier = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public float getAnimationSpeed() {
|
|
||||||
int modifier = 1000;
|
|
||||||
double length = -motion.length();
|
|
||||||
if (Math.abs(length) < 1 / 512f)
|
|
||||||
return 0;
|
|
||||||
return (((int) (length * modifier + 100 * Math.signum(length))) / 100) * 100;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static MovementContext readNBT(World world, CompoundNBT nbt) {
|
|
||||||
BlockState state = NBTUtil.readBlockState(nbt.getCompound("State"));
|
|
||||||
MovementContext context = new MovementContext(world, state);
|
|
||||||
context.motion = VecHelper.readNBT(nbt.getList("Motion", NBT.TAG_DOUBLE));
|
|
||||||
context.relativeMotion = VecHelper.readNBT(nbt.getList("RelativeMotion", NBT.TAG_DOUBLE));
|
|
||||||
context.rotation = VecHelper.readNBT(nbt.getList("Rotation", NBT.TAG_DOUBLE));
|
|
||||||
if (nbt.contains("Position"))
|
|
||||||
context.position = VecHelper.readNBT(nbt.getList("Position", NBT.TAG_DOUBLE));
|
|
||||||
context.movementSpeedModifier = nbt.getFloat("SpeedModifier");
|
|
||||||
context.data = nbt.getCompound("Data");
|
|
||||||
return context;
|
|
||||||
}
|
|
||||||
|
|
||||||
public CompoundNBT writeToNBT(CompoundNBT nbt) {
|
|
||||||
nbt.put("State", NBTUtil.writeBlockState(state));
|
|
||||||
nbt.put("Motion", VecHelper.writeNBT(motion));
|
|
||||||
nbt.put("RelativeMotion", VecHelper.writeNBT(relativeMotion));
|
|
||||||
nbt.put("Rotation", VecHelper.writeNBT(rotation));
|
|
||||||
if (position != null)
|
|
||||||
nbt.put("Position", VecHelper.writeNBT(position));
|
|
||||||
nbt.putFloat("SpeedModifier", movementSpeedModifier);
|
|
||||||
nbt.put("Data", data);
|
|
||||||
return nbt;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
default boolean isActive(MovementContext context) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
default void tick(MovementContext context) {
|
|
||||||
}
|
|
||||||
|
|
||||||
default void startMoving(MovementContext context) {
|
|
||||||
}
|
|
||||||
|
|
||||||
default void visitNewPosition(MovementContext context, BlockPos pos) {
|
|
||||||
}
|
|
||||||
|
|
||||||
default Vec3d getActiveAreaOffset(MovementContext context) {
|
|
||||||
return Vec3d.ZERO;
|
|
||||||
}
|
|
||||||
|
|
||||||
@OnlyIn(value = Dist.CLIENT)
|
|
||||||
default SuperByteBuffer renderInContraption(MovementContext context) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
package com.simibubi.create.modules.contraptions.components.contraptions;
|
||||||
|
|
||||||
|
public interface IPortableBlock {
|
||||||
|
|
||||||
|
public MovementBehaviour getMovementBehaviour();
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,79 @@
|
||||||
|
package com.simibubi.create.modules.contraptions.components.contraptions;
|
||||||
|
|
||||||
|
import com.simibubi.create.AllTileEntities;
|
||||||
|
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.nbt.CompoundNBT;
|
||||||
|
import net.minecraft.tileentity.TileEntity;
|
||||||
|
import net.minecraft.tileentity.TileEntityType;
|
||||||
|
import net.minecraftforge.items.CapabilityItemHandler;
|
||||||
|
import net.minecraftforge.items.IItemHandler;
|
||||||
|
import net.minecraftforge.items.IItemHandlerModifiable;
|
||||||
|
import net.minecraftforge.items.ItemStackHandler;
|
||||||
|
|
||||||
|
public class MountedStorage {
|
||||||
|
|
||||||
|
private static final ItemStackHandler dummyHandler = new ItemStackHandler();
|
||||||
|
|
||||||
|
ItemStackHandler handler;
|
||||||
|
boolean working;
|
||||||
|
|
||||||
|
public MountedStorage(TileEntity te) {
|
||||||
|
handler = dummyHandler;
|
||||||
|
if (te != null) {
|
||||||
|
IItemHandler teHandler =
|
||||||
|
te.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY).orElse(dummyHandler);
|
||||||
|
if (teHandler != dummyHandler && teHandler instanceof IItemHandlerModifiable) {
|
||||||
|
IItemHandlerModifiable inv = (IItemHandlerModifiable) teHandler;
|
||||||
|
handler = new ItemStackHandler(teHandler.getSlots());
|
||||||
|
for (int slot = 0; slot < handler.getSlots(); slot++) {
|
||||||
|
handler.setStackInSlot(slot, inv.getStackInSlot(slot));
|
||||||
|
inv.setStackInSlot(slot, ItemStack.EMPTY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
working = te != null && handler != dummyHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MountedStorage(CompoundNBT nbt) {
|
||||||
|
handler = new ItemStackHandler();
|
||||||
|
working = nbt != null;
|
||||||
|
if (working)
|
||||||
|
handler.deserializeNBT(nbt);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void fill(TileEntity te) {
|
||||||
|
IItemHandler teHandler = te.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY).orElse(dummyHandler);
|
||||||
|
if (teHandler != dummyHandler && teHandler instanceof IItemHandlerModifiable) {
|
||||||
|
IItemHandlerModifiable inv = (IItemHandlerModifiable) teHandler;
|
||||||
|
for (int slot = 0; slot < Math.min(inv.getSlots(), handler.getSlots()); slot++)
|
||||||
|
inv.setStackInSlot(slot, handler.getStackInSlot(slot));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public IItemHandlerModifiable getItemHandler() {
|
||||||
|
return handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CompoundNBT serialize() {
|
||||||
|
return working ? handler.serializeNBT() : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isWorking() {
|
||||||
|
return working;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean canUseAsStorage(TileEntity te) {
|
||||||
|
if (te == null)
|
||||||
|
return false;
|
||||||
|
TileEntityType<?> type = te.getType();
|
||||||
|
if (type == TileEntityType.CHEST || type == TileEntityType.SHULKER_BOX || type == TileEntityType.BARREL)
|
||||||
|
return true;
|
||||||
|
if (type == AllTileEntities.FLEXCRATE.type)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
package com.simibubi.create.modules.contraptions.components.contraptions;
|
||||||
|
|
||||||
|
import com.simibubi.create.foundation.utility.SuperByteBuffer;
|
||||||
|
|
||||||
|
import net.minecraft.entity.item.ItemEntity;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.util.math.Vec3d;
|
||||||
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
|
import net.minecraftforge.items.ItemHandlerHelper;
|
||||||
|
|
||||||
|
public abstract class MovementBehaviour {
|
||||||
|
|
||||||
|
public boolean isActive(MovementContext context) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void tick(MovementContext context) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void startMoving(MovementContext context) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void visitNewPosition(MovementContext context, BlockPos pos) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vec3d getActiveAreaOffset(MovementContext context) {
|
||||||
|
return Vec3d.ZERO;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void dropItem(MovementContext context, ItemStack stack) {
|
||||||
|
ItemStack remainder = ItemHandlerHelper.insertItem(context.contraption.inventory, stack, false);
|
||||||
|
if (remainder.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
Vec3d vec = context.position;
|
||||||
|
ItemEntity itemEntity = new ItemEntity(context.world, vec.x, vec.y, vec.z, remainder);
|
||||||
|
itemEntity.setMotion(context.motion.add(0, 0.5f, 0).scale(context.world.rand.nextFloat() * .3f));
|
||||||
|
context.world.addEntity(itemEntity);
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnlyIn(value = Dist.CLIENT)
|
||||||
|
public SuperByteBuffer renderInContraption(MovementContext context) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stopMoving(MovementContext context) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,72 @@
|
||||||
|
package com.simibubi.create.modules.contraptions.components.contraptions;
|
||||||
|
|
||||||
|
import com.simibubi.create.foundation.utility.VecHelper;
|
||||||
|
|
||||||
|
import net.minecraft.block.BlockState;
|
||||||
|
import net.minecraft.nbt.CompoundNBT;
|
||||||
|
import net.minecraft.nbt.NBTUtil;
|
||||||
|
import net.minecraft.util.math.Vec3d;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
import net.minecraftforge.common.util.Constants.NBT;
|
||||||
|
|
||||||
|
public class MovementContext {
|
||||||
|
|
||||||
|
public Vec3d position;
|
||||||
|
public Vec3d motion;
|
||||||
|
public Vec3d relativeMotion;
|
||||||
|
public Vec3d rotation;
|
||||||
|
public World world;
|
||||||
|
public BlockState state;
|
||||||
|
|
||||||
|
public boolean stall;
|
||||||
|
public CompoundNBT data;
|
||||||
|
public Contraption contraption;
|
||||||
|
|
||||||
|
public MovementContext(World world, BlockState state) {
|
||||||
|
this.world = world;
|
||||||
|
this.state = state;
|
||||||
|
|
||||||
|
motion = Vec3d.ZERO;
|
||||||
|
relativeMotion = Vec3d.ZERO;
|
||||||
|
rotation = Vec3d.ZERO;
|
||||||
|
position = null;
|
||||||
|
data = new CompoundNBT();
|
||||||
|
stall = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getAnimationSpeed() {
|
||||||
|
int modifier = 1000;
|
||||||
|
double length = -motion.length();
|
||||||
|
if (world.isRemote && contraption.stalled)
|
||||||
|
return 700;
|
||||||
|
if (Math.abs(length) < 1 / 512f)
|
||||||
|
return 0;
|
||||||
|
return (((int) (length * modifier + 100 * Math.signum(length))) / 100) * 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MovementContext readNBT(World world, CompoundNBT nbt) {
|
||||||
|
BlockState state = NBTUtil.readBlockState(nbt.getCompound("State"));
|
||||||
|
MovementContext context = new MovementContext(world, state);
|
||||||
|
context.motion = VecHelper.readNBT(nbt.getList("Motion", NBT.TAG_DOUBLE));
|
||||||
|
context.relativeMotion = VecHelper.readNBT(nbt.getList("RelativeMotion", NBT.TAG_DOUBLE));
|
||||||
|
context.rotation = VecHelper.readNBT(nbt.getList("Rotation", NBT.TAG_DOUBLE));
|
||||||
|
if (nbt.contains("Position"))
|
||||||
|
context.position = VecHelper.readNBT(nbt.getList("Position", NBT.TAG_DOUBLE));
|
||||||
|
context.stall = nbt.getBoolean("Stall");
|
||||||
|
context.data = nbt.getCompound("Data");
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CompoundNBT writeToNBT(CompoundNBT nbt) {
|
||||||
|
nbt.put("State", NBTUtil.writeBlockState(state));
|
||||||
|
nbt.put("Motion", VecHelper.writeNBT(motion));
|
||||||
|
nbt.put("RelativeMotion", VecHelper.writeNBT(relativeMotion));
|
||||||
|
nbt.put("Rotation", VecHelper.writeNBT(rotation));
|
||||||
|
if (position != null)
|
||||||
|
nbt.put("Position", VecHelper.writeNBT(position));
|
||||||
|
nbt.putBoolean("Stall", stall);
|
||||||
|
nbt.put("Data", data);
|
||||||
|
return nbt;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,9 +1,12 @@
|
||||||
package com.simibubi.create.modules.contraptions.components.contraptions.bearing;
|
package com.simibubi.create.modules.contraptions.components.contraptions.bearing;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
|
|
||||||
import com.simibubi.create.AllBlockTags;
|
import com.simibubi.create.AllBlockTags;
|
||||||
import com.simibubi.create.modules.contraptions.components.contraptions.Contraption;
|
import com.simibubi.create.modules.contraptions.components.contraptions.Contraption;
|
||||||
|
|
||||||
import net.minecraft.nbt.CompoundNBT;
|
import net.minecraft.nbt.CompoundNBT;
|
||||||
|
import net.minecraft.tileentity.TileEntity;
|
||||||
import net.minecraft.util.Direction;
|
import net.minecraft.util.Direction;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
|
@ -26,10 +29,10 @@ public class BearingContraption extends Contraption {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void add(BlockPos pos, BlockInfo block) {
|
public void add(BlockPos pos, Pair<BlockInfo, TileEntity> capture) {
|
||||||
if (AllBlockTags.WINDMILL_SAILS.matches(block.state))
|
if (AllBlockTags.WINDMILL_SAILS.matches(capture.getKey().state))
|
||||||
sailBlocks++;
|
sailBlocks++;
|
||||||
super.add(pos, block);
|
super.add(pos, capture);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package com.simibubi.create.modules.contraptions.components.contraptions.bearing;
|
package com.simibubi.create.modules.contraptions.components.contraptions.bearing;
|
||||||
|
|
||||||
import com.simibubi.create.AllTileEntities;
|
import com.simibubi.create.AllTileEntities;
|
||||||
|
import com.simibubi.create.foundation.utility.ServerSpeedProvider;
|
||||||
import com.simibubi.create.modules.contraptions.base.GeneratingKineticTileEntity;
|
import com.simibubi.create.modules.contraptions.base.GeneratingKineticTileEntity;
|
||||||
import com.simibubi.create.modules.contraptions.components.contraptions.Contraption;
|
import com.simibubi.create.modules.contraptions.components.contraptions.Contraption;
|
||||||
import com.simibubi.create.modules.contraptions.components.contraptions.ContraptionEntity;
|
import com.simibubi.create.modules.contraptions.components.contraptions.ContraptionEntity;
|
||||||
|
@ -9,6 +10,8 @@ import com.simibubi.create.modules.contraptions.components.contraptions.IControl
|
||||||
import net.minecraft.nbt.CompoundNBT;
|
import net.minecraft.nbt.CompoundNBT;
|
||||||
import net.minecraft.state.properties.BlockStateProperties;
|
import net.minecraft.state.properties.BlockStateProperties;
|
||||||
import net.minecraft.util.Direction;
|
import net.minecraft.util.Direction;
|
||||||
|
import net.minecraft.util.Direction.Axis;
|
||||||
|
import net.minecraft.util.Direction.AxisDirection;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.util.math.MathHelper;
|
import net.minecraft.util.math.MathHelper;
|
||||||
import net.minecraft.util.math.Vec3d;
|
import net.minecraft.util.math.Vec3d;
|
||||||
|
@ -30,7 +33,7 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity imp
|
||||||
public float getAddedStressCapacity() {
|
public float getAddedStressCapacity() {
|
||||||
return isWindmill ? super.getAddedStressCapacity() : 0;
|
return isWindmill ? super.getAddedStressCapacity() : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float getStressApplied() {
|
public float getStressApplied() {
|
||||||
return isWindmill ? 0 : super.getStressApplied();
|
return isWindmill ? 0 : super.getStressApplied();
|
||||||
|
@ -90,6 +93,8 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity imp
|
||||||
}
|
}
|
||||||
|
|
||||||
public float getInterpolatedAngle(float partialTicks) {
|
public float getInterpolatedAngle(float partialTicks) {
|
||||||
|
if (movedContraption != null && movedContraption.isStalled())
|
||||||
|
partialTicks = 0;
|
||||||
return MathHelper.lerp(partialTicks, angle, angle + getAngularSpeed());
|
return MathHelper.lerp(partialTicks, angle, angle + getAngularSpeed());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,7 +105,10 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity imp
|
||||||
}
|
}
|
||||||
|
|
||||||
public float getAngularSpeed() {
|
public float getAngularSpeed() {
|
||||||
return getSpeed() * 3 / 10f;
|
float speed = getSpeed() * 3 / 10f;
|
||||||
|
if (world.isRemote)
|
||||||
|
speed *= ServerSpeedProvider.get();
|
||||||
|
return speed;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void assembleConstruct() {
|
public void assembleConstruct() {
|
||||||
|
@ -148,6 +156,8 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity imp
|
||||||
if (!world.isRemote && assembleNextTick) {
|
if (!world.isRemote && assembleNextTick) {
|
||||||
assembleNextTick = false;
|
assembleNextTick = false;
|
||||||
if (running) {
|
if (running) {
|
||||||
|
if (movedContraption != null)
|
||||||
|
movedContraption.getContraption().stop(world);
|
||||||
boolean canDisassemble = Math.abs(angle) < 45 || Math.abs(angle) > 7 * 45;
|
boolean canDisassemble = Math.abs(angle) < 45 || Math.abs(angle) > 7 * 45;
|
||||||
if (speed == 0 && (canDisassemble || movedContraption == null
|
if (speed == 0 && (canDisassemble || movedContraption == null
|
||||||
|| movedContraption.getContraption().blocks.isEmpty())) {
|
|| movedContraption.getContraption().blocks.isEmpty())) {
|
||||||
|
@ -165,17 +175,21 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity imp
|
||||||
if (!running)
|
if (!running)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
float angularSpeed = getAngularSpeed();
|
if (!(movedContraption != null && movedContraption.isStalled())) {
|
||||||
float newAngle = angle + angularSpeed;
|
float angularSpeed = getAngularSpeed();
|
||||||
angle = (float) (newAngle % 360);
|
float newAngle = angle + angularSpeed;
|
||||||
|
angle = (float) (newAngle % 360);
|
||||||
|
}
|
||||||
|
|
||||||
applyRotation();
|
applyRotation();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void applyRotation() {
|
private void applyRotation() {
|
||||||
if (movedContraption != null) {
|
if (movedContraption != null) {
|
||||||
Direction direction = getBlockState().get(BlockStateProperties.FACING);
|
Axis axis = getBlockState().get(BlockStateProperties.FACING).getAxis();
|
||||||
|
Direction direction = Direction.getFacingFromAxis(AxisDirection.POSITIVE, axis);
|
||||||
Vec3d vec = new Vec3d(1, 1, 1).scale(angle).mul(new Vec3d(direction.getDirectionVec()));
|
Vec3d vec = new Vec3d(1, 1, 1).scale(angle).mul(new Vec3d(direction.getDirectionVec()));
|
||||||
movedContraption.rotateTo(vec.x, vec.y, -vec.z);
|
movedContraption.rotateTo(vec.x, vec.y, vec.z);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,6 +197,7 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity imp
|
||||||
public void attach(ContraptionEntity contraption) {
|
public void attach(ContraptionEntity contraption) {
|
||||||
if (contraption.getContraption() instanceof BearingContraption) {
|
if (contraption.getContraption() instanceof BearingContraption) {
|
||||||
this.movedContraption = contraption;
|
this.movedContraption = contraption;
|
||||||
|
markDirty();
|
||||||
BlockPos anchor = pos.offset(getBlockState().get(BlockStateProperties.FACING));
|
BlockPos anchor = pos.offset(getBlockState().get(BlockStateProperties.FACING));
|
||||||
movedContraption.setPosition(anchor.getX(), anchor.getY(), anchor.getZ());
|
movedContraption.setPosition(anchor.getX(), anchor.getY(), anchor.getZ());
|
||||||
if (!world.isRemote)
|
if (!world.isRemote)
|
||||||
|
@ -190,4 +205,15 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity imp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStall() {
|
||||||
|
if (!world.isRemote)
|
||||||
|
sendData();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isValid() {
|
||||||
|
return !isRemoved();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@ public class MechanicalBearingTileEntityRenderer extends KineticTileEntityRender
|
||||||
superBuffer.rotateCentered(Axis.X, AngleHelper.rad(-90 - AngleHelper.verticalAngle(facing)));
|
superBuffer.rotateCentered(Axis.X, AngleHelper.rad(-90 - AngleHelper.verticalAngle(facing)));
|
||||||
if (facing.getAxis().isHorizontal())
|
if (facing.getAxis().isHorizontal())
|
||||||
superBuffer.rotateCentered(Axis.Y, AngleHelper.rad(AngleHelper.horizontalAngle(facing.getOpposite())));
|
superBuffer.rotateCentered(Axis.Y, AngleHelper.rad(AngleHelper.horizontalAngle(facing.getOpposite())));
|
||||||
float interpolatedAngle = bearingTe.getInterpolatedAngle(partialTicks);
|
float interpolatedAngle = bearingTe.getInterpolatedAngle(partialTicks - 1);
|
||||||
kineticRotationTransform(superBuffer, bearingTe, facing.getAxis(), (float) (interpolatedAngle / 180 * Math.PI),
|
kineticRotationTransform(superBuffer, bearingTe, facing.getAxis(), (float) (interpolatedAngle / 180 * Math.PI),
|
||||||
getWorld());
|
getWorld());
|
||||||
superBuffer.translate(x, y, z).renderInto(buffer);
|
superBuffer.translate(x, y, z).renderInto(buffer);
|
||||||
|
|
|
@ -73,6 +73,8 @@ public class CartAssemblerBlock extends AbstractRailBlock {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Contraption contraption = MountedContraption.assembleMinecart(world, pos, cart);
|
Contraption contraption = MountedContraption.assembleMinecart(world, pos, cart);
|
||||||
|
if (contraption == null)
|
||||||
|
return;
|
||||||
ContraptionEntity entity = new ContraptionEntity(world, contraption,
|
ContraptionEntity entity = new ContraptionEntity(world, contraption,
|
||||||
ContraptionEntity.yawFromMotion(cart.getMotion()));
|
ContraptionEntity.yawFromMotion(cart.getMotion()));
|
||||||
entity.setPosition(pos.getX(), pos.getY(), pos.getZ());
|
entity.setPosition(pos.getX(), pos.getY(), pos.getZ());
|
||||||
|
|
|
@ -4,6 +4,8 @@ import static com.simibubi.create.modules.contraptions.components.contraptions.m
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
|
|
||||||
import com.simibubi.create.AllBlocks;
|
import com.simibubi.create.AllBlocks;
|
||||||
import com.simibubi.create.modules.contraptions.components.contraptions.Contraption;
|
import com.simibubi.create.modules.contraptions.components.contraptions.Contraption;
|
||||||
|
|
||||||
|
@ -11,6 +13,7 @@ import net.minecraft.block.BlockState;
|
||||||
import net.minecraft.entity.item.minecart.AbstractMinecartEntity;
|
import net.minecraft.entity.item.minecart.AbstractMinecartEntity;
|
||||||
import net.minecraft.state.properties.BlockStateProperties;
|
import net.minecraft.state.properties.BlockStateProperties;
|
||||||
import net.minecraft.state.properties.RailShape;
|
import net.minecraft.state.properties.RailShape;
|
||||||
|
import net.minecraft.tileentity.TileEntity;
|
||||||
import net.minecraft.util.Direction;
|
import net.minecraft.util.Direction;
|
||||||
import net.minecraft.util.Direction.Axis;
|
import net.minecraft.util.Direction.Axis;
|
||||||
import net.minecraft.util.Direction.AxisDirection;
|
import net.minecraft.util.Direction.AxisDirection;
|
||||||
|
@ -36,9 +39,9 @@ public class MountedContraption extends Contraption {
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
Axis axis = state.get(RAIL_SHAPE) == RailShape.EAST_WEST ? Axis.X : Axis.Z;
|
Axis axis = state.get(RAIL_SHAPE) == RailShape.EAST_WEST ? Axis.X : Axis.Z;
|
||||||
contraption.add(pos, new BlockInfo(pos,
|
contraption.add(pos, Pair.of(new BlockInfo(pos,
|
||||||
AllBlocks.MINECART_ANCHOR.block.getDefaultState().with(BlockStateProperties.HORIZONTAL_AXIS, axis),
|
AllBlocks.MINECART_ANCHOR.block.getDefaultState().with(BlockStateProperties.HORIZONTAL_AXIS, axis),
|
||||||
null));
|
null), null));
|
||||||
contraption.removeBlocksFromWorld(world, BlockPos.ZERO);
|
contraption.removeBlocksFromWorld(world, BlockPos.ZERO);
|
||||||
contraption.initActors(world);
|
contraption.initActors(world);
|
||||||
|
|
||||||
|
@ -59,11 +62,13 @@ public class MountedContraption extends Contraption {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected BlockInfo capture(World world, BlockPos pos) {
|
protected Pair<BlockInfo, TileEntity> capture(World world, BlockPos pos) {
|
||||||
BlockInfo capture = super.capture(world, pos);
|
Pair<BlockInfo, TileEntity> pair = super.capture(world, pos);
|
||||||
|
BlockInfo capture = pair.getKey();
|
||||||
if (AllBlocks.CART_ASSEMBLER.typeOf(capture.state))
|
if (AllBlocks.CART_ASSEMBLER.typeOf(capture.state))
|
||||||
return new BlockInfo(capture.pos, CartAssemblerBlock.createAnchor(capture.state), null);
|
return Pair.of(new BlockInfo(capture.pos, CartAssemblerBlock.createAnchor(capture.state), null),
|
||||||
return capture;
|
pair.getValue());
|
||||||
|
return pair;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -72,7 +77,7 @@ public class MountedContraption extends Contraption {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void disassemble(IWorld world, BlockPos offset, float yaw, float pitch) {
|
public void disassemble(World world, BlockPos offset, float yaw, float pitch) {
|
||||||
super.disassemble(world, offset, yaw, pitch, (pos, state) -> AllBlocks.MINECART_ANCHOR.typeOf(state));
|
super.disassemble(world, offset, yaw, pitch, (pos, state) -> AllBlocks.MINECART_ANCHOR.typeOf(state));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ package com.simibubi.create.modules.contraptions.components.contraptions.piston;
|
||||||
|
|
||||||
import com.simibubi.create.AllBlocks;
|
import com.simibubi.create.AllBlocks;
|
||||||
import com.simibubi.create.AllTileEntities;
|
import com.simibubi.create.AllTileEntities;
|
||||||
|
import com.simibubi.create.foundation.utility.ServerSpeedProvider;
|
||||||
import com.simibubi.create.modules.contraptions.base.KineticTileEntity;
|
import com.simibubi.create.modules.contraptions.base.KineticTileEntity;
|
||||||
import com.simibubi.create.modules.contraptions.components.contraptions.ContraptionEntity;
|
import com.simibubi.create.modules.contraptions.components.contraptions.ContraptionEntity;
|
||||||
import com.simibubi.create.modules.contraptions.components.contraptions.IControlContraption;
|
import com.simibubi.create.modules.contraptions.components.contraptions.IControlContraption;
|
||||||
|
@ -105,6 +106,9 @@ public class MechanicalPistonTileEntity extends KineticTileEntity implements ICo
|
||||||
public void tick() {
|
public void tick() {
|
||||||
super.tick();
|
super.tick();
|
||||||
|
|
||||||
|
if (movedContraption != null && movedContraption.isStalled())
|
||||||
|
return;
|
||||||
|
|
||||||
if (!world.isRemote && assembleNextTick) {
|
if (!world.isRemote && assembleNextTick) {
|
||||||
assembleNextTick = false;
|
assembleNextTick = false;
|
||||||
if (running) {
|
if (running) {
|
||||||
|
@ -122,6 +126,8 @@ public class MechanicalPistonTileEntity extends KineticTileEntity implements ICo
|
||||||
return;
|
return;
|
||||||
|
|
||||||
float movementSpeed = getMovementSpeed();
|
float movementSpeed = getMovementSpeed();
|
||||||
|
if (world.isRemote)
|
||||||
|
movementSpeed *= ServerSpeedProvider.get();
|
||||||
float newOffset = offset + movementSpeed;
|
float newOffset = offset + movementSpeed;
|
||||||
|
|
||||||
if (movedContraption == null)
|
if (movedContraption == null)
|
||||||
|
@ -146,7 +152,8 @@ public class MechanicalPistonTileEntity extends KineticTileEntity implements ICo
|
||||||
if (movedContraption != null) {
|
if (movedContraption != null) {
|
||||||
Vec3d constructOffset = getConstructOffset(0.5f);
|
Vec3d constructOffset = getConstructOffset(0.5f);
|
||||||
Vec3d vec = constructOffset.add(new Vec3d(movedContraption.getContraption().getAnchor()));
|
Vec3d vec = constructOffset.add(new Vec3d(movedContraption.getContraption().getAnchor()));
|
||||||
movedContraption.setPosition(vec.x, vec.y, vec.z);
|
movedContraption.move(vec.x - movedContraption.posX, vec.y - movedContraption.posY,
|
||||||
|
vec.z - movedContraption.posZ);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -234,14 +241,14 @@ public class MechanicalPistonTileEntity extends KineticTileEntity implements ICo
|
||||||
|
|
||||||
public float getMovementSpeed() {
|
public float getMovementSpeed() {
|
||||||
Direction pistonDirection = getBlockState().get(BlockStateProperties.FACING);
|
Direction pistonDirection = getBlockState().get(BlockStateProperties.FACING);
|
||||||
int movementModifier = pistonDirection.getAxisDirection().getOffset()
|
int movementModifier =
|
||||||
* (pistonDirection.getAxis() == Axis.Z ? -1 : 1);
|
pistonDirection.getAxisDirection().getOffset() * (pistonDirection.getAxis() == Axis.Z ? -1 : 1);
|
||||||
return getSpeed() * -movementModifier / 512f;
|
return getSpeed() * -movementModifier / 512f;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Vec3d getConstructOffset(float partialTicks) {
|
public Vec3d getConstructOffset(float partialTicks) {
|
||||||
float interpolatedOffset = MathHelper.clamp(offset + (partialTicks - .5f) * getMovementSpeed(), 0,
|
float interpolatedOffset =
|
||||||
extensionLength);
|
MathHelper.clamp(offset + (partialTicks - .5f) * getMovementSpeed(), 0, extensionLength);
|
||||||
return new Vec3d(getBlockState().get(BlockStateProperties.FACING).getDirectionVec()).scale(interpolatedOffset);
|
return new Vec3d(getBlockState().get(BlockStateProperties.FACING).getDirectionVec()).scale(interpolatedOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -254,4 +261,15 @@ public class MechanicalPistonTileEntity extends KineticTileEntity implements ICo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStall() {
|
||||||
|
if (!world.isRemote)
|
||||||
|
sendData();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isValid() {
|
||||||
|
return !isRemoved();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,8 +8,11 @@ import static net.minecraft.state.properties.BlockStateProperties.FACING;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
|
|
||||||
import com.simibubi.create.AllBlocks;
|
import com.simibubi.create.AllBlocks;
|
||||||
import com.simibubi.create.config.AllConfigs;
|
import com.simibubi.create.config.AllConfigs;
|
||||||
|
import com.simibubi.create.foundation.utility.NBTHelper;
|
||||||
import com.simibubi.create.modules.contraptions.components.contraptions.Contraption;
|
import com.simibubi.create.modules.contraptions.components.contraptions.Contraption;
|
||||||
import com.simibubi.create.modules.contraptions.components.contraptions.piston.MechanicalPistonBlock.PistonState;
|
import com.simibubi.create.modules.contraptions.components.contraptions.piston.MechanicalPistonBlock.PistonState;
|
||||||
|
|
||||||
|
@ -132,13 +135,13 @@ public class PistonContraption extends Contraption {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void add(BlockPos pos, BlockInfo block) {
|
@Override
|
||||||
// super.add(pos, block);
|
public void add(BlockPos pos, Pair<BlockInfo, TileEntity> capture) {
|
||||||
super.add(pos.offset(orientation, -initialExtensionProgress), block);
|
super.add(pos.offset(orientation, -initialExtensionProgress), capture);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void disassemble(IWorld world, BlockPos offset, float yaw, float pitch) {
|
public void disassemble(World world, BlockPos offset, float yaw, float pitch) {
|
||||||
super.disassemble(world, offset, yaw, pitch, (pos, state) -> {
|
super.disassemble(world, offset, yaw, pitch, (pos, state) -> {
|
||||||
BlockPos pistonPos = anchor.offset(orientation, -initialExtensionProgress - 1);
|
BlockPos pistonPos = anchor.offset(orientation, -initialExtensionProgress - 1);
|
||||||
BlockState pistonState = world.getBlockState(pistonPos);
|
BlockState pistonState = world.getBlockState(pistonPos);
|
||||||
|
@ -175,7 +178,7 @@ public class PistonContraption extends Contraption {
|
||||||
initialExtensionProgress = nbt.getInt("InitialLength");
|
initialExtensionProgress = nbt.getInt("InitialLength");
|
||||||
orientation = Direction.byIndex(nbt.getInt("Orientation"));
|
orientation = Direction.byIndex(nbt.getInt("Orientation"));
|
||||||
if (nbt.contains("BoundsBack"))
|
if (nbt.contains("BoundsBack"))
|
||||||
pistonCollisionBox = readAABB(nbt.getList("BoundsBack", 5));
|
pistonCollisionBox = NBTHelper.readAABB(nbt.getList("BoundsBack", 5));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -183,7 +186,7 @@ public class PistonContraption extends Contraption {
|
||||||
CompoundNBT nbt = super.writeNBT();
|
CompoundNBT nbt = super.writeNBT();
|
||||||
|
|
||||||
if (pistonCollisionBox != null) {
|
if (pistonCollisionBox != null) {
|
||||||
ListNBT bb = writeAABB(pistonCollisionBox);
|
ListNBT bb = NBTHelper.writeAABB(pistonCollisionBox);
|
||||||
nbt.put("BoundsBack", bb);
|
nbt.put("BoundsBack", bb);
|
||||||
}
|
}
|
||||||
nbt.putInt("InitialLength", initialExtensionProgress);
|
nbt.putInt("InitialLength", initialExtensionProgress);
|
||||||
|
|
|
@ -57,9 +57,8 @@ public class NozzleTileEntity extends SmartTileEntity {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initialize() {
|
public void initialize() {
|
||||||
super.initialize();
|
|
||||||
fanPos = pos.offset(getBlockState().get(NozzleBlock.FACING).getOpposite());
|
fanPos = pos.offset(getBlockState().get(NozzleBlock.FACING).getOpposite());
|
||||||
lazyTick();
|
super.initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -47,11 +47,6 @@ public class FlywheelTileEntity extends GeneratingKineticTileEntity {
|
||||||
return generatedCapacity;
|
return generatedCapacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void initialize() {
|
|
||||||
super.initialize();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AxisAlignedBB getRenderBoundingBox() {
|
public AxisAlignedBB getRenderBoundingBox() {
|
||||||
return super.getRenderBoundingBox().grow(2);
|
return super.getRenderBoundingBox().grow(2);
|
||||||
|
|
|
@ -39,12 +39,6 @@ public class EngineTileEntity extends SmartTileEntity {
|
||||||
return super.getRenderBoundingBox().grow(1.5f);
|
return super.getRenderBoundingBox().grow(1.5f);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void initialize() {
|
|
||||||
super.initialize();
|
|
||||||
lazyTick();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void lazyTick() {
|
public void lazyTick() {
|
||||||
super.lazyTick();
|
super.lazyTick();
|
||||||
|
|
|
@ -3,7 +3,9 @@ package com.simibubi.create.modules.contraptions.components.saw;
|
||||||
import com.simibubi.create.foundation.block.IWithTileEntity;
|
import com.simibubi.create.foundation.block.IWithTileEntity;
|
||||||
import com.simibubi.create.foundation.utility.AllShapes;
|
import com.simibubi.create.foundation.utility.AllShapes;
|
||||||
import com.simibubi.create.modules.contraptions.base.DirectionalAxisKineticBlock;
|
import com.simibubi.create.modules.contraptions.base.DirectionalAxisKineticBlock;
|
||||||
import com.simibubi.create.modules.contraptions.components.contraptions.IHaveMovementBehavior;
|
import com.simibubi.create.modules.contraptions.components.actors.SawMovementBehaviour;
|
||||||
|
import com.simibubi.create.modules.contraptions.components.contraptions.IPortableBlock;
|
||||||
|
import com.simibubi.create.modules.contraptions.components.contraptions.MovementBehaviour;
|
||||||
|
|
||||||
import net.minecraft.block.Block;
|
import net.minecraft.block.Block;
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
|
@ -29,11 +31,11 @@ import net.minecraft.world.IBlockReader;
|
||||||
import net.minecraft.world.IWorldReader;
|
import net.minecraft.world.IWorldReader;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
public class SawBlock extends DirectionalAxisKineticBlock
|
public class SawBlock extends DirectionalAxisKineticBlock implements IWithTileEntity<SawTileEntity>, IPortableBlock {
|
||||||
implements IWithTileEntity<SawTileEntity>, IHaveMovementBehavior {
|
|
||||||
|
|
||||||
public static final BooleanProperty RUNNING = BooleanProperty.create("running");
|
public static final BooleanProperty RUNNING = BooleanProperty.create("running");
|
||||||
public static DamageSource damageSourceSaw = new DamageSource("create.saw").setDamageBypassesArmor();
|
public static DamageSource damageSourceSaw = new DamageSource("create.saw").setDamageBypassesArmor();
|
||||||
|
public static MovementBehaviour MOVEMENT = new SawMovementBehaviour();
|
||||||
|
|
||||||
public SawBlock() {
|
public SawBlock() {
|
||||||
super(Properties.from(Blocks.ANDESITE));
|
super(Properties.from(Blocks.ANDESITE));
|
||||||
|
@ -103,7 +105,7 @@ public class SawBlock extends DirectionalAxisKineticBlock
|
||||||
return PushReaction.PUSH_ONLY;
|
return PushReaction.PUSH_ONLY;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isHorizontal(BlockState state) {
|
public static boolean isHorizontal(BlockState state) {
|
||||||
return state.get(FACING).getAxis().isHorizontal();
|
return state.get(FACING).getAxis().isHorizontal();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,7 +135,11 @@ public class SawBlock extends DirectionalAxisKineticBlock
|
||||||
|
|
||||||
worldIn.removeTileEntity(pos);
|
worldIn.removeTileEntity(pos);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MovementBehaviour getMovementBehaviour() {
|
||||||
|
return MOVEMENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,8 +4,8 @@ import java.util.Random;
|
||||||
|
|
||||||
import com.simibubi.create.AllBlocks;
|
import com.simibubi.create.AllBlocks;
|
||||||
import com.simibubi.create.foundation.block.ProperDirectionalBlock;
|
import com.simibubi.create.foundation.block.ProperDirectionalBlock;
|
||||||
import com.simibubi.create.foundation.utility.VecHelper;
|
import com.simibubi.create.modules.contraptions.components.contraptions.IPortableBlock;
|
||||||
import com.simibubi.create.modules.contraptions.components.contraptions.IHaveMovementBehavior;
|
import com.simibubi.create.modules.contraptions.components.contraptions.MovementBehaviour;
|
||||||
|
|
||||||
import net.minecraft.block.Block;
|
import net.minecraft.block.Block;
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
|
@ -16,15 +16,14 @@ import net.minecraft.state.StateContainer.Builder;
|
||||||
import net.minecraft.state.properties.BlockStateProperties;
|
import net.minecraft.state.properties.BlockStateProperties;
|
||||||
import net.minecraft.util.Direction;
|
import net.minecraft.util.Direction;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.util.math.Vec3d;
|
|
||||||
import net.minecraft.world.IBlockReader;
|
import net.minecraft.world.IBlockReader;
|
||||||
import net.minecraft.world.IWorld;
|
import net.minecraft.world.IWorld;
|
||||||
import net.minecraft.world.TickPriority;
|
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
public class ContactBlock extends ProperDirectionalBlock implements IHaveMovementBehavior {
|
public class ContactBlock extends ProperDirectionalBlock implements IPortableBlock {
|
||||||
|
|
||||||
public static final BooleanProperty POWERED = BlockStateProperties.POWERED;
|
public static final BooleanProperty POWERED = BlockStateProperties.POWERED;
|
||||||
|
public static MovementBehaviour MOVEMENT = new ContactMovementBehaviour();
|
||||||
|
|
||||||
public ContactBlock() {
|
public ContactBlock() {
|
||||||
super(Properties.from(Blocks.ANDESITE));
|
super(Properties.from(Blocks.ANDESITE));
|
||||||
|
@ -102,33 +101,8 @@ public class ContactBlock extends ProperDirectionalBlock implements IHaveMovemen
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Vec3d getActiveAreaOffset(MovementContext context) {
|
public MovementBehaviour getMovementBehaviour() {
|
||||||
return new Vec3d(context.state.get(FACING).getDirectionVec()).scale(.65f);
|
return MOVEMENT;
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void visitNewPosition(MovementContext context, BlockPos pos) {
|
|
||||||
BlockState block = context.state;
|
|
||||||
World world = context.world;
|
|
||||||
|
|
||||||
if (world.isRemote)
|
|
||||||
return;
|
|
||||||
|
|
||||||
BlockState visitedState = world.getBlockState(pos);
|
|
||||||
if (!AllBlocks.CONTACT.typeOf(visitedState))
|
|
||||||
return;
|
|
||||||
|
|
||||||
Vec3d contact = new Vec3d(block.get(FACING).getDirectionVec());
|
|
||||||
contact = VecHelper.rotate(contact, context.rotation.x, context.rotation.y, context.rotation.z);
|
|
||||||
Direction direction = Direction.getFacingFromVector(contact.x, contact.y, contact.z);
|
|
||||||
|
|
||||||
if (!hasValidContact(world, pos.offset(direction.getOpposite()), direction))
|
|
||||||
return;
|
|
||||||
|
|
||||||
int ticksToStayActive = 4;
|
|
||||||
world.setBlockState(pos, visitedState.with(POWERED, true));
|
|
||||||
world.getPendingBlockTicks().scheduleTick(pos, this, ticksToStayActive, TickPriority.NORMAL);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,60 @@
|
||||||
|
package com.simibubi.create.modules.contraptions.redstone;
|
||||||
|
|
||||||
|
import com.simibubi.create.AllBlocks;
|
||||||
|
import com.simibubi.create.foundation.utility.VecHelper;
|
||||||
|
import com.simibubi.create.modules.contraptions.components.contraptions.MovementBehaviour;
|
||||||
|
import com.simibubi.create.modules.contraptions.components.contraptions.MovementContext;
|
||||||
|
|
||||||
|
import net.minecraft.block.BlockState;
|
||||||
|
import net.minecraft.nbt.NBTUtil;
|
||||||
|
import net.minecraft.util.Direction;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.util.math.Vec3d;
|
||||||
|
import net.minecraft.world.TickPriority;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
|
public class ContactMovementBehaviour extends MovementBehaviour {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Vec3d getActiveAreaOffset(MovementContext context) {
|
||||||
|
return new Vec3d(context.state.get(ContactBlock.FACING).getDirectionVec()).scale(.65f);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitNewPosition(MovementContext context, BlockPos pos) {
|
||||||
|
BlockState block = context.state;
|
||||||
|
World world = context.world;
|
||||||
|
|
||||||
|
if (world.isRemote)
|
||||||
|
return;
|
||||||
|
|
||||||
|
deactivateLastVisitedContact(context);
|
||||||
|
BlockState visitedState = world.getBlockState(pos);
|
||||||
|
if (!AllBlocks.CONTACT.typeOf(visitedState))
|
||||||
|
return;
|
||||||
|
|
||||||
|
Vec3d contact = new Vec3d(block.get(ContactBlock.FACING).getDirectionVec());
|
||||||
|
contact = VecHelper.rotate(contact, context.rotation.x, context.rotation.y, context.rotation.z);
|
||||||
|
Direction direction = Direction.getFacingFromVector(contact.x, contact.y, contact.z);
|
||||||
|
|
||||||
|
if (!ContactBlock.hasValidContact(world, pos.offset(direction.getOpposite()), direction))
|
||||||
|
return;
|
||||||
|
world.setBlockState(pos, visitedState.with(ContactBlock.POWERED, true));
|
||||||
|
context.data.put("lastContact", NBTUtil.writeBlockPos(pos));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stopMoving(MovementContext context) {
|
||||||
|
deactivateLastVisitedContact(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void deactivateLastVisitedContact(MovementContext context) {
|
||||||
|
if (context.data.contains("lastContact")) {
|
||||||
|
BlockPos last = NBTUtil.readBlockPos(context.data.getCompound("lastContact"));
|
||||||
|
context.world.getPendingBlockTicks().scheduleTick(last, AllBlocks.CONTACT.get(), 1, TickPriority.NORMAL);
|
||||||
|
context.data.remove("lastContact");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -8,6 +8,7 @@ import java.util.List;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
import com.simibubi.create.AllBlocks;
|
import com.simibubi.create.AllBlocks;
|
||||||
|
import com.simibubi.create.foundation.utility.ServerSpeedProvider;
|
||||||
import com.simibubi.create.foundation.utility.VecHelper;
|
import com.simibubi.create.foundation.utility.VecHelper;
|
||||||
import com.simibubi.create.modules.contraptions.relays.belt.AllBeltAttachments.BeltAttachmentState;
|
import com.simibubi.create.modules.contraptions.relays.belt.AllBeltAttachments.BeltAttachmentState;
|
||||||
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Slope;
|
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Slope;
|
||||||
|
@ -62,6 +63,7 @@ public class BeltInventory {
|
||||||
float beltSpeed = belt.getDirectionAwareBeltMovementSpeed();
|
float beltSpeed = belt.getDirectionAwareBeltMovementSpeed();
|
||||||
Direction movementFacing = belt.getMovementFacing();
|
Direction movementFacing = belt.getMovementFacing();
|
||||||
float spacing = 1;
|
float spacing = 1;
|
||||||
|
boolean onClient = belt.getWorld().isRemote;
|
||||||
|
|
||||||
Items: while (iterator.hasNext()) {
|
Items: while (iterator.hasNext()) {
|
||||||
stackInFront = current;
|
stackInFront = current;
|
||||||
|
@ -76,9 +78,10 @@ public class BeltInventory {
|
||||||
}
|
}
|
||||||
|
|
||||||
float movement = beltSpeed;
|
float movement = beltSpeed;
|
||||||
|
if (onClient)
|
||||||
|
movement *= ServerSpeedProvider.get();
|
||||||
|
|
||||||
// Don't move if locked
|
// Don't move if locked
|
||||||
boolean onClient = belt.getWorld().isRemote;
|
|
||||||
if (onClient && current.locked)
|
if (onClient && current.locked)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,6 @@ import com.simibubi.create.modules.contraptions.GogglesItem;
|
||||||
import com.simibubi.create.modules.contraptions.base.IRotate.SpeedLevel;
|
import com.simibubi.create.modules.contraptions.base.IRotate.SpeedLevel;
|
||||||
|
|
||||||
import net.minecraft.entity.player.ServerPlayerEntity;
|
import net.minecraft.entity.player.ServerPlayerEntity;
|
||||||
import net.minecraft.item.ItemStack;
|
|
||||||
import net.minecraft.util.math.AxisAlignedBB;
|
import net.minecraft.util.math.AxisAlignedBB;
|
||||||
import net.minecraft.util.math.MathHelper;
|
import net.minecraft.util.math.MathHelper;
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package com.simibubi.create.modules.curiosities.tools;
|
package com.simibubi.create.modules.curiosities.tools;
|
||||||
|
|
||||||
import com.simibubi.create.foundation.advancement.AllCriterionTriggers;
|
import com.simibubi.create.foundation.advancement.AllCriterionTriggers;
|
||||||
import com.simibubi.create.foundation.advancement.SandpaperUseTrigger;
|
|
||||||
import com.simibubi.create.foundation.block.render.CustomRenderedItemModel;
|
import com.simibubi.create.foundation.block.render.CustomRenderedItemModel;
|
||||||
import com.simibubi.create.foundation.item.IHaveCustomItemModel;
|
import com.simibubi.create.foundation.item.IHaveCustomItemModel;
|
||||||
import com.simibubi.create.foundation.utility.VecHelper;
|
import com.simibubi.create.foundation.utility.VecHelper;
|
||||||
|
|
|
@ -37,19 +37,23 @@ public class TransposerTileEntity extends ExtractorTileEntity {
|
||||||
inserting = new InsertingBehaviour(this,
|
inserting = new InsertingBehaviour(this,
|
||||||
Attachments.toward(() -> AttachedLogisticalBlock.getBlockFacing(getBlockState()).getOpposite()));
|
Attachments.toward(() -> AttachedLogisticalBlock.getBlockFacing(getBlockState()).getOpposite()));
|
||||||
behaviours.add(inserting);
|
behaviours.add(inserting);
|
||||||
|
applyFilteringCallbacks();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void applyFilteringCallbacks() {
|
||||||
extracting.withAmountThreshold(this::amountToExtract).withAdditionalFilter(this::shouldExtract);
|
extracting.withAmountThreshold(this::amountToExtract).withAdditionalFilter(this::shouldExtract);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void filterChanged(ItemStack stack) {
|
public void filterChanged(ItemStack stack) {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected int amountToExtract(ItemStack stack) {
|
public int amountToExtract(ItemStack stack) {
|
||||||
ItemStack tester = stack.copy();
|
ItemStack tester = stack.copy();
|
||||||
tester.setCount(64);
|
tester.setCount(64);
|
||||||
return 64 - inserting.insert(tester, true).getCount();
|
return 64 - inserting.insert(tester, true).getCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean shouldExtract(ItemStack stack) {
|
public boolean shouldExtract(ItemStack stack) {
|
||||||
if (isTargetingBelt()) {
|
if (isTargetingBelt()) {
|
||||||
Direction facing = AttachedLogisticalBlock.getBlockFacing(getBlockState()).getOpposite();
|
Direction facing = AttachedLogisticalBlock.getBlockFacing(getBlockState()).getOpposite();
|
||||||
BlockPos targetPos = pos.offset(facing);
|
BlockPos targetPos = pos.offset(facing);
|
||||||
|
@ -79,7 +83,7 @@ public class TransposerTileEntity extends ExtractorTileEntity {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onExtract(ItemStack stack) {
|
public void onExtract(ItemStack stack) {
|
||||||
if (isTargetingBelt()) {
|
if (isTargetingBelt()) {
|
||||||
Direction facing = AttachedLogisticalBlock.getBlockFacing(getBlockState()).getOpposite();
|
Direction facing = AttachedLogisticalBlock.getBlockFacing(getBlockState()).getOpposite();
|
||||||
BlockPos targetPos = pos.offset(facing);
|
BlockPos targetPos = pos.offset(facing);
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
package com.simibubi.create.modules.schematics.block;
|
||||||
|
|
||||||
|
import net.minecraft.block.BlockState;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.util.math.MathHelper;
|
||||||
|
|
||||||
|
public class LaunchedBlock {
|
||||||
|
|
||||||
|
private final SchematicannonTileEntity te;
|
||||||
|
public int totalTicks;
|
||||||
|
public int ticksRemaining;
|
||||||
|
public BlockPos target;
|
||||||
|
public BlockState state;
|
||||||
|
|
||||||
|
public LaunchedBlock(SchematicannonTileEntity schematicannonTileEntity, BlockPos target, BlockState state) {
|
||||||
|
te = schematicannonTileEntity;
|
||||||
|
this.target = target;
|
||||||
|
this.state = state;
|
||||||
|
totalTicks = (int) (Math.max(10, MathHelper.sqrt(MathHelper.sqrt(target.distanceSq(te.getPos()))) * 4f));
|
||||||
|
ticksRemaining = totalTicks;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LaunchedBlock(SchematicannonTileEntity schematicannonTileEntity, BlockPos target, BlockState state,
|
||||||
|
int ticksLeft, int total) {
|
||||||
|
te = schematicannonTileEntity;
|
||||||
|
this.target = target;
|
||||||
|
this.state = state;
|
||||||
|
this.totalTicks = total;
|
||||||
|
this.ticksRemaining = ticksLeft;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void update() {
|
||||||
|
if (ticksRemaining > 0)
|
||||||
|
ticksRemaining--;
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,14 +11,12 @@ import net.minecraft.entity.player.ServerPlayerEntity;
|
||||||
import net.minecraft.inventory.InventoryHelper;
|
import net.minecraft.inventory.InventoryHelper;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.tileentity.TileEntity;
|
import net.minecraft.tileentity.TileEntity;
|
||||||
import net.minecraft.util.Direction;
|
|
||||||
import net.minecraft.util.Hand;
|
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.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.IWorld;
|
|
||||||
import net.minecraft.world.IWorldReader;
|
import net.minecraft.world.IWorldReader;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
import net.minecraftforge.fml.network.NetworkHooks;
|
import net.minecraftforge.fml.network.NetworkHooks;
|
||||||
|
@ -39,13 +37,6 @@ public class SchematicannonBlock extends Block {
|
||||||
return new SchematicannonTileEntity();
|
return new SchematicannonTileEntity();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public BlockState updatePostPlacement(BlockState stateIn, Direction facing, BlockState facingState, IWorld worldIn,
|
|
||||||
BlockPos currentPos, BlockPos facingPos) {
|
|
||||||
((SchematicannonTileEntity) worldIn.getTileEntity(currentPos)).findInventories();
|
|
||||||
return stateIn;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isSolid(BlockState state) {
|
public boolean isSolid(BlockState state) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
package com.simibubi.create.modules.schematics.block;
|
||||||
|
|
||||||
|
import com.simibubi.create.AllItems;
|
||||||
|
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.item.Items;
|
||||||
|
import net.minecraftforge.items.ItemStackHandler;
|
||||||
|
|
||||||
|
public class SchematicannonInventory extends ItemStackHandler {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private final SchematicannonTileEntity te;
|
||||||
|
|
||||||
|
public SchematicannonInventory(SchematicannonTileEntity schematicannonTileEntity) {
|
||||||
|
super(5);
|
||||||
|
te = schematicannonTileEntity;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onContentsChanged(int slot) {
|
||||||
|
super.onContentsChanged(slot);
|
||||||
|
te.markDirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isItemValid(int slot, ItemStack stack) {
|
||||||
|
switch (slot) {
|
||||||
|
case 0: // Blueprint Slot
|
||||||
|
return AllItems.BLUEPRINT.typeOf(stack);
|
||||||
|
case 1: // Blueprint output
|
||||||
|
return false;
|
||||||
|
case 2: // Book input
|
||||||
|
return stack.isItemEqual(new ItemStack(Items.BOOK))
|
||||||
|
|| stack.isItemEqual(new ItemStack(Items.WRITTEN_BOOK));
|
||||||
|
case 3: // Material List output
|
||||||
|
return false;
|
||||||
|
case 4: // Gunpowder
|
||||||
|
return stack.isItemEqual(new ItemStack(Items.GUNPOWDER));
|
||||||
|
default:
|
||||||
|
return super.isItemValid(slot, stack);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -56,7 +56,7 @@ public class SchematicannonRenderer extends SafeTileEntityRenderer<Schematicanno
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!tileEntityIn.flyingBlocks.isEmpty()) {
|
if (!tileEntityIn.flyingBlocks.isEmpty()) {
|
||||||
for (SchematicannonTileEntity.LaunchedBlock block : tileEntityIn.flyingBlocks) {
|
for (LaunchedBlock block : tileEntityIn.flyingBlocks) {
|
||||||
|
|
||||||
if (block.ticksRemaining == 0)
|
if (block.ticksRemaining == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -9,7 +9,8 @@ import com.simibubi.create.AllItems;
|
||||||
import com.simibubi.create.AllTileEntities;
|
import com.simibubi.create.AllTileEntities;
|
||||||
import com.simibubi.create.config.AllConfigs;
|
import com.simibubi.create.config.AllConfigs;
|
||||||
import com.simibubi.create.config.CSchematics;
|
import com.simibubi.create.config.CSchematics;
|
||||||
import com.simibubi.create.foundation.block.SyncedTileEntity;
|
import com.simibubi.create.foundation.behaviour.base.SmartTileEntity;
|
||||||
|
import com.simibubi.create.foundation.behaviour.base.TileEntityBehaviour;
|
||||||
import com.simibubi.create.foundation.type.Cuboid;
|
import com.simibubi.create.foundation.type.Cuboid;
|
||||||
import com.simibubi.create.modules.schematics.MaterialChecklist;
|
import com.simibubi.create.modules.schematics.MaterialChecklist;
|
||||||
import com.simibubi.create.modules.schematics.SchematicWorld;
|
import com.simibubi.create.modules.schematics.SchematicWorld;
|
||||||
|
@ -34,7 +35,6 @@ import net.minecraft.state.properties.BedPart;
|
||||||
import net.minecraft.state.properties.BlockStateProperties;
|
import net.minecraft.state.properties.BlockStateProperties;
|
||||||
import net.minecraft.state.properties.DoubleBlockHalf;
|
import net.minecraft.state.properties.DoubleBlockHalf;
|
||||||
import net.minecraft.state.properties.SlabType;
|
import net.minecraft.state.properties.SlabType;
|
||||||
import net.minecraft.tileentity.ITickableTileEntity;
|
|
||||||
import net.minecraft.tileentity.TileEntity;
|
import net.minecraft.tileentity.TileEntity;
|
||||||
import net.minecraft.tileentity.TileEntityType;
|
import net.minecraft.tileentity.TileEntityType;
|
||||||
import net.minecraft.util.Direction;
|
import net.minecraft.util.Direction;
|
||||||
|
@ -42,7 +42,6 @@ import net.minecraft.util.SoundCategory;
|
||||||
import net.minecraft.util.SoundEvents;
|
import net.minecraft.util.SoundEvents;
|
||||||
import net.minecraft.util.math.AxisAlignedBB;
|
import net.minecraft.util.math.AxisAlignedBB;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.util.math.MathHelper;
|
|
||||||
import net.minecraft.util.text.ITextComponent;
|
import net.minecraft.util.text.ITextComponent;
|
||||||
import net.minecraft.util.text.StringTextComponent;
|
import net.minecraft.util.text.StringTextComponent;
|
||||||
import net.minecraft.world.gen.feature.template.Template;
|
import net.minecraft.world.gen.feature.template.Template;
|
||||||
|
@ -51,9 +50,8 @@ import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
import net.minecraftforge.common.util.LazyOptional;
|
import net.minecraftforge.common.util.LazyOptional;
|
||||||
import net.minecraftforge.items.CapabilityItemHandler;
|
import net.minecraftforge.items.CapabilityItemHandler;
|
||||||
import net.minecraftforge.items.IItemHandler;
|
import net.minecraftforge.items.IItemHandler;
|
||||||
import net.minecraftforge.items.ItemStackHandler;
|
|
||||||
|
|
||||||
public class SchematicannonTileEntity extends SyncedTileEntity implements ITickableTileEntity, INamedContainerProvider {
|
public class SchematicannonTileEntity extends SmartTileEntity implements INamedContainerProvider {
|
||||||
|
|
||||||
public static final int NEIGHBOUR_CHECKING = 100;
|
public static final int NEIGHBOUR_CHECKING = 100;
|
||||||
public static final int MAX_ANCHOR_DISTANCE = 256;
|
public static final int MAX_ANCHOR_DISTANCE = 256;
|
||||||
|
@ -105,63 +103,6 @@ public class SchematicannonTileEntity extends SyncedTileEntity implements ITicka
|
||||||
// Render
|
// Render
|
||||||
public boolean firstRenderTick;
|
public boolean firstRenderTick;
|
||||||
|
|
||||||
public class SchematicannonInventory extends ItemStackHandler {
|
|
||||||
public SchematicannonInventory() {
|
|
||||||
super(5);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onContentsChanged(int slot) {
|
|
||||||
super.onContentsChanged(slot);
|
|
||||||
markDirty();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isItemValid(int slot, ItemStack stack) {
|
|
||||||
switch (slot) {
|
|
||||||
case 0: // Blueprint Slot
|
|
||||||
return AllItems.BLUEPRINT.typeOf(stack);
|
|
||||||
case 1: // Blueprint output
|
|
||||||
return false;
|
|
||||||
case 2: // Book input
|
|
||||||
return stack.isItemEqual(new ItemStack(Items.BOOK))
|
|
||||||
|| stack.isItemEqual(new ItemStack(Items.WRITTEN_BOOK));
|
|
||||||
case 3: // Material List output
|
|
||||||
return false;
|
|
||||||
case 4: // Gunpowder
|
|
||||||
return stack.isItemEqual(new ItemStack(Items.GUNPOWDER));
|
|
||||||
default:
|
|
||||||
return super.isItemValid(slot, stack);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class LaunchedBlock {
|
|
||||||
public int totalTicks;
|
|
||||||
public int ticksRemaining;
|
|
||||||
public BlockPos target;
|
|
||||||
public BlockState state;
|
|
||||||
|
|
||||||
public LaunchedBlock(BlockPos target, BlockState state) {
|
|
||||||
this.target = target;
|
|
||||||
this.state = state;
|
|
||||||
totalTicks = (int) (Math.max(10, MathHelper.sqrt(MathHelper.sqrt(target.distanceSq(pos))) * 4f));
|
|
||||||
ticksRemaining = totalTicks;
|
|
||||||
}
|
|
||||||
|
|
||||||
public LaunchedBlock(BlockPos target, BlockState state, int ticksLeft, int total) {
|
|
||||||
this.target = target;
|
|
||||||
this.state = state;
|
|
||||||
this.totalTicks = total;
|
|
||||||
this.ticksRemaining = ticksLeft;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void update() {
|
|
||||||
if (ticksRemaining > 0)
|
|
||||||
ticksRemaining--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public SchematicannonTileEntity() {
|
public SchematicannonTileEntity() {
|
||||||
this(AllTileEntities.SCHEMATICANNON.type);
|
this(AllTileEntities.SCHEMATICANNON.type);
|
||||||
}
|
}
|
||||||
|
@ -179,9 +120,10 @@ public class SchematicannonTileEntity extends SyncedTileEntity implements ITicka
|
||||||
|
|
||||||
public SchematicannonTileEntity(TileEntityType<?> tileEntityTypeIn) {
|
public SchematicannonTileEntity(TileEntityType<?> tileEntityTypeIn) {
|
||||||
super(tileEntityTypeIn);
|
super(tileEntityTypeIn);
|
||||||
|
setLazyTickRate(30);
|
||||||
attachedInventories = new LinkedList<>();
|
attachedInventories = new LinkedList<>();
|
||||||
flyingBlocks = new LinkedList<>();
|
flyingBlocks = new LinkedList<>();
|
||||||
inventory = new SchematicannonInventory();
|
inventory = new SchematicannonInventory(this);
|
||||||
statusMsg = "idle";
|
statusMsg = "idle";
|
||||||
state = State.STOPPED;
|
state = State.STOPPED;
|
||||||
replaceMode = 2;
|
replaceMode = 2;
|
||||||
|
@ -271,7 +213,7 @@ public class SchematicannonTileEntity extends SyncedTileEntity implements ITicka
|
||||||
|
|
||||||
// Always write to Server tile
|
// Always write to Server tile
|
||||||
if (world == null || !world.isRemote) {
|
if (world == null || !world.isRemote) {
|
||||||
flyingBlocks.add(new LaunchedBlock(readBlockPos, readBlockState, int1, int2));
|
flyingBlocks.add(new LaunchedBlock(this, readBlockPos, readBlockState, int1, int2));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -284,7 +226,7 @@ public class SchematicannonTileEntity extends SyncedTileEntity implements ITicka
|
||||||
|
|
||||||
// Add new server side blocks
|
// Add new server side blocks
|
||||||
if (i >= flyingBlocks.size()) {
|
if (i >= flyingBlocks.size()) {
|
||||||
flyingBlocks.add(new LaunchedBlock(readBlockPos, readBlockState, int1, int2));
|
flyingBlocks.add(new LaunchedBlock(this, readBlockPos, readBlockState, int1, int2));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -346,6 +288,8 @@ public class SchematicannonTileEntity extends SyncedTileEntity implements ITicka
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void tick() {
|
public void tick() {
|
||||||
|
super.tick();
|
||||||
|
|
||||||
if (neighbourCheckCooldown-- <= 0) {
|
if (neighbourCheckCooldown-- <= 0) {
|
||||||
neighbourCheckCooldown = NEIGHBOUR_CHECKING;
|
neighbourCheckCooldown = NEIGHBOUR_CHECKING;
|
||||||
findInventories();
|
findInventories();
|
||||||
|
@ -757,7 +701,7 @@ public class SchematicannonTileEntity extends SyncedTileEntity implements ITicka
|
||||||
protected void launchBlock(BlockPos target, BlockState state) {
|
protected void launchBlock(BlockPos target, BlockState state) {
|
||||||
if (state.getBlock() != Blocks.AIR)
|
if (state.getBlock() != Blocks.AIR)
|
||||||
blocksPlaced++;
|
blocksPlaced++;
|
||||||
flyingBlocks.add(new LaunchedBlock(target, state));
|
flyingBlocks.add(new LaunchedBlock(this, target, state));
|
||||||
world.playSound(null, pos.getX(), pos.getY(), pos.getZ(), SoundEvents.ENTITY_GENERIC_EXPLODE,
|
world.playSound(null, pos.getX(), pos.getY(), pos.getZ(), SoundEvents.ENTITY_GENERIC_EXPLODE,
|
||||||
SoundCategory.BLOCKS, .1f, 1.1f);
|
SoundCategory.BLOCKS, .1f, 1.1f);
|
||||||
}
|
}
|
||||||
|
@ -817,4 +761,14 @@ public class SchematicannonTileEntity extends SyncedTileEntity implements ITicka
|
||||||
sendUpdate = true;
|
sendUpdate = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addBehaviours(List<TileEntityBehaviour> behaviours) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void lazyTick() {
|
||||||
|
super.lazyTick();
|
||||||
|
findInventories();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
{
|
||||||
|
"forge_marker": 1,
|
||||||
|
"defaults": {
|
||||||
|
"model": "create:block/portable_storage_interface"
|
||||||
|
},
|
||||||
|
"variants": {
|
||||||
|
"facing": {
|
||||||
|
"north": { "x": 90 },
|
||||||
|
"south": { "x": 90, "y": 180 },
|
||||||
|
"west": { "x": 90, "y": 270 },
|
||||||
|
"up": { },
|
||||||
|
"down": { "x": 180 },
|
||||||
|
"east": { "x": 90, "y": 90 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -96,6 +96,7 @@
|
||||||
"block.create.belt": "Mechanical Belt",
|
"block.create.belt": "Mechanical Belt",
|
||||||
"block.create.crushing_wheel": "Crushing Wheel",
|
"block.create.crushing_wheel": "Crushing Wheel",
|
||||||
"block.create.drill": "Mechanical Drill",
|
"block.create.drill": "Mechanical Drill",
|
||||||
|
"block.create.portable_storage_interface": "Portable Storage Interface",
|
||||||
"block.create.harvester": "Mechanical Harvester",
|
"block.create.harvester": "Mechanical Harvester",
|
||||||
"block.create.saw": "Mechanical Saw",
|
"block.create.saw": "Mechanical Saw",
|
||||||
"block.create.water_wheel": "Water Wheel",
|
"block.create.water_wheel": "Water Wheel",
|
||||||
|
|
|
@ -0,0 +1,165 @@
|
||||||
|
{
|
||||||
|
"credit": "Made with Blockbench",
|
||||||
|
"parent": "block/block",
|
||||||
|
"textures": {
|
||||||
|
"0": "create:block/brass_casing",
|
||||||
|
"5": "create:block/andesite_casing_short",
|
||||||
|
"6": "create:block/gearbox_top",
|
||||||
|
"7": "block/dark_oak_log",
|
||||||
|
"1_2": "create:block/transposer",
|
||||||
|
"particle": "create:block/extractor"
|
||||||
|
},
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"name": "Center",
|
||||||
|
"from": [2, 1, 2],
|
||||||
|
"to": [14, 11, 14],
|
||||||
|
"faces": {
|
||||||
|
"up": {"uv": [2, 4, 14, 16], "texture": "#7"},
|
||||||
|
"down": {"uv": [2, 2, 14, 14], "texture": "#6"}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Side",
|
||||||
|
"from": [0, 0, 0],
|
||||||
|
"to": [2, 12, 16],
|
||||||
|
"faces": {
|
||||||
|
"north": {"uv": [14, 4, 16, 16], "texture": "#5"},
|
||||||
|
"east": {"uv": [0, 4, 16, 16], "texture": "#5"},
|
||||||
|
"south": {"uv": [0, 4, 2, 16], "texture": "#5"},
|
||||||
|
"west": {"uv": [0, 4, 16, 16], "texture": "#5"},
|
||||||
|
"up": {"uv": [0, 0, 2, 16], "texture": "#6"},
|
||||||
|
"down": {"uv": [0, 0, 2, 16], "texture": "#6"}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Side",
|
||||||
|
"from": [14, 0, 0],
|
||||||
|
"to": [16, 12, 16],
|
||||||
|
"faces": {
|
||||||
|
"north": {"uv": [0, 4, 2, 16], "texture": "#5"},
|
||||||
|
"east": {"uv": [0, 4, 16, 16], "texture": "#5"},
|
||||||
|
"south": {"uv": [14, 4, 16, 16], "texture": "#5"},
|
||||||
|
"west": {"uv": [0, 4, 16, 16], "texture": "#5"},
|
||||||
|
"up": {"uv": [14, 0, 16, 16], "texture": "#6"},
|
||||||
|
"down": {"uv": [14, 0, 16, 16], "texture": "#6"}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Short Side",
|
||||||
|
"from": [2, 0, 0],
|
||||||
|
"to": [14, 12, 2],
|
||||||
|
"faces": {
|
||||||
|
"north": {"uv": [2, 4, 14, 16], "texture": "#5"},
|
||||||
|
"south": {"uv": [2, 4, 14, 16], "texture": "#5"},
|
||||||
|
"up": {"uv": [2, 0, 14, 2], "texture": "#6"},
|
||||||
|
"down": {"uv": [2, 14, 14, 16], "texture": "#6"}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Short Side",
|
||||||
|
"from": [2, 0, 14],
|
||||||
|
"to": [14, 12, 16],
|
||||||
|
"faces": {
|
||||||
|
"north": {"uv": [2, 4, 14, 16], "texture": "#5"},
|
||||||
|
"south": {"uv": [2, 4, 14, 16], "texture": "#5"},
|
||||||
|
"up": {"uv": [2, 14, 14, 16], "texture": "#6"},
|
||||||
|
"down": {"uv": [2, 0, 14, 2], "texture": "#6"}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"from": [4, 11, 4],
|
||||||
|
"to": [12, 15, 12],
|
||||||
|
"faces": {
|
||||||
|
"north": {"uv": [1, 4, 5, 12], "rotation": 90, "texture": "#0"},
|
||||||
|
"east": {"uv": [1, 4, 5, 12], "rotation": 90, "texture": "#0"},
|
||||||
|
"south": {"uv": [1, 4, 5, 12], "rotation": 90, "texture": "#0"},
|
||||||
|
"west": {"uv": [1, 4, 5, 12], "rotation": 90, "texture": "#0"},
|
||||||
|
"up": {"uv": [7, 7, 15, 15], "rotation": 90, "texture": "#1_2"}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"from": [3, 11, 11],
|
||||||
|
"to": [5, 16, 13],
|
||||||
|
"faces": {
|
||||||
|
"north": {"uv": [0, 14, 5, 16], "rotation": 90, "texture": "#0"},
|
||||||
|
"east": {"uv": [11, 14, 16, 16], "rotation": 270, "texture": "#1_2"},
|
||||||
|
"south": {"uv": [6, 14, 11, 16], "rotation": 90, "texture": "#1_2"},
|
||||||
|
"west": {"uv": [6, 6, 11, 8], "rotation": 90, "texture": "#1_2"},
|
||||||
|
"up": {"uv": [4, 6, 6, 8], "rotation": 180, "texture": "#1_2"}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"from": [11, 11, 11],
|
||||||
|
"to": [13, 16, 13],
|
||||||
|
"faces": {
|
||||||
|
"north": {"uv": [0, 16, 5, 14], "rotation": 90, "texture": "#0"},
|
||||||
|
"east": {"uv": [11, 6, 6, 8], "rotation": 270, "texture": "#1_2"},
|
||||||
|
"south": {"uv": [6, 16, 11, 14], "rotation": 90, "texture": "#1_2"},
|
||||||
|
"west": {"uv": [16, 14, 11, 16], "rotation": 90, "texture": "#1_2"},
|
||||||
|
"up": {"uv": [6, 6, 4, 8], "rotation": 180, "texture": "#1_2"}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"from": [3, 11, 3],
|
||||||
|
"to": [5, 16, 5],
|
||||||
|
"faces": {
|
||||||
|
"north": {"uv": [11, 14, 6, 16], "rotation": 270, "texture": "#1_2"},
|
||||||
|
"east": {"uv": [11, 16, 16, 14], "rotation": 270, "texture": "#1_2"},
|
||||||
|
"south": {"uv": [5, 14, 0, 16], "rotation": 270, "texture": "#0"},
|
||||||
|
"west": {"uv": [6, 8, 11, 6], "rotation": 90, "texture": "#1_2"},
|
||||||
|
"up": {"uv": [4, 8, 6, 6], "rotation": 180, "texture": "#1_2"}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"from": [11, 11, 3],
|
||||||
|
"to": [13, 16, 5],
|
||||||
|
"faces": {
|
||||||
|
"north": {"uv": [11, 16, 6, 14], "rotation": 270, "texture": "#1_2"},
|
||||||
|
"east": {"uv": [11, 8, 6, 6], "rotation": 270, "texture": "#1_2"},
|
||||||
|
"south": {"uv": [5, 16, 0, 14], "rotation": 270, "texture": "#0"},
|
||||||
|
"west": {"uv": [16, 16, 11, 14], "rotation": 90, "texture": "#1_2"},
|
||||||
|
"up": {"uv": [6, 8, 4, 6], "rotation": 180, "texture": "#1_2"}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"display": {
|
||||||
|
"thirdperson_righthand": {
|
||||||
|
"rotation": [75, 45, 0],
|
||||||
|
"translation": [0, 2.5, 0],
|
||||||
|
"scale": [0.375, 0.375, 0.375]
|
||||||
|
},
|
||||||
|
"thirdperson_lefthand": {
|
||||||
|
"rotation": [75, 45, 0],
|
||||||
|
"translation": [0, 2.5, 0],
|
||||||
|
"scale": [0.375, 0.375, 0.375]
|
||||||
|
},
|
||||||
|
"firstperson_righthand": {
|
||||||
|
"rotation": [0, 45, 0],
|
||||||
|
"scale": [0.4, 0.4, 0.4]
|
||||||
|
},
|
||||||
|
"firstperson_lefthand": {
|
||||||
|
"rotation": [0, 225, 0],
|
||||||
|
"scale": [0.4, 0.4, 0.4]
|
||||||
|
},
|
||||||
|
"ground": {
|
||||||
|
"translation": [0, 3, 0],
|
||||||
|
"scale": [0.25, 0.25, 0.25]
|
||||||
|
},
|
||||||
|
"gui": {
|
||||||
|
"rotation": [30, -45, -90],
|
||||||
|
"scale": [0.625, 0.625, 0.625]
|
||||||
|
},
|
||||||
|
"fixed": {
|
||||||
|
"rotation": [-90, 0, 0],
|
||||||
|
"scale": [0.5, 0.5, 0.5]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"groups": [
|
||||||
|
{
|
||||||
|
"name": "group",
|
||||||
|
"origin": [8, 8, 8],
|
||||||
|
"children": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -3,7 +3,7 @@
|
||||||
"parent": "block/block",
|
"parent": "block/block",
|
||||||
"textures": {
|
"textures": {
|
||||||
"0": "create:block/brass_casing",
|
"0": "create:block/brass_casing",
|
||||||
"1": "create:block/black_stained_glass",
|
"1": "block/black_stained_glass",
|
||||||
"2": "create:item/goggles",
|
"2": "create:item/goggles",
|
||||||
"particle": "create:block/brass_casing"
|
"particle": "create:block/brass_casing"
|
||||||
},
|
},
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"parent": "create:block/portable_storage_interface"
|
||||||
|
}
|
Binary file not shown.
Before Width: | Height: | Size: 423 B After Width: | Height: | Size: 439 B |
Binary file not shown.
Before Width: | Height: | Size: 307 B After Width: | Height: | Size: 564 B |
|
@ -0,0 +1,19 @@
|
||||||
|
{
|
||||||
|
"type": "minecraft:block",
|
||||||
|
"pools": [
|
||||||
|
{
|
||||||
|
"rolls": 1,
|
||||||
|
"entries": [
|
||||||
|
{
|
||||||
|
"type": "minecraft:item",
|
||||||
|
"name": "create:portable_storage_interface"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"conditions": [
|
||||||
|
{
|
||||||
|
"condition": "minecraft:survives_explosion"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
Loading…
Reference in a new issue