merged mc1.15/dev into mc1.15-registrate

This commit is contained in:
simibubi 2020-05-02 00:34:36 +02:00
commit 901cb00426
190 changed files with 6600 additions and 1702 deletions

View file

@ -14,6 +14,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.PloughBlock;
import com.simibubi.create.modules.contraptions.components.actors.PortableStorageInterfaceBlock; 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.ClockworkBearingBlock; import com.simibubi.create.modules.contraptions.components.contraptions.bearing.ClockworkBearingBlock;
@ -86,9 +87,6 @@ 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.ScoriaBlock; import com.simibubi.create.modules.palettes.ScoriaBlock;
import com.simibubi.create.modules.palettes.VerticalCTGlassBlock; import com.simibubi.create.modules.palettes.VerticalCTGlassBlock;
import com.simibubi.create.modules.schematics.block.CreativeCrateBlock;
import com.simibubi.create.modules.schematics.block.SchematicTableBlock;
import com.simibubi.create.modules.schematics.block.SchematicannonBlock;
import com.tterrag.registrate.builders.BlockBuilder; import com.tterrag.registrate.builders.BlockBuilder;
import com.tterrag.registrate.builders.ItemBuilder; import com.tterrag.registrate.builders.ItemBuilder;
import com.tterrag.registrate.providers.ProviderType; import com.tterrag.registrate.providers.ProviderType;
@ -172,9 +170,10 @@ public enum AllBlocks implements NonNullSupplier<Block> {
ROTATION_CHASSIS(RadialChassisBlock::new), ROTATION_CHASSIS(RadialChassisBlock::new),
DRILL(DrillBlock::new), DRILL(DrillBlock::new),
SAW(SawBlock::new), SAW(SawBlock::new),
HARVESTER(HarvesterBlock::new),
DEPLOYER(DeployerBlock::new), DEPLOYER(DeployerBlock::new),
PORTABLE_STORAGE_INTERFACE(PortableStorageInterfaceBlock::new), PORTABLE_STORAGE_INTERFACE(PortableStorageInterfaceBlock::new),
HARVESTER(HarvesterBlock::new),
PLOUGH(PloughBlock::new),
ANALOG_LEVER(AnalogLeverBlock::new), ANALOG_LEVER(AnalogLeverBlock::new),
ANDESITE_CASING(() -> new CasingBlock("andesite_casing")), ANDESITE_CASING(() -> new CasingBlock("andesite_casing")),

View file

@ -5,8 +5,6 @@ import com.simibubi.create.modules.schematics.block.SchematicTableBlock;
import com.simibubi.create.modules.schematics.block.SchematicannonBlock; import com.simibubi.create.modules.schematics.block.SchematicannonBlock;
import com.tterrag.registrate.util.RegistryEntry; import com.tterrag.registrate.util.RegistryEntry;
import net.minecraftforge.client.model.generators.ModelFile.UncheckedModelFile;
public class AllBlocksNew { public class AllBlocksNew {
private static final CreateRegistrate REGISTRATE = Create.registrate(); private static final CreateRegistrate REGISTRATE = Create.registrate();

View file

@ -5,6 +5,8 @@ import java.util.function.Function;
import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.Lang;
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.ContraptionEntityRenderer; import com.simibubi.create.modules.contraptions.components.contraptions.ContraptionEntityRenderer;
import com.simibubi.create.modules.contraptions.components.contraptions.glue.SuperGlueEntity;
import com.simibubi.create.modules.contraptions.components.contraptions.glue.SuperGlueRenderer;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityClassification; import net.minecraft.entity.EntityClassification;
@ -23,6 +25,8 @@ public enum AllEntities {
ContraptionEntity::build), ContraptionEntity::build),
STATIONARY_CONTRAPTION(ContraptionEntity::new, EntityClassification.MISC, 30, 40, STATIONARY_CONTRAPTION(ContraptionEntity::new, EntityClassification.MISC, 30, 40,
false, ContraptionEntity::build), false, ContraptionEntity::build),
SUPER_GLUE(SuperGlueEntity::new, EntityClassification.MISC, 30, Integer.MAX_VALUE, false, SuperGlueEntity::build),
; ;
private IFactory<?> factory; private IFactory<?> factory;
@ -63,8 +67,8 @@ public enum AllEntities {
@SuppressWarnings("unchecked") // TODO 1.15 this generic stuff is incompatible with the enum system - need strong types @SuppressWarnings("unchecked") // TODO 1.15 this generic stuff is incompatible with the enum system - need strong types
@OnlyIn(value = Dist.CLIENT) @OnlyIn(value = Dist.CLIENT)
public static void registerRenderers() { public static void registerRenderers() {
// RenderingRegistry.registerEntityRenderingHandler(CardboardBoxEntity.class, CardboardBoxEntityRenderer::new);
RenderingRegistry.registerEntityRenderingHandler((EntityType<ContraptionEntity>) CONTRAPTION.type, ContraptionEntityRenderer::new); RenderingRegistry.registerEntityRenderingHandler((EntityType<ContraptionEntity>) CONTRAPTION.type, ContraptionEntityRenderer::new);
RenderingRegistry.registerEntityRenderingHandler((EntityType<SuperGlueEntity>) SUPER_GLUE.type, SuperGlueRenderer::new);
} }
} }

View file

@ -16,6 +16,8 @@ import com.simibubi.create.foundation.utility.data.ITaggable;
import com.simibubi.create.modules.IModule; import com.simibubi.create.modules.IModule;
import com.simibubi.create.modules.contraptions.GogglesItem; import com.simibubi.create.modules.contraptions.GogglesItem;
import com.simibubi.create.modules.contraptions.WrenchItem; import com.simibubi.create.modules.contraptions.WrenchItem;
import com.simibubi.create.modules.contraptions.components.contraptions.glue.SuperGlueItem;
import com.simibubi.create.modules.contraptions.components.contraptions.mounted.MinecartContraptionItem;
import com.simibubi.create.modules.contraptions.relays.belt.item.BeltConnectorItem; import com.simibubi.create.modules.contraptions.relays.belt.item.BeltConnectorItem;
import com.simibubi.create.modules.contraptions.relays.gearbox.VerticalGearboxItem; import com.simibubi.create.modules.contraptions.relays.gearbox.VerticalGearboxItem;
import com.simibubi.create.modules.curiosities.ChromaticCompoundCubeItem; import com.simibubi.create.modules.curiosities.ChromaticCompoundCubeItem;
@ -38,6 +40,7 @@ import com.simibubi.create.modules.schematics.item.SchematicItem;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.color.ItemColors; import net.minecraft.client.renderer.color.ItemColors;
import net.minecraft.client.renderer.tileentity.ItemStackTileEntityRenderer; import net.minecraft.client.renderer.tileentity.ItemStackTileEntityRenderer;
import net.minecraft.entity.item.minecart.AbstractMinecartEntity.Type;
import net.minecraft.item.Item; import net.minecraft.item.Item;
import net.minecraft.item.Item.Properties; import net.minecraft.item.Item.Properties;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
@ -75,8 +78,8 @@ public enum AllItems {
ZINC_INGOT((TaggedItem) new TaggedItem().withForgeTags("ingots/zinc")), ZINC_INGOT((TaggedItem) new TaggedItem().withForgeTags("ingots/zinc")),
BRASS_INGOT((TaggedItem) new TaggedItem().withForgeTags("ingots/brass")), BRASS_INGOT((TaggedItem) new TaggedItem().withForgeTags("ingots/brass")),
SAND_PAPER(SandPaperItem::new), FLOUR,
RED_SAND_PAPER(SandPaperItem::new), DOUGH,
OBSIDIAN_DUST, OBSIDIAN_DUST,
ROSE_QUARTZ, ROSE_QUARTZ,
POLISHED_ROSE_QUARTZ, POLISHED_ROSE_QUARTZ,
@ -86,23 +89,20 @@ public enum AllItems {
ELECTRON_TUBE, ELECTRON_TUBE,
INTEGRATED_CIRCUIT, INTEGRATED_CIRCUIT,
__SCHEMATICS__(module()),
EMPTY_BLUEPRINT(Item::new, stackSize(1)),
BLUEPRINT_AND_QUILL(SchematicAndQuillItem::new, stackSize(1)),
BLUEPRINT(SchematicItem::new),
__CONTRAPTIONS__(module()), __CONTRAPTIONS__(module()),
BELT_CONNECTOR(BeltConnectorItem::new), BELT_CONNECTOR(BeltConnectorItem::new),
VERTICAL_GEARBOX(VerticalGearboxItem::new), VERTICAL_GEARBOX(VerticalGearboxItem::new),
FLOUR,
DOUGH,
PROPELLER, PROPELLER,
WHISK, WHISK,
BRASS_HAND, BRASS_HAND,
SLOT_COVER, SLOT_COVER,
ZINC_HANDLE, SUPER_GLUE(SuperGlueItem::new),
SAND_PAPER(SandPaperItem::new),
RED_SAND_PAPER(SandPaperItem::new),
WRENCH(WrenchItem::new), WRENCH(WrenchItem::new),
GOGGLES(GogglesItem::new), GOGGLES(GogglesItem::new),
MINECART_CONTRAPTION(p -> new MinecartContraptionItem(Type.RIDEABLE, p)),
FURNACE_MINECART_CONTRAPTION(p -> new MinecartContraptionItem(Type.FURNACE, p)),
__LOGISTICS__(module()), __LOGISTICS__(module()),
FILTER(FilterItem::new), FILTER(FilterItem::new),
@ -114,6 +114,7 @@ public enum AllItems {
TERRAIN_ZAPPER(TerrainzapperItem::new), TERRAIN_ZAPPER(TerrainzapperItem::new),
DEFORESTER(DeforesterItem::new), DEFORESTER(DeforesterItem::new),
SYMMETRY_WAND(SymmetryWandItem::new), SYMMETRY_WAND(SymmetryWandItem::new),
ZINC_HANDLE,
BLAZING_PICKAXE(p -> new BlazingToolItem(1, -2.8F, p, PICKAXE)), BLAZING_PICKAXE(p -> new BlazingToolItem(1, -2.8F, p, PICKAXE)),
BLAZING_SHOVEL(p -> new BlazingToolItem(1.5F, -3.0F, p, SHOVEL)), BLAZING_SHOVEL(p -> new BlazingToolItem(1.5F, -3.0F, p, SHOVEL)),
@ -129,6 +130,11 @@ public enum AllItems {
SHADOW_STEEL_MATTOCK(p -> new ShadowSteelToolItem(2.5F, -1.5F, p, SHOVEL, AXE, HOE)), SHADOW_STEEL_MATTOCK(p -> new ShadowSteelToolItem(2.5F, -1.5F, p, SHOVEL, AXE, HOE)),
SHADOW_STEEL_SWORD(p -> new SwordItem(AllToolTiers.SHADOW_STEEL, 3, -2.0F, p)), SHADOW_STEEL_SWORD(p -> new SwordItem(AllToolTiers.SHADOW_STEEL, 3, -2.0F, p)),
__SCHEMATICS__(module()),
EMPTY_BLUEPRINT(Item::new, stackSize(1)),
BLUEPRINT_AND_QUILL(SchematicAndQuillItem::new, stackSize(1)),
BLUEPRINT(SchematicItem::new),
; ;
private static class CategoryTracker { private static class CategoryTracker {
@ -197,7 +203,8 @@ public enum AllItems {
continue; continue;
entry.item = entry.taggedItem.getItemSupplier().apply(new Properties()); entry.item = entry.taggedItem.getItemSupplier().apply(new Properties());
entry.item = entry.taggedItem.getItemSupplier().apply(entry.specialProperties.apply(defaultProperties(entry))); entry.item =
entry.taggedItem.getItemSupplier().apply(entry.specialProperties.apply(defaultProperties(entry)));
entry.item.setRegistryName(Create.ID, Lang.asId(entry.name())); entry.item.setRegistryName(Create.ID, Lang.asId(entry.name()));
registry.register(entry.item); registry.register(entry.item);
} }
@ -224,11 +231,11 @@ public enum AllItems {
private Set<ResourceLocation> tagSetItem = new HashSet<>(); private Set<ResourceLocation> tagSetItem = new HashSet<>();
private Function<Properties, Item> itemSupplier; private Function<Properties, Item> itemSupplier;
public TaggedItem(){ public TaggedItem() {
this(Item::new); this(Item::new);
} }
public TaggedItem(Function<Properties, Item> itemSupplierIn){ public TaggedItem(Function<Properties, Item> itemSupplierIn) {
this.itemSupplier = itemSupplierIn; this.itemSupplier = itemSupplierIn;
} }

View file

@ -13,6 +13,7 @@ import com.simibubi.create.foundation.packet.SimplePacketBase;
import com.simibubi.create.foundation.utility.ServerSpeedProvider; import com.simibubi.create.foundation.utility.ServerSpeedProvider;
import com.simibubi.create.modules.contraptions.components.contraptions.CancelPlayerFallPacket; import com.simibubi.create.modules.contraptions.components.contraptions.CancelPlayerFallPacket;
import com.simibubi.create.modules.contraptions.components.contraptions.ContraptionStallPacket; import com.simibubi.create.modules.contraptions.components.contraptions.ContraptionStallPacket;
import com.simibubi.create.modules.contraptions.components.contraptions.glue.GlueEffectPacket;
import com.simibubi.create.modules.contraptions.relays.advanced.sequencer.ConfigureSequencedGearshiftPacket; import com.simibubi.create.modules.contraptions.relays.advanced.sequencer.ConfigureSequencedGearshiftPacket;
import com.simibubi.create.modules.curiosities.symmetry.SymmetryEffectPacket; import com.simibubi.create.modules.curiosities.symmetry.SymmetryEffectPacket;
import com.simibubi.create.modules.curiosities.zapper.ZapperBeamPacket; import com.simibubi.create.modules.curiosities.zapper.ZapperBeamPacket;
@ -51,6 +52,7 @@ public enum AllPackets {
CONFIGURE_CONFIG(ConfigureConfigPacket.class, ConfigureConfigPacket::new), CONFIGURE_CONFIG(ConfigureConfigPacket.class, ConfigureConfigPacket::new),
CONTRAPTION_STALL(ContraptionStallPacket.class, ContraptionStallPacket::new), CONTRAPTION_STALL(ContraptionStallPacket.class, ContraptionStallPacket::new),
TOOL_HARVEST(AbstractToolItem.HarvestPacket.class, AbstractToolItem.HarvestPacket::new), TOOL_HARVEST(AbstractToolItem.HarvestPacket.class, AbstractToolItem.HarvestPacket::new),
GLUE_EFFECT(GlueEffectPacket.class, GlueEffectPacket::new),
; ;

View file

@ -8,6 +8,9 @@ import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
@EventBusSubscriber(value = Dist.CLIENT) @EventBusSubscriber(value = Dist.CLIENT)
public enum AllSpecialTextures { public enum AllSpecialTextures {
BLANK("blank.png"),
CHECKERED("checkerboard.png"),
HIGHLIGHT_CHECKERED("highlighted_checkerboard.png"),
SELECTION("selection.png"), SELECTION("selection.png"),
; ;

View file

@ -16,6 +16,7 @@ import com.simibubi.create.modules.contraptions.components.contraptions.bearing.
import com.simibubi.create.modules.contraptions.components.contraptions.bearing.ClockworkBearingTileEntity; import com.simibubi.create.modules.contraptions.components.contraptions.bearing.ClockworkBearingTileEntity;
import com.simibubi.create.modules.contraptions.components.contraptions.bearing.MechanicalBearingTileEntity; import com.simibubi.create.modules.contraptions.components.contraptions.bearing.MechanicalBearingTileEntity;
import com.simibubi.create.modules.contraptions.components.contraptions.chassis.ChassisTileEntity; import com.simibubi.create.modules.contraptions.components.contraptions.chassis.ChassisTileEntity;
import com.simibubi.create.modules.contraptions.components.contraptions.mounted.CartAssemblerTileEntity;
import com.simibubi.create.modules.contraptions.components.contraptions.piston.MechanicalPistonTileEntity; import com.simibubi.create.modules.contraptions.components.contraptions.piston.MechanicalPistonTileEntity;
import com.simibubi.create.modules.contraptions.components.contraptions.piston.MechanicalPistonTileEntityRenderer; import com.simibubi.create.modules.contraptions.components.contraptions.piston.MechanicalPistonTileEntityRenderer;
import com.simibubi.create.modules.contraptions.components.contraptions.pulley.PulleyRenderer; import com.simibubi.create.modules.contraptions.components.contraptions.pulley.PulleyRenderer;
@ -148,6 +149,7 @@ public enum AllTileEntities {
SPEED_GAUGE(SpeedGaugeTileEntity::new, AllBlocks.SPEED_GAUGE), SPEED_GAUGE(SpeedGaugeTileEntity::new, AllBlocks.SPEED_GAUGE),
STRESS_GAUGE(StressGaugeTileEntity::new, AllBlocks.STRESS_GAUGE), STRESS_GAUGE(StressGaugeTileEntity::new, AllBlocks.STRESS_GAUGE),
ANALOG_LEVER(AnalogLeverTileEntity::new, AllBlocks.ANALOG_LEVER), ANALOG_LEVER(AnalogLeverTileEntity::new, AllBlocks.ANALOG_LEVER),
CART_ASSEMBLER(CartAssemblerTileEntity::new, AllBlocks.CART_ASSEMBLER),
// Logistics // Logistics
REDSTONE_BRIDGE(RedstoneLinkTileEntity::new, AllBlocks.REDSTONE_BRIDGE), REDSTONE_BRIDGE(RedstoneLinkTileEntity::new, AllBlocks.REDSTONE_BRIDGE),

View file

@ -80,8 +80,6 @@ public class ClientEvents {
IRenderTypeBuffer.Impl buffer = Minecraft.getInstance().getBufferBuilders().getEntityVertexConsumers(); IRenderTypeBuffer.Impl buffer = Minecraft.getInstance().getBufferBuilders().getEntityVertexConsumers();
CreateClient.schematicHandler.render(ms, buffer, 0xF000F0, OverlayTexture.DEFAULT_UV); CreateClient.schematicHandler.render(ms, buffer, 0xF000F0, OverlayTexture.DEFAULT_UV);
CreateClient.schematicAndQuillHandler.render(ms, buffer);
CreateClient.schematicHologram.render(ms, buffer);
KineticDebugger.renderSourceOutline(ms, buffer); KineticDebugger.renderSourceOutline(ms, buffer);
ChassisRangeDisplay.renderOutlines(event.getPartialTicks(), ms, buffer); ChassisRangeDisplay.renderOutlines(event.getPartialTicks(), ms, buffer);
TerrainZapperRenderHandler.render(ms, buffer); TerrainZapperRenderHandler.render(ms, buffer);

View file

@ -16,7 +16,6 @@ import com.simibubi.create.modules.contraptions.components.contraptions.Contrapt
import com.simibubi.create.modules.schematics.ClientSchematicLoader; import com.simibubi.create.modules.schematics.ClientSchematicLoader;
import com.simibubi.create.modules.schematics.client.SchematicAndQuillHandler; import com.simibubi.create.modules.schematics.client.SchematicAndQuillHandler;
import com.simibubi.create.modules.schematics.client.SchematicHandler; import com.simibubi.create.modules.schematics.client.SchematicHandler;
import com.simibubi.create.modules.schematics.client.SchematicHologram;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
@ -41,10 +40,8 @@ public class CreateClient {
public static ClientSchematicLoader schematicSender; public static ClientSchematicLoader schematicSender;
public static SchematicHandler schematicHandler; public static SchematicHandler schematicHandler;
public static SchematicHologram schematicHologram;
public static SchematicAndQuillHandler schematicAndQuillHandler; public static SchematicAndQuillHandler schematicAndQuillHandler;
public static SuperByteBufferCache bufferCache; public static SuperByteBufferCache bufferCache;
public static int renderTicks;
public static void addListeners(IEventBus modEventBus) { public static void addListeners(IEventBus modEventBus) {
DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> { DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> {
@ -59,7 +56,6 @@ public class CreateClient {
public static void clientInit(FMLClientSetupEvent event) { public static void clientInit(FMLClientSetupEvent event) {
schematicSender = new ClientSchematicLoader(); schematicSender = new ClientSchematicLoader();
schematicHandler = new SchematicHandler(); schematicHandler = new SchematicHandler();
schematicHologram = new SchematicHologram();
schematicAndQuillHandler = new SchematicAndQuillHandler(); schematicAndQuillHandler = new SchematicAndQuillHandler();
bufferCache = new SuperByteBufferCache(); bufferCache = new SuperByteBufferCache();
@ -82,7 +78,6 @@ public class CreateClient {
schematicSender.tick(); schematicSender.tick();
schematicAndQuillHandler.tick(); schematicAndQuillHandler.tick();
schematicHandler.tick(); schematicHandler.tick();
schematicHologram.tick();
ChassisRangeDisplay.clientTick(); ChassisRangeDisplay.clientTick();
} }

View file

@ -41,7 +41,7 @@ public enum ScreenResources {
FILTER("filter.png", 200, 100), FILTER("filter.png", 200, 100),
ATTRIBUTE_FILTER("filter.png", 0, 100, 200, 86), ATTRIBUTE_FILTER("filter.png", 0, 100, 200, 86),
SEQUENCER("sequencer.png", 156, 128), SEQUENCER("sequencer.png", 156, 128),
SEQUENCER_INSTRUCTION("sequencer.png", 14, 47, 131, 18), SEQUENCER_INSTRUCTION("sequencer.png", 14, 47, 131, 18),
SEQUENCER_WAIT("sequencer.png", 14, 65, 131, 18), SEQUENCER_WAIT("sequencer.png", 14, 65, 131, 18),
@ -79,6 +79,7 @@ public enum ScreenResources {
// JEI // JEI
JEI_SLOT("jei/widgets.png", 18, 18), JEI_SLOT("jei/widgets.png", 18, 18),
JEI_CHANCE_SLOT("jei/widgets.png", 20, 156, 18, 18),
JEI_CATALYST_SLOT("jei/widgets.png", 0, 156, 18, 18), JEI_CATALYST_SLOT("jei/widgets.png", 0, 156, 18, 18),
JEI_ARROW("jei/widgets.png", 19, 10, 42, 10), JEI_ARROW("jei/widgets.png", 19, 10, 42, 10),
JEI_LONG_ARROW("jei/widgets.png", 19, 0, 71, 10), JEI_LONG_ARROW("jei/widgets.png", 19, 0, 71, 10),
@ -132,6 +133,9 @@ public enum ScreenResources {
I_MOVE_PLACE(9, 1), I_MOVE_PLACE(9, 1),
I_MOVE_PLACE_RETURNED(10, 1), I_MOVE_PLACE_RETURNED(10, 1),
I_MOVE_NEVER_PLACE(11, 1), I_MOVE_NEVER_PLACE(11, 1),
I_CART_ROTATE(12, 1),
I_CART_ROTATE_PAUSED(13, 1),
I_CART_ROTATE_LOCKED(14, 1),
I_DONT_REPLACE(0, 2), I_DONT_REPLACE(0, 2),
I_REPLACE_SOLID(1, 2), I_REPLACE_SOLID(1, 2),

View file

@ -1,7 +1,6 @@
package com.simibubi.create.compat.jei; package com.simibubi.create.compat.jei;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
@ -28,13 +27,11 @@ import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.modules.contraptions.components.crafter.MechanicalCraftingRecipe; import com.simibubi.create.modules.contraptions.components.crafter.MechanicalCraftingRecipe;
import com.simibubi.create.modules.contraptions.components.mixer.MixingRecipe; import com.simibubi.create.modules.contraptions.components.mixer.MixingRecipe;
import com.simibubi.create.modules.contraptions.components.press.MechanicalPressTileEntity; import com.simibubi.create.modules.contraptions.components.press.MechanicalPressTileEntity;
import com.simibubi.create.modules.contraptions.processing.ProcessingOutput;
import com.simibubi.create.modules.logistics.block.inventories.FlexcrateScreen; import com.simibubi.create.modules.logistics.block.inventories.FlexcrateScreen;
import com.simibubi.create.modules.schematics.block.SchematicannonScreen; import com.simibubi.create.modules.schematics.block.SchematicannonScreen;
import mezz.jei.api.IModPlugin; import mezz.jei.api.IModPlugin;
import mezz.jei.api.JeiPlugin; import mezz.jei.api.JeiPlugin;
import mezz.jei.api.gui.ingredient.IGuiItemStackGroup;
import mezz.jei.api.registration.IGuiHandlerRegistration; import mezz.jei.api.registration.IGuiHandlerRegistration;
import mezz.jei.api.registration.IRecipeCatalystRegistration; import mezz.jei.api.registration.IRecipeCatalystRegistration;
import mezz.jei.api.registration.IRecipeCategoryRegistration; import mezz.jei.api.registration.IRecipeCategoryRegistration;
@ -226,28 +223,4 @@ public class CreateJEI implements IModPlugin {
return byType; return byType;
} }
public static void addStochasticTooltip(IGuiItemStackGroup itemStacks, List<ProcessingOutput> results) {
itemStacks.addTooltipCallback((slotIndex, input, ingredient, tooltip) -> {
if (input)
return;
ProcessingOutput output = results.get(slotIndex - 1);
if (output.getChance() != 1)
tooltip.add(1, TextFormatting.GOLD
+ Lang.translate("recipe.processing.chance", (int) (output.getChance() * 100)));
});
}
public static void addCatalystTooltip(IGuiItemStackGroup itemStacks, Map<Integer, Float> catalystIndices) {
itemStacks.addTooltipCallback((slotIndex, input, ingredient, tooltip) -> {
if (!input)
return;
if (!catalystIndices.containsKey(slotIndex))
return;
Float chance = catalystIndices.get(slotIndex);
tooltip.add(1, TextFormatting.YELLOW + Lang.translate("recipe.processing.catalyst"));
tooltip.add(2, TextFormatting.GOLD
+ Lang.translate("recipe.processing.chanceToReturn", (int) (chance.floatValue() * 100)));
});
}
} }

View file

@ -2,38 +2,18 @@ package com.simibubi.create.compat.jei.category;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.RenderSystem;
import com.simibubi.create.AllItems; import com.simibubi.create.AllItems;
import com.simibubi.create.Create;
import com.simibubi.create.compat.jei.DoubleItemIcon;
import com.simibubi.create.foundation.gui.ScreenElementRenderer; import com.simibubi.create.foundation.gui.ScreenElementRenderer;
import com.simibubi.create.foundation.utility.Lang;
import mezz.jei.api.gui.drawable.IDrawable;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks; import net.minecraft.block.Blocks;
import net.minecraft.block.FlowingFluidBlock; import net.minecraft.block.FlowingFluidBlock;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items; import net.minecraft.item.Items;
import net.minecraft.item.crafting.AbstractCookingRecipe; import net.minecraft.item.crafting.AbstractCookingRecipe;
import net.minecraft.util.ResourceLocation;
public class BlastingViaFanCategory extends ProcessingViaFanCategory<AbstractCookingRecipe> { public class BlastingViaFanCategory extends ProcessingViaFanCategory<AbstractCookingRecipe> {
private static ResourceLocation ID = new ResourceLocation(Create.ID, "blasting_via_fan");
private IDrawable icon;
public BlastingViaFanCategory() { public BlastingViaFanCategory() {
icon = new DoubleItemIcon(() -> new ItemStack(AllItems.PROPELLER.get()), super("blasting_via_fan", doubleItemIcon(AllItems.PROPELLER.get(), Items.LAVA_BUCKET));
() -> new ItemStack(Items.LAVA_BUCKET));
}
@Override
public IDrawable getIcon() {
return icon;
}
@Override
public ResourceLocation getUid() {
return ID;
} }
@Override @Override
@ -41,11 +21,6 @@ public class BlastingViaFanCategory extends ProcessingViaFanCategory<AbstractCoo
return AbstractCookingRecipe.class; return AbstractCookingRecipe.class;
} }
@Override
public String getTitle() {
return Lang.translate("recipe.blastingViaFan");
}
@Override @Override
public void renderAttachedBlock() { public void renderAttachedBlock() {
BlockState state = Blocks.LAVA.getDefaultState().with(FlowingFluidBlock.LEVEL, 8); BlockState state = Blocks.LAVA.getDefaultState().with(FlowingFluidBlock.LEVEL, 8);

View file

@ -5,21 +5,15 @@ import java.util.Arrays;
import java.util.List; import java.util.List;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.Create;
import com.simibubi.create.ScreenResources; import com.simibubi.create.ScreenResources;
import com.simibubi.create.compat.jei.DoubleItemIcon;
import com.simibubi.create.compat.jei.EmptyBackground;
import com.simibubi.create.compat.jei.category.BlockCuttingCategory.CondensedBlockCuttingRecipe; import com.simibubi.create.compat.jei.category.BlockCuttingCategory.CondensedBlockCuttingRecipe;
import com.simibubi.create.compat.jei.category.animations.AnimatedSaw; import com.simibubi.create.compat.jei.category.animations.AnimatedSaw;
import com.simibubi.create.foundation.item.ItemHelper; import com.simibubi.create.foundation.item.ItemHelper;
import com.simibubi.create.foundation.utility.Lang;
import mezz.jei.api.constants.VanillaTypes; import mezz.jei.api.constants.VanillaTypes;
import mezz.jei.api.gui.IRecipeLayout; import mezz.jei.api.gui.IRecipeLayout;
import mezz.jei.api.gui.drawable.IDrawable;
import mezz.jei.api.gui.ingredient.IGuiItemStackGroup; import mezz.jei.api.gui.ingredient.IGuiItemStackGroup;
import mezz.jei.api.ingredients.IIngredients; import mezz.jei.api.ingredients.IIngredients;
import mezz.jei.api.recipe.category.IRecipeCategory;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.item.Items; import net.minecraft.item.Items;
import net.minecraft.item.crafting.IRecipe; import net.minecraft.item.crafting.IRecipe;
@ -27,27 +21,12 @@ import net.minecraft.item.crafting.Ingredient;
import net.minecraft.item.crafting.StonecuttingRecipe; import net.minecraft.item.crafting.StonecuttingRecipe;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
public class BlockCuttingCategory implements IRecipeCategory<CondensedBlockCuttingRecipe> { public class BlockCuttingCategory extends CreateRecipeCategory<CondensedBlockCuttingRecipe> {
private AnimatedSaw saw; private AnimatedSaw saw = new AnimatedSaw();
private static ResourceLocation ID = new ResourceLocation(Create.ID, "block_cutting");
private IDrawable icon;
private IDrawable background = new EmptyBackground(177, 70);
public BlockCuttingCategory() { public BlockCuttingCategory() {
icon = new DoubleItemIcon(() -> new ItemStack(AllBlocks.SAW.get()), super("block_cutting", doubleItemIcon(AllBlocks.SAW.get(), Items.STONE_BRICK_STAIRS), emptyBackground(177, 70));
() -> new ItemStack(Items.STONE_BRICK_STAIRS));
saw = new AnimatedSaw();
}
@Override
public IDrawable getIcon() {
return icon;
}
@Override
public ResourceLocation getUid() {
return ID;
} }
@Override @Override
@ -55,16 +34,6 @@ public class BlockCuttingCategory implements IRecipeCategory<CondensedBlockCutti
return CondensedBlockCuttingRecipe.class; return CondensedBlockCuttingRecipe.class;
} }
@Override
public String getTitle() {
return Lang.translate("recipe.block_cutting");
}
@Override
public IDrawable getBackground() {
return background;
}
@Override @Override
public void setIngredients(CondensedBlockCuttingRecipe recipe, IIngredients ingredients) { public void setIngredients(CondensedBlockCuttingRecipe recipe, IIngredients ingredients) {
ingredients.setInputIngredients(recipe.getIngredients()); ingredients.setInputIngredients(recipe.getIngredients());

View file

@ -9,8 +9,6 @@ import java.util.stream.Collectors;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.RenderSystem;
import com.simibubi.create.AllItems; import com.simibubi.create.AllItems;
import com.simibubi.create.Create;
import com.simibubi.create.compat.jei.DoubleItemIcon;
import com.simibubi.create.compat.jei.ScreenResourceWrapper; import com.simibubi.create.compat.jei.ScreenResourceWrapper;
import com.simibubi.create.foundation.gui.ScreenElementRenderer; import com.simibubi.create.foundation.gui.ScreenElementRenderer;
import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.Lang;
@ -18,38 +16,21 @@ import com.simibubi.create.modules.curiosities.zapper.blockzapper.BlockzapperUpg
import mezz.jei.api.constants.VanillaTypes; import mezz.jei.api.constants.VanillaTypes;
import mezz.jei.api.gui.IRecipeLayout; import mezz.jei.api.gui.IRecipeLayout;
import mezz.jei.api.gui.drawable.IDrawable;
import mezz.jei.api.gui.ingredient.IGuiItemStackGroup; import mezz.jei.api.gui.ingredient.IGuiItemStackGroup;
import mezz.jei.api.ingredients.IIngredients; import mezz.jei.api.ingredients.IIngredients;
import mezz.jei.api.recipe.category.IRecipeCategory;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.util.ITooltipFlag; import net.minecraft.client.util.ITooltipFlag;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.Ingredient; import net.minecraft.item.crafting.Ingredient;
import net.minecraft.item.crafting.ShapedRecipe; import net.minecraft.item.crafting.ShapedRecipe;
import net.minecraft.util.NonNullList; import net.minecraft.util.NonNullList;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.ITextComponent;
public class BlockzapperUpgradeCategory implements IRecipeCategory<BlockzapperUpgradeRecipe> { public class BlockzapperUpgradeCategory extends CreateRecipeCategory<BlockzapperUpgradeRecipe> {
private static ResourceLocation ID = new ResourceLocation(Create.ID, "blockzapper_upgrade");
private IDrawable icon;
public BlockzapperUpgradeCategory() { public BlockzapperUpgradeCategory() {
icon = new DoubleItemIcon(() -> new ItemStack(AllItems.PLACEMENT_HANDGUN.get()), super("blockzapper_upgrade", itemIcon(AllItems.PLACEMENT_HANDGUN.get()),
() -> ItemStack.EMPTY); // replace with uparrow when available new ScreenResourceWrapper(BLOCKZAPPER_UPGRADE_RECIPE));
}
@Override
public IDrawable getIcon() {
return icon;
}
@Override
public ResourceLocation getUid() {
return ID;
} }
@Override @Override
@ -57,16 +38,6 @@ public class BlockzapperUpgradeCategory implements IRecipeCategory<BlockzapperUp
return BlockzapperUpgradeRecipe.class; return BlockzapperUpgradeRecipe.class;
} }
@Override
public String getTitle() {
return Lang.translate("recipe.blockzapperUpgrade");
}
@Override
public IDrawable getBackground() {
return new ScreenResourceWrapper(BLOCKZAPPER_UPGRADE_RECIPE);
}
@Override @Override
public void setIngredients(BlockzapperUpgradeRecipe recipe, IIngredients ingredients) { public void setIngredients(BlockzapperUpgradeRecipe recipe, IIngredients ingredients) {
ingredients.setInputIngredients(recipe.getIngredients()); ingredients.setInputIngredients(recipe.getIngredients());
@ -90,8 +61,6 @@ public class BlockzapperUpgradeCategory implements IRecipeCategory<BlockzapperUp
i++; i++;
} }
} }
// itemStacks.init(9, false, BLOCKZAPPER_UPGRADE_RECIPE.width / 2 - 9, BLOCKZAPPER_UPGRADE_RECIPE.height - 18 - 10);
// itemStacks.set(9, recipe.getRecipeOutput());
} }
@Override @Override
@ -110,11 +79,11 @@ public class BlockzapperUpgradeCategory implements IRecipeCategory<BlockzapperUp
@Override @Override
public void draw(BlockzapperUpgradeRecipe recipe, double mouseX, double mouseY) { public void draw(BlockzapperUpgradeRecipe recipe, double mouseX, double mouseY) {
FontRenderer font = Minecraft.getInstance().fontRenderer; FontRenderer font = Minecraft.getInstance().fontRenderer;
String componentName = Lang String componentName =
.translate("blockzapper.component." + Lang.asId(recipe.getUpgradedComponent().name())); Lang.translate("blockzapper.component." + Lang.asId(recipe.getUpgradedComponent().name()));
String text = "+ " + recipe.getTier().color + componentName; String text = "+ " + recipe.getTier().color + componentName;
font.drawStringWithShadow(text, font.drawStringWithShadow(text, (BLOCKZAPPER_UPGRADE_RECIPE.width - font.getStringWidth(text)) / 2, 57,
(BLOCKZAPPER_UPGRADE_RECIPE.width - font.getStringWidth(text)) / 2, 57, 0x8B8B8B); 0x8B8B8B);
RenderSystem.pushMatrix(); RenderSystem.pushMatrix();
RenderSystem.translated(126, 0, 0); RenderSystem.translated(126, 0, 0);

View file

@ -0,0 +1,106 @@
package com.simibubi.create.compat.jei.category;
import java.util.List;
import java.util.Map;
import com.simibubi.create.Create;
import com.simibubi.create.ScreenResources;
import com.simibubi.create.compat.jei.DoubleItemIcon;
import com.simibubi.create.compat.jei.EmptyBackground;
import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.modules.contraptions.processing.ProcessingOutput;
import com.simibubi.create.modules.contraptions.processing.ProcessingRecipe;
import mezz.jei.api.gui.drawable.IDrawable;
import mezz.jei.api.gui.ingredient.IGuiItemStackGroup;
import mezz.jei.api.recipe.category.IRecipeCategory;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.IRecipe;
import net.minecraft.util.IItemProvider;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.text.TextFormatting;
public abstract class CreateRecipeCategory<T extends IRecipe<?>> implements IRecipeCategory<T> {
private ResourceLocation uid;
private String name;
private IDrawable icon;
private IDrawable background;
public CreateRecipeCategory(String id, IDrawable icon, IDrawable background) {
uid = new ResourceLocation(Create.ID, id);
name = id;
this.background = background;
this.icon = icon;
}
@Override
public IDrawable getIcon() {
return icon;
}
@Override
public ResourceLocation getUid() {
return uid;
}
@Override
public String getTitle() {
return Lang.translate("recipe." + name);
}
@Override
public IDrawable getBackground() {
return background;
}
protected static ScreenResources getRenderedSlot(IRecipe<?> recipe, int index) {
ScreenResources jeiSlot = ScreenResources.JEI_SLOT;
if (!(recipe instanceof ProcessingRecipe))
return jeiSlot;
ProcessingRecipe<?> processingRecipe = (ProcessingRecipe<?>) recipe;
List<ProcessingOutput> rollableResults = processingRecipe.getRollableResults();
if (rollableResults.size() <= index)
return jeiSlot;
if (processingRecipe.getRollableResults().get(index).getChance() == 1)
return jeiSlot;
return ScreenResources.JEI_CHANCE_SLOT;
}
protected static IDrawable emptyBackground(int width, int height) {
return new EmptyBackground(width, height);
}
protected static IDrawable doubleItemIcon(IItemProvider item1, IItemProvider item2) {
return new DoubleItemIcon(() -> new ItemStack(item1), () -> new ItemStack(item2));
}
protected static IDrawable itemIcon(IItemProvider item) {
return new DoubleItemIcon(() -> new ItemStack(item), () -> ItemStack.EMPTY);
}
protected static void addStochasticTooltip(IGuiItemStackGroup itemStacks, List<ProcessingOutput> results) {
itemStacks.addTooltipCallback((slotIndex, input, ingredient, tooltip) -> {
if (input)
return;
ProcessingOutput output = results.get(slotIndex - 1);
if (output.getChance() != 1)
tooltip.add(1, TextFormatting.GOLD
+ Lang.translate("recipe.processing.chance", (int) (output.getChance() * 100)));
});
}
protected static void addCatalystTooltip(IGuiItemStackGroup itemStacks, Map<Integer, Float> catalystIndices) {
itemStacks.addTooltipCallback((slotIndex, input, ingredient, tooltip) -> {
if (!input)
return;
if (!catalystIndices.containsKey(slotIndex))
return;
Float chance = catalystIndices.get(slotIndex);
tooltip.add(1, TextFormatting.YELLOW + Lang.translate("recipe.processing.catalyst"));
tooltip.add(2, TextFormatting.GOLD
+ Lang.translate("recipe.processing.chanceToReturn", (int) (chance.floatValue() * 100)));
});
}
}

View file

@ -5,45 +5,23 @@ import java.util.List;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllItems; import com.simibubi.create.AllItems;
import com.simibubi.create.Create;
import com.simibubi.create.ScreenResources; import com.simibubi.create.ScreenResources;
import com.simibubi.create.compat.jei.CreateJEI;
import com.simibubi.create.compat.jei.DoubleItemIcon;
import com.simibubi.create.compat.jei.EmptyBackground;
import com.simibubi.create.compat.jei.category.animations.AnimatedCrushingWheels; import com.simibubi.create.compat.jei.category.animations.AnimatedCrushingWheels;
import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.modules.contraptions.components.crusher.AbstractCrushingRecipe; import com.simibubi.create.modules.contraptions.components.crusher.AbstractCrushingRecipe;
import com.simibubi.create.modules.contraptions.processing.ProcessingOutput; import com.simibubi.create.modules.contraptions.processing.ProcessingOutput;
import mezz.jei.api.constants.VanillaTypes; import mezz.jei.api.constants.VanillaTypes;
import mezz.jei.api.gui.IRecipeLayout; import mezz.jei.api.gui.IRecipeLayout;
import mezz.jei.api.gui.drawable.IDrawable;
import mezz.jei.api.gui.ingredient.IGuiItemStackGroup; import mezz.jei.api.gui.ingredient.IGuiItemStackGroup;
import mezz.jei.api.ingredients.IIngredients; import mezz.jei.api.ingredients.IIngredients;
import mezz.jei.api.recipe.category.IRecipeCategory;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ResourceLocation;
public class CrushingCategory implements IRecipeCategory<AbstractCrushingRecipe> { public class CrushingCategory extends CreateRecipeCategory<AbstractCrushingRecipe> {
private static ResourceLocation ID = new ResourceLocation(Create.ID, "crushing");
private AnimatedCrushingWheels crushingWheels = new AnimatedCrushingWheels(); private AnimatedCrushingWheels crushingWheels = new AnimatedCrushingWheels();
private IDrawable icon;
private IDrawable background = new EmptyBackground(177, 100);
public CrushingCategory() { public CrushingCategory() {
icon = new DoubleItemIcon(() -> new ItemStack(AllBlocks.CRUSHING_WHEEL.get()), super("crushing", doubleItemIcon(AllBlocks.CRUSHING_WHEEL.get(), AllItems.CRUSHED_GOLD.get()),
() -> new ItemStack(AllItems.CRUSHED_GOLD.get())); emptyBackground(177, 100));
}
@Override
public IDrawable getBackground() {
return background;
}
@Override
public ResourceLocation getUid() {
return ID;
} }
@Override @Override
@ -51,16 +29,6 @@ public class CrushingCategory implements IRecipeCategory<AbstractCrushingRecipe>
return AbstractCrushingRecipe.class; return AbstractCrushingRecipe.class;
} }
@Override
public String getTitle() {
return Lang.translate("recipe.crushing");
}
@Override
public IDrawable getIcon() {
return icon;
}
@Override @Override
public void setIngredients(AbstractCrushingRecipe recipe, IIngredients ingredients) { public void setIngredients(AbstractCrushingRecipe recipe, IIngredients ingredients) {
ingredients.setInputIngredients(recipe.getIngredients()); ingredients.setInputIngredients(recipe.getIngredients());
@ -81,7 +49,7 @@ public class CrushingCategory implements IRecipeCategory<AbstractCrushingRecipe>
itemStacks.set(outputIndex + 1, results.get(outputIndex).getStack()); itemStacks.set(outputIndex + 1, results.get(outputIndex).getStack());
} }
CreateJEI.addStochasticTooltip(itemStacks, results); addStochasticTooltip(itemStacks, results);
} }
@Override @Override
@ -93,7 +61,7 @@ public class CrushingCategory implements IRecipeCategory<AbstractCrushingRecipe>
int size = results.size(); int size = results.size();
int offset = -size * 19 / 2; int offset = -size * 19 / 2;
for (int outputIndex = 0; outputIndex < results.size(); outputIndex++) for (int outputIndex = 0; outputIndex < results.size(); outputIndex++)
ScreenResources.JEI_SLOT.draw(getBackground().getWidth() / 2 + offset + 19 * outputIndex, 78); getRenderedSlot(recipe, outputIndex).draw(getBackground().getWidth() / 2 + offset + 19 * outputIndex, 78);
crushingWheels.draw(92, 49); crushingWheels.draw(92, 49);
} }

View file

@ -3,65 +3,39 @@ package com.simibubi.create.compat.jei.category;
import java.util.Arrays; import java.util.Arrays;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.Create;
import com.simibubi.create.ScreenResources; import com.simibubi.create.ScreenResources;
import com.simibubi.create.compat.jei.DoubleItemIcon;
import com.simibubi.create.compat.jei.EmptyBackground;
import com.simibubi.create.compat.jei.category.animations.AnimatedCrafter; import com.simibubi.create.compat.jei.category.animations.AnimatedCrafter;
import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.Lang;
import mezz.jei.api.constants.VanillaTypes; import mezz.jei.api.constants.VanillaTypes;
import mezz.jei.api.gui.IRecipeLayout; import mezz.jei.api.gui.IRecipeLayout;
import mezz.jei.api.gui.drawable.IDrawable;
import mezz.jei.api.gui.ingredient.IGuiItemStackGroup; import mezz.jei.api.gui.ingredient.IGuiItemStackGroup;
import mezz.jei.api.ingredients.IIngredients; import mezz.jei.api.ingredients.IIngredients;
import mezz.jei.api.recipe.category.IRecipeCategory;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.Ingredient; import net.minecraft.item.crafting.Ingredient;
import net.minecraft.item.crafting.ShapedRecipe; import net.minecraft.item.crafting.ShapedRecipe;
import net.minecraft.util.NonNullList; import net.minecraft.util.NonNullList;
import net.minecraft.util.ResourceLocation;
public class MechanicalCraftingCategory implements IRecipeCategory<ShapedRecipe> { public class MechanicalCraftingCategory extends CreateRecipeCategory<ShapedRecipe> {
private AnimatedCrafter crafter; private AnimatedCrafter crafter;
private ResourceLocation id;
private IDrawable icon;
private IDrawable background;
private boolean large; private boolean large;
public MechanicalCraftingCategory(boolean large) { public MechanicalCraftingCategory(boolean large) {
super("mechanical_crafting" + (large ? "_large" : ""), itemIcon(AllBlocks.MECHANICAL_CRAFTER.get()),
emptyBackground(large ? 177 : 177, large ? 235 : 81));
this.large = large; this.large = large;
icon = new DoubleItemIcon(() -> new ItemStack(AllBlocks.MECHANICAL_CRAFTER.get()), () -> ItemStack.EMPTY);
crafter = new AnimatedCrafter(large); crafter = new AnimatedCrafter(large);
id = new ResourceLocation(Create.ID, "mechanical_crafting" + (large ? "_large" : ""));
background = new EmptyBackground(large ? 177 : 177, large ? 235 : 81);
} }
public static boolean isSmall(ShapedRecipe recipe) { public static boolean isSmall(ShapedRecipe recipe) {
return Math.max((recipe).getWidth(), (recipe).getHeight()) <= 4; return Math.max((recipe).getWidth(), (recipe).getHeight()) <= 4;
} }
@Override
public IDrawable getIcon() {
return icon;
}
@Override
public ResourceLocation getUid() {
return id;
}
@Override @Override
public String getTitle() { public String getTitle() {
return Lang.translate("recipe.mechanical_crafting"); return Lang.translate("recipe.mechanical_crafting");
} }
@Override
public IDrawable getBackground() {
return background;
}
@Override @Override
public void setIngredients(ShapedRecipe recipe, IIngredients ingredients) { public void setIngredients(ShapedRecipe recipe, IIngredients ingredients) {
ingredients.setInputIngredients(recipe.getIngredients()); ingredients.setInputIngredients(recipe.getIngredients());

View file

@ -5,45 +5,22 @@ import java.util.List;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllItems; import com.simibubi.create.AllItems;
import com.simibubi.create.Create;
import com.simibubi.create.ScreenResources; import com.simibubi.create.ScreenResources;
import com.simibubi.create.compat.jei.CreateJEI;
import com.simibubi.create.compat.jei.DoubleItemIcon;
import com.simibubi.create.compat.jei.EmptyBackground;
import com.simibubi.create.compat.jei.category.animations.AnimatedMillstone; import com.simibubi.create.compat.jei.category.animations.AnimatedMillstone;
import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.modules.contraptions.components.crusher.AbstractCrushingRecipe; import com.simibubi.create.modules.contraptions.components.crusher.AbstractCrushingRecipe;
import com.simibubi.create.modules.contraptions.processing.ProcessingOutput; import com.simibubi.create.modules.contraptions.processing.ProcessingOutput;
import mezz.jei.api.constants.VanillaTypes; import mezz.jei.api.constants.VanillaTypes;
import mezz.jei.api.gui.IRecipeLayout; import mezz.jei.api.gui.IRecipeLayout;
import mezz.jei.api.gui.drawable.IDrawable;
import mezz.jei.api.gui.ingredient.IGuiItemStackGroup; import mezz.jei.api.gui.ingredient.IGuiItemStackGroup;
import mezz.jei.api.ingredients.IIngredients; import mezz.jei.api.ingredients.IIngredients;
import mezz.jei.api.recipe.category.IRecipeCategory;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ResourceLocation;
public class MillingCategory implements IRecipeCategory<AbstractCrushingRecipe> { public class MillingCategory extends CreateRecipeCategory<AbstractCrushingRecipe> {
private static ResourceLocation ID = new ResourceLocation(Create.ID, "milling");
private AnimatedMillstone millstone = new AnimatedMillstone(); private AnimatedMillstone millstone = new AnimatedMillstone();
private IDrawable icon;
private IDrawable background = new EmptyBackground(177, 53);
public MillingCategory() { public MillingCategory() {
icon = new DoubleItemIcon(() -> new ItemStack(AllBlocks.MILLSTONE.get()), super("milling", doubleItemIcon(AllBlocks.MILLSTONE.get(), AllItems.FLOUR.get()), emptyBackground(177, 53));
() -> new ItemStack(AllItems.FLOUR.get()));
}
@Override
public IDrawable getBackground() {
return background;
}
@Override
public ResourceLocation getUid() {
return ID;
} }
@Override @Override
@ -51,16 +28,6 @@ public class MillingCategory implements IRecipeCategory<AbstractCrushingRecipe>
return AbstractCrushingRecipe.class; return AbstractCrushingRecipe.class;
} }
@Override
public String getTitle() {
return Lang.translate("recipe.milling");
}
@Override
public IDrawable getIcon() {
return icon;
}
@Override @Override
public void setIngredients(AbstractCrushingRecipe recipe, IIngredients ingredients) { public void setIngredients(AbstractCrushingRecipe recipe, IIngredients ingredients) {
ingredients.setInputIngredients(recipe.getIngredients()); ingredients.setInputIngredients(recipe.getIngredients());
@ -83,7 +50,7 @@ public class MillingCategory implements IRecipeCategory<AbstractCrushingRecipe>
itemStacks.set(outputIndex + 1, results.get(outputIndex).getStack()); itemStacks.set(outputIndex + 1, results.get(outputIndex).getStack());
} }
CreateJEI.addStochasticTooltip(itemStacks, results); addStochasticTooltip(itemStacks, results);
} }
@Override @Override
@ -95,17 +62,19 @@ public class MillingCategory implements IRecipeCategory<AbstractCrushingRecipe>
ScreenResources.JEI_ARROW.draw(85, 32); ScreenResources.JEI_ARROW.draw(85, 32);
ScreenResources.JEI_DOWN_ARROW.draw(43, 4); ScreenResources.JEI_DOWN_ARROW.draw(43, 4);
if (size > 1) { millstone.draw(57, 27);
for (int i = 0; i < size; i++) {
int xOffset = i % 2 == 0 ? 0 : 19; if (size == 1) {
int yOffset = (i / 2) * -19; getRenderedSlot(recipe, 0).draw(139, 27);
ScreenResources.JEI_SLOT.draw(133 + xOffset, 27 + yOffset); return;
} }
} else {
ScreenResources.JEI_SLOT.draw(139, 27); for (int i = 0; i < size; i++) {
int xOffset = i % 2 == 0 ? 0 : 19;
int yOffset = (i / 2) * -19;
getRenderedSlot(recipe, i).draw(133 + xOffset, 27 + yOffset);
} }
millstone.draw(57, 27);
} }
} }

View file

@ -10,59 +10,32 @@ import org.apache.commons.lang3.mutable.MutableInt;
import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.tuple.Pair;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.Create;
import com.simibubi.create.ScreenResources; import com.simibubi.create.ScreenResources;
import com.simibubi.create.compat.jei.CreateJEI;
import com.simibubi.create.compat.jei.DoubleItemIcon;
import com.simibubi.create.compat.jei.EmptyBackground;
import com.simibubi.create.compat.jei.category.animations.AnimatedMixer; import com.simibubi.create.compat.jei.category.animations.AnimatedMixer;
import com.simibubi.create.foundation.item.ItemHelper; import com.simibubi.create.foundation.item.ItemHelper;
import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.modules.contraptions.components.mixer.MixingRecipe; import com.simibubi.create.modules.contraptions.components.mixer.MixingRecipe;
import com.simibubi.create.modules.contraptions.processing.ProcessingIngredient; import com.simibubi.create.modules.contraptions.processing.ProcessingIngredient;
import mezz.jei.api.constants.VanillaTypes; import mezz.jei.api.constants.VanillaTypes;
import mezz.jei.api.gui.IRecipeLayout; import mezz.jei.api.gui.IRecipeLayout;
import mezz.jei.api.gui.drawable.IDrawable;
import mezz.jei.api.gui.ingredient.IGuiItemStackGroup; import mezz.jei.api.gui.ingredient.IGuiItemStackGroup;
import mezz.jei.api.ingredients.IIngredients; import mezz.jei.api.ingredients.IIngredients;
import mezz.jei.api.recipe.category.IRecipeCategory;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.Ingredient; import net.minecraft.item.crafting.Ingredient;
import net.minecraft.util.NonNullList; import net.minecraft.util.NonNullList;
import net.minecraft.util.ResourceLocation;
public class MixingCategory implements IRecipeCategory<MixingRecipe> { public class MixingCategory extends CreateRecipeCategory<MixingRecipe> {
private AnimatedMixer mixer; private AnimatedMixer mixer = new AnimatedMixer();
private static ResourceLocation ID = new ResourceLocation(Create.ID, "mixing");
private IDrawable icon;
private IDrawable background = new EmptyBackground(177, 70);
public MixingCategory() { public MixingCategory() {
icon = new DoubleItemIcon(() -> new ItemStack(AllBlocks.MECHANICAL_MIXER.get()), super("mixing", doubleItemIcon(AllBlocks.MECHANICAL_MIXER.get(), AllBlocks.BASIN.get()),
() -> new ItemStack(AllBlocks.BASIN.get())); emptyBackground(177, 70));
mixer = new AnimatedMixer();
} }
@Override @Override
public IDrawable getIcon() { public Class<? extends MixingRecipe> getRecipeClass() {
return icon; return MixingRecipe.class;
}
@Override
public ResourceLocation getUid() {
return ID;
}
@Override
public String getTitle() {
return Lang.translate("recipe.mixing");
}
@Override
public IDrawable getBackground() {
return background;
} }
@Override @Override
@ -77,7 +50,7 @@ public class MixingCategory implements IRecipeCategory<MixingRecipe> {
NonNullList<Ingredient> recipeIngredients = recipe.getIngredients(); NonNullList<Ingredient> recipeIngredients = recipe.getIngredients();
List<Pair<Ingredient, MutableInt>> actualIngredients = ItemHelper.condenseIngredients(recipeIngredients); List<Pair<Ingredient, MutableInt>> actualIngredients = ItemHelper.condenseIngredients(recipeIngredients);
Map<Integer, Float> catalystIndices = new HashMap<>(9); Map<Integer, Float> catalystIndices = new HashMap<>(9);
for (int i = 0; i < actualIngredients.size(); i++) { for (int i = 0; i < actualIngredients.size(); i++) {
for (ProcessingIngredient processingIngredient : recipe.getRollableIngredients()) { for (ProcessingIngredient processingIngredient : recipe.getRollableIngredients()) {
@ -107,13 +80,11 @@ public class MixingCategory implements IRecipeCategory<MixingRecipe> {
itemStacks.init(i, false, 141, 50); itemStacks.init(i, false, 141, 50);
itemStacks.set(i, recipe.getRecipeOutput().getStack()); itemStacks.set(i, recipe.getRecipeOutput().getStack());
CreateJEI.addCatalystTooltip(itemStacks, catalystIndices); addCatalystTooltip(itemStacks, catalystIndices);
} }
@Override @Override
public void draw(MixingRecipe recipe, double mouseX, double mouseY) { public void draw(MixingRecipe recipe, double mouseX, double mouseY) {
// this might actually be pretty bad with big ingredients. ^ its a draw method
List<Pair<Ingredient, MutableInt>> actualIngredients = ItemHelper.condenseIngredients(recipe.getIngredients()); List<Pair<Ingredient, MutableInt>> actualIngredients = ItemHelper.condenseIngredients(recipe.getIngredients());
int size = actualIngredients.size(); int size = actualIngredients.size();
@ -135,9 +106,4 @@ public class MixingCategory implements IRecipeCategory<MixingRecipe> {
mixer.draw(getBackground().getWidth() / 2 + 20, 8); mixer.draw(getBackground().getWidth() / 2 + 20, 8);
} }
@Override
public Class<? extends MixingRecipe> getRecipeClass() {
return MixingRecipe.class;
}
} }

View file

@ -5,29 +5,16 @@ import java.util.Arrays;
import java.util.List; import java.util.List;
import com.simibubi.create.AllItems; import com.simibubi.create.AllItems;
import com.simibubi.create.Create;
import com.simibubi.create.ScreenResources; import com.simibubi.create.ScreenResources;
import com.simibubi.create.compat.jei.ConversionRecipe; import com.simibubi.create.compat.jei.ConversionRecipe;
import com.simibubi.create.compat.jei.CreateJEI;
import com.simibubi.create.compat.jei.DoubleItemIcon;
import com.simibubi.create.compat.jei.EmptyBackground;
import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.modules.contraptions.processing.ProcessingOutput; import com.simibubi.create.modules.contraptions.processing.ProcessingOutput;
import mezz.jei.api.constants.VanillaTypes; import mezz.jei.api.constants.VanillaTypes;
import mezz.jei.api.gui.IRecipeLayout; import mezz.jei.api.gui.IRecipeLayout;
import mezz.jei.api.gui.drawable.IDrawable;
import mezz.jei.api.gui.ingredient.IGuiItemStackGroup; import mezz.jei.api.gui.ingredient.IGuiItemStackGroup;
import mezz.jei.api.ingredients.IIngredients; import mezz.jei.api.ingredients.IIngredients;
import mezz.jei.api.recipe.category.IRecipeCategory;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ResourceLocation;
public class MysteriousItemConversionCategory implements IRecipeCategory<ConversionRecipe> { public class MysteriousItemConversionCategory extends CreateRecipeCategory<ConversionRecipe> {
private static ResourceLocation ID = new ResourceLocation(Create.ID, "mystery_conversion");
private IDrawable icon;
private IDrawable background = new EmptyBackground(177, 50);
public static List<ConversionRecipe> getRecipes() { public static List<ConversionRecipe> getRecipes() {
List<ConversionRecipe> recipes = new ArrayList<>(); List<ConversionRecipe> recipes = new ArrayList<>();
@ -37,17 +24,7 @@ public class MysteriousItemConversionCategory implements IRecipeCategory<Convers
} }
public MysteriousItemConversionCategory() { public MysteriousItemConversionCategory() {
icon = new DoubleItemIcon(() -> AllItems.CHROMATIC_COMPOUND.asStack(), () -> ItemStack.EMPTY); super("mystery_conversion", itemIcon(AllItems.CHROMATIC_COMPOUND.get()), emptyBackground(177, 50));
}
@Override
public IDrawable getIcon() {
return icon;
}
@Override
public ResourceLocation getUid() {
return ID;
} }
@Override @Override
@ -55,16 +32,6 @@ public class MysteriousItemConversionCategory implements IRecipeCategory<Convers
return ConversionRecipe.class; return ConversionRecipe.class;
} }
@Override
public String getTitle() {
return Lang.translate("recipe.mystery_conversion");
}
@Override
public IDrawable getBackground() {
return background;
}
@Override @Override
public void setIngredients(ConversionRecipe recipe, IIngredients ingredients) { public void setIngredients(ConversionRecipe recipe, IIngredients ingredients) {
ingredients.setInputIngredients(recipe.getIngredients()); ingredients.setInputIngredients(recipe.getIngredients());
@ -75,13 +42,10 @@ public class MysteriousItemConversionCategory implements IRecipeCategory<Convers
public void setRecipe(IRecipeLayout recipeLayout, ConversionRecipe recipe, IIngredients ingredients) { public void setRecipe(IRecipeLayout recipeLayout, ConversionRecipe recipe, IIngredients ingredients) {
IGuiItemStackGroup itemStacks = recipeLayout.getItemStacks(); IGuiItemStackGroup itemStacks = recipeLayout.getItemStacks();
List<ProcessingOutput> results = recipe.getRollableResults(); List<ProcessingOutput> results = recipe.getRollableResults();
itemStacks.init(0, true, 26, 16); itemStacks.init(0, true, 26, 16);
itemStacks.set(0, Arrays.asList(recipe.getIngredients().get(0).getMatchingStacks())); itemStacks.set(0, Arrays.asList(recipe.getIngredients().get(0).getMatchingStacks()));
itemStacks.init(1, false, 131, 16); itemStacks.init(1, false, 131, 16);
itemStacks.set(1, results.get(0).getStack()); itemStacks.set(1, results.get(0).getStack());
CreateJEI.addStochasticTooltip(itemStacks, results);
} }
@Override @Override

View file

@ -3,47 +3,25 @@ package com.simibubi.create.compat.jei.category;
import java.util.Arrays; import java.util.Arrays;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.Create;
import com.simibubi.create.ScreenResources; import com.simibubi.create.ScreenResources;
import com.simibubi.create.compat.jei.DoubleItemIcon;
import com.simibubi.create.compat.jei.EmptyBackground;
import com.simibubi.create.compat.jei.category.animations.AnimatedPress; import com.simibubi.create.compat.jei.category.animations.AnimatedPress;
import com.simibubi.create.foundation.utility.Lang;
import mezz.jei.api.constants.VanillaTypes; import mezz.jei.api.constants.VanillaTypes;
import mezz.jei.api.gui.IRecipeLayout; import mezz.jei.api.gui.IRecipeLayout;
import mezz.jei.api.gui.drawable.IDrawable;
import mezz.jei.api.gui.ingredient.IGuiItemStackGroup; import mezz.jei.api.gui.ingredient.IGuiItemStackGroup;
import mezz.jei.api.ingredients.IIngredients; import mezz.jei.api.ingredients.IIngredients;
import mezz.jei.api.recipe.category.IRecipeCategory;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.ICraftingRecipe; import net.minecraft.item.crafting.ICraftingRecipe;
import net.minecraft.item.crafting.IRecipe; import net.minecraft.item.crafting.IRecipe;
import net.minecraft.item.crafting.Ingredient; import net.minecraft.item.crafting.Ingredient;
import net.minecraft.util.NonNullList; import net.minecraft.util.NonNullList;
import net.minecraft.util.ResourceLocation;
public class PackingCategory implements IRecipeCategory<IRecipe<?>> { public class PackingCategory extends CreateRecipeCategory<IRecipe<?>> {
private AnimatedPress press; private AnimatedPress press = new AnimatedPress(true);
private static ResourceLocation ID = new ResourceLocation(Create.ID, "packing");
private IDrawable icon;
private IDrawable background = new EmptyBackground(177, 70);
public PackingCategory() { public PackingCategory() {
icon = new DoubleItemIcon(() -> new ItemStack(AllBlocks.MECHANICAL_PRESS.get()), super("packing", doubleItemIcon(AllBlocks.MECHANICAL_PRESS.get(), AllBlocks.BASIN.get()),
() -> new ItemStack(AllBlocks.BASIN.get())); emptyBackground(177, 70));
press = new AnimatedPress(true);
}
@Override
public IDrawable getIcon() {
return icon;
}
@Override
public ResourceLocation getUid() {
return ID;
} }
@Override @Override
@ -51,16 +29,6 @@ public class PackingCategory implements IRecipeCategory<IRecipe<?>> {
return ICraftingRecipe.class; return ICraftingRecipe.class;
} }
@Override
public String getTitle() {
return Lang.translate("recipe.packing");
}
@Override
public IDrawable getBackground() {
return background;
}
@Override @Override
public void setIngredients(IRecipe<?> recipe, IIngredients ingredients) { public void setIngredients(IRecipe<?> recipe, IIngredients ingredients) {
ingredients.setInputIngredients(recipe.getIngredients()); ingredients.setInputIngredients(recipe.getIngredients());

View file

@ -5,66 +5,35 @@ import java.util.List;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.RenderSystem;
import com.simibubi.create.AllItems; import com.simibubi.create.AllItems;
import com.simibubi.create.Create;
import com.simibubi.create.ScreenResources; import com.simibubi.create.ScreenResources;
import com.simibubi.create.compat.jei.CreateJEI;
import com.simibubi.create.compat.jei.DoubleItemIcon;
import com.simibubi.create.compat.jei.EmptyBackground;
import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.modules.contraptions.processing.ProcessingOutput; import com.simibubi.create.modules.contraptions.processing.ProcessingOutput;
import com.simibubi.create.modules.curiosities.tools.SandPaperPolishingRecipe; import com.simibubi.create.modules.curiosities.tools.SandPaperPolishingRecipe;
import mezz.jei.api.constants.VanillaTypes; import mezz.jei.api.constants.VanillaTypes;
import mezz.jei.api.gui.IRecipeLayout; import mezz.jei.api.gui.IRecipeLayout;
import mezz.jei.api.gui.drawable.IDrawable;
import mezz.jei.api.gui.ingredient.IGuiItemStackGroup; import mezz.jei.api.gui.ingredient.IGuiItemStackGroup;
import mezz.jei.api.ingredients.IIngredients; import mezz.jei.api.ingredients.IIngredients;
import mezz.jei.api.recipe.category.IRecipeCategory;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.ItemRenderer; import net.minecraft.client.renderer.ItemRenderer;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.Ingredient; import net.minecraft.item.crafting.Ingredient;
import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.CompoundNBT;
import net.minecraft.util.NonNullList; import net.minecraft.util.NonNullList;
import net.minecraft.util.ResourceLocation;
public class PolishingCategory implements IRecipeCategory<SandPaperPolishingRecipe> { public class PolishingCategory extends CreateRecipeCategory<SandPaperPolishingRecipe> {
private static ResourceLocation ID = new ResourceLocation(Create.ID, "sandpaper_polishing");
private IDrawable icon;
private IDrawable background = new EmptyBackground(177, 55);
private ItemStack renderedSandpaper; private ItemStack renderedSandpaper;
public PolishingCategory() { public PolishingCategory() {
icon = new DoubleItemIcon(() -> AllItems.SAND_PAPER.asStack(), () -> ItemStack.EMPTY); super("sandpaper_polishing", itemIcon(AllItems.SAND_PAPER.get()), emptyBackground(177, 55));
renderedSandpaper = AllItems.SAND_PAPER.asStack(); renderedSandpaper = AllItems.SAND_PAPER.asStack();
} }
@Override
public IDrawable getIcon() {
return icon;
}
@Override
public ResourceLocation getUid() {
return ID;
}
@Override @Override
public Class<? extends SandPaperPolishingRecipe> getRecipeClass() { public Class<? extends SandPaperPolishingRecipe> getRecipeClass() {
return SandPaperPolishingRecipe.class; return SandPaperPolishingRecipe.class;
} }
@Override
public String getTitle() {
return Lang.translate("recipe.sandpaper_polishing");
}
@Override
public IDrawable getBackground() {
return background;
}
@Override @Override
public void setIngredients(SandPaperPolishingRecipe recipe, IIngredients ingredients) { public void setIngredients(SandPaperPolishingRecipe recipe, IIngredients ingredients) {
ingredients.setInputIngredients(recipe.getIngredients()); ingredients.setInputIngredients(recipe.getIngredients());
@ -81,13 +50,13 @@ public class PolishingCategory implements IRecipeCategory<SandPaperPolishingReci
itemStacks.init(1, false, 131, 28); itemStacks.init(1, false, 131, 28);
itemStacks.set(1, results.get(0).getStack()); itemStacks.set(1, results.get(0).getStack());
CreateJEI.addStochasticTooltip(itemStacks, results); addStochasticTooltip(itemStacks, results);
} }
@Override @Override
public void draw(SandPaperPolishingRecipe recipe, double mouseX, double mouseY) { public void draw(SandPaperPolishingRecipe recipe, double mouseX, double mouseY) {
ScreenResources.JEI_SLOT.draw(26, 28); ScreenResources.JEI_SLOT.draw(26, 28);
ScreenResources.JEI_SLOT.draw(131, 28); getRenderedSlot(recipe, 0).draw(131, 28);
ScreenResources.JEI_SHADOW.draw(61, 21); ScreenResources.JEI_SHADOW.draw(61, 21);
ScreenResources.JEI_LONG_ARROW.draw(52, 32); ScreenResources.JEI_LONG_ARROW.draw(52, 32);

View file

@ -5,46 +5,23 @@ import java.util.List;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllItems; import com.simibubi.create.AllItems;
import com.simibubi.create.Create;
import com.simibubi.create.ScreenResources; import com.simibubi.create.ScreenResources;
import com.simibubi.create.compat.jei.CreateJEI;
import com.simibubi.create.compat.jei.DoubleItemIcon;
import com.simibubi.create.compat.jei.EmptyBackground;
import com.simibubi.create.compat.jei.category.animations.AnimatedPress; import com.simibubi.create.compat.jei.category.animations.AnimatedPress;
import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.modules.contraptions.components.press.PressingRecipe; import com.simibubi.create.modules.contraptions.components.press.PressingRecipe;
import com.simibubi.create.modules.contraptions.processing.ProcessingOutput; import com.simibubi.create.modules.contraptions.processing.ProcessingOutput;
import mezz.jei.api.constants.VanillaTypes; import mezz.jei.api.constants.VanillaTypes;
import mezz.jei.api.gui.IRecipeLayout; import mezz.jei.api.gui.IRecipeLayout;
import mezz.jei.api.gui.drawable.IDrawable;
import mezz.jei.api.gui.ingredient.IGuiItemStackGroup; import mezz.jei.api.gui.ingredient.IGuiItemStackGroup;
import mezz.jei.api.ingredients.IIngredients; import mezz.jei.api.ingredients.IIngredients;
import mezz.jei.api.recipe.category.IRecipeCategory;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ResourceLocation;
public class PressingCategory implements IRecipeCategory<PressingRecipe> { public class PressingCategory extends CreateRecipeCategory<PressingRecipe> {
private AnimatedPress press; private AnimatedPress press = new AnimatedPress(false);
private static ResourceLocation ID = new ResourceLocation(Create.ID, "pressing");
private IDrawable icon;
private IDrawable background = new EmptyBackground(177, 70);
public PressingCategory() { public PressingCategory() {
icon = new DoubleItemIcon(() -> new ItemStack(AllBlocks.MECHANICAL_PRESS.get()), super("pressing", doubleItemIcon(AllBlocks.MECHANICAL_PRESS.get(), AllItems.IRON_SHEET.get()),
() -> new ItemStack(AllItems.IRON_SHEET.get())); emptyBackground(177, 70));
press = new AnimatedPress(false);
}
@Override
public IDrawable getIcon() {
return icon;
}
@Override
public ResourceLocation getUid() {
return ID;
} }
@Override @Override
@ -52,16 +29,6 @@ public class PressingCategory implements IRecipeCategory<PressingRecipe> {
return PressingRecipe.class; return PressingRecipe.class;
} }
@Override
public String getTitle() {
return Lang.translate("recipe.pressing");
}
@Override
public IDrawable getBackground() {
return background;
}
@Override @Override
public void setIngredients(PressingRecipe recipe, IIngredients ingredients) { public void setIngredients(PressingRecipe recipe, IIngredients ingredients) {
ingredients.setInputIngredients(recipe.getIngredients()); ingredients.setInputIngredients(recipe.getIngredients());
@ -79,16 +46,16 @@ public class PressingCategory implements IRecipeCategory<PressingRecipe> {
itemStacks.init(outputIndex + 1, false, 131 + 19 * outputIndex, 50); itemStacks.init(outputIndex + 1, false, 131 + 19 * outputIndex, 50);
itemStacks.set(outputIndex + 1, results.get(outputIndex).getStack()); itemStacks.set(outputIndex + 1, results.get(outputIndex).getStack());
} }
CreateJEI.addStochasticTooltip(itemStacks, results); addStochasticTooltip(itemStacks, results);
} }
@Override @Override
public void draw(PressingRecipe recipe, double mouseX, double mouseY) { public void draw(PressingRecipe recipe, double mouseX, double mouseY) {
ScreenResources.JEI_SLOT.draw(26, 50); ScreenResources.JEI_SLOT.draw(26, 50);
ScreenResources.JEI_SLOT.draw(131, 50); getRenderedSlot(recipe, 0).draw(131, 50);
if (recipe.getRollableResults().size() > 1) if (recipe.getRollableResults().size() > 1)
ScreenResources.JEI_SLOT.draw(131 + 19, 50); getRenderedSlot(recipe, 1).draw(131 + 19, 50);
ScreenResources.JEI_SHADOW.draw(61, 41); ScreenResources.JEI_SHADOW.draw(61, 41);
ScreenResources.JEI_LONG_ARROW.draw(52, 54); ScreenResources.JEI_LONG_ARROW.draw(52, 54);
press.draw(getBackground().getWidth() / 2, 8); press.draw(getBackground().getWidth() / 2, 8);

View file

@ -6,7 +6,6 @@ import com.mojang.blaze3d.systems.RenderSystem;
import com.simibubi.create.AllBlockPartials; import com.simibubi.create.AllBlockPartials;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.ScreenResources; import com.simibubi.create.ScreenResources;
import com.simibubi.create.compat.jei.EmptyBackground;
import com.simibubi.create.compat.jei.category.animations.AnimatedKinetics; import com.simibubi.create.compat.jei.category.animations.AnimatedKinetics;
import com.simibubi.create.foundation.gui.ScreenElementRenderer; import com.simibubi.create.foundation.gui.ScreenElementRenderer;
@ -15,22 +14,18 @@ import mezz.jei.api.gui.IRecipeLayout;
import mezz.jei.api.gui.drawable.IDrawable; import mezz.jei.api.gui.drawable.IDrawable;
import mezz.jei.api.gui.ingredient.IGuiItemStackGroup; import mezz.jei.api.gui.ingredient.IGuiItemStackGroup;
import mezz.jei.api.ingredients.IIngredients; import mezz.jei.api.ingredients.IIngredients;
import mezz.jei.api.recipe.category.IRecipeCategory;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.client.renderer.model.IBakedModel; import net.minecraft.client.renderer.model.IBakedModel;
import net.minecraft.item.crafting.IRecipe; import net.minecraft.item.crafting.IRecipe;
import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
public abstract class ProcessingViaFanCategory<T extends IRecipe<?>> implements IRecipeCategory<T> { public abstract class ProcessingViaFanCategory<T extends IRecipe<?>> extends CreateRecipeCategory<T> {
private IDrawable background = new EmptyBackground(177, 70); public ProcessingViaFanCategory(String name, IDrawable icon) {
super(name, icon, emptyBackground(177, 70));
@Override
public IDrawable getBackground() {
return background;
} }
@Override @Override
public void setIngredients(T recipe, IIngredients ingredients) { public void setIngredients(T recipe, IIngredients ingredients) {
ingredients.setInputIngredients(recipe.getIngredients()); ingredients.setInputIngredients(recipe.getIngredients());

View file

@ -4,46 +4,23 @@ import java.util.Arrays;
import java.util.List; import java.util.List;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.Create;
import com.simibubi.create.ScreenResources; import com.simibubi.create.ScreenResources;
import com.simibubi.create.compat.jei.CreateJEI;
import com.simibubi.create.compat.jei.DoubleItemIcon;
import com.simibubi.create.compat.jei.EmptyBackground;
import com.simibubi.create.compat.jei.category.animations.AnimatedSaw; import com.simibubi.create.compat.jei.category.animations.AnimatedSaw;
import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.modules.contraptions.components.saw.CuttingRecipe; import com.simibubi.create.modules.contraptions.components.saw.CuttingRecipe;
import com.simibubi.create.modules.contraptions.processing.ProcessingOutput; import com.simibubi.create.modules.contraptions.processing.ProcessingOutput;
import mezz.jei.api.constants.VanillaTypes; import mezz.jei.api.constants.VanillaTypes;
import mezz.jei.api.gui.IRecipeLayout; import mezz.jei.api.gui.IRecipeLayout;
import mezz.jei.api.gui.drawable.IDrawable;
import mezz.jei.api.gui.ingredient.IGuiItemStackGroup; import mezz.jei.api.gui.ingredient.IGuiItemStackGroup;
import mezz.jei.api.ingredients.IIngredients; import mezz.jei.api.ingredients.IIngredients;
import mezz.jei.api.recipe.category.IRecipeCategory;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items; import net.minecraft.item.Items;
import net.minecraft.util.ResourceLocation;
public class SawingCategory implements IRecipeCategory<CuttingRecipe> { public class SawingCategory extends CreateRecipeCategory<CuttingRecipe> {
private AnimatedSaw saw; private AnimatedSaw saw = new AnimatedSaw();
private static ResourceLocation ID = new ResourceLocation(Create.ID, "sawing");
private IDrawable icon;
private IDrawable background = new EmptyBackground(177, 70);
public SawingCategory() { public SawingCategory() {
icon = new DoubleItemIcon(() -> new ItemStack(AllBlocks.SAW.get()), () -> new ItemStack(Items.OAK_LOG)); super("sawing", doubleItemIcon(AllBlocks.SAW.get(), Items.OAK_LOG), emptyBackground(177, 70));
saw = new AnimatedSaw();
}
@Override
public IDrawable getIcon() {
return icon;
}
@Override
public ResourceLocation getUid() {
return ID;
} }
@Override @Override
@ -51,16 +28,6 @@ public class SawingCategory implements IRecipeCategory<CuttingRecipe> {
return CuttingRecipe.class; return CuttingRecipe.class;
} }
@Override
public String getTitle() {
return Lang.translate("recipe.sawing");
}
@Override
public IDrawable getBackground() {
return background;
}
@Override @Override
public void setIngredients(CuttingRecipe recipe, IIngredients ingredients) { public void setIngredients(CuttingRecipe recipe, IIngredients ingredients) {
ingredients.setInputIngredients(recipe.getIngredients()); ingredients.setInputIngredients(recipe.getIngredients());
@ -81,8 +48,8 @@ public class SawingCategory implements IRecipeCategory<CuttingRecipe> {
itemStacks.init(outputIndex + 1, false, 117 + xOffset, 47 + yOffset); itemStacks.init(outputIndex + 1, false, 117 + xOffset, 47 + yOffset);
itemStacks.set(outputIndex + 1, results.get(outputIndex).getStack()); itemStacks.set(outputIndex + 1, results.get(outputIndex).getStack());
} }
CreateJEI.addStochasticTooltip(itemStacks, results); addStochasticTooltip(itemStacks, results);
} }
@Override @Override
@ -92,7 +59,7 @@ public class SawingCategory implements IRecipeCategory<CuttingRecipe> {
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
int xOffset = i % 2 == 0 ? 0 : 19; int xOffset = i % 2 == 0 ? 0 : 19;
int yOffset = (i / 2) * -19; int yOffset = (i / 2) * -19;
ScreenResources.JEI_SLOT.draw(117 + xOffset, 47 + yOffset); getRenderedSlot(recipe, i).draw(117 + xOffset, 47 + yOffset);
} }
ScreenResources.JEI_DOWN_ARROW.draw(70, 6); ScreenResources.JEI_DOWN_ARROW.draw(70, 6);
ScreenResources.JEI_SHADOW.draw(58, 55); ScreenResources.JEI_SHADOW.draw(58, 55);

View file

@ -1,36 +1,16 @@
package com.simibubi.create.compat.jei.category; package com.simibubi.create.compat.jei.category;
import com.simibubi.create.AllItems; import com.simibubi.create.AllItems;
import com.simibubi.create.Create;
import com.simibubi.create.compat.jei.DoubleItemIcon;
import com.simibubi.create.foundation.gui.ScreenElementRenderer; import com.simibubi.create.foundation.gui.ScreenElementRenderer;
import com.simibubi.create.foundation.utility.Lang;
import mezz.jei.api.gui.drawable.IDrawable;
import net.minecraft.block.Blocks; import net.minecraft.block.Blocks;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items; import net.minecraft.item.Items;
import net.minecraft.item.crafting.SmokingRecipe; import net.minecraft.item.crafting.SmokingRecipe;
import net.minecraft.util.ResourceLocation;
public class SmokingViaFanCategory extends ProcessingViaFanCategory<SmokingRecipe> { public class SmokingViaFanCategory extends ProcessingViaFanCategory<SmokingRecipe> {
private static ResourceLocation ID = new ResourceLocation(Create.ID, "smoking_via_fan");
private IDrawable icon;
public SmokingViaFanCategory() { public SmokingViaFanCategory() {
icon = new DoubleItemIcon(() -> new ItemStack(AllItems.PROPELLER.get()), super("smoking_via_fan", doubleItemIcon(AllItems.PROPELLER.get(), Items.BLAZE_POWDER));
() -> new ItemStack(Items.BLAZE_POWDER));
}
@Override
public IDrawable getIcon() {
return icon;
}
@Override
public ResourceLocation getUid() {
return ID;
} }
@Override @Override
@ -38,11 +18,6 @@ public class SmokingViaFanCategory extends ProcessingViaFanCategory<SmokingRecip
return SmokingRecipe.class; return SmokingRecipe.class;
} }
@Override
public String getTitle() {
return Lang.translate("recipe.smokingViaFan");
}
@Override @Override
public void renderAttachedBlock() { public void renderAttachedBlock() {
ScreenElementRenderer.renderBlock(() -> Blocks.FIRE.getDefaultState()); ScreenElementRenderer.renderBlock(() -> Blocks.FIRE.getDefaultState());

View file

@ -5,52 +5,24 @@ import java.util.List;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.RenderSystem;
import com.simibubi.create.AllItems; import com.simibubi.create.AllItems;
import com.simibubi.create.Create;
import com.simibubi.create.ScreenResources; import com.simibubi.create.ScreenResources;
import com.simibubi.create.compat.jei.CreateJEI;
import com.simibubi.create.compat.jei.DoubleItemIcon;
import com.simibubi.create.compat.jei.EmptyBackground;
import com.simibubi.create.foundation.gui.ScreenElementRenderer; import com.simibubi.create.foundation.gui.ScreenElementRenderer;
import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.modules.contraptions.components.fan.SplashingRecipe; import com.simibubi.create.modules.contraptions.components.fan.SplashingRecipe;
import com.simibubi.create.modules.contraptions.processing.ProcessingOutput; import com.simibubi.create.modules.contraptions.processing.ProcessingOutput;
import mezz.jei.api.constants.VanillaTypes; import mezz.jei.api.constants.VanillaTypes;
import mezz.jei.api.gui.IRecipeLayout; import mezz.jei.api.gui.IRecipeLayout;
import mezz.jei.api.gui.drawable.IDrawable;
import mezz.jei.api.gui.ingredient.IGuiItemStackGroup; import mezz.jei.api.gui.ingredient.IGuiItemStackGroup;
import mezz.jei.api.ingredients.IIngredients; import mezz.jei.api.ingredients.IIngredients;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks; import net.minecraft.block.Blocks;
import net.minecraft.block.FlowingFluidBlock; import net.minecraft.block.FlowingFluidBlock;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items; import net.minecraft.item.Items;
import net.minecraft.util.ResourceLocation;
public class SplashingCategory extends ProcessingViaFanCategory<SplashingRecipe> { public class SplashingCategory extends ProcessingViaFanCategory<SplashingRecipe> {
private static ResourceLocation ID = new ResourceLocation(Create.ID, "splashing");
private IDrawable icon;
private IDrawable background = new EmptyBackground(177, 70);
public SplashingCategory() { public SplashingCategory() {
icon = new DoubleItemIcon(() -> new ItemStack(AllItems.PROPELLER.get()), super("splashing", doubleItemIcon(AllItems.PROPELLER.get(), Items.WATER_BUCKET));
() -> new ItemStack(Items.WATER_BUCKET));
}
@Override
public IDrawable getBackground() {
return background;
}
@Override
public IDrawable getIcon() {
return icon;
}
@Override
public ResourceLocation getUid() {
return ID;
} }
@Override @Override
@ -58,11 +30,6 @@ public class SplashingCategory extends ProcessingViaFanCategory<SplashingRecipe>
return SplashingRecipe.class; return SplashingRecipe.class;
} }
@Override
public String getTitle() {
return Lang.translate("recipe.splashing");
}
@Override @Override
public void setIngredients(SplashingRecipe recipe, IIngredients ingredients) { public void setIngredients(SplashingRecipe recipe, IIngredients ingredients) {
ingredients.setInputIngredients(recipe.getIngredients()); ingredients.setInputIngredients(recipe.getIngredients());
@ -85,7 +52,7 @@ public class SplashingCategory extends ProcessingViaFanCategory<SplashingRecipe>
itemStacks.set(outputIndex + 1, results.get(outputIndex).getStack()); itemStacks.set(outputIndex + 1, results.get(outputIndex).getStack());
} }
CreateJEI.addStochasticTooltip(itemStacks, results); addStochasticTooltip(itemStacks, results);
} }
@Override @Override
@ -97,14 +64,15 @@ public class SplashingCategory extends ProcessingViaFanCategory<SplashingRecipe>
ScreenResources.JEI_SHADOW.draw(66, 39); ScreenResources.JEI_SHADOW.draw(66, 39);
ScreenResources.JEI_LONG_ARROW.draw(53, 51); ScreenResources.JEI_LONG_ARROW.draw(53, 51);
if (size > 1) { if (size == 1) {
for (int i = 0; i < size; i++) { getRenderedSlot(recipe, 0).draw(139, 47);
int xOffset = i % 2 == 0 ? 0 : 19; return;
int yOffset = (i / 2) * -19; }
ScreenResources.JEI_SLOT.draw(133 + xOffset, 47 + yOffset);
} for (int i = 0; i < size; i++) {
} else { int xOffset = i % 2 == 0 ? 0 : 19;
ScreenResources.JEI_SLOT.draw(139, 47); int yOffset = (i / 2) * -19;
getRenderedSlot(recipe, i).draw(133 + xOffset, 47 + yOffset);
} }
} }

View file

@ -12,6 +12,8 @@ public class CClient extends ConfigBase {
public ConfigFloat fanParticleDensity = f(.5f, 0, 1, "fanParticleDensity"); public ConfigFloat fanParticleDensity = f(.5f, 0, 1, "fanParticleDensity");
public ConfigBool rainbowDebug = public ConfigBool rainbowDebug =
b(true, "enableRainbowDebug", "Show colourful debug information while the F3-Menu is open."); b(true, "enableRainbowDebug", "Show colourful debug information while the F3-Menu is open.");
public ConfigBool showHiddenSuperGlue =
b(false, "showHiddenSuperGlue", "Show indications for hidden glue between blocks while holding the item.");
@Override @Override
public String getName() { public String getName() {

View file

@ -5,9 +5,9 @@ public class CDamageControl extends ConfigBase {
public ConfigBool freezeCrushing = b(false, "freezeCrushing", Comments.freezeCrushing); public ConfigBool freezeCrushing = b(false, "freezeCrushing", Comments.freezeCrushing);
public ConfigBool freezeExtractors = b(false, "freezeExtractors", Comments.freezeExtractors); public ConfigBool freezeExtractors = b(false, "freezeExtractors", Comments.freezeExtractors);
public ConfigBool freezeInWorldProcessing = b(false, "freezeInWorldProcessing", Comments.freezeInWorldProcessing); public ConfigBool freezeInWorldProcessing = b(false, "freezeInWorldProcessing", Comments.freezeInWorldProcessing);
public ConfigBool freezeRotationPropagator = b(false, "freezeRotationPropagator", Comments.freezeRotationPropagator); public ConfigBool freezeRotationPropagator =
public ConfigBool freezeBearingConstructs = b(false, "freezeBearingConstructs", Comments.freezeBearingConstructs); b(false, "freezeRotationPropagator", Comments.freezeRotationPropagator);
public ConfigBool freezePistonConstructs = b(false, "freezePistonConstructs", Comments.freezePistonConstructs); public ConfigBool freezeContraptions = b(false, "freezeContraptions", Comments.freezeContraptions);
@Override @Override
public String getName() { public String getName() {
@ -20,8 +20,7 @@ public class CDamageControl extends ConfigBase {
static String freezeInWorldProcessing = "In case Encased Fans tried smelting your hardware."; static String freezeInWorldProcessing = "In case Encased Fans tried smelting your hardware.";
static String freezeRotationPropagator = static String freezeRotationPropagator =
"Pauses rotation logic altogether - Use if crash mentions RotationPropagators."; "Pauses rotation logic altogether - Use if crash mentions RotationPropagators.";
static String freezeBearingConstructs = "In case Mechanical Bearings turned against you."; static String freezeContraptions = "In case Moving contraptions pushed it too far.";
static String freezePistonConstructs = "In case Mechanical Pistons pushed it too far.";
} }
} }

View file

@ -75,6 +75,8 @@ public class ValueBoxRenderer {
} }
box.render(highlighted); box.render(highlighted);
RenderSystem.disableBlend();
RenderSystem.disableAlphaTest();
} }
public static void renderText(ValueBox box, FontRenderer font, String text) { public static void renderText(ValueBox box, FontRenderer font, String text) {

View file

@ -0,0 +1,59 @@
package com.simibubi.create.foundation.behaviour.base;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.tileentity.TileEntityType;
import net.minecraft.util.math.BlockPos;
public abstract class PosBoundSmartTileEntity extends SmartTileEntity {
private boolean newPositionVisited;
public PosBoundSmartTileEntity(TileEntityType<?> tileEntityTypeIn) {
super(tileEntityTypeIn);
newPositionVisited = true;
}
@Override
public void initialize() {
if (!world.isRemote && newPositionVisited) {
newPositionVisited = false;
initInNewPosition();
}
super.initialize();
}
@Override
public void read(CompoundNBT compound) {
long positionInTag = new BlockPos(compound.getInt("x"), compound.getInt("y"), compound.getInt("z")).toLong();
long positionKey = compound.getLong("BoundPosition");
newPositionVisited = false;
if (!hasWorld() || !world.isRemote) {
if (positionInTag != positionKey) {
removePositionDependentData(compound);
newPositionVisited = true;
}
}
super.read(compound);
}
/**
* Server-only. When this TE realizes, that it's reading its tag in a different
* position, it should remove all position dependent information here.
*
* @param nbt
*/
protected void removePositionDependentData(CompoundNBT nbt) {
}
/**
* Server-only. When a TE has been created or moved, it will call this before the
* regular init.
*/
protected void initInNewPosition() {
}
}

View file

@ -86,8 +86,9 @@ public abstract class SmartTileEntity extends SyncedTileEntity implements ITicka
list.forEach(b -> behaviours.put(b.getType(), b)); list.forEach(b -> behaviours.put(b.getType(), b));
} }
forEachBehaviour(tb -> tb.readNBT(compound));
super.read(compound); super.read(compound);
forEachBehaviour(tb -> tb.readNBT(compound));
if (world != null && world.isRemote) if (world != null && world.isRemote)
updateClient(compound); updateClient(compound);
} }
@ -106,7 +107,7 @@ public abstract class SmartTileEntity extends SyncedTileEntity implements ITicka
public void lazyTick() { public void lazyTick() {
} }
protected void forEachBehaviour(Consumer<TileEntityBehaviour> action) { protected void forEachBehaviour(Consumer<TileEntityBehaviour> action) {
behaviours.values().forEach(tb -> { behaviours.values().forEach(tb -> {
if (!tb.isPaused()) if (!tb.isPaused())

View file

@ -39,8 +39,7 @@ public class FilteringBehaviour extends TileEntityBehaviour {
filter = ItemStack.EMPTY; filter = ItemStack.EMPTY;
slotPositioning = slot; slotPositioning = slot;
showCount = false; showCount = false;
callback = stack -> { callback = stack -> {};
};
textShift = Vec3d.ZERO; textShift = Vec3d.ZERO;
count = 0; count = 0;
ticksUntilScrollPacket = -1; ticksUntilScrollPacket = -1;
@ -114,11 +113,7 @@ public class FilteringBehaviour extends TileEntityBehaviour {
public void setFilter(ItemStack stack) { public void setFilter(ItemStack stack) {
filter = stack.copy(); filter = stack.copy();
callback.accept(filter); callback.accept(filter);
count = (filter.getItem() instanceof FilterItem) ? 0 : Math.min(stack.getCount(), stack.getMaxStackSize());
if (filter.getItem() instanceof FilterItem)
count = 0;
else
count = stack.getCount();
forceClientState = true; forceClientState = true;
tileEntity.markDirty(); tileEntity.markDirty();

View file

@ -87,12 +87,14 @@ public class FilteringHandler {
return false; return false;
if (!filtering.testHit(objectMouseOver.getHitVec())) if (!filtering.testHit(objectMouseOver.getHitVec()))
return false; return false;
if (filtering.getFilter().isEmpty()) ItemStack filterItem = filtering.getFilter();
if (filterItem.isEmpty())
return false; return false;
filtering.ticksUntilScrollPacket = 10; filtering.ticksUntilScrollPacket = 10;
filtering.scrollableValue = (int) MathHelper int maxAmount = (filterItem.getItem() instanceof FilterItem) ? 64 : filterItem.getMaxStackSize();
.clamp(filtering.scrollableValue + delta * (AllKeys.ctrlDown() ? 16 : 1), 0, 64); filtering.scrollableValue =
(int) MathHelper.clamp(filtering.scrollableValue + delta * (AllKeys.ctrlDown() ? 16 : 1), 0, maxAmount);
return true; return true;
} }

View file

@ -34,6 +34,7 @@ public class LinkBehaviour extends TileEntityBehaviour {
ValueBoxTransform secondSlot; ValueBoxTransform secondSlot;
Vec3d textShift; Vec3d textShift;
public boolean newPosition;
private Mode mode; private Mode mode;
private Supplier<Boolean> transmission; private Supplier<Boolean> transmission;
private Consumer<Boolean> signalCallback; private Consumer<Boolean> signalCallback;
@ -45,6 +46,7 @@ public class LinkBehaviour extends TileEntityBehaviour {
firstSlot = slots.getLeft(); firstSlot = slots.getLeft();
secondSlot = slots.getRight(); secondSlot = slots.getRight();
textShift = Vec3d.ZERO; textShift = Vec3d.ZERO;
newPosition = true;
} }
public static LinkBehaviour receiver(SmartTileEntity te, Pair<ValueBoxTransform, ValueBoxTransform> slots, public static LinkBehaviour receiver(SmartTileEntity te, Pair<ValueBoxTransform, ValueBoxTransform> slots,
@ -84,6 +86,8 @@ public class LinkBehaviour extends TileEntityBehaviour {
} }
public void updateReceiver(boolean networkPowered) { public void updateReceiver(boolean networkPowered) {
if (!newPosition)
return;
signalCallback.accept(networkPowered); signalCallback.accept(networkPowered);
} }
@ -97,6 +101,7 @@ public class LinkBehaviour extends TileEntityBehaviour {
if (tileEntity.getWorld().isRemote) if (tileEntity.getWorld().isRemote)
return; return;
getHandler().addToNetwork(this); getHandler().addToNetwork(this);
newPosition = true;
} }
public Pair<Frequency, Frequency> getNetworkKey() { public Pair<Frequency, Frequency> getNetworkKey() {
@ -116,10 +121,15 @@ public class LinkBehaviour extends TileEntityBehaviour {
super.writeNBT(compound); super.writeNBT(compound);
compound.put("FrequencyFirst", frequencyFirst.getStack().write(new CompoundNBT())); compound.put("FrequencyFirst", frequencyFirst.getStack().write(new CompoundNBT()));
compound.put("FrequencyLast", frequencyLast.getStack().write(new CompoundNBT())); compound.put("FrequencyLast", frequencyLast.getStack().write(new CompoundNBT()));
compound.putLong("LastKnownPosition", tileEntity.getPos().toLong());
} }
@Override @Override
public void readNBT(CompoundNBT compound) { public void readNBT(CompoundNBT compound) {
long positionInTag = tileEntity.getPos().toLong();
long positionKey = compound.getLong("LastKnownPosition");
newPosition = positionInTag != positionKey;
super.readNBT(compound); super.readNBT(compound);
frequencyFirst = new Frequency(ItemStack.read(compound.getCompound("FrequencyFirst"))); frequencyFirst = new Frequency(ItemStack.read(compound.getCompound("FrequencyFirst")));
frequencyLast = new Frequency(ItemStack.read(compound.getCompound("FrequencyLast"))); frequencyLast = new Frequency(ItemStack.read(compound.getCompound("FrequencyLast")));

View file

@ -1,5 +1,7 @@
package com.simibubi.create.foundation.behaviour.scrollvalue; package com.simibubi.create.foundation.behaviour.scrollvalue;
import com.mojang.blaze3d.platform.GlStateManager.DestFactor;
import com.mojang.blaze3d.platform.GlStateManager.SourceFactor;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.RenderSystem;
import com.simibubi.create.AllItems; import com.simibubi.create.AllItems;
import com.simibubi.create.AllKeys; import com.simibubi.create.AllKeys;
@ -60,7 +62,10 @@ public class ScrollValueRenderer {
} }
} else } else
render(world, pos, face, behaviour, highlight); render(world, pos, face, behaviour, highlight);
TessellatorHelper.cleanUpAfterDrawing(); TessellatorHelper.cleanUpAfterDrawing();
RenderSystem.enableAlphaTest();
RenderSystem.blendFunc(SourceFactor.SRC_ALPHA, DestFactor.ONE_MINUS_SRC_ALPHA);
} }
protected static void render(ClientWorld world, BlockPos pos, Direction face, ScrollValueBehaviour behaviour, protected static void render(ClientWorld world, BlockPos pos, Direction face, ScrollValueBehaviour behaviour,

View file

@ -3,12 +3,9 @@ package com.simibubi.create.foundation.block.render;
import java.util.List; import java.util.List;
import java.util.Random; import java.util.Random;
import org.apache.commons.lang3.tuple.Pair;
import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.matrix.MatrixStack;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.client.renderer.Matrix4f;
import net.minecraft.client.renderer.model.BakedQuad; import net.minecraft.client.renderer.model.BakedQuad;
import net.minecraft.client.renderer.model.IBakedModel; import net.minecraft.client.renderer.model.IBakedModel;
import net.minecraft.client.renderer.model.ItemCameraTransforms.TransformType; import net.minecraft.client.renderer.model.ItemCameraTransforms.TransformType;

View file

@ -2,8 +2,6 @@ package com.simibubi.create.foundation.gui;
import java.util.function.Supplier; import java.util.function.Supplier;
import org.lwjgl.opengl.GL11;
import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.platform.GlStateManager.DestFactor; import com.mojang.blaze3d.platform.GlStateManager.DestFactor;
import com.mojang.blaze3d.platform.GlStateManager.SourceFactor; import com.mojang.blaze3d.platform.GlStateManager.SourceFactor;
@ -16,15 +14,13 @@ import net.minecraft.block.Blocks;
import net.minecraft.block.FireBlock; import net.minecraft.block.FireBlock;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.BlockRendererDispatcher; import net.minecraft.client.renderer.BlockRendererDispatcher;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.renderer.IRenderTypeBuffer;
import net.minecraft.client.renderer.RenderHelper; import net.minecraft.client.renderer.RenderHelper;
import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.RenderTypeLookup; import net.minecraft.client.renderer.RenderTypeLookup;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.model.IBakedModel; import net.minecraft.client.renderer.model.IBakedModel;
import net.minecraft.client.renderer.texture.AtlasTexture;
import net.minecraft.client.renderer.texture.OverlayTexture; import net.minecraft.client.renderer.texture.OverlayTexture;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
@ -79,7 +75,7 @@ public class ScreenElementRenderer {
boolean stateMode = transformsAndModel == null; boolean stateMode = transformsAndModel == null;
boolean fire = false; boolean fire = false;
if (stateMode) { if (transformsAndModel == null) {
blockToRender = transformsAndState.get(); blockToRender = transformsAndState.get();
fire = (blockToRender.getBlock() instanceof FireBlock); fire = (blockToRender.getBlock() instanceof FireBlock);
modelToRender = blockRenderer.getModelForState(blockToRender); modelToRender = blockRenderer.getModelForState(blockToRender);
@ -92,7 +88,8 @@ public class ScreenElementRenderer {
RenderType renderType = RenderTypeLookup.getEntityBlockLayer(blockToRender); RenderType renderType = RenderTypeLookup.getEntityBlockLayer(blockToRender);
IVertexBuilder vb = buffer.getBuffer(renderType); IVertexBuilder vb = buffer.getBuffer(renderType);
MatrixStack ms = new MatrixStack(); MatrixStack ms = new MatrixStack();
mc.getTextureManager().bindTexture(AtlasTexture.LOCATION_BLOCKS_TEXTURE);
RenderSystem.pushMatrix(); RenderSystem.pushMatrix();
if (fire) { if (fire) {
blockRenderer.renderBlock(blockToRender, ms, buffer, 0xF000F0, OverlayTexture.DEFAULT_UV, blockRenderer.renderBlock(blockToRender, ms, buffer, 0xF000F0, OverlayTexture.DEFAULT_UV,
@ -111,7 +108,7 @@ public class ScreenElementRenderer {
} }
RenderSystem.popMatrix(); RenderSystem.popMatrix();
if (stateMode && !blockToRender.getFluidState().isEmpty()) { if (blockToRender != null && !blockToRender.getFluidState().isEmpty()) {
RenderHelper.disableStandardItemLighting(); RenderHelper.disableStandardItemLighting();
RenderSystem.translatef(0, -300, 0); RenderSystem.translatef(0, -300, 0);
blockRenderer.renderFluid(new BlockPos(0, 300, 0), mc.world, vb, blockToRender.getFluidState()); blockRenderer.renderFluid(new BlockPos(0, 300, 0), mc.world, vb, blockToRender.getFluidState());

View file

@ -0,0 +1,12 @@
package com.simibubi.create.foundation.gui.widgets;
import com.simibubi.create.foundation.utility.AngleHelper;
public class InterpolatedChasingAngle extends InterpolatedChasingValue {
@Override
protected float getCurrentDiff() {
return AngleHelper.getShortestAngleDiff(value, getTarget());
}
}

View file

@ -7,11 +7,15 @@ public class InterpolatedChasingValue extends InterpolatedValue {
float eps = 1 / 4096f; float eps = 1 / 4096f;
public void tick() { public void tick() {
float diff = target - value; float diff = getCurrentDiff();
if (Math.abs(diff) < eps) if (Math.abs(diff) < eps)
return; return;
set(value + (diff) * speed); set(value + (diff) * speed);
} }
protected float getCurrentDiff() {
return getTarget() - value;
}
public InterpolatedChasingValue withSpeed(float speed) { public InterpolatedChasingValue withSpeed(float speed) {
this.speed = speed; this.speed = speed;
@ -22,5 +26,15 @@ public class InterpolatedChasingValue extends InterpolatedValue {
this.target = target; this.target = target;
return this; return this;
} }
public InterpolatedChasingValue start(float value) {
lastValue = this.value = value;
target(value);
return this;
}
public float getTarget() {
return target;
}
} }

View file

@ -19,16 +19,16 @@ public class AngleHelper {
public static float rad(float angle) { public static float rad(float angle) {
return (float) (angle / 180 * Math.PI); return (float) (angle / 180 * Math.PI);
} }
public static float deg(float angle) { public static float deg(float angle) {
return (float) (angle * 180 / Math.PI); return (float) (angle * 180 / Math.PI);
} }
public static float angleLerp(float pct, float current, float target) { public static float angleLerp(float pct, float current, float target) {
return current + getShortestAngleDiff(current, target) * pct; return current + getShortestAngleDiff(current, target) * pct;
} }
public static float getShortestAngleDiff(double current, double target) { public static float getShortestAngleDiff(double current, double target) {
current = current % 360; current = current % 360;
target = target % 360; target = target % 360;
return (float) (((((target - current) % 360) + 540) % 360) - 180); return (float) (((((target - current) % 360) + 540) % 360) - 180);

View file

@ -1,6 +1,11 @@
package com.simibubi.create.foundation.utility; package com.simibubi.create.foundation.utility;
import static net.minecraft.util.Direction.*; import static net.minecraft.util.Direction.DOWN;
import static net.minecraft.util.Direction.EAST;
import static net.minecraft.util.Direction.NORTH;
import static net.minecraft.util.Direction.SOUTH;
import static net.minecraft.util.Direction.UP;
import static net.minecraft.util.Direction.WEST;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;

View file

@ -1,5 +1,7 @@
package com.simibubi.create.foundation.utility; package com.simibubi.create.foundation.utility;
import org.lwjgl.opengl.GL11;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
@ -20,4 +22,14 @@ public class GlHelper {
RenderSystem.popMatrix(); RenderSystem.popMatrix();
} }
public static void enableTextureRepeat() {
RenderSystem.texParameter(GL11.GL_TEXTURE_2D, 10242, GL11.GL_REPEAT);
RenderSystem.texParameter(GL11.GL_TEXTURE_2D, 10243, GL11.GL_REPEAT);
}
public static void disableTextureRepeat() {
RenderSystem.texParameter(GL11.GL_TEXTURE_2D, 10242, GL11.GL_CLAMP);
RenderSystem.texParameter(GL11.GL_TEXTURE_2D, 10243, GL11.GL_CLAMP);
}
} }

View file

@ -9,7 +9,6 @@ import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.renderer.IRenderTypeBuffer;
import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.texture.OverlayTexture; import net.minecraft.client.renderer.texture.OverlayTexture;
import net.minecraft.entity.MobEntity;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;

View file

@ -10,6 +10,7 @@ import net.minecraft.util.math.BlockPos;
public class Iterate { public class Iterate {
public static final boolean[] trueAndFalse = { true, false }; public static final boolean[] trueAndFalse = { true, false };
public static final int[] zeroAndOne = { 1, -1 };
public static final int[] positiveAndNegative = { 1, -1 }; public static final int[] positiveAndNegative = { 1, -1 };
public static final Direction[] directions = Direction.values(); public static final Direction[] directions = Direction.values();
public static final Direction[] horizontalDirections = getHorizontals(); public static final Direction[] horizontalDirections = getHorizontals();

View file

@ -0,0 +1,37 @@
package com.simibubi.create.foundation.utility;
import java.util.function.BiFunction;
import net.minecraft.block.BlockState;
import net.minecraft.fluid.IFluidState;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.IWorld;
public class RayTraceWorld implements IBlockReader {
private IWorld template;
private BiFunction<BlockPos, BlockState, BlockState> stateGetter;
public RayTraceWorld(IWorld template, BiFunction<BlockPos, BlockState, BlockState> stateGetter) {
this.template = template;
this.stateGetter = stateGetter;
}
@Override
public TileEntity getTileEntity(BlockPos pos) {
return template.getTileEntity(pos);
}
@Override
public BlockState getBlockState(BlockPos pos) {
return stateGetter.apply(pos, template.getBlockState(pos));
}
@Override
public IFluidState getFluidState(BlockPos pos) {
return template.getFluidState(pos);
}
}

View file

@ -22,13 +22,14 @@ public class RaycastHelper {
return worldIn.rayTraceBlocks(context); return worldIn.rayTraceBlocks(context);
} }
public static PredicateTraceResult rayTraceUntil(PlayerEntity playerIn, double range, Predicate<BlockPos> predicate) { public static PredicateTraceResult rayTraceUntil(PlayerEntity playerIn, double range,
Predicate<BlockPos> predicate) {
Vec3d origin = getTraceOrigin(playerIn); Vec3d origin = getTraceOrigin(playerIn);
Vec3d target = getTraceTarget(playerIn, range, origin); Vec3d target = getTraceTarget(playerIn, range, origin);
return rayTraceUntil(origin, target, predicate); return rayTraceUntil(origin, target, predicate);
} }
private static Vec3d getTraceTarget(PlayerEntity playerIn, double range, Vec3d origin) { public static Vec3d getTraceTarget(PlayerEntity playerIn, double range, Vec3d origin) {
float f = playerIn.rotationPitch; float f = playerIn.rotationPitch;
float f1 = playerIn.rotationYaw; float f1 = playerIn.rotationYaw;
float f2 = MathHelper.cos(-f1 * 0.017453292F - (float) Math.PI); float f2 = MathHelper.cos(-f1 * 0.017453292F - (float) Math.PI);
@ -42,7 +43,7 @@ public class RaycastHelper {
return vec3d1; return vec3d1;
} }
private static Vec3d getTraceOrigin(PlayerEntity playerIn) { public static Vec3d getTraceOrigin(PlayerEntity playerIn) {
double d0 = playerIn.getX(); double d0 = playerIn.getX();
double d1 = playerIn.getY() + (double) playerIn.getEyeHeight(); double d1 = playerIn.getY() + (double) playerIn.getEyeHeight();
double d2 = playerIn.getZ(); double d2 = playerIn.getZ();
@ -50,7 +51,7 @@ public class RaycastHelper {
return vec3d; return vec3d;
} }
private static PredicateTraceResult rayTraceUntil(Vec3d start, Vec3d end, Predicate<BlockPos> predicate) { public static PredicateTraceResult rayTraceUntil(Vec3d start, Vec3d end, Predicate<BlockPos> predicate) {
if (Double.isNaN(start.x) || Double.isNaN(start.y) || Double.isNaN(start.z)) if (Double.isNaN(start.x) || Double.isNaN(start.y) || Double.isNaN(start.z))
return null; return null;
if (Double.isNaN(end.x) || Double.isNaN(end.y) || Double.isNaN(end.z)) if (Double.isNaN(end.x) || Double.isNaN(end.y) || Double.isNaN(end.z))
@ -174,7 +175,7 @@ public class RaycastHelper {
this.pos = pos; this.pos = pos;
this.facing = facing; this.facing = facing;
} }
public PredicateTraceResult() { public PredicateTraceResult() {
// missed, no result // missed, no result
} }
@ -186,7 +187,7 @@ public class RaycastHelper {
public BlockPos getPos() { public BlockPos getPos() {
return pos; return pos;
} }
public boolean missed() { public boolean missed() {
return this.pos == null; return this.pos == null;
} }

View file

@ -10,10 +10,10 @@ import com.simibubi.create.foundation.block.render.SpriteShiftEntry;
import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.BufferBuilder.DrawState; import net.minecraft.client.renderer.BufferBuilder.DrawState;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.GLAllocation; import net.minecraft.client.renderer.GLAllocation;
import net.minecraft.client.renderer.Matrix4f; import net.minecraft.client.renderer.Matrix4f;
import net.minecraft.client.renderer.Vector4f; import net.minecraft.client.renderer.Vector4f;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis; import net.minecraft.util.Direction.Axis;

View file

@ -27,9 +27,7 @@ public class TessellatorHelper {
RenderSystem.pushMatrix(); RenderSystem.pushMatrix();
RenderSystem.pushLightingAttributes(); RenderSystem.pushLightingAttributes();
RenderSystem.enableBlend(); RenderSystem.enableBlend();
RenderSystem.enableAlphaTest();
RenderSystem.color4f(1, 1, 1, 1); RenderSystem.color4f(1, 1, 1, 1);
ActiveRenderInfo renderInfo = mc.gameRenderer.getActiveRenderInfo(); ActiveRenderInfo renderInfo = mc.gameRenderer.getActiveRenderInfo();
Vec3d view = renderInfo.getProjectedView(); Vec3d view = renderInfo.getProjectedView();
RenderSystem.translated(-view.x, -view.y, -view.z); RenderSystem.translated(-view.x, -view.y, -view.z);
@ -83,10 +81,9 @@ public class TessellatorHelper {
} }
public static void cleanUpAfterDrawing() { public static void cleanUpAfterDrawing() {
RenderSystem.disableAlphaTest();
RenderSystem.disableBlend();
RenderSystem.popAttributes(); RenderSystem.popAttributes();
RenderSystem.popMatrix(); RenderSystem.popMatrix();
RenderSystem.disableBlend();
} }
public static void drawString(String str, float x, float y, float z, boolean scalesUp, boolean hasDepth) { public static void drawString(String str, float x, float y, float z, boolean scalesUp, boolean hasDepth) {

View file

@ -1,6 +1,7 @@
package com.simibubi.create.foundation.utility; package com.simibubi.create.foundation.utility;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
@ -8,8 +9,16 @@ import java.util.Set;
import com.google.common.base.Predicates; import com.google.common.base.Predicates;
import net.minecraft.block.BambooBlock;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.CactusBlock;
import net.minecraft.block.ChorusFlowerBlock;
import net.minecraft.block.ChorusPlantBlock;
import net.minecraft.block.KelpBlock;
import net.minecraft.block.KelpTopBlock;
import net.minecraft.block.LeavesBlock; import net.minecraft.block.LeavesBlock;
import net.minecraft.block.SugarCaneBlock;
import net.minecraft.tags.BlockTags; import net.minecraft.tags.BlockTags;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
@ -40,6 +49,41 @@ public class TreeCutter {
Set<BlockPos> visited = new HashSet<>(); Set<BlockPos> visited = new HashSet<>();
List<BlockPos> frontier = new LinkedList<>(); List<BlockPos> frontier = new LinkedList<>();
// Bamboo, Sugar Cane, Cactus
BlockState stateAbove = reader.getBlockState(pos.up());
if (isVerticalPlant(stateAbove)) {
logs.add(pos.up());
for (int i = 1; i < 256; i++) {
BlockPos current = pos.up(i);
if (!isVerticalPlant(reader.getBlockState(current)))
break;
logs.add(current);
}
Collections.reverse(logs);
return new Tree(logs, leaves);
}
// Chorus
if (isChorus(stateAbove)) {
frontier.add(pos.up());
while (!frontier.isEmpty()) {
BlockPos current = frontier.remove(0);
visited.add(current);
logs.add(current);
for (Direction direction : Iterate.directions) {
BlockPos offset = current.offset(direction);
if (visited.contains(offset))
continue;
if (!isChorus(reader.getBlockState(offset)))
continue;
frontier.add(offset);
}
}
Collections.reverse(logs);
return new Tree(logs, leaves);
}
// Regular Tree
if (!validateCut(reader, pos)) if (!validateCut(reader, pos))
return null; return null;
@ -94,6 +138,25 @@ public class TreeCutter {
return new Tree(logs, leaves); return new Tree(logs, leaves);
} }
public static boolean isChorus(BlockState stateAbove) {
return stateAbove.getBlock() instanceof ChorusPlantBlock || stateAbove.getBlock() instanceof ChorusFlowerBlock;
}
public static boolean isVerticalPlant(BlockState stateAbove) {
Block block = stateAbove.getBlock();
if (block instanceof BambooBlock)
return true;
if (block instanceof CactusBlock)
return true;
if (block instanceof SugarCaneBlock)
return true;
if (block instanceof KelpBlock)
return true;
if (block instanceof KelpTopBlock)
return true;
return false;
}
/** /**
* Checks whether a tree was fully cut by seeing whether the layer above the cut * Checks whether a tree was fully cut by seeing whether the layer above the cut
* is not supported by any more logs. * is not supported by any more logs.

View file

@ -2,6 +2,7 @@ package com.simibubi.create.foundation.utility;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.function.Predicate;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
@ -11,6 +12,7 @@ import net.minecraft.fluid.Fluid;
import net.minecraft.item.crafting.RecipeManager; import net.minecraft.item.crafting.RecipeManager;
import net.minecraft.scoreboard.Scoreboard; import net.minecraft.scoreboard.Scoreboard;
import net.minecraft.tags.NetworkTagManager; import net.minecraft.tags.NetworkTagManager;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.SoundCategory; import net.minecraft.util.SoundCategory;
import net.minecraft.util.SoundEvent; import net.minecraft.util.SoundEvent;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
@ -34,6 +36,26 @@ public class WrappedWorld extends World {
return world; return world;
} }
@Override
public BlockState getBlockState(BlockPos pos) {
return world.getBlockState(pos);
}
@Override
public boolean hasBlockState(BlockPos p_217375_1_, Predicate<BlockState> p_217375_2_) {
return world.hasBlockState(p_217375_1_, p_217375_2_);
}
@Override
public TileEntity getTileEntity(BlockPos pos) {
return world.getTileEntity(pos);
}
@Override
public boolean setBlockState(BlockPos pos, BlockState newState, int flags) {
return world.setBlockState(pos, newState, flags);
}
@Override @Override
public int getLight(BlockPos pos) { public int getLight(BlockPos pos) {
return 15; return 15;
@ -55,8 +77,7 @@ public class WrappedWorld extends World {
} }
@Override @Override
public void playEvent(PlayerEntity player, int type, BlockPos pos, int data) { public void playEvent(PlayerEntity player, int type, BlockPos pos, int data) {}
}
@Override @Override
public List<? extends PlayerEntity> getPlayers() { public List<? extends PlayerEntity> getPlayers() {
@ -65,13 +86,11 @@ public class WrappedWorld extends World {
@Override @Override
public void playSound(PlayerEntity player, double x, double y, double z, SoundEvent soundIn, SoundCategory category, public void playSound(PlayerEntity player, double x, double y, double z, SoundEvent soundIn, SoundCategory category,
float volume, float pitch) { float volume, float pitch) {}
}
@Override @Override
public void playMovingSound(PlayerEntity p_217384_1_, Entity p_217384_2_, SoundEvent p_217384_3_, public void playMovingSound(PlayerEntity p_217384_1_, Entity p_217384_2_, SoundEvent p_217384_3_,
SoundCategory p_217384_4_, float p_217384_5_, float p_217384_6_) { SoundCategory p_217384_4_, float p_217384_5_, float p_217384_6_) {}
}
@Override @Override
public Entity getEntityByID(int id) { public Entity getEntityByID(int id) {
@ -90,8 +109,7 @@ public class WrappedWorld extends World {
} }
@Override @Override
public void registerMapData(MapData mapDataIn) { public void registerMapData(MapData mapDataIn) {}
}
@Override @Override
public int getNextMapId() { public int getNextMapId() {
@ -99,8 +117,7 @@ public class WrappedWorld extends World {
} }
@Override @Override
public void sendBlockBreakProgress(int breakerId, BlockPos pos, int progress) { public void sendBlockBreakProgress(int breakerId, BlockPos pos, int progress) {}
}
@Override @Override
public Scoreboard getScoreboard() { public Scoreboard getScoreboard() {

View file

@ -0,0 +1,102 @@
package com.simibubi.create.foundation.utility.outliner;
import com.mojang.blaze3d.vertex.IVertexBuilder;
import com.simibubi.create.AllSpecialTextures;
import com.simibubi.create.foundation.utility.ColorHelper;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.Vec3d;
public class AABBOutline extends Outline {
protected AxisAlignedBB bb;
protected AllSpecialTextures faceTexture;
protected AllSpecialTextures highlightedTexture;
protected Direction highlightedFace;
public boolean disableCull = false;
public AABBOutline(AxisAlignedBB bb) {
this.bb = bb;
}
@Override
public void render(BufferBuilder buffer) {
Vec3d color = ColorHelper.getRGB(0xFFFFFF);
float alpha = 1f;
renderBB(bb, buffer, color, alpha, !disableCull);
}
public void setTextures(AllSpecialTextures faceTexture, AllSpecialTextures highlightTexture) {
this.faceTexture = faceTexture;
this.highlightedTexture = highlightTexture;
}
public void highlightFace(Direction face) {
this.highlightedFace = face;
}
public void renderBB(AxisAlignedBB bb, IVertexBuilder builder, Vec3d color, float alpha, boolean doCulling) {
Vec3d projectedView = Minecraft.getInstance().gameRenderer.getActiveRenderInfo().getProjectedView();
boolean inside = bb.contains(projectedView);
bb = bb.grow(inside ? -1 / 128d : 1 / 128d);
Vec3d xyz = new Vec3d(bb.minX, bb.minY, bb.minZ);
Vec3d Xyz = new Vec3d(bb.maxX, bb.minY, bb.minZ);
Vec3d xYz = new Vec3d(bb.minX, bb.maxY, bb.minZ);
Vec3d XYz = new Vec3d(bb.maxX, bb.maxY, bb.minZ);
Vec3d xyZ = new Vec3d(bb.minX, bb.minY, bb.maxZ);
Vec3d XyZ = new Vec3d(bb.maxX, bb.minY, bb.maxZ);
Vec3d xYZ = new Vec3d(bb.minX, bb.maxY, bb.maxZ);
Vec3d XYZ = new Vec3d(bb.maxX, bb.maxY, bb.maxZ);
renderFace(Direction.NORTH, xYz, XYz, Xyz, xyz, builder);
renderFace(Direction.SOUTH, XYZ, xYZ, xyZ, XyZ, builder);
renderFace(Direction.EAST, XYz, XYZ, XyZ, Xyz, builder);
renderFace(Direction.WEST, xYZ, xYz, xyz, xyZ, builder);
renderFace(Direction.UP, xYZ, XYZ, XYz, xYz, builder);
renderFace(Direction.DOWN, xyz, Xyz, XyZ, xyZ, builder);
Vec3d start = xyz;
AllSpecialTextures.BLANK.bind();
renderAACuboidLine(start, Xyz, color, alpha, builder);
renderAACuboidLine(start, xYz, color, alpha, builder);
renderAACuboidLine(start, xyZ, color, alpha, builder);
start = XyZ;
renderAACuboidLine(start, xyZ, color, alpha, builder);
renderAACuboidLine(start, XYZ, color, alpha, builder);
renderAACuboidLine(start, Xyz, color, alpha, builder);
start = XYz;
renderAACuboidLine(start, xYz, color, alpha, builder);
renderAACuboidLine(start, Xyz, color, alpha, builder);
renderAACuboidLine(start, XYZ, color, alpha, builder);
start = xYZ;
renderAACuboidLine(start, XYZ, color, alpha, builder);
renderAACuboidLine(start, xyZ, color, alpha, builder);
renderAACuboidLine(start, xYz, color, alpha, builder);
}
protected void renderFace(Direction direction, Vec3d p1, Vec3d p2, Vec3d p3, Vec3d p4, IVertexBuilder builder) {
if (direction == highlightedFace && highlightedTexture != null)
highlightedTexture.bind();
else if (faceTexture != null)
faceTexture.bind();
else
return;
Vec3d uDiff = p2.subtract(p1);
Vec3d vDiff = p4.subtract(p1);
Axis axis = direction.getAxis();
float maxU = (float) Math.abs(axis == Axis.X ? uDiff.z : uDiff.x);
float maxV = (float) Math.abs(axis == Axis.Y ? vDiff.z : vDiff.y);
putQuadUV(p1, p2, p3, p4, 0, 0, maxU, maxV, new Vec3d(1, 1, 1), 1, builder);
}
}

View file

@ -0,0 +1,140 @@
package com.simibubi.create.foundation.utility.outliner;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import com.simibubi.create.AllSpecialTextures;
import com.simibubi.create.foundation.utility.ColorHelper;
import net.minecraft.client.renderer.BufferBuilder;
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.Vec3d;
public class BlockClusterOutline extends Outline {
private Cluster cluster;
private float alpha;
public BlockClusterOutline(Iterable<BlockPos> selection) {
cluster = new Cluster();
selection.forEach(cluster::include);
alpha = .5f;
}
@Override
public void render(BufferBuilder buffer) {
Vec3d color = ColorHelper.getRGB(0xDDDDDD);
AllSpecialTextures.SELECTION.bind();
for (MergeEntry face : cluster.visibleFaces.keySet()) {
AxisDirection axisDirection = cluster.visibleFaces.get(face);
Direction direction = Direction.getFacingFromAxis(axisDirection, face.axis);
BlockPos pos = face.pos;
if (axisDirection == AxisDirection.POSITIVE)
pos = pos.offset(direction.getOpposite());
renderFace(pos, direction, color, alpha * .25f, 1 / 64d, buffer);
}
AllSpecialTextures.BLANK.bind();
for (MergeEntry edge : cluster.visibleEdges) {
lineWidth = 1 / 16f * alpha;
Vec3d start = new Vec3d(edge.pos);
Direction direction = Direction.getFacingFromAxis(AxisDirection.POSITIVE, edge.axis);
renderAACuboidLine(start, new Vec3d(edge.pos.offset(direction)), color, 1, buffer);
}
}
public void setAlpha(float alpha) {
this.alpha = alpha;
}
private static class Cluster {
Map<MergeEntry, AxisDirection> visibleFaces;
Set<MergeEntry> visibleEdges;
public Cluster() {
visibleEdges = new HashSet<>();
visibleFaces = new HashMap<>();
}
public void include(BlockPos pos) {
// 6 FACES
for (Axis axis : Axis.values()) {
Direction direction = Direction.getFacingFromAxis(AxisDirection.POSITIVE, axis);
for (int offset : new int[] { 0, 1 }) {
MergeEntry entry = new MergeEntry(axis, pos.offset(direction, offset));
if (visibleFaces.remove(entry) == null)
visibleFaces.put(entry, offset == 0 ? AxisDirection.NEGATIVE : AxisDirection.POSITIVE);
}
}
// 12 EDGES
for (Axis axis : Axis.values()) {
for (Axis axis2 : Axis.values()) {
if (axis == axis2)
continue;
for (Axis axis3 : Axis.values()) {
if (axis == axis3)
continue;
if (axis2 == axis3)
continue;
Direction direction = Direction.getFacingFromAxis(AxisDirection.POSITIVE, axis2);
Direction direction2 = Direction.getFacingFromAxis(AxisDirection.POSITIVE, axis3);
for (int offset : new int[] { 0, 1 }) {
BlockPos entryPos = pos.offset(direction, offset);
for (int offset2 : new int[] { 0, 1 }) {
entryPos = entryPos.offset(direction2, offset2);
MergeEntry entry = new MergeEntry(axis, entryPos);
if (!visibleEdges.remove(entry))
visibleEdges.add(entry);
}
}
}
break;
}
}
}
}
private static class MergeEntry {
Axis axis;
BlockPos pos;
public MergeEntry(Axis axis, BlockPos pos) {
this.axis = axis;
this.pos = pos;
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (!(o instanceof MergeEntry))
return false;
MergeEntry other = (MergeEntry) o;
return this.axis == other.axis && this.pos.equals(other.pos);
}
@Override
public int hashCode() {
return this.pos.hashCode() * 31 + axis.ordinal();
}
}
}

View file

@ -0,0 +1,46 @@
package com.simibubi.create.foundation.utility.outliner;
import com.simibubi.create.foundation.utility.ColorHelper;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
public class ChasingAABBOutline extends AABBOutline {
AxisAlignedBB targetBB;
AxisAlignedBB prevBB;
public ChasingAABBOutline(AxisAlignedBB bb) {
super(bb);
prevBB = bb.grow(0);
targetBB = bb.grow(0);
}
public void target(AxisAlignedBB target) {
targetBB = target;
}
public void tick() {
prevBB = bb;
bb = interpolateBBs(bb, targetBB, .5f);
}
@Override
public void render(BufferBuilder buffer) {
Vec3d color = ColorHelper.getRGB(0xFFFFFF);
float alpha = 1f;
renderBB(interpolateBBs(prevBB, bb, Minecraft.getInstance().getRenderPartialTicks()), buffer, color, alpha,
true);
}
private static AxisAlignedBB interpolateBBs(AxisAlignedBB current, AxisAlignedBB target, float pt) {
return new AxisAlignedBB(MathHelper.lerp(pt, current.minX, target.minX),
MathHelper.lerp(pt, current.minY, target.minY), MathHelper.lerp(pt, current.minZ, target.minZ),
MathHelper.lerp(pt, current.maxX, target.maxX), MathHelper.lerp(pt, current.maxY, target.maxY),
MathHelper.lerp(pt, current.maxZ, target.maxZ));
}
}

View file

@ -0,0 +1,97 @@
package com.simibubi.create.foundation.utility.outliner;
import com.mojang.blaze3d.vertex.IVertexBuilder;
import com.simibubi.create.foundation.utility.VecHelper;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
public abstract class Outline {
protected float lineWidth = 1 / 32f;
public abstract void render(BufferBuilder buffer);
public void renderAACuboidLine(Vec3d start, Vec3d end, Vec3d rgb, float alpha, IVertexBuilder builder) {
Vec3d diff = end.subtract(start);
if (diff.x + diff.y + diff.z < 0) {
Vec3d temp = start;
start = end;
end = temp;
diff = diff.scale(-1);
}
Vec3d extension = diff.normalize().scale(lineWidth / 2);
Vec3d plane = VecHelper.planeByNormal(diff);
Axis axis = Direction.getFacingFromVector(diff.x, diff.y, diff.z).getAxis();
start = start.subtract(extension);
end = end.add(extension);
plane = plane.scale(lineWidth / 2);
Vec3d a1 = plane.add(start);
Vec3d b1 = plane.add(end);
plane = VecHelper.rotate(plane, -90, axis);
Vec3d a2 = plane.add(start);
Vec3d b2 = plane.add(end);
plane = VecHelper.rotate(plane, -90, axis);
Vec3d a3 = plane.add(start);
Vec3d b3 = plane.add(end);
plane = VecHelper.rotate(plane, -90, axis);
Vec3d a4 = plane.add(start);
Vec3d b4 = plane.add(end);
putQuad(b4, b3, b2, b1, rgb, alpha, builder);
putQuad(a1, a2, a3, a4, rgb, alpha, builder);
putQuad(a1, b1, b2, a2, rgb, alpha, builder);
putQuad(a2, b2, b3, a3, rgb, alpha, builder);
putQuad(a3, b3, b4, a4, rgb, alpha, builder);
putQuad(a4, b4, b1, a1, rgb, alpha, builder);
}
protected void renderFace(BlockPos pos, Direction face, Vec3d rgb, float alpha, double scaleOffset,
IVertexBuilder builder) {
Vec3d center = VecHelper.getCenterOf(pos);
Vec3d offset = new Vec3d(face.getDirectionVec());
Vec3d plane = VecHelper.planeByNormal(offset);
Axis axis = face.getAxis();
offset = offset.scale(1 / 2f + scaleOffset);
plane = plane.scale(1 / 2f).add(offset);
int deg = face.getAxisDirection().getOffset() * 90;
Vec3d a1 = plane.add(center);
plane = VecHelper.rotate(plane, deg, axis);
Vec3d a2 = plane.add(center);
plane = VecHelper.rotate(plane, deg, axis);
Vec3d a3 = plane.add(center);
plane = VecHelper.rotate(plane, deg, axis);
Vec3d a4 = plane.add(center);
putQuad(a1, a2, a3, a4, rgb, alpha, builder);
}
public void putQuad(Vec3d v1, Vec3d v2, Vec3d v3, Vec3d v4, Vec3d rgb, float alpha, IVertexBuilder builder) {
putQuadUV(v1, v2, v3, v4, 0, 0, 1, 1, rgb, alpha, builder);
}
public void putQuadUV(Vec3d v1, Vec3d v2, Vec3d v3, Vec3d v4, float minU, float minV, float maxU, float maxV,
Vec3d rgb, float alpha, IVertexBuilder builder) {
putVertex(v1, rgb, minU, minV, alpha, builder);
putVertex(v2, rgb, maxU, minV, alpha, builder);
putVertex(v3, rgb, maxU, maxV, alpha, builder);
putVertex(v4, rgb, minU, maxV, alpha, builder);
}
protected void putVertex(Vec3d pos, Vec3d rgb, float u, float v, float alpha, IVertexBuilder builder) {
int i = 15 << 20 | 15 << 4;
int j = i >> 16 & '\uffff';
int k = i & '\uffff';
builder.vertex(pos.x, pos.y, pos.z).texture(u, v).color((float) rgb.x, (float) rgb.y, (float) rgb.z, alpha)
.light(j, k).endVertex();
}
}

View file

@ -0,0 +1,55 @@
package com.simibubi.create.foundation.utility.outliner;
import com.mojang.blaze3d.vertex.IVertexBuilder;
import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.player.ClientPlayerEntity;
import net.minecraft.client.particle.IParticleRenderType;
import net.minecraft.client.particle.Particle;
import net.minecraft.client.renderer.ActiveRenderInfo;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
public class OutlineParticle<O extends Outline> extends Particle {
protected O outline;
protected OutlineParticle(O outline, World worldIn, double xCoordIn, double yCoordIn, double zCoordIn) {
super(worldIn, xCoordIn, yCoordIn, zCoordIn);
this.outline = outline;
this.maxAge = 1024;
}
public static <O extends Outline> OutlineParticle<O> create(O outline) {
Minecraft mc = Minecraft.getInstance();
ClientPlayerEntity player = mc.player;
OutlineParticle<O> effect =
new OutlineParticle<>(outline, mc.world, player.getX(), player.getY(), player.getZ());
mc.particles.addEffect(effect);
return effect;
}
public void remove() {
isExpired = true;
}
@Override
public void buildGeometry(IVertexBuilder builder, ActiveRenderInfo renderInfo, float p_225606_3_) {
Vec3d view = renderInfo.getProjectedView();
// GlStateManager.translated(-view.x, -view.y, -view.z);
// TODO
// GlStateManager.enableBlend();
// getOutline().render(buffer);
// GlStateManager.disableBlend();
}
@Override
public IParticleRenderType getRenderType() {
return IParticleRenderType.CUSTOM;
}
public O getOutline() {
return outline;
}
}

View file

@ -0,0 +1,111 @@
package com.simibubi.create.foundation.utility.render;
import java.util.Iterator;
import org.lwjgl.opengl.GL13;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.systems.RenderSystem;
import com.simibubi.create.Create;
import com.simibubi.create.config.AllConfigs;
import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.foundation.utility.WrappedWorld;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.IRenderTypeBuffer;
import net.minecraft.client.renderer.LightTexture;
import net.minecraft.client.renderer.RenderHelper;
import net.minecraft.client.renderer.WorldRenderer;
import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher;
import net.minecraft.crash.ReportedException;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
public class StructureRenderer {
protected static LightingWorld lightingWorld;
public static void renderTileEntities(World world, Vec3d position, Vec3d rotation,
Iterable<TileEntity> customRenderTEs, MatrixStack ms, IRenderTypeBuffer buffer) {
float pt = Minecraft.getInstance().getRenderPartialTicks();
if (lightingWorld == null)
lightingWorld = new LightingWorld(world);
lightingWorld.setWorld(world);
lightingWorld.setTransform(position, rotation);
for (Iterator<TileEntity> iterator = customRenderTEs.iterator(); iterator.hasNext();) {
TileEntity tileEntity = iterator.next();
if (TileEntityRendererDispatcher.instance.getRenderer(tileEntity) == null) {
iterator.remove();
continue;
}
try {
BlockPos pos = tileEntity.getPos();
if (!tileEntity.hasFastRenderer()) {
RenderHelper.enable();
int i = WorldRenderer.getLightmapCoordinates(lightingWorld, pos);
int j = LightTexture.getBlockLightCoordinates(i);
int k = LightTexture.getSkyLightCoordinates(i);
RenderSystem.glMultiTexCoord2f(GL13.GL_TEXTURE1, (float) j, (float) k);
RenderSystem.color4f(1.0F, 1.0F, 1.0F, 1.0F);
}
RenderSystem.disableCull();
World prevTileWorld = tileEntity.getWorld();
tileEntity.setLocation(lightingWorld, pos);
TileEntityRendererDispatcher.instance.render(tileEntity, pt, ms, buffer);
tileEntity.setLocation(prevTileWorld, pos);
RenderSystem.enableCull();
} catch (ReportedException e) {
if (AllConfigs.CLIENT.explainRenderErrors.get()) {
Create.logger.error("TileEntity " + tileEntity.getType().getRegistryName().toString()
+ " didn't want to render while moved.\n", e);
} else {
Create.logger.error("TileEntity " + tileEntity.getType().getRegistryName().toString()
+ " didn't want to render while moved.\n");
}
iterator.remove();
continue;
}
}
}
private static class LightingWorld extends WrappedWorld {
private Vec3d offset;
private Vec3d rotation;
public LightingWorld(World world) {
super(world);
}
void setWorld(World world) {
this.world = world;
}
void setTransform(Vec3d offset, Vec3d rotation) {
this.offset = offset;
this.rotation = rotation;
}
@Override
public int getBaseLightLevel(BlockPos pos, int minLight) {
return super.getBaseLightLevel(transformPos(pos), minLight);
}
private BlockPos transformPos(BlockPos pos) {
Vec3d vec = VecHelper.getCenterOf(pos);
vec = VecHelper.rotate(vec, rotation.x, rotation.y, rotation.z);
vec = vec.add(offset).subtract(VecHelper.getCenterOf(BlockPos.ZERO));
return new BlockPos(vec);
}
}
}

View file

@ -1,9 +1,6 @@
package com.simibubi.create.foundation.world; package com.simibubi.create.foundation.world;
import java.util.Optional; import java.util.Optional;
import java.util.function.Supplier;
import javax.annotation.Nonnull;
import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.tuple.Pair;

View file

@ -1,7 +1,6 @@
package com.simibubi.create.modules.contraptions; package com.simibubi.create.modules.contraptions;
import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.systems.RenderSystem;
import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.AnimationTickHolder;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;

View file

@ -1,7 +1,6 @@
package com.simibubi.create.modules.contraptions.base; package com.simibubi.create.modules.contraptions.base;
import com.simibubi.create.foundation.item.ItemDescription.Palette; import com.simibubi.create.foundation.item.ItemDescription.Palette;
import com.simibubi.create.modules.contraptions.RotationPropagator;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
@ -45,7 +44,10 @@ public abstract class KineticBlock extends Block implements IRotate {
return tool == ToolType.AXE || tool == ToolType.PICKAXE; return tool == ToolType.AXE || tool == ToolType.PICKAXE;
} }
// IRotate @Override
public void onBlockAdded(BlockState state, World worldIn, BlockPos pos, BlockState oldState, boolean isMoving) {
// onBlockAdded is useless for init, as sometimes the TE gets re-instantiated
}
@Override @Override
public boolean hasShaftTowards(IWorldReader world, BlockPos pos, BlockState state, Direction face) { public boolean hasShaftTowards(IWorldReader world, BlockPos pos, BlockState state, Direction face) {
@ -57,8 +59,6 @@ public abstract class KineticBlock extends Block implements IRotate {
return false; return false;
} }
// Block
@Override @Override
public boolean hasTileEntity(BlockState state) { public boolean hasTileEntity(BlockState state) {
return true; return true;
@ -72,8 +72,8 @@ public abstract class KineticBlock extends Block implements IRotate {
@Override @Override
public abstract TileEntity createTileEntity(BlockState state, IBlockReader world); public abstract TileEntity createTileEntity(BlockState state, IBlockReader world);
@SuppressWarnings("deprecation")
@Override @Override
@SuppressWarnings("deprecation")
public void updateNeighbors(BlockState stateIn, IWorld worldIn, BlockPos pos, int flags) { public void updateNeighbors(BlockState stateIn, IWorld worldIn, BlockPos pos, int flags) {
super.updateNeighbors(stateIn, worldIn, pos, flags); super.updateNeighbors(stateIn, worldIn, pos, flags);
if (worldIn.isRemote()) if (worldIn.isRemote())
@ -83,8 +83,11 @@ public abstract class KineticBlock extends Block implements IRotate {
if (!(tileEntity instanceof KineticTileEntity)) if (!(tileEntity instanceof KineticTileEntity))
return; return;
// Remove previous information when block is added
KineticTileEntity kte = (KineticTileEntity) tileEntity; KineticTileEntity kte = (KineticTileEntity) tileEntity;
RotationPropagator.handleAdded(worldIn.getWorld(), pos, kte); kte.warnOfMovement();
kte.clearKineticInformation();
kte.updateSpeed = true;
} }
// @Override // TODO 1.15 register layer // @Override // TODO 1.15 register layer

View file

@ -41,12 +41,14 @@ public abstract class KineticTileEntity extends SmartTileEntity
public @Nullable Long network; public @Nullable Long network;
public @Nullable BlockPos source; public @Nullable BlockPos source;
public boolean networkDirty; public boolean networkDirty;
public boolean updateSpeed;
protected KineticEffectHandler effects; protected KineticEffectHandler effects;
protected float speed; protected float speed;
protected float capacity; protected float capacity;
protected float stress; protected float stress;
protected boolean overStressed; protected boolean overStressed;
protected boolean wasMoved;
private int flickerTally; private int flickerTally;
private int networkSize; private int networkSize;
@ -57,6 +59,7 @@ public abstract class KineticTileEntity extends SmartTileEntity
public KineticTileEntity(TileEntityType<?> typeIn) { public KineticTileEntity(TileEntityType<?> typeIn) {
super(typeIn); super(typeIn);
effects = new KineticEffectHandler(this); effects = new KineticEffectHandler(this);
updateSpeed = true;
} }
@Override @Override
@ -73,6 +76,9 @@ public abstract class KineticTileEntity extends SmartTileEntity
@Override @Override
public void tick() { public void tick() {
if (!world.isRemote && needsSpeedUpdate())
attachKinetics();
super.tick(); super.tick();
effects.tick(); effects.tick();
@ -179,6 +185,9 @@ public abstract class KineticTileEntity extends SmartTileEntity
public CompoundNBT write(CompoundNBT compound) { public CompoundNBT write(CompoundNBT compound) {
compound.putFloat("Speed", speed); compound.putFloat("Speed", speed);
if (needsSpeedUpdate())
compound.putBoolean("NeedsSpeedUpdate", true);
if (hasSource()) if (hasSource())
compound.put("Source", NBTUtil.writeBlockPos(source)); compound.put("Source", NBTUtil.writeBlockPos(source));
@ -188,7 +197,7 @@ public abstract class KineticTileEntity extends SmartTileEntity
networkTag.putFloat("Stress", stress); networkTag.putFloat("Stress", stress);
networkTag.putFloat("Capacity", capacity); networkTag.putFloat("Capacity", capacity);
networkTag.putInt("Size", networkSize); networkTag.putInt("Size", networkSize);
if (lastStressApplied != 0) if (lastStressApplied != 0)
networkTag.putFloat("AddedStress", lastStressApplied); networkTag.putFloat("AddedStress", lastStressApplied);
if (lastCapacityProvided != 0) if (lastCapacityProvided != 0)
@ -200,16 +209,21 @@ public abstract class KineticTileEntity extends SmartTileEntity
return super.write(compound); return super.write(compound);
} }
public boolean needsSpeedUpdate() {
return updateSpeed;
}
@Override @Override
public void read(CompoundNBT compound) { public void read(CompoundNBT compound) {
clearKineticInformation();
// DO NOT READ kinetic information when placed after movement
if (wasMoved) {
super.read(compound);
return;
}
speed = compound.getFloat("Speed"); speed = compound.getFloat("Speed");
source = null;
network = null;
overStressed = false;
stress = 0;
capacity = 0;
lastStressApplied = 0;
lastCapacityProvided = 0;
if (compound.contains("Source")) if (compound.contains("Source"))
source = NBTUtil.readBlockPos(compound.getCompound("Source")); source = NBTUtil.readBlockPos(compound.getCompound("Source"));
@ -313,6 +327,7 @@ public abstract class KineticTileEntity extends SmartTileEntity
} }
public void attachKinetics() { public void attachKinetics() {
updateSpeed = false;
RotationPropagator.handleAdded(world, pos, this); RotationPropagator.handleAdded(world, pos, this);
} }
@ -414,6 +429,21 @@ public abstract class KineticTileEntity extends SmartTileEntity
} }
public void clearKineticInformation() {
speed = 0;
source = null;
network = null;
overStressed = false;
stress = 0;
capacity = 0;
lastStressApplied = 0;
lastCapacityProvided = 0;
}
public void warnOfMovement() {
wasMoved = true;
}
public int getFlickerScore() { public int getFlickerScore() {
return flickerTally; return flickerTally;
} }

View file

@ -0,0 +1,60 @@
package com.simibubi.create.modules.contraptions.components.actors;
import com.simibubi.create.foundation.utility.AllShapes;
import com.simibubi.create.modules.contraptions.components.contraptions.IPortableBlock;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.HorizontalBlock;
import net.minecraft.item.BlockItemUseContext;
import net.minecraft.state.StateContainer.Builder;
import net.minecraft.util.Direction;
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;
import net.minecraft.world.IWorldReader;
public abstract class AttachedActorBlock extends HorizontalBlock implements IPortableBlock {
public AttachedActorBlock() {
super(Properties.from(Blocks.IRON_BLOCK));
}
@Override
public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) {
Direction direction = state.get(HORIZONTAL_FACING);
return AllShapes.HARVESTER_BASE.get(direction);
}
@Override
protected void fillStateContainer(Builder<Block, BlockState> builder) {
builder.add(HORIZONTAL_FACING);
super.fillStateContainer(builder);
}
@Override
public boolean isValidPosition(BlockState state, IWorldReader worldIn, BlockPos pos) {
Direction direction = state.get(HORIZONTAL_FACING);
BlockPos offset = pos.offset(direction.getOpposite());
return Block.hasSolidSide(worldIn.getBlockState(offset), worldIn, offset, direction);
}
@Override
public BlockState getStateForPlacement(BlockItemUseContext context) {
Direction facing;
if (context.getFace().getAxis().isVertical())
facing = context.getPlacementHorizontalFacing().getOpposite();
else {
BlockState blockState =
context.getWorld().getBlockState(context.getPos().offset(context.getFace().getOpposite()));
if (blockState.getBlock() instanceof AttachedActorBlock)
facing = blockState.get(HORIZONTAL_FACING);
else
facing = context.getFace();
}
return getDefaultState().with(HORIZONTAL_FACING, facing);
}
}

View file

@ -6,9 +6,11 @@ import com.simibubi.create.modules.contraptions.components.contraptions.Movement
import com.simibubi.create.modules.contraptions.components.contraptions.MovementContext; import com.simibubi.create.modules.contraptions.components.contraptions.MovementContext;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.FallingBlock;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.item.ItemEntity; import net.minecraft.entity.item.ItemEntity;
import net.minecraft.entity.item.minecart.AbstractMinecartEntity; import net.minecraft.entity.item.minecart.AbstractMinecartEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.CompoundNBT;
import net.minecraft.nbt.NBTUtil; import net.minecraft.nbt.NBTUtil;
import net.minecraft.util.DamageSource; import net.minecraft.util.DamageSource;
@ -32,30 +34,10 @@ public class BlockBreakingMovementBehaviour extends MovementBehaviour {
World world = context.world; World world = context.world;
BlockState stateVisited = world.getBlockState(pos); BlockState stateVisited = world.getBlockState(pos);
if (!stateVisited.isNormalCube(world, pos))
damageEntities(context, pos, world);
if (world.isRemote) if (world.isRemote)
return; return;
if (stateVisited.getCollisionShape(world, pos).isEmpty()) {
DamageSource damageSource = getDamageSource();
if (damageSource == null)
return;
for (Entity entity : world.getEntitiesWithinAABB(Entity.class, new AxisAlignedBB(pos))) {
if (entity instanceof ItemEntity)
return;
if (entity instanceof ContraptionEntity)
return;
if (entity instanceof AbstractMinecartEntity)
for (Entity passenger : entity.getRecursivePassengers())
if (passenger instanceof ContraptionEntity
&& ((ContraptionEntity) passenger).getContraption() == context.contraption)
return;
float damage = (float) MathHelper.clamp(Math.abs(context.relativeMotion.length() * 10) + 1, 5, 20);
entity.attackEntityFrom(damageSource, damage);
entity.setMotion(entity.getMotion().add(context.relativeMotion.scale(3)));
}
return;
}
if (!canBreak(world, pos, stateVisited)) if (!canBreak(world, pos, stateVisited))
return; return;
@ -63,10 +45,44 @@ public class BlockBreakingMovementBehaviour extends MovementBehaviour {
context.stall = true; context.stall = true;
} }
public void damageEntities(MovementContext context, BlockPos pos, World world) {
DamageSource damageSource = getDamageSource();
if (damageSource == null && !throwsEntities())
return;
Entities: for (Entity entity : world.getEntitiesWithinAABB(Entity.class, new AxisAlignedBB(pos))) {
if (entity instanceof ItemEntity)
continue;
if (entity instanceof ContraptionEntity)
continue;
if (entity instanceof AbstractMinecartEntity)
for (Entity passenger : entity.getRecursivePassengers())
if (passenger instanceof ContraptionEntity
&& ((ContraptionEntity) passenger).getContraption() == context.contraption)
continue Entities;
float damage = (float) MathHelper.clamp(Math.abs(context.relativeMotion.length() * 10) + 1, 5, 20);
if (damageSource != null && !world.isRemote)
entity.attackEntityFrom(damageSource, damage);
if (throwsEntities() && (world.isRemote == (entity instanceof PlayerEntity))) {
Vec3d motionBoost = context.motion.add(0, context.motion.length() / 4f, 0);
int maxBoost = 4;
if (motionBoost.length() > maxBoost) {
motionBoost = motionBoost.subtract(motionBoost.normalize().scale(motionBoost.length() - maxBoost));
}
entity.setMotion(entity.getMotion().add(motionBoost));
entity.velocityChanged = true;
}
}
}
protected DamageSource getDamageSource() { protected DamageSource getDamageSource() {
return null; return null;
} }
protected boolean throwsEntities() {
return getDamageSource() != null;
}
@Override @Override
public void stopMoving(MovementContext context) { public void stopMoving(MovementContext context) {
CompoundNBT data = context.data; CompoundNBT data = context.data;
@ -89,6 +105,27 @@ public class BlockBreakingMovementBehaviour extends MovementBehaviour {
@Override @Override
public void tick(MovementContext context) { public void tick(MovementContext context) {
tickBreaker(context);
CompoundNBT data = context.data;
if (!data.contains("WaitingTicks"))
return;
int waitingTicks = data.getInt("WaitingTicks");
if (waitingTicks-- > 0) {
data.putInt("WaitingTicks", waitingTicks);
context.stall = true;
return;
}
BlockPos pos = NBTUtil.readBlockPos(data.getCompound("LastPos"));
data.remove("WaitingTicks");
data.remove("LastPos");
context.stall = false;
visitNewPosition(context, pos);
}
public void tickBreaker(MovementContext context) {
CompoundNBT data = context.data; CompoundNBT data = context.data;
if (context.world.isRemote) if (context.world.isRemote)
return; return;
@ -128,14 +165,24 @@ public class BlockBreakingMovementBehaviour extends MovementBehaviour {
destroyProgress += MathHelper.clamp((int) (breakSpeed / blockHardness), 1, 10 - destroyProgress); destroyProgress += MathHelper.clamp((int) (breakSpeed / blockHardness), 1, 10 - destroyProgress);
if (destroyProgress >= 10) { if (destroyProgress >= 10) {
BlockHelper.destroyBlock(context.world, breakingPos, 1f, stack -> this.dropItem(context, stack));
onBlockBroken(context, breakingPos);
ticksUntilNextProgress = -1;
world.sendBlockBreakProgress(id, breakingPos, -1); world.sendBlockBreakProgress(id, breakingPos, -1);
// break falling blocks from top to bottom
BlockPos ogPos = breakingPos;
BlockState stateAbove = world.getBlockState(breakingPos.up());
while (stateAbove.getBlock() instanceof FallingBlock) {
breakingPos = breakingPos.up();
stateAbove = world.getBlockState(breakingPos.up());
}
stateToBreak = world.getBlockState(breakingPos);
context.stall = false;
BlockHelper.destroyBlock(context.world, breakingPos, 1f, stack -> this.dropItem(context, stack));
onBlockBroken(context, ogPos, stateToBreak);
ticksUntilNextProgress = -1;
data.remove("Progress"); data.remove("Progress");
data.remove("TicksUntilNextProgress"); data.remove("TicksUntilNextProgress");
data.remove("BreakingPos"); data.remove("BreakingPos");
context.stall = false;
return; return;
} }
@ -150,7 +197,15 @@ public class BlockBreakingMovementBehaviour extends MovementBehaviour {
return BlockBreakingKineticTileEntity.isBreakable(state, blockHardness); return BlockBreakingKineticTileEntity.isBreakable(state, blockHardness);
} }
protected void onBlockBroken(MovementContext context, BlockPos pos) { protected void onBlockBroken(MovementContext context, BlockPos pos, BlockState brokenState) {
// Check for falling blocks
if (!(brokenState.getBlock() instanceof FallingBlock))
return;
CompoundNBT data = context.data;
data.putInt("WaitingTicks", 10);
data.put("LastPos", NBTUtil.writeBlockPos(pos));
context.stall = true;
} }
} }

View file

@ -4,8 +4,11 @@ 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.MovementContext; import com.simibubi.create.modules.contraptions.components.contraptions.MovementContext;
import net.minecraft.block.BlockState;
import net.minecraft.util.DamageSource; import net.minecraft.util.DamageSource;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.api.distmarker.OnlyIn;
@ -27,10 +30,15 @@ public class DrillMovementBehaviour extends BlockBreakingMovementBehaviour {
public SuperByteBuffer renderInContraption(MovementContext context) { public SuperByteBuffer renderInContraption(MovementContext context) {
return DrillTileEntityRenderer.renderInContraption(context); return DrillTileEntityRenderer.renderInContraption(context);
} }
@Override @Override
protected DamageSource getDamageSource() { protected DamageSource getDamageSource() {
return DrillBlock.damageSourceDrill; return DrillBlock.damageSourceDrill;
} }
@Override
public boolean canBreak(World world, BlockPos breakingPos, BlockState state) {
return super.canBreak(world, breakingPos, state) && !state.getCollisionShape(world, breakingPos).isEmpty();
}
} }

View file

@ -1,33 +1,16 @@
package com.simibubi.create.modules.contraptions.components.actors; package com.simibubi.create.modules.contraptions.components.actors;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.foundation.utility.AllShapes;
import com.simibubi.create.modules.contraptions.components.contraptions.IPortableBlock; import com.simibubi.create.modules.contraptions.components.contraptions.IPortableBlock;
import com.simibubi.create.modules.contraptions.components.contraptions.MovementBehaviour; import com.simibubi.create.modules.contraptions.components.contraptions.MovementBehaviour;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.HorizontalBlock;
import net.minecraft.block.material.PushReaction;
import net.minecraft.item.BlockItemUseContext;
import net.minecraft.state.StateContainer.Builder;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction;
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; import net.minecraft.world.IBlockReader;
import net.minecraft.world.IWorldReader;
public class HarvesterBlock extends HorizontalBlock implements IPortableBlock { public class HarvesterBlock extends AttachedActorBlock implements IPortableBlock {
public static MovementBehaviour MOVEMENT = new HarvesterMovementBehaviour(); public static MovementBehaviour MOVEMENT = new HarvesterMovementBehaviour();
public HarvesterBlock() {
super(Properties.from(Blocks.IRON_BLOCK));
}
@Override @Override
public boolean hasTileEntity(BlockState state) { public boolean hasTileEntity(BlockState state) {
return true; return true;
@ -38,51 +21,11 @@ public class HarvesterBlock extends HorizontalBlock implements IPortableBlock {
return new HarvesterTileEntity(); return new HarvesterTileEntity();
} }
@Override
public PushReaction getPushReaction(BlockState state) {
return PushReaction.PUSH_ONLY;
}
@Override
public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) {
Direction direction = state.get(HORIZONTAL_FACING);
return AllShapes.HARVESTER_BASE.get(direction);
}
@Override
protected void fillStateContainer(Builder<Block, BlockState> builder) {
builder.add(HORIZONTAL_FACING);
super.fillStateContainer(builder);
}
// @Override // TOOD 1.15 register layer // @Override // TOOD 1.15 register layer
// public BlockRenderLayer getRenderLayer() { // public BlockRenderLayer getRenderLayer() {
// return BlockRenderLayer.CUTOUT; // return BlockRenderLayer.CUTOUT;
// } // }
@Override
public boolean isValidPosition(BlockState state, IWorldReader worldIn, BlockPos pos) {
Direction direction = state.get(HORIZONTAL_FACING);
BlockPos offset = pos.offset(direction.getOpposite());
return Block.hasSolidSide(worldIn.getBlockState(offset), worldIn, offset, direction);
}
@Override
public BlockState getStateForPlacement(BlockItemUseContext context) {
Direction facing;
if (context.getFace().getAxis().isVertical())
facing = context.getPlacementHorizontalFacing().getOpposite();
else {
BlockState blockState =
context.getWorld().getBlockState(context.getPos().offset(context.getFace().getOpposite()));
if (AllBlocks.HARVESTER.typeOf(blockState))
facing = blockState.get(HORIZONTAL_FACING);
else
facing = context.getFace();
}
return getDefaultState().with(HORIZONTAL_FACING, facing);
}
@Override @Override
public MovementBehaviour getMovementBehaviour() { public MovementBehaviour getMovementBehaviour() {
return MOVEMENT; return MOVEMENT;

View file

@ -42,7 +42,7 @@ public class HarvesterMovementBehaviour extends MovementBehaviour {
@Override @Override
public Vec3d getActiveAreaOffset(MovementContext context) { public Vec3d getActiveAreaOffset(MovementContext context) {
return new Vec3d(context.state.get(HORIZONTAL_FACING).getDirectionVec()).scale(.5); return new Vec3d(context.state.get(HORIZONTAL_FACING).getDirectionVec()).scale(.45);
} }
@Override @Override

View file

@ -0,0 +1,34 @@
package com.simibubi.create.modules.contraptions.components.actors;
import java.util.UUID;
import com.mojang.authlib.GameProfile;
import com.simibubi.create.modules.contraptions.components.contraptions.MovementBehaviour;
import net.minecraft.world.server.ServerWorld;
import net.minecraftforge.common.util.FakePlayer;
public class PloughBlock extends AttachedActorBlock {
public static MovementBehaviour MOVEMENT = new PloughMovementBehaviour();
@Override
public MovementBehaviour getMovementBehaviour() {
return MOVEMENT;
}
/**
* The OnHoeUse event takes a player, so we better not pass null
*/
static class PloughFakePlayer extends FakePlayer {
public static final GameProfile PLOUGH_PROFILE =
new GameProfile(UUID.fromString("9e2faded-eeee-4ec2-c314-dad129ae971d"), "Plough");
public PloughFakePlayer(ServerWorld world) {
super(world, PLOUGH_PROFILE);
}
}
}

View file

@ -0,0 +1,88 @@
package com.simibubi.create.modules.contraptions.components.actors;
import static net.minecraft.block.HorizontalBlock.HORIZONTAL_FACING;
import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.modules.contraptions.components.actors.PloughBlock.PloughFakePlayer;
import com.simibubi.create.modules.contraptions.components.contraptions.MovementContext;
import net.minecraft.block.BlockState;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemUseContext;
import net.minecraft.item.Items;
import net.minecraft.util.Hand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.util.math.RayTraceContext;
import net.minecraft.util.math.RayTraceContext.BlockMode;
import net.minecraft.util.math.RayTraceContext.FluidMode;
import net.minecraft.util.math.RayTraceResult.Type;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import net.minecraft.world.server.ServerWorld;
public class PloughMovementBehaviour extends BlockBreakingMovementBehaviour {
@Override
public boolean isActive(MovementContext context) {
return !VecHelper.isVecPointingTowards(context.relativeMotion,
context.state.get(HORIZONTAL_FACING).getOpposite());
}
@Override
public void visitNewPosition(MovementContext context, BlockPos pos) {
super.visitNewPosition(context, pos);
World world = context.world;
if (world.isRemote)
return;
BlockPos below = pos.down();
if (!world.isBlockPresent(below))
return;
Vec3d vec = VecHelper.getCenterOf(pos);
PloughFakePlayer player = getPlayer(context);
if (player == null)
return;
BlockRayTraceResult ray = world
.rayTraceBlocks(new RayTraceContext(vec, vec.add(0, -1, 0), BlockMode.OUTLINE, FluidMode.NONE, player));
if (ray == null || ray.getType() != Type.BLOCK)
return;
ItemUseContext ctx = new ItemUseContext(player, Hand.MAIN_HAND, ray);
new ItemStack(Items.DIAMOND_HOE).onItemUse(ctx);
}
@Override
public Vec3d getActiveAreaOffset(MovementContext context) {
return new Vec3d(context.state.get(HORIZONTAL_FACING).getDirectionVec()).scale(.45);
}
@Override
protected boolean throwsEntities() {
return true;
}
@Override
public boolean canBreak(World world, BlockPos breakingPos, BlockState state) {
return state.getCollisionShape(world, breakingPos).isEmpty();
}
@Override
public void stopMoving(MovementContext context) {
super.stopMoving(context);
if (context.temporaryData instanceof PloughFakePlayer)
((PloughFakePlayer) context.temporaryData).remove();
}
private PloughFakePlayer getPlayer(MovementContext context) {
if (!(context.temporaryData instanceof PloughFakePlayer) && context.world instanceof ServerWorld) {
PloughFakePlayer player = new PloughFakePlayer((ServerWorld) context.world);
player.setHeldItem(Hand.MAIN_HAND, new ItemStack(Items.DIAMOND_HOE));
context.temporaryData = player;
}
return (PloughFakePlayer) context.temporaryData;
}
}

View file

@ -6,6 +6,7 @@ import com.simibubi.create.foundation.utility.TreeCutter.Tree;
import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.modules.contraptions.components.contraptions.MovementContext; import com.simibubi.create.modules.contraptions.components.contraptions.MovementContext;
import com.simibubi.create.modules.contraptions.components.saw.SawBlock; import com.simibubi.create.modules.contraptions.components.saw.SawBlock;
import com.simibubi.create.modules.contraptions.components.saw.SawTileEntity;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.entity.item.ItemEntity; import net.minecraft.entity.item.ItemEntity;
@ -31,12 +32,13 @@ public class SawMovementBehaviour extends BlockBreakingMovementBehaviour {
@Override @Override
public boolean canBreak(World world, BlockPos breakingPos, BlockState state) { public boolean canBreak(World world, BlockPos breakingPos, BlockState state) {
return super.canBreak(world, breakingPos, state) return super.canBreak(world, breakingPos, state) && SawTileEntity.isSawable(state);
&& (state.isIn(BlockTags.LOGS) || state.isIn(BlockTags.LEAVES));
} }
@Override @Override
protected void onBlockBroken(MovementContext context, BlockPos pos) { protected void onBlockBroken(MovementContext context, BlockPos pos, BlockState brokenState) {
if (brokenState.isIn(BlockTags.LEAVES))
return;
Tree tree = TreeCutter.cutTree(context.world, pos); Tree tree = TreeCutter.cutTree(context.world, pos);
if (tree != null) { if (tree != null) {
for (BlockPos log : tree.logs) for (BlockPos log : tree.logs)

View file

@ -1,6 +1,7 @@
package com.simibubi.create.modules.contraptions.components.contraptions; package com.simibubi.create.modules.contraptions.components.contraptions;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.modules.contraptions.components.actors.AttachedActorBlock;
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.actors.PortableStorageInterfaceBlock;
import com.simibubi.create.modules.contraptions.components.contraptions.bearing.ClockworkBearingBlock; import com.simibubi.create.modules.contraptions.components.contraptions.bearing.ClockworkBearingBlock;
@ -11,6 +12,8 @@ import com.simibubi.create.modules.contraptions.components.contraptions.chassis.
import com.simibubi.create.modules.contraptions.components.contraptions.piston.MechanicalPistonBlock; import com.simibubi.create.modules.contraptions.components.contraptions.piston.MechanicalPistonBlock;
import com.simibubi.create.modules.contraptions.components.contraptions.piston.MechanicalPistonBlock.PistonState; import com.simibubi.create.modules.contraptions.components.contraptions.piston.MechanicalPistonBlock.PistonState;
import com.simibubi.create.modules.contraptions.components.contraptions.pulley.PulleyBlock; import com.simibubi.create.modules.contraptions.components.contraptions.pulley.PulleyBlock;
import com.simibubi.create.modules.contraptions.components.contraptions.pulley.PulleyBlock.MagnetBlock;
import com.simibubi.create.modules.contraptions.components.contraptions.pulley.PulleyBlock.RopeBlock;
import com.simibubi.create.modules.contraptions.components.contraptions.pulley.PulleyTileEntity; import com.simibubi.create.modules.contraptions.components.contraptions.pulley.PulleyTileEntity;
import com.simibubi.create.modules.logistics.block.AttachedLogisticalBlock; import com.simibubi.create.modules.logistics.block.AttachedLogisticalBlock;
import com.simibubi.create.modules.logistics.block.RedstoneLinkBlock; import com.simibubi.create.modules.logistics.block.RedstoneLinkBlock;
@ -82,7 +85,7 @@ public class BlockMovementTraits {
if (block instanceof PulleyBlock) { if (block instanceof PulleyBlock) {
TileEntity te = world.getTileEntity(pos); TileEntity te = world.getTileEntity(pos);
if (te instanceof PulleyTileEntity) if (te instanceof PulleyTileEntity)
return !((PulleyTileEntity) te).running && ((PulleyTileEntity) te).offset == 0; return !((PulleyTileEntity) te).running;
} }
if (AllBlocks.BELT.typeOf(blockState)) if (AllBlocks.BELT.typeOf(blockState))
@ -126,6 +129,10 @@ public class BlockMovementTraits {
return true; return true;
if (block instanceof RedstoneLinkBlock) if (block instanceof RedstoneLinkBlock)
return true; return true;
if (block instanceof RopeBlock)
return true;
if (block instanceof MagnetBlock)
return true;
return false; return false;
} }
@ -169,7 +176,7 @@ public class BlockMovementTraits {
return direction == (state.get(BlockStateProperties.HANGING) ? Direction.UP : Direction.DOWN); return direction == (state.get(BlockStateProperties.HANGING) ? Direction.UP : Direction.DOWN);
if (block instanceof AbstractRailBlock) if (block instanceof AbstractRailBlock)
return direction == Direction.DOWN; return direction == Direction.DOWN;
if (block instanceof HarvesterBlock) if (block instanceof AttachedActorBlock)
return direction == state.get(HarvesterBlock.HORIZONTAL_FACING).getOpposite(); return direction == state.get(HarvesterBlock.HORIZONTAL_FACING).getOpposite();
return false; return false;
} }
@ -185,8 +192,10 @@ public class BlockMovementTraits {
return state.get(BlockStateProperties.FACING) == facing; return state.get(BlockStateProperties.FACING) == facing;
if (AllBlocks.PORTABLE_STORAGE_INTERFACE.typeOf(state)) if (AllBlocks.PORTABLE_STORAGE_INTERFACE.typeOf(state))
return state.get(PortableStorageInterfaceBlock.FACING) == facing; return state.get(PortableStorageInterfaceBlock.FACING) == facing;
if (AllBlocks.HARVESTER.typeOf(state)) if (state.getBlock() instanceof AttachedActorBlock)
return state.get(BlockStateProperties.HORIZONTAL_FACING) == facing; return state.get(BlockStateProperties.HORIZONTAL_FACING) == facing;
if (AllBlocks.ROPE_PULLEY.typeOf(state))
return facing == Direction.DOWN;
return isBrittle(state); return isBrittle(state);
} }

View file

@ -10,18 +10,19 @@ import java.util.Map;
import java.util.Set; import java.util.Set;
import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.platform.GlStateManager;
import com.mojang.blaze3d.platform.GlStateManager.DestFactor; import com.mojang.blaze3d.platform.GlStateManager.DestFactor;
import com.mojang.blaze3d.platform.GlStateManager.SourceFactor; import com.mojang.blaze3d.platform.GlStateManager.SourceFactor;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.RenderSystem;
import com.simibubi.create.AllItems; import com.simibubi.create.AllItems;
import com.simibubi.create.AllKeys; import com.simibubi.create.AllKeys;
import com.simibubi.create.foundation.utility.TessellatorHelper; import com.simibubi.create.foundation.utility.TessellatorHelper;
import com.simibubi.create.foundation.utility.outliner.BlockClusterOutline;
import com.simibubi.create.foundation.utility.outliner.Outline;
import com.simibubi.create.foundation.utility.outliner.OutlineParticle;
import com.simibubi.create.modules.contraptions.components.contraptions.chassis.ChassisTileEntity; import com.simibubi.create.modules.contraptions.components.contraptions.chassis.ChassisTileEntity;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.renderer.IRenderTypeBuffer;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
@ -35,13 +36,15 @@ public class ChassisRangeDisplay {
private static GroupEntry lastHoveredGroup = null; private static GroupEntry lastHoveredGroup = null;
private static class Entry { private static class Entry {
Set<BlockPos> includedPositions; BlockClusterOutline outline;
OutlineParticle<Outline> particle;
ChassisTileEntity te; ChassisTileEntity te;
int timer; int timer;
public Entry(ChassisTileEntity te) { public Entry(ChassisTileEntity te) {
this.te = te; this.te = te;
includedPositions = createSelection(te); outline = new BlockClusterOutline(createSelection(te));
particle = OutlineParticle.create(outline);
timer = DISPLAY_TIME; timer = DISPLAY_TIME;
} }
@ -85,14 +88,19 @@ public class ChassisRangeDisplay {
World world = Minecraft.getInstance().world; World world = Minecraft.getInstance().world;
boolean hasWrench = AllItems.WRENCH.typeOf(player.getHeldItemMainhand()); boolean hasWrench = AllItems.WRENCH.typeOf(player.getHeldItemMainhand());
for (Iterator<BlockPos> iterator = entries.keySet().iterator(); iterator.hasNext();) for (Iterator<BlockPos> iterator = entries.keySet().iterator(); iterator.hasNext();) {
if (tickEntry(entries.get(iterator.next()), hasWrench)) Entry entry = entries.get(iterator.next());
if (tickEntry(entry, hasWrench)) {
entry.particle.remove();
iterator.remove(); iterator.remove();
}
}
for (Iterator<GroupEntry> iterator = groupEntries.iterator(); iterator.hasNext();) { for (Iterator<GroupEntry> iterator = groupEntries.iterator(); iterator.hasNext();) {
GroupEntry group = iterator.next(); GroupEntry group = iterator.next();
if (tickEntry(group, hasWrench)) { if (tickEntry(group, hasWrench)) {
iterator.remove(); iterator.remove();
group.particle.remove();
if (group == lastHoveredGroup) if (group == lastHoveredGroup)
lastHoveredGroup = null; lastHoveredGroup = null;
} }
@ -118,8 +126,11 @@ public class ChassisRangeDisplay {
if (ctrl) { if (ctrl) {
GroupEntry existingGroupForPos = getExistingGroupForPos(pos); GroupEntry existingGroupForPos = getExistingGroupForPos(pos);
if (existingGroupForPos != null) { if (existingGroupForPos != null) {
for (ChassisTileEntity included : existingGroupForPos.includedTEs) for (ChassisTileEntity included : existingGroupForPos.includedTEs) {
entries.remove(included.getPos()); Entry removed = entries.remove(included.getPos());
if (removed != null)
removed.particle.remove();
}
existingGroupForPos.timer = DISPLAY_TIME; existingGroupForPos.timer = DISPLAY_TIME;
return; return;
} }
@ -167,13 +178,19 @@ public class ChassisRangeDisplay {
public static void display(ChassisTileEntity chassis) { public static void display(ChassisTileEntity chassis) {
deselect(); deselect();
if (AllKeys.ctrlDown()) { if (AllKeys.ctrlDown()) {
groupEntries.forEach(e -> e.particle.remove());
groupEntries.clear(); groupEntries.clear();
GroupEntry hoveredGroup = new GroupEntry(chassis); GroupEntry hoveredGroup = new GroupEntry(chassis);
for (ChassisTileEntity included : hoveredGroup.includedTEs) for (ChassisTileEntity included : hoveredGroup.includedTEs) {
entries.remove(included.getPos()); Entry remove = entries.remove(included.getPos());
if (remove != null)
remove.particle.remove();
}
groupEntries.add(hoveredGroup); groupEntries.add(hoveredGroup);
} else { } else {
entries.put(chassis.getPos(), new Entry(chassis)); Entry old = entries.put(chassis.getPos(), new Entry(chassis));
if (old != null)
old.particle.remove();
} }
} }
@ -196,17 +213,23 @@ public class ChassisRangeDisplay {
} }
public static void renderPositions(Entry entry, float partialTicks) { public static void renderPositions(Entry entry, float partialTicks) {
TessellatorHelper.begin(); // GlStateManager.pushMatrix();
BlockPos size = new BlockPos(1, 1, 1); // RenderHelper.disableStandardItemLighting();
// GlStateManager.normal3f(0.0F, 1.0F, 0.0F);
// GlStateManager.color4f(1, 1, 1, 1);
// GlStateManager.enableTexture();
// GlStateManager.depthMask(false);
// GlStateManager.enableBlend();
// GlStateManager.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA);
//
float timer = entry.timer - partialTicks; float timer = entry.timer - partialTicks;
float alpha = timer > 20 ? .5f : timer / 40f; float alpha = timer > 20 ? 1 : timer / 20f;
RenderSystem.color4f(1, .7f, 0, alpha); entry.outline.setAlpha(alpha);
Set<BlockPos> includedPositions = entry.includedPositions; // entry.outline.render(Tessellator.getInstance().getBuffer());
GlStateManager.depthMask(false); //
for (BlockPos pos : includedPositions) // GlStateManager.disableBlend();
TessellatorHelper.cube(Tessellator.getInstance().getBuffer(), pos, size, 1 / 16f - 1 / 64f, true, false); // GlStateManager.depthMask(true);
TessellatorHelper.draw(); // GlStateManager.popMatrix();
GlStateManager.depthMask(true);
} }
private static GroupEntry getExistingGroupForPos(BlockPos pos) { private static GroupEntry getExistingGroupForPos(BlockPos pos) {

View file

@ -25,14 +25,19 @@ import com.simibubi.create.foundation.utility.WrappedWorld;
import com.simibubi.create.modules.contraptions.base.KineticTileEntity; import com.simibubi.create.modules.contraptions.base.KineticTileEntity;
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;
import com.simibubi.create.modules.contraptions.components.contraptions.glue.SuperGlueEntity;
import com.simibubi.create.modules.contraptions.components.contraptions.glue.SuperGlueHandler;
import com.simibubi.create.modules.contraptions.components.contraptions.piston.MechanicalPistonBlock; import com.simibubi.create.modules.contraptions.components.contraptions.piston.MechanicalPistonBlock;
import com.simibubi.create.modules.contraptions.components.contraptions.piston.PistonPoleBlock;
import com.simibubi.create.modules.contraptions.components.contraptions.piston.MechanicalPistonBlock.PistonState; import com.simibubi.create.modules.contraptions.components.contraptions.piston.MechanicalPistonBlock.PistonState;
import com.simibubi.create.modules.contraptions.components.contraptions.piston.MechanicalPistonHeadBlock; import com.simibubi.create.modules.contraptions.components.contraptions.piston.MechanicalPistonHeadBlock;
import com.simibubi.create.modules.contraptions.components.contraptions.piston.PistonPoleBlock;
import com.simibubi.create.modules.contraptions.components.contraptions.pulley.PulleyBlock;
import com.simibubi.create.modules.contraptions.components.contraptions.pulley.PulleyBlock.MagnetBlock;
import com.simibubi.create.modules.contraptions.components.contraptions.pulley.PulleyBlock.RopeBlock;
import com.simibubi.create.modules.contraptions.components.contraptions.pulley.PulleyTileEntity;
import com.simibubi.create.modules.contraptions.components.saw.SawBlock; import com.simibubi.create.modules.contraptions.components.saw.SawBlock;
import com.simibubi.create.modules.contraptions.redstone.ContactBlock; import com.simibubi.create.modules.contraptions.redstone.ContactBlock;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock; import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock;
import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity;
import com.simibubi.create.modules.logistics.block.inventories.FlexcrateBlock; import com.simibubi.create.modules.logistics.block.inventories.FlexcrateBlock;
import net.minecraft.block.AbstractButtonBlock; import net.minecraft.block.AbstractButtonBlock;
@ -54,6 +59,7 @@ 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;
import net.minecraft.util.Rotation;
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.util.math.Vec3d;
@ -71,6 +77,7 @@ public abstract class Contraption {
public List<MutablePair<BlockInfo, MovementContext>> actors; public List<MutablePair<BlockInfo, MovementContext>> actors;
public CombinedInvWrapper inventory; public CombinedInvWrapper inventory;
public List<TileEntity> customRenderTEs; public List<TileEntity> customRenderTEs;
public Set<Pair<BlockPos, Direction>> superglue;
public AxisAlignedBB bounds; public AxisAlignedBB bounds;
public boolean stalled; public boolean stalled;
@ -80,13 +87,16 @@ public abstract class Contraption {
protected BlockPos anchor; protected BlockPos anchor;
List<BlockPos> renderOrder; List<BlockPos> renderOrder;
protected List<SuperGlueEntity> glueToRemove;
public Contraption() { public Contraption() {
blocks = new HashMap<>(); blocks = new HashMap<>();
storage = new HashMap<>(); storage = new HashMap<>();
actors = new ArrayList<>(); actors = new ArrayList<>();
superglue = new HashSet<>();
renderOrder = new ArrayList<>(); renderOrder = new ArrayList<>();
customRenderTEs = new ArrayList<>(); customRenderTEs = new ArrayList<>();
glueToRemove = new ArrayList<>();
} }
public Set<BlockPos> getColliders(World world, Direction movementDirection) { public Set<BlockPos> getColliders(World world, Direction movementDirection) {
@ -118,7 +128,8 @@ public abstract class Contraption {
if (bounds == null) if (bounds == null)
bounds = new AxisAlignedBB(BlockPos.ZERO); bounds = new AxisAlignedBB(BlockPos.ZERO);
frontier.add(pos); if (!BlockMovementTraits.isBrittle(world.getBlockState(pos)))
frontier.add(pos);
if (!addToInitialFrontier(world, pos, forcedDirection, frontier)) if (!addToInitialFrontier(world, pos, forcedDirection, frontier))
return false; return false;
for (int limit = 100000; limit > 0; limit--) { for (int limit = 100000; limit > 0; limit--) {
@ -148,6 +159,8 @@ public abstract class Contraption {
if (!world.isBlockPresent(pos)) if (!world.isBlockPresent(pos))
return false; return false;
if (isAnchoringBlockAt(pos))
return true;
if (!BlockMovementTraits.movementNecessary(world, pos)) if (!BlockMovementTraits.movementNecessary(world, pos))
return true; return true;
if (!BlockMovementTraits.movementAllowed(world, pos)) if (!BlockMovementTraits.movementAllowed(world, pos))
@ -155,6 +168,7 @@ public abstract class Contraption {
BlockState state = world.getBlockState(pos); BlockState state = world.getBlockState(pos);
if (isChassis(state) && !moveChassis(world, pos, forcedDirection, frontier, visited)) if (isChassis(state) && !moveChassis(world, pos, forcedDirection, frontier, visited))
return false; return false;
if (AllBlocks.FLEXCRATE.typeOf(state)) if (AllBlocks.FLEXCRATE.typeOf(state))
FlexcrateBlock.splitCrate(world, pos); FlexcrateBlock.splitCrate(world, pos);
if (AllBlocks.BELT.typeOf(state)) { if (AllBlocks.BELT.typeOf(state)) {
@ -165,7 +179,27 @@ public abstract class Contraption {
if (prevPos != null && !visited.contains(prevPos)) if (prevPos != null && !visited.contains(prevPos))
frontier.add(prevPos); frontier.add(prevPos);
} }
// Pulleys drag their rope and their attached structure
if (state.getBlock() instanceof PulleyBlock) {
int limit = AllConfigs.SERVER.kinetics.maxRopeLength.get();
BlockPos ropePos = pos;
while (limit-- >= 0) {
ropePos = ropePos.down();
if (!world.isBlockPresent(ropePos))
break;
BlockState ropeState = world.getBlockState(ropePos);
Block block = ropeState.getBlock();
if (!(block instanceof RopeBlock) && !(block instanceof MagnetBlock)) {
if (!visited.contains(ropePos))
frontier.add(ropePos);
break;
}
add(ropePos, capture(world, ropePos));
}
}
// Pistons drag their attaches poles and extension
if (state.getBlock() instanceof MechanicalPistonBlock) { if (state.getBlock() instanceof MechanicalPistonBlock) {
int limit = AllConfigs.SERVER.kinetics.maxPistonPoles.get(); int limit = AllConfigs.SERVER.kinetics.maxPistonPoles.get();
Direction direction = state.get(MechanicalPistonBlock.FACING); Direction direction = state.get(MechanicalPistonBlock.FACING);
@ -189,7 +223,7 @@ public abstract class Contraption {
if (limit <= -1) if (limit <= -1)
return false; return false;
} }
BlockPos searchPos = pos; BlockPos searchPos = pos;
while (limit-- >= 0) { while (limit-- >= 0) {
searchPos = searchPos.offset(direction.getOpposite()); searchPos = searchPos.offset(direction.getOpposite());
@ -203,17 +237,21 @@ public abstract class Contraption {
} }
break; break;
} }
if (limit <= -1) if (limit <= -1)
return false; return false;
} }
// Doors try to stay whole
if (state.getBlock() instanceof DoorBlock) { if (state.getBlock() instanceof DoorBlock) {
BlockPos otherPartPos = pos.up(state.get(DoorBlock.HALF) == DoubleBlockHalf.LOWER ? 1 : -1); BlockPos otherPartPos = pos.up(state.get(DoorBlock.HALF) == DoubleBlockHalf.LOWER ? 1 : -1);
if (!visited.contains(otherPartPos)) if (!visited.contains(otherPartPos))
frontier.add(otherPartPos); frontier.add(otherPartPos);
} }
Map<Direction, SuperGlueEntity> superglue = SuperGlueHandler.gatherGlue(world, pos);
// Slime blocks drag adjacent blocks if possible
boolean isSlimeBlock = state.getBlock() instanceof SlimeBlock; boolean isSlimeBlock = state.getBlock() instanceof SlimeBlock;
for (Direction offset : Direction.values()) { for (Direction offset : Direction.values()) {
BlockPos offsetPos = pos.offset(offset); BlockPos offsetPos = pos.offset(offset);
@ -225,14 +263,24 @@ public abstract class Contraption {
return false; return false;
continue; continue;
} }
if (!visited.contains(offsetPos)
&& (isSlimeBlock || BlockMovementTraits.isBlockAttachedTowards(blockState, offset.getOpposite()))) boolean wasVisited = visited.contains(offsetPos);
boolean faceHasGlue = superglue.containsKey(offset);
boolean blockAttachedTowardsFace =
BlockMovementTraits.isBlockAttachedTowards(blockState, offset.getOpposite());
boolean brittle = BlockMovementTraits.isBrittle(blockState);
if (!wasVisited && ((isSlimeBlock && !brittle) || blockAttachedTowardsFace || faceHasGlue))
frontier.add(offsetPos); frontier.add(offsetPos);
if (faceHasGlue)
addGlue(superglue.get(offset));
} }
add(pos, capture(world, pos)); add(pos, capture(world, pos));
if (blocks.size() > AllConfigs.SERVER.kinetics.maxBlocksMoved.get()) if (blocks.size() > AllConfigs.SERVER.kinetics.maxBlocksMoved.get())
return false; return false;
return true; return true;
} }
@ -295,6 +343,14 @@ public abstract class Contraption {
return compoundnbt; return compoundnbt;
} }
public void addGlue(SuperGlueEntity entity) {
BlockPos pos = entity.getHangingPosition();
Direction direction = entity.getFacingDirection();
BlockPos localPos = pos.subtract(anchor);
this.superglue.add(Pair.of(localPos, direction));
glueToRemove.add(entity);
}
public void add(BlockPos pos, Pair<BlockInfo, TileEntity> pair) { public void add(BlockPos pos, Pair<BlockInfo, TileEntity> pair) {
BlockInfo captured = pair.getKey(); BlockInfo captured = pair.getKey();
BlockPos localPos = pos.subtract(anchor); BlockPos localPos = pos.subtract(anchor);
@ -371,6 +427,13 @@ public abstract class Contraption {
getActors().add(MutablePair.of(info, context)); getActors().add(MutablePair.of(info, context));
}); });
superglue.clear();
nbt.getList("Superglue", 10).forEach(c -> {
CompoundNBT comp = (CompoundNBT) c;
superglue.add(Pair.of(NBTUtil.readBlockPos(comp.getCompound("Pos")),
Direction.byIndex(comp.getByte("Direction"))));
});
storage.clear(); storage.clear();
nbt.getList("Storage", 10).forEach(c -> { nbt.getList("Storage", 10).forEach(c -> {
CompoundNBT comp = (CompoundNBT) c; CompoundNBT comp = (CompoundNBT) c;
@ -409,6 +472,14 @@ public abstract class Contraption {
actorsNBT.add(compound); actorsNBT.add(compound);
} }
ListNBT superglueNBT = new ListNBT();
for (Pair<BlockPos, Direction> glueEntry : superglue) {
CompoundNBT c = new CompoundNBT();
c.put("Pos", NBTUtil.writeBlockPos(glueEntry.getKey()));
c.putByte("Direction", (byte) glueEntry.getValue().getIndex());
superglueNBT.add(c);
}
ListNBT storageNBT = new ListNBT(); ListNBT storageNBT = new ListNBT();
for (BlockPos pos : storage.keySet()) { for (BlockPos pos : storage.keySet()) {
CompoundNBT c = new CompoundNBT(); CompoundNBT c = new CompoundNBT();
@ -422,6 +493,7 @@ public abstract class Contraption {
nbt.put("Blocks", blocksNBT); nbt.put("Blocks", blocksNBT);
nbt.put("Actors", actorsNBT); nbt.put("Actors", actorsNBT);
nbt.put("Superglue", superglueNBT);
nbt.put("Storage", storageNBT); nbt.put("Storage", storageNBT);
nbt.put("Anchor", NBTUtil.writeBlockPos(anchor)); nbt.put("Anchor", NBTUtil.writeBlockPos(anchor));
nbt.putBoolean("Stalled", stalled); nbt.putBoolean("Stalled", stalled);
@ -435,11 +507,7 @@ public abstract class Contraption {
} }
public static boolean isFrozen() { public static boolean isFrozen() {
return AllConfigs.SERVER.control.freezePistonConstructs.get(); return AllConfigs.SERVER.control.freezeContraptions.get();
}
public void disassemble(World world, BlockPos offset, Vec3d rotation) {
disassemble(world, offset, rotation, (pos, state) -> false);
} }
public void removeBlocksFromWorld(IWorld world, BlockPos offset) { public void removeBlocksFromWorld(IWorld world, BlockPos offset) {
@ -448,6 +516,8 @@ public abstract class Contraption {
public void removeBlocksFromWorld(IWorld world, BlockPos offset, BiPredicate<BlockPos, BlockState> customRemoval) { public void removeBlocksFromWorld(IWorld world, BlockPos offset, BiPredicate<BlockPos, BlockState> customRemoval) {
storage.values().forEach(MountedStorage::empty); storage.values().forEach(MountedStorage::empty);
glueToRemove.forEach(SuperGlueEntity::remove);
for (boolean brittles : Iterate.trueAndFalse) { for (boolean brittles : Iterate.trueAndFalse) {
for (BlockInfo block : blocks.values()) { for (BlockInfo block : blocks.values()) {
if (brittles != BlockMovementTraits.isBrittle(block.state)) if (brittles != BlockMovementTraits.isBrittle(block.state))
@ -465,7 +535,11 @@ public abstract class Contraption {
} }
} }
public void disassemble(World world, BlockPos offset, Vec3d rotation, public void addBlocksToWorld(World world, BlockPos offset, Vec3d rotation) {
addBlocksToWorld(world, offset, rotation, (pos, state) -> false);
}
public void addBlocksToWorld(World world, BlockPos offset, Vec3d rotation,
BiPredicate<BlockPos, BlockState> customPlacement) { BiPredicate<BlockPos, BlockState> customPlacement) {
stop(world); stop(world);
@ -497,8 +571,16 @@ public abstract class Contraption {
&& !blockState.getCollisionShape(world, targetPos).isEmpty()) && !blockState.getCollisionShape(world, targetPos).isEmpty())
continue; continue;
world.destroyBlock(targetPos, blockState.getCollisionShape(world, targetPos).isEmpty()); world.destroyBlock(targetPos, true);
world.setBlockState(targetPos, state, 3 | BlockFlags.IS_MOVING); world.setBlockState(targetPos, state, 3 | BlockFlags.IS_MOVING);
boolean verticalRotation = transform.rotationAxis == null || transform.rotationAxis.isHorizontal();
verticalRotation = verticalRotation && transform.rotation != Rotation.NONE;
if (verticalRotation) {
if (state.getBlock() instanceof RopeBlock || state.getBlock() instanceof MagnetBlock)
world.destroyBlock(targetPos, true);
}
TileEntity tileEntity = world.getTileEntity(targetPos); TileEntity tileEntity = world.getTileEntity(targetPos);
CompoundNBT tag = block.nbt; CompoundNBT tag = block.nbt;
if (tileEntity != null && tag != null) { if (tileEntity != null && tag != null) {
@ -506,32 +588,34 @@ public abstract class Contraption {
tag.putInt("y", targetPos.getY()); tag.putInt("y", targetPos.getY());
tag.putInt("z", targetPos.getZ()); tag.putInt("z", targetPos.getZ());
if (tileEntity instanceof BeltTileEntity) { if (verticalRotation && tileEntity instanceof PulleyTileEntity) {
tag.remove("Length"); tag.remove("Offset");
tag.remove("Index"); tag.remove("InitialOffset");
tag.putBoolean("DontClearAttachments", true);
} }
tileEntity.read(tag); tileEntity.read(tag);
if (tileEntity instanceof KineticTileEntity) {
KineticTileEntity kineticTileEntity = (KineticTileEntity) tileEntity;
kineticTileEntity.source = null;
kineticTileEntity.setSpeed(0);
kineticTileEntity.network = null;
kineticTileEntity.attachKinetics();
}
if (storage.containsKey(block.pos)) { if (storage.containsKey(block.pos)) {
MountedStorage mountedStorage = storage.get(block.pos); MountedStorage mountedStorage = storage.get(block.pos);
if (mountedStorage.isWorking()) if (mountedStorage.isWorking())
mountedStorage.fill(tileEntity); mountedStorage.fill(tileEntity);
} }
} }
}
}
for (Pair<BlockPos, Direction> pair : superglue) {
BlockPos targetPos = transform.apply(pair.getKey());
Direction targetFacing = transform.transformFacing(pair.getValue());
SuperGlueEntity entity = new SuperGlueEntity(world, targetPos, targetFacing);
if (entity.onValidSurface()) {
if (!world.isRemote)
world.addEntity(entity);
} }
} }
} }
public void initActors(World world) { public void initActors(World world) {

View file

@ -12,16 +12,24 @@ import org.apache.commons.lang3.tuple.MutablePair;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.simibubi.create.AllEntities; import com.simibubi.create.AllEntities;
import com.simibubi.create.AllPackets; import com.simibubi.create.AllPackets;
import com.simibubi.create.foundation.item.ItemHelper;
import com.simibubi.create.foundation.utility.AngleHelper;
import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.utility.VecHelper;
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.mounted.CartAssemblerTileEntity.CartMovementMode;
import com.simibubi.create.modules.contraptions.components.contraptions.mounted.MountedContraption;
import com.simibubi.create.modules.contraptions.components.contraptions.piston.LinearActuatorTileEntity; import com.simibubi.create.modules.contraptions.components.contraptions.piston.LinearActuatorTileEntity;
import net.minecraft.block.BlockState;
import net.minecraft.block.material.PushReaction; import net.minecraft.block.material.PushReaction;
import net.minecraft.client.Minecraft; 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.BoatEntity; import net.minecraft.entity.item.BoatEntity;
import net.minecraft.entity.item.minecart.AbstractMinecartEntity; import net.minecraft.entity.item.minecart.FurnaceMinecartEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.item.crafting.Ingredient;
import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.CompoundNBT;
import net.minecraft.nbt.ListNBT; import net.minecraft.nbt.ListNBT;
import net.minecraft.nbt.NBTUtil; import net.minecraft.nbt.NBTUtil;
@ -30,11 +38,14 @@ import net.minecraft.network.PacketBuffer;
import net.minecraft.network.datasync.DataParameter; import net.minecraft.network.datasync.DataParameter;
import net.minecraft.network.datasync.DataSerializers; import net.minecraft.network.datasync.DataSerializers;
import net.minecraft.network.datasync.EntityDataManager; import net.minecraft.network.datasync.EntityDataManager;
import net.minecraft.tags.BlockTags;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.DamageSource;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.ReuseableStream; import net.minecraft.util.ReuseableStream;
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.math.Vec3d; import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.shapes.IBooleanFunction; import net.minecraft.util.math.shapes.IBooleanFunction;
import net.minecraft.util.math.shapes.ISelectionContext; import net.minecraft.util.math.shapes.ISelectionContext;
@ -42,7 +53,6 @@ import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.util.math.shapes.VoxelShapes; import net.minecraft.util.math.shapes.VoxelShapes;
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.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.fml.common.registry.IEntityAdditionalSpawnData; import net.minecraftforge.fml.common.registry.IEntityAdditionalSpawnData;
@ -53,12 +63,14 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
protected Contraption contraption; protected Contraption contraption;
protected float initialAngle; protected float initialAngle;
protected float forcedAngle;
protected BlockPos controllerPos; protected BlockPos controllerPos;
protected Vec3d motionBeforeStall; protected Vec3d motionBeforeStall;
protected boolean stationary; protected boolean stationary;
final List<Entity> collidingEntities = new ArrayList<>(); final List<Entity> collidingEntities = new ArrayList<>();
private static final Ingredient FUEL_ITEMS = Ingredient.fromItems(Items.COAL, Items.CHARCOAL);
private static final DataParameter<Boolean> STALLED = private static final DataParameter<Boolean> STALLED =
EntityDataManager.createKey(ContraptionEntity.class, DataSerializers.BOOLEAN); EntityDataManager.createKey(ContraptionEntity.class, DataSerializers.BOOLEAN);
@ -78,20 +90,27 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
super(entityTypeIn, worldIn); super(entityTypeIn, worldIn);
motionBeforeStall = Vec3d.ZERO; motionBeforeStall = Vec3d.ZERO;
stationary = entityTypeIn == AllEntities.STATIONARY_CONTRAPTION.type; stationary = entityTypeIn == AllEntities.STATIONARY_CONTRAPTION.type;
forcedAngle = -1;
} }
public static ContraptionEntity createMounted(World world, Contraption contraption, float initialAngle) { public static ContraptionEntity createMounted(World world, Contraption contraption, float initialAngle) {
ContraptionEntity entity = new ContraptionEntity(AllEntities.CONTRAPTION.type, world); ContraptionEntity entity = new ContraptionEntity(AllEntities.CONTRAPTION.type, world);
entity.contraption = contraption; entity.contraption = contraption;
entity.initialAngle = initialAngle; entity.initialAngle = initialAngle;
entity.prevYaw = initialAngle; entity.forceYaw(initialAngle);
entity.yaw = initialAngle;
entity.targetYaw = initialAngle;
if (contraption != null) if (contraption != null)
contraption.gatherStoredItems(); contraption.gatherStoredItems();
return entity; return entity;
} }
public static ContraptionEntity createMounted(World world, Contraption contraption, float initialAngle,
Direction facing) {
ContraptionEntity entity = createMounted(world, contraption, initialAngle);
entity.forcedAngle = facing.getHorizontalAngle();
entity.forceYaw(entity.forcedAngle);
return entity;
}
public static ContraptionEntity createStationary(World world, Contraption contraption) { public static ContraptionEntity createStationary(World world, Contraption contraption) {
ContraptionEntity entity = new ContraptionEntity(AllEntities.STATIONARY_CONTRAPTION.type, world); ContraptionEntity entity = new ContraptionEntity(AllEntities.STATIONARY_CONTRAPTION.type, world);
entity.contraption = contraption; entity.contraption = contraption;
@ -156,6 +175,14 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
} }
public void tickAsPassenger(Entity e) { public void tickAsPassenger(Entity e) {
boolean rotationLock = false;
boolean pauseWhileRotating = false;
if (contraption instanceof MountedContraption) {
rotationLock = ((MountedContraption) contraption).rotationMode == CartMovementMode.ROTATION_LOCKED;
pauseWhileRotating = ((MountedContraption) contraption).rotationMode == CartMovementMode.ROTATE_PAUSED;
}
Entity riding = e; Entity riding = e;
while (riding.getRidingEntity() != null) while (riding.getRidingEntity() != null)
riding = riding.getRidingEntity(); riding = riding.getRidingEntity();
@ -163,20 +190,28 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
if (riding instanceof BoatEntity) if (riding instanceof BoatEntity)
movementVector = getPositionVec().subtract(prevPosX, prevPosY, prevPosZ); movementVector = getPositionVec().subtract(prevPosX, prevPosY, prevPosZ);
Vec3d motion = movementVector.normalize(); Vec3d motion = movementVector.normalize();
boolean rotating = false;
if (motion.length() > 0) { if (!rotationLock) {
targetYaw = yawFromVector(motion); if (motion.length() > 0) {
if (targetYaw < 0) targetYaw = yawFromVector(motion);
targetYaw += 360; if (targetYaw < 0)
if (yaw < 0) targetYaw += 360;
yaw += 360; if (yaw < 0)
yaw += 360;
}
prevYaw = yaw;
yaw = angleLerp(0.4f, yaw, targetYaw);
if (Math.abs(AngleHelper.getShortestAngleDiff(yaw, targetYaw)) < 1f)
yaw = targetYaw;
else
rotating = true;
} }
prevYaw = yaw;
yaw = angleLerp(0.4f, yaw, targetYaw);
boolean wasStalled = isStalled(); boolean wasStalled = isStalled();
tickActors(movementVector); if (!rotating || !pauseWhileRotating)
tickActors(movementVector);
if (isStalled()) { if (isStalled()) {
if (!wasStalled) if (!wasStalled)
motionBeforeStall = riding.getMotion(); motionBeforeStall = riding.getMotion();
@ -188,6 +223,39 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
motionBeforeStall = Vec3d.ZERO; motionBeforeStall = Vec3d.ZERO;
} }
if (!isStalled() && (riding instanceof FurnaceMinecartEntity)) {
FurnaceMinecartEntity furnaceCart = (FurnaceMinecartEntity) riding;
CompoundNBT nbt = furnaceCart.serializeNBT();
int fuel = nbt.getInt("Fuel");
int fuelBefore = fuel;
double pushX = nbt.getDouble("PushX");
double pushZ = nbt.getDouble("PushZ");
int i = MathHelper.floor(furnaceCart.getX());
int j = MathHelper.floor(furnaceCart.getY());
int k = MathHelper.floor(furnaceCart.getZ());
if (furnaceCart.world.getBlockState(new BlockPos(i, j - 1, k)).isIn(BlockTags.RAILS))
--j;
BlockPos blockpos = new BlockPos(i, j, k);
BlockState blockstate = this.world.getBlockState(blockpos);
if (furnaceCart.canUseRail() && blockstate.isIn(BlockTags.RAILS))
if (fuel > 1)
riding.setMotion(riding.getMotion().normalize().scale(1));
if (fuel < 5 && contraption != null) {
ItemStack coal = ItemHelper.extract(contraption.inventory, FUEL_ITEMS, 1, false);
if (!coal.isEmpty())
fuel += 3600;
}
if (fuel != fuelBefore || pushX != 0 || pushZ != 0) {
nbt.putInt("Fuel", fuel);
nbt.putDouble("PushX", 0);
nbt.putDouble("PushZ", 0);
furnaceCart.deserializeNBT(nbt);
}
}
super.tick(); super.tick();
} }
@ -210,12 +278,12 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
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(getPositionVec()); actorPosition = actorPosition.add(rotationOffset).add(getAnchorVec());
boolean newPosVisited = false; boolean newPosVisited = false;
BlockPos gridPosition = new BlockPos(actorPosition); BlockPos gridPosition = new BlockPos(actorPosition);
if (!stalledPreviously) { if (!context.stall) {
Vec3d previousPosition = context.position; Vec3d previousPosition = context.position;
if (previousPosition != null) { if (previousPosition != null) {
context.motion = actorPosition.subtract(previousPosition); context.motion = actorPosition.subtract(previousPosition);
@ -245,13 +313,11 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
} }
} }
} }
} }
} }
context.rotation = rotationVec; context.rotation = rotationVec;
context.position = actorPosition; context.position = actorPosition;
if (actor.isActive(context)) { if (actor.isActive(context)) {
if (newPosVisited && !context.stall) { if (newPosVisited && !context.stall) {
actor.visitNewPosition(context, gridPosition); actor.visitNewPosition(context, gridPosition);
@ -280,6 +346,12 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
setPosition(x + getX() + x, getY() + y, getZ() + z); setPosition(x + getX() + x, getY() + y, getZ() + z);
} }
private Vec3d getAnchorVec() {
if (contraption != null && contraption.getType() == AllContraptionTypes.MOUNTED)
return new Vec3d(getX() - .5, getY(), getZ() - .5);
return getPositionVec();
}
public void rotateTo(double roll, double yaw, double pitch) { public void rotateTo(double roll, double yaw, double pitch) {
rotate(getShortestAngleDiff(this.roll, roll), getShortestAngleDiff(this.yaw, yaw), rotate(getShortestAngleDiff(this.roll, roll), getShortestAngleDiff(this.yaw, yaw),
getShortestAngleDiff(this.pitch, pitch)); getShortestAngleDiff(this.pitch, pitch));
@ -298,23 +370,13 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
@Override @Override
public void setPosition(double x, double y, double z) { public void setPosition(double x, double y, double z) {
Entity e = getRidingEntity(); super.setPosition(x, y, z);
if (e != null && e instanceof AbstractMinecartEntity) {
Entity riding = e;
while (riding.getRidingEntity() != null)
riding = riding.getRidingEntity();
x = riding.getX() - .5;
z = riding.getZ() - .5;
}
this.setPos(x, y, z);
if (this.isAddedToWorld() && !this.world.isRemote && world instanceof ServerWorld)
((ServerWorld) this.world).chunkCheck(this); // Forge - Process chunk registration after moving.
if (contraption != null) { if (contraption != null) {
AxisAlignedBB cbox = contraption.getBoundingBox(); AxisAlignedBB cbox = contraption.getBoundingBox();
if (cbox != null) if (cbox != null) {
this.setBoundingBox(cbox.offset(x, y, z)); Vec3d actualVec = getAnchorVec();
this.setBoundingBox(cbox.offset(actualVec));
}
} }
} }
@ -362,7 +424,7 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
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");
targetYaw = yaw = prevYaw = initialAngle; forceYaw(compound.contains("ForcedYaw") ? compound.getFloat("ForcedYaw") : initialAngle);
dataManager.set(STALLED, compound.getBoolean("Stalled")); dataManager.set(STALLED, compound.getBoolean("Stalled"));
ListNBT vecNBT = compound.getList("CachedMotion", 6); ListNBT vecNBT = compound.getList("CachedMotion", 6);
if (!vecNBT.isEmpty()) { if (!vecNBT.isEmpty()) {
@ -375,6 +437,10 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
controllerPos = NBTUtil.readBlockPos(compound.getCompound("Controller")); controllerPos = NBTUtil.readBlockPos(compound.getCompound("Controller"));
} }
public void forceYaw(float forcedYaw) {
targetYaw = yaw = prevYaw = forcedYaw;
}
public void checkController() { public void checkController() {
if (controllerPos == null) if (controllerPos == null)
return; return;
@ -394,14 +460,18 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
@Override @Override
protected void writeAdditional(CompoundNBT compound) { protected void writeAdditional(CompoundNBT compound) {
compound.put("Contraption", getContraption().writeNBT()); if (contraption != null)
compound.putFloat("InitialAngle", initialAngle); compound.put("Contraption", contraption.writeNBT());
if (!stationary) if (!stationary && motionBeforeStall != null)
compound.put("CachedMotion", compound.put("CachedMotion",
newDoubleNBTList(motionBeforeStall.x, motionBeforeStall.y, motionBeforeStall.z)); newDoubleNBTList(motionBeforeStall.x, motionBeforeStall.y, motionBeforeStall.z));
compound.putBoolean("Stalled", isStalled());
if (controllerPos != null) if (controllerPos != null)
compound.put("Controller", NBTUtil.writeBlockPos(controllerPos)); compound.put("Controller", NBTUtil.writeBlockPos(controllerPos));
if (forcedAngle != -1)
compound.putFloat("ForcedYaw", forcedAngle);
compound.putFloat("InitialAngle", initialAngle);
compound.putBoolean("Stalled", isStalled());
} }
@Override @Override
@ -423,14 +493,14 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
public void disassemble() { public void disassemble() {
if (getContraption() != null) { if (getContraption() != null) {
BlockPos offset = new BlockPos(getPositionVec().add(.5, .5, .5)); BlockPos offset = new BlockPos(getAnchorVec().add(.5, .5, .5));
Vec3d rotation = new Vec3d(getRoll(1), getYaw(1), getPitch(1)); Vec3d rotation = new Vec3d(getRoll(1), getYaw(1), getPitch(1));
getContraption().disassemble(world, offset, rotation); getContraption().addBlocksToWorld(world, offset, rotation);
preventMovedEntitiesFromGettingStuck(); preventMovedEntitiesFromGettingStuck();
} }
remove(); remove();
} }
@Override @Override
protected void doWaterSplashEffect() { protected void doWaterSplashEffect() {
} }
@ -532,4 +602,18 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
super.setMotion(vec); super.setMotion(vec);
} }
@Override
public boolean canBeCollidedWith() {
return false;
}
@Override
public boolean attackEntityFrom(DamageSource source, float amount) {
return false;
}
public float getInitialAngle() {
return initialAngle;
}
} }

View file

@ -1,6 +1,7 @@
package com.simibubi.create.modules.contraptions.components.contraptions; package com.simibubi.create.modules.contraptions.components.contraptions;
import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.platform.GlStateManager;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.RenderSystem;
import com.simibubi.create.foundation.utility.TessellatorHelper; import com.simibubi.create.foundation.utility.TessellatorHelper;
import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.utility.VecHelper;
@ -37,6 +38,8 @@ public class ContraptionEntityRenderer extends EntityRenderer<ContraptionEntity>
return; return;
if (entity.getContraption() == null) if (entity.getContraption() == null)
return; return;
if (entity.getContraption().getType() == AllContraptionTypes.MOUNTED && entity.getRidingEntity() == null)
return;
// TODO 1.15 buffered render // TODO 1.15 buffered render
RenderSystem.pushMatrix(); RenderSystem.pushMatrix();
@ -78,6 +81,7 @@ public class ContraptionEntityRenderer extends EntityRenderer<ContraptionEntity>
RenderSystem.translatef((float) cartX, (float) cartY, (float) cartZ); RenderSystem.translatef((float) cartX, (float) cartY, (float) cartZ);
} }
GlStateManager.translatef(-.5f, 0, -.5f);
} }
Vec3d rotationOffset = VecHelper.getCenterOf(BlockPos.ZERO); Vec3d rotationOffset = VecHelper.getCenterOf(BlockPos.ZERO);

View file

@ -1,23 +1,17 @@
package com.simibubi.create.modules.contraptions.components.contraptions; package com.simibubi.create.modules.contraptions.components.contraptions;
import java.util.Iterator;
import java.util.Random; import java.util.Random;
import java.util.function.Consumer; import java.util.function.Consumer;
import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.tuple.Pair;
import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL13;
import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.systems.RenderSystem;
import com.simibubi.create.Create;
import com.simibubi.create.CreateClient; import com.simibubi.create.CreateClient;
import com.simibubi.create.config.AllConfigs;
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.foundation.utility.VecHelper; import com.simibubi.create.foundation.utility.render.StructureRenderer;
import com.simibubi.create.foundation.utility.WrappedWorld;
import net.minecraft.block.BlockRenderType; import net.minecraft.block.BlockRenderType;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
@ -26,15 +20,9 @@ import net.minecraft.client.renderer.BlockModelRenderer;
import net.minecraft.client.renderer.BlockRendererDispatcher; import net.minecraft.client.renderer.BlockRendererDispatcher;
import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.renderer.IRenderTypeBuffer;
import net.minecraft.client.renderer.LightTexture;
import net.minecraft.client.renderer.RenderHelper;
import net.minecraft.client.renderer.WorldRenderer;
import net.minecraft.client.renderer.model.IBakedModel; import net.minecraft.client.renderer.model.IBakedModel;
import net.minecraft.client.renderer.texture.OverlayTexture; import net.minecraft.client.renderer.texture.OverlayTexture;
import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.crash.ReportedException;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
import net.minecraft.world.LightType; import net.minecraft.world.LightType;
@ -46,59 +34,19 @@ public class ContraptionRenderer {
public static final Compartment<Contraption> CONTRAPTION = new Compartment<>(); public static final Compartment<Contraption> CONTRAPTION = new Compartment<>();
protected static PlacementSimulationWorld renderWorld; protected static PlacementSimulationWorld renderWorld;
protected static LightingWorld lightingWorld;
public static void render(World world, Contraption c, Consumer<SuperByteBuffer> transform, MatrixStack ms, BufferBuilder buffer) { public static void render(World world, Contraption c, Consumer<SuperByteBuffer> transform, MatrixStack ms,
SuperByteBuffer contraptionBuffer = CreateClient.bufferCache.get(CONTRAPTION, c, () -> renderContraption(c, ms)); BufferBuilder buffer) {
SuperByteBuffer contraptionBuffer =
CreateClient.bufferCache.get(CONTRAPTION, c, () -> renderContraption(c, ms));
transform.accept(contraptionBuffer); transform.accept(contraptionBuffer);
contraptionBuffer.light((lx, ly, lz) -> getLight(world, lx, ly, lz)).renderInto(ms, buffer); contraptionBuffer.light((lx, ly, lz) -> getLight(world, lx, ly, lz)).renderInto(ms, buffer);
renderActors(world, c, transform, ms, buffer); renderActors(world, c, transform, ms, buffer);
} }
public static void renderTEsWithGL(World world, Contraption c, Vec3d position, Vec3d rotation, MatrixStack ms, IRenderTypeBuffer buffer) { public static void renderTEsWithGL(World world, Contraption c, Vec3d position, Vec3d rotation, MatrixStack ms,
float pt = Minecraft.getInstance().getRenderPartialTicks(); IRenderTypeBuffer buffer) {
StructureRenderer.renderTileEntities(world, position, rotation, c.customRenderTEs, ms, buffer);
if (lightingWorld == null)
lightingWorld = new LightingWorld(world);
lightingWorld.setWorld(world);
lightingWorld.setTransform(position, rotation);
for (Iterator<TileEntity> iterator = c.customRenderTEs.iterator(); iterator.hasNext();) {
TileEntity tileEntity = iterator.next();
if (TileEntityRendererDispatcher.instance.getRenderer(tileEntity) == null) {
iterator.remove();
continue;
}
try {
BlockPos pos = tileEntity.getPos();
if (!tileEntity.hasFastRenderer()) {
RenderHelper.enable();
int i = WorldRenderer.getLightmapCoordinates(lightingWorld, pos);
int j = LightTexture.getBlockLightCoordinates(i);
int k = LightTexture.getSkyLightCoordinates(i);
RenderSystem.glMultiTexCoord2f(GL13.GL_TEXTURE1, (float) j, (float) k);
RenderSystem.color4f(1.0F, 1.0F, 1.0F, 1.0F);
}
World prevTileWorld = tileEntity.getWorld();
tileEntity.setLocation(lightingWorld, pos);
TileEntityRendererDispatcher.instance.render(tileEntity, pt, ms, buffer);
tileEntity.setLocation(prevTileWorld, pos);
} catch (ReportedException e) {
if (AllConfigs.CLIENT.explainRenderErrors.get()) {
Create.logger.error("TileEntity " + tileEntity.getType().getRegistryName().toString()
+ " didn't want to render while moved.\n", e);
} else {
Create.logger.error("TileEntity " + tileEntity.getType().getRegistryName().toString()
+ " didn't want to render while moved.\n");
}
iterator.remove();
continue;
}
}
} }
private static SuperByteBuffer renderContraption(Contraption c, MatrixStack ms) { private static SuperByteBuffer renderContraption(Contraption c, MatrixStack ms) {
@ -130,8 +78,8 @@ public class ContraptionRenderer {
return new SuperByteBuffer(builder); return new SuperByteBuffer(builder);
} }
private static void renderActors(World world, Contraption c, Consumer<SuperByteBuffer> transform, private static void renderActors(World world, Contraption c, Consumer<SuperByteBuffer> transform, MatrixStack ms,
MatrixStack ms, BufferBuilder buffer) { BufferBuilder buffer) {
for (Pair<BlockInfo, MovementContext> actor : c.getActors()) { for (Pair<BlockInfo, MovementContext> actor : c.getActors()) {
MovementContext context = actor.getRight(); MovementContext context = actor.getRight();
if (context == null) if (context == null)
@ -171,36 +119,4 @@ public class ContraptionRenderer {
return ((int) sky) << 20 | ((int) block) << 4; return ((int) sky) << 20 | ((int) block) << 4;
} }
private static class LightingWorld extends WrappedWorld {
private Vec3d offset;
private Vec3d rotation;
public LightingWorld(World world) {
super(world);
}
void setWorld(World world) {
this.world = world;
}
void setTransform(Vec3d offset, Vec3d rotation) {
this.offset = offset;
this.rotation = rotation;
}
@Override
public int getBaseLightLevel(BlockPos pos, int minLight) {
return super.getBaseLightLevel(transformPos(pos), minLight);
}
private BlockPos transformPos(BlockPos pos) {
Vec3d vec = VecHelper.getCenterOf(pos);
vec = VecHelper.rotate(vec, rotation.x, rotation.y, rotation.z);
vec = vec.add(offset).subtract(VecHelper.getCenterOf(BlockPos.ZERO));
return new BlockPos(vec);
}
}
} }

View file

@ -163,14 +163,14 @@ public class StructureTransform {
return state; return state;
} }
protected Axis transformAxis(Axis axisIn) { public Axis transformAxis(Axis axisIn) {
Direction facing = Direction.getFacingFromAxis(AxisDirection.POSITIVE, axisIn); Direction facing = Direction.getFacingFromAxis(AxisDirection.POSITIVE, axisIn);
facing = transformFacing(facing); facing = transformFacing(facing);
Axis axis = facing.getAxis(); Axis axis = facing.getAxis();
return axis; return axis;
} }
protected Direction transformFacing(Direction facing) { public Direction transformFacing(Direction facing) {
for (int i = 0; i < rotation.ordinal(); i++) for (int i = 0; i < rotation.ordinal(); i++)
facing = DirectionHelper.rotateAround(facing, rotationAxis); facing = DirectionHelper.rotateAround(facing, rotationAxis);
return facing; return facing;

View file

@ -36,6 +36,11 @@ public class BearingContraption extends Contraption {
return construct; return construct;
} }
@Override
protected boolean isAnchoringBlockAt(BlockPos pos) {
return pos.equals(anchor.offset(facing.getOpposite()));
}
@Override @Override
public void add(BlockPos pos, Pair<BlockInfo, TileEntity> capture) { public void add(BlockPos pos, Pair<BlockInfo, TileEntity> capture) {
BlockPos localPos = pos.subtract(anchor); BlockPos localPos = pos.subtract(anchor);
@ -62,7 +67,7 @@ public class BearingContraption extends Contraption {
public int getSailBlocks() { public int getSailBlocks() {
return sailBlocks; return sailBlocks;
} }
public Direction getFacing() { public Direction getFacing() {
return facing; return facing;
} }

View file

@ -7,7 +7,6 @@ import com.simibubi.create.foundation.utility.SuperByteBuffer;
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 net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.renderer.IRenderTypeBuffer;
import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher; import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher;

View file

@ -148,6 +148,9 @@ public class ClockworkBearingTileEntity extends KineticTileEntity implements IBe
} }
public void assemble() { public void assemble() {
if (!(world.getBlockState(pos).getBlock() instanceof ClockworkBearingBlock))
return;
Direction direction = getBlockState().get(BlockStateProperties.FACING); Direction direction = getBlockState().get(BlockStateProperties.FACING);
// Collect Construct // Collect Construct
@ -182,7 +185,7 @@ public class ClockworkBearingTileEntity extends KineticTileEntity implements IBe
} }
public void disassemble() { public void disassemble() {
if (!running) if (!running && hourHand == null && minuteHand == null)
return; return;
hourAngle = 0; hourAngle = 0;
@ -205,7 +208,7 @@ public class ClockworkBearingTileEntity extends KineticTileEntity implements IBe
public void attach(ContraptionEntity contraption) { public void attach(ContraptionEntity contraption) {
if (!(contraption.getContraption() instanceof ClockworkContraption)) if (!(contraption.getContraption() instanceof ClockworkContraption))
return; return;
ClockworkContraption cc = (ClockworkContraption) contraption.getContraption(); ClockworkContraption cc = (ClockworkContraption) contraption.getContraption();
markDirty(); markDirty();
Direction facing = getBlockState().get(BlockStateProperties.FACING); Direction facing = getBlockState().get(BlockStateProperties.FACING);
@ -217,8 +220,10 @@ public class ClockworkBearingTileEntity extends KineticTileEntity implements IBe
this.minuteHand = contraption; this.minuteHand = contraption;
minuteHand.setPosition(anchor.getX(), anchor.getY(), anchor.getZ()); minuteHand.setPosition(anchor.getX(), anchor.getY(), anchor.getZ());
} }
if (!world.isRemote) if (!world.isRemote) {
this.running = true;
sendData(); sendData();
}
} }
@Override @Override
@ -302,5 +307,5 @@ public class ClockworkBearingTileEntity extends KineticTileEntity implements IBe
public boolean isRunning() { public boolean isRunning() {
return running; return running;
} }
} }

View file

@ -32,6 +32,11 @@ public class ClockworkContraption extends Contraption {
ignoreBlocks.add(anchor.add(blockPos)); ignoreBlocks.add(anchor.add(blockPos));
} }
@Override
protected boolean isAnchoringBlockAt(BlockPos pos) {
return pos.equals(anchor.offset(facing.getOpposite(), offset + 1));
}
public static Pair<ClockworkContraption, ClockworkContraption> assembleClockworkAt(World world, BlockPos pos, public static Pair<ClockworkContraption, ClockworkContraption> assembleClockworkAt(World world, BlockPos pos,
Direction direction) { Direction direction) {
if (isFrozen()) if (isFrozen())

View file

@ -150,6 +150,9 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity imp
} }
public void assemble() { public void assemble() {
if (!(world.getBlockState(pos).getBlock() instanceof MechanicalBearingBlock))
return;
Direction direction = getBlockState().get(FACING); Direction direction = getBlockState().get(FACING);
// Collect Construct // Collect Construct
@ -161,6 +164,7 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity imp
if (contraption.blocks.isEmpty()) if (contraption.blocks.isEmpty())
return; return;
contraption.removeBlocksFromWorld(world, BlockPos.ZERO); contraption.removeBlocksFromWorld(world, BlockPos.ZERO);
movedContraption = ContraptionEntity.createStationary(world, contraption).controlledBy(this); movedContraption = ContraptionEntity.createStationary(world, contraption).controlledBy(this);
BlockPos anchor = pos.offset(direction); BlockPos anchor = pos.offset(direction);
movedContraption.setPosition(anchor.getX(), anchor.getY(), anchor.getZ()); movedContraption.setPosition(anchor.getX(), anchor.getY(), anchor.getZ());
@ -172,7 +176,7 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity imp
sendData(); sendData();
updateGeneratedRotation(); updateGeneratedRotation();
} }
@Override @Override
public void updateGeneratedRotation() { public void updateGeneratedRotation() {
super.updateGeneratedRotation(); super.updateGeneratedRotation();
@ -180,7 +184,7 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity imp
} }
public void disassemble() { public void disassemble() {
if (!running) if (!running && movedContraption == null)
return; return;
if (movedContraption != null) if (movedContraption != null)
movedContraption.disassemble(); movedContraption.disassemble();
@ -267,8 +271,10 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity imp
markDirty(); markDirty();
BlockPos anchor = pos.offset(blockState.get(FACING)); BlockPos anchor = pos.offset(blockState.get(FACING));
movedContraption.setPosition(anchor.getX(), anchor.getY(), anchor.getZ()); movedContraption.setPosition(anchor.getX(), anchor.getY(), anchor.getZ());
if (!world.isRemote) if (!world.isRemote) {
this.running = true;
sendData(); sendData();
}
} }
@Override @Override
@ -298,7 +304,7 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity imp
public boolean isAttachedTo(ContraptionEntity contraption) { public boolean isAttachedTo(ContraptionEntity contraption) {
return movedContraption == contraption; return movedContraption == contraption;
} }
public boolean isRunning() { public boolean isRunning() {
return running; return running;
} }

View file

@ -167,11 +167,7 @@ public class ChassisTileEntity extends SmartTileEntity {
// Ignore replaceable Blocks and Air-like // Ignore replaceable Blocks and Air-like
if (!BlockMovementTraits.movementNecessary(world, current)) if (!BlockMovementTraits.movementNecessary(world, current))
break; break;
if (AllBlocks.MECHANICAL_PISTON_HEAD.typeOf(currentState)) if (BlockMovementTraits.isBrittle(currentState))
break;
if (AllBlocks.MECHANICAL_PISTON.typeOf(currentState))
break;
if (AllBlocks.STICKY_MECHANICAL_PISTON.typeOf(currentState))
break; break;
positions.add(current); positions.add(current);
@ -212,6 +208,8 @@ public class ChassisTileEntity extends SmartTileEntity {
continue; continue;
if (!BlockMovementTraits.movementNecessary(world, searchPos)) if (!BlockMovementTraits.movementNecessary(world, searchPos))
continue; continue;
if (BlockMovementTraits.isBrittle(searchedState))
continue;
localVisited.add(searchPos); localVisited.add(searchPos);
if (!searchPos.equals(pos)) if (!searchPos.equals(pos))

View file

@ -0,0 +1,49 @@
package com.simibubi.create.modules.contraptions.components.contraptions.glue;
import java.util.function.Supplier;
import com.simibubi.create.foundation.packet.SimplePacketBase;
import net.minecraft.client.Minecraft;
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.fml.DistExecutor;
import net.minecraftforge.fml.network.NetworkEvent.Context;
public class GlueEffectPacket extends SimplePacketBase {
private BlockPos pos;
private Direction direction;
private boolean fullBlock;
public GlueEffectPacket(BlockPos pos, Direction direction, boolean fullBlock) {
this.pos = pos;
this.direction = direction;
this.fullBlock = fullBlock;
}
public GlueEffectPacket(PacketBuffer buffer) {
pos = buffer.readBlockPos();
direction = Direction.byIndex(buffer.readByte());
fullBlock = buffer.readBoolean();
}
public void write(PacketBuffer buffer) {
buffer.writeBlockPos(pos);
buffer.writeByte(direction.getIndex());
buffer.writeBoolean(fullBlock);
}
public void handle(Supplier<Context> context) {
context.get().enqueueWork(() -> DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> {
Minecraft mc = Minecraft.getInstance();
if (!mc.player.getPosition().withinDistance(pos, 100))
return;
SuperGlueItem.spawnParticles(mc.world, pos, direction, fullBlock);
}));
context.get().setPacketHandled(true);
}
}

View file

@ -0,0 +1,369 @@
package com.simibubi.create.modules.contraptions.components.contraptions.glue;
import javax.annotation.Nullable;
import org.apache.commons.lang3.Validate;
import com.simibubi.create.AllEntities;
import com.simibubi.create.AllItems;
import com.simibubi.create.AllPackets;
import com.simibubi.create.AllSoundEvents;
import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.player.ClientPlayerEntity;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntitySize;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.MoverType;
import net.minecraft.entity.Pose;
import net.minecraft.entity.effect.LightningBoltEntity;
import net.minecraft.entity.item.ItemEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.network.IPacket;
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.ActionResultType;
import net.minecraft.util.DamageSource;
import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.Hand;
import net.minecraft.util.Mirror;
import net.minecraft.util.Rotation;
import net.minecraft.util.SoundEvents;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.RayTraceResult;
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.fml.DistExecutor;
import net.minecraftforge.fml.common.registry.IEntityAdditionalSpawnData;
import net.minecraftforge.fml.network.NetworkHooks;
import net.minecraftforge.fml.network.PacketDistributor;
public class SuperGlueEntity extends Entity implements IEntityAdditionalSpawnData {
private int validationTimer;
protected BlockPos hangingPosition;
protected Direction facingDirection = Direction.SOUTH;
public SuperGlueEntity(EntityType<?> type, World world) {
super(type, world);
}
public SuperGlueEntity(World world, BlockPos pos, Direction direction) {
this(AllEntities.SUPER_GLUE.type, world);
hangingPosition = pos;
facingDirection = direction;
updateFacingWithBoundingBox();
}
@Override
protected void registerData() {
}
public int getWidthPixels() {
return 12;
}
public int getHeightPixels() {
return 12;
}
public void onBroken(@Nullable Entity breaker) {
playSound(SoundEvents.ENTITY_SLIME_SQUISH_SMALL, 1.0F, 1.0F);
if (onValidSurface()) {
AllPackets.channel.send(PacketDistributor.TRACKING_ENTITY.with(() -> this),
new GlueEffectPacket(getHangingPosition(), getFacingDirection().getOpposite(), false));
playSound(AllSoundEvents.SLIME_ADDED.get(), 0.5F, 0.5F);
}
}
public void playPlaceSound() {
playSound(AllSoundEvents.SLIME_ADDED.get(), 0.5F, 0.75F);
}
protected void updateFacingWithBoundingBox() {
Validate.notNull(getFacingDirection());
if (getFacingDirection().getAxis().isHorizontal()) {
this.rotationPitch = 0.0F;
this.rotationYaw = getFacingDirection().getHorizontalIndex() * 90;
} else {
this.rotationPitch = -90 * getFacingDirection().getAxisDirection().getOffset();
this.rotationYaw = 0.0F;
}
this.prevRotationPitch = this.rotationPitch;
this.prevRotationYaw = this.rotationYaw;
this.updateBoundingBox();
}
protected void updateBoundingBox() {
if (this.getFacingDirection() != null) {
double x = hangingPosition.getX() + 0.5 - facingDirection.getXOffset() * 0.5;
double y = hangingPosition.getY() + 0.5 - facingDirection.getYOffset() * 0.5;
double z = hangingPosition.getZ() + 0.5 - facingDirection.getZOffset() * 0.5;
this.setPos(x, y, z);
double d1 = (double) this.getWidthPixels();
double d2 = (double) this.getHeightPixels();
double d3 = (double) this.getWidthPixels();
Axis axis = this.getFacingDirection().getAxis();
double depth = 2 - 1 / 128f;
switch (axis) {
case X:
d1 = depth;
break;
case Y:
d2 = depth;
break;
case Z:
d3 = depth;
}
d1 = d1 / 32.0D;
d2 = d2 / 32.0D;
d3 = d3 / 32.0D;
this.setBoundingBox(new AxisAlignedBB(x - d1, y - d2, z - d3, x + d1, y + d2, z + d3));
}
}
@Override
public void tick() {
if (this.validationTimer++ == 10 && !this.world.isRemote) {
this.validationTimer = 0;
if (isAlive() && !this.onValidSurface()) {
remove();
onBroken(null);
}
}
}
public boolean onValidSurface() {
BlockPos pos = hangingPosition;
BlockPos pos2 = hangingPosition.offset(getFacingDirection().getOpposite());
if (!world.isAreaLoaded(pos, 0) || !world.isAreaLoaded(pos2, 0))
return true;
if (world.isAirBlock(pos) && world.isAirBlock(pos2))
return false;
return world.getEntitiesInAABBexcluding(this, getBoundingBox(), e -> e instanceof SuperGlueEntity).isEmpty();
}
@Override
public boolean canBeCollidedWith() {
return true;
}
@Override
public boolean hitByEntity(Entity entity) {
return entity instanceof PlayerEntity
? attackEntityFrom(DamageSource.causePlayerDamage((PlayerEntity) entity), 0)
: false;
}
@Override
public Direction getHorizontalFacing() {
return this.getFacingDirection();
}
@Override
public boolean attackEntityFrom(DamageSource source, float amount) {
if (this.isInvulnerableTo(source))
return false;
if (isAlive() && !world.isRemote) {
remove();
markVelocityChanged();
onBroken(source.getTrueSource());
}
return true;
}
@Override
public void move(MoverType typeIn, Vec3d pos) {
if (!world.isRemote && isAlive() && pos.lengthSquared() > 0.0D) {
remove();
onBroken(null);
}
}
@Override
public void addVelocity(double x, double y, double z) {
if (!world.isRemote && isAlive() && x * x + y * y + z * z > 0.0D) {
remove();
onBroken(null);
}
}
@Override
protected float getEyeHeight(Pose poseIn, EntitySize sizeIn) {
return 0.0F;
}
@Override
public ItemStack getPickedResult(RayTraceResult target) {
return AllItems.SUPER_GLUE.asStack();
}
@Override
public void applyEntityCollision(Entity entityIn) {
super.applyEntityCollision(entityIn);
}
@Override
public boolean processInitialInteract(PlayerEntity player, Hand hand) {
DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> {
triggerPlaceBlock(player, hand);
});
return true;
}
@OnlyIn(Dist.CLIENT)
private void triggerPlaceBlock(PlayerEntity player, Hand hand) {
if (player instanceof ClientPlayerEntity && player.world instanceof ClientWorld) {
ClientPlayerEntity cPlayer = (ClientPlayerEntity) player;
Minecraft mc = Minecraft.getInstance();
RayTraceResult ray =
cPlayer.pick(mc.playerController.getBlockReachDistance(), mc.getRenderPartialTicks(), false);
if (ray instanceof BlockRayTraceResult) {
for (Hand handIn : Hand.values()) {
ItemStack itemstack = cPlayer.getHeldItem(handIn);
int countBefore = itemstack.getCount();
ActionResultType actionResultType = mc.playerController.func_217292_a(cPlayer,
(ClientWorld) cPlayer.world, handIn, (BlockRayTraceResult) ray);
if (actionResultType == ActionResultType.SUCCESS) {
cPlayer.swingArm(handIn);
if (!itemstack.isEmpty()
&& (itemstack.getCount() != countBefore || mc.playerController.isInCreativeMode()))
mc.gameRenderer.itemRenderer.resetEquippedProgress(handIn);
return;
}
}
}
}
}
@Override
public void writeAdditional(CompoundNBT compound) {
compound.putByte("Facing", (byte) this.getFacingDirection().getIndex());
BlockPos blockpos = this.getHangingPosition();
compound.putInt("TileX", blockpos.getX());
compound.putInt("TileY", blockpos.getY());
compound.putInt("TileZ", blockpos.getZ());
}
@Override
public void readAdditional(CompoundNBT compound) {
this.hangingPosition =
new BlockPos(compound.getInt("TileX"), compound.getInt("TileY"), compound.getInt("TileZ"));
this.facingDirection = Direction.byIndex(compound.getByte("Facing"));
updateFacingWithBoundingBox();
}
@Override
public ItemEntity entityDropItem(ItemStack stack, float yOffset) {
float xOffset = (float) this.getFacingDirection().getXOffset() * 0.15F;
float zOffset = (float) this.getFacingDirection().getZOffset() * 0.15F;
ItemEntity itementity =
new ItemEntity(this.world, this.getX() + xOffset, this.getY() + yOffset, this.getZ() + zOffset, stack);
itementity.setDefaultPickupDelay();
this.world.addEntity(itementity);
return itementity;
}
@Override
protected boolean shouldSetPosAfterLoading() {
return false;
}
@Override
public void setPosition(double x, double y, double z) {
hangingPosition = new BlockPos(x, y, z);
updateBoundingBox();
isAirBorne = true;
}
@Override
public float getRotatedYaw(Rotation transformRotation) {
if (this.getFacingDirection().getAxis() != Direction.Axis.Y) {
switch (transformRotation) {
case CLOCKWISE_180:
this.facingDirection = this.getFacingDirection().getOpposite();
break;
case COUNTERCLOCKWISE_90:
this.facingDirection = this.getFacingDirection().rotateYCCW();
break;
case CLOCKWISE_90:
this.facingDirection = this.getFacingDirection().rotateY();
default:
break;
}
}
float f = MathHelper.wrapDegrees(this.rotationYaw);
switch (transformRotation) {
case CLOCKWISE_180:
return f + 180.0F;
case COUNTERCLOCKWISE_90:
return f + 90.0F;
case CLOCKWISE_90:
return f + 270.0F;
default:
return f;
}
}
public BlockPos getHangingPosition() {
return this.hangingPosition;
}
@Override
public float getMirroredYaw(Mirror transformMirror) {
return this.getRotatedYaw(transformMirror.toRotation(this.getFacingDirection()));
}
public Direction getAttachedDirection(BlockPos pos) {
return !pos.equals(hangingPosition) ? getFacingDirection() : getFacingDirection().getOpposite();
}
@Override
public void onStruckByLightning(LightningBoltEntity lightningBolt) {
}
@Override
public void recalculateSize() {
}
public static EntityType.Builder<?> build(EntityType.Builder<?> builder) {
@SuppressWarnings("unchecked")
EntityType.Builder<SuperGlueEntity> entityBuilder = (EntityType.Builder<SuperGlueEntity>) builder;
return entityBuilder;
}
@Override
public IPacket<?> createSpawnPacket() {
return NetworkHooks.getEntitySpawningPacket(this);
}
@Override
public void writeSpawnData(PacketBuffer buffer) {
CompoundNBT compound = new CompoundNBT();
writeAdditional(compound);
buffer.writeCompoundTag(compound);
}
@Override
public void readSpawnData(PacketBuffer additionalData) {
readAdditional(additionalData.readCompoundTag());
}
public Direction getFacingDirection() {
return facingDirection;
}
}

View file

@ -0,0 +1,105 @@
package com.simibubi.create.modules.contraptions.components.contraptions.glue;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.simibubi.create.AllItems;
import com.simibubi.create.AllPackets;
import com.simibubi.create.foundation.utility.RayTraceWorld;
import net.minecraft.block.Blocks;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.util.Direction;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.util.math.RayTraceContext;
import net.minecraft.util.math.RayTraceResult.Type;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.IWorld;
import net.minecraft.world.World;
import net.minecraftforge.event.world.BlockEvent.EntityPlaceEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
import net.minecraftforge.fml.network.PacketDistributor;
@EventBusSubscriber
public class SuperGlueHandler {
public static Map<Direction, SuperGlueEntity> gatherGlue(IWorld world, BlockPos pos) {
List<SuperGlueEntity> entities = world.getEntitiesWithinAABB(SuperGlueEntity.class, new AxisAlignedBB(pos));
Map<Direction, SuperGlueEntity> map = new HashMap<>();
for (SuperGlueEntity entity : entities)
map.put(entity.getAttachedDirection(pos), entity);
return map;
}
@SubscribeEvent
public static void glueListensForBlockPlacement(EntityPlaceEvent event) {
IWorld world = event.getWorld();
Entity entity = event.getEntity();
BlockPos pos = event.getPos();
if (entity == null || world == null || pos == null)
return;
if (event.isCanceled())
return;
if (world.isRemote())
return;
Map<Direction, SuperGlueEntity> gatheredGlue = gatherGlue(world, pos);
for (Direction direction : gatheredGlue.keySet())
AllPackets.channel.send(PacketDistributor.TRACKING_ENTITY_AND_SELF.with(() -> entity),
new GlueEffectPacket(pos, direction, true));
if (entity instanceof PlayerEntity)
glueInOffHandAppliesOnBlockPlace(event, pos, (PlayerEntity) entity);
}
public static void glueInOffHandAppliesOnBlockPlace(EntityPlaceEvent event, BlockPos pos, PlayerEntity placer) {
ItemStack itemstack = placer.getHeldItemOffhand();
if (!AllItems.SUPER_GLUE.typeOf(itemstack))
return;
double distance = placer.getAttribute(PlayerEntity.REACH_DISTANCE).getValue();
Vec3d start = placer.getEyePosition(1);
Vec3d look = placer.getLook(1);
Vec3d end = start.add(look.x * distance, look.y * distance, look.z * distance);
World world = placer.world;
RayTraceWorld rayTraceWorld =
new RayTraceWorld(world, (p, state) -> p.equals(pos) ? Blocks.AIR.getDefaultState() : state);
BlockRayTraceResult ray = rayTraceWorld.rayTraceBlocks(new RayTraceContext(start, end,
RayTraceContext.BlockMode.OUTLINE, RayTraceContext.FluidMode.NONE, placer));
Direction face = ray.getFace();
if (ray == null || face == null || ray.getType() == Type.MISS)
return;
if (!ray.getPos().offset(face).equals(pos)) {
event.setCanceled(true);
return;
}
SuperGlueEntity entity = new SuperGlueEntity(world, ray.getPos(), face.getOpposite());
CompoundNBT compoundnbt = itemstack.getTag();
if (compoundnbt != null)
EntityType.applyItemNBT(world, placer, entity, compoundnbt);
if (entity.onValidSurface()) {
if (!world.isRemote) {
entity.playPlaceSound();
world.addEntity(entity);
AllPackets.channel.send(PacketDistributor.TRACKING_ENTITY_AND_SELF.with(() -> entity),
new GlueEffectPacket(ray.getPos(), face, true));
}
itemstack.damageItem(1, placer, SuperGlueItem::onBroken);
}
}
}

View file

@ -0,0 +1,104 @@
package com.simibubi.create.modules.contraptions.components.contraptions.glue;
import com.simibubi.create.foundation.utility.VecHelper;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemUseContext;
import net.minecraft.item.Items;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.particles.ItemParticleData;
import net.minecraft.particles.ParticleTypes;
import net.minecraft.util.ActionResultType;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
public class SuperGlueItem extends Item {
public SuperGlueItem(Properties properties) {
super(properties);
}
@Override
public boolean isDamageable() {
return true;
}
@Override
public int getMaxDamage(ItemStack stack) {
return 99;
}
@Override
public int getItemStackLimit(ItemStack stack) {
return 1;
}
@Override
public ActionResultType onItemUse(ItemUseContext context) {
BlockPos blockpos = context.getPos();
Direction direction = context.getFace();
BlockPos blockpos1 = blockpos.offset(direction);
PlayerEntity playerentity = context.getPlayer();
ItemStack itemstack = context.getItem();
if (playerentity != null && !this.canPlace(playerentity, direction, itemstack, blockpos1))
return ActionResultType.FAIL;
World world = context.getWorld();
SuperGlueEntity entity = new SuperGlueEntity(world, blockpos1, direction);
CompoundNBT compoundnbt = itemstack.getTag();
if (compoundnbt != null)
EntityType.applyItemNBT(world, playerentity, entity, compoundnbt);
if (!entity.onValidSurface())
return ActionResultType.FAIL;
if (!world.isRemote) {
entity.playPlaceSound();
world.addEntity(entity);
}
itemstack.damageItem(1, playerentity, SuperGlueItem::onBroken);
return ActionResultType.SUCCESS;
}
public static void onBroken(PlayerEntity player) {
}
protected boolean canPlace(PlayerEntity entity, Direction facing, ItemStack stack, BlockPos pos) {
return !World.isOutsideBuildHeight(pos) && entity.canPlayerEdit(pos, facing, stack);
}
@OnlyIn(Dist.CLIENT)
public static void spawnParticles(World world, BlockPos pos, Direction direction, boolean fullBlock) {
Vec3d vec = new Vec3d(direction.getDirectionVec());
Vec3d plane = VecHelper.planeByNormal(vec);
Vec3d facePos = VecHelper.getCenterOf(pos).add(vec.scale(.5f));
float distance = fullBlock ? 1f : .25f + .25f * (world.rand.nextFloat() - .5f);
plane = plane.scale(distance);
ItemStack stack = new ItemStack(Items.SLIME_BALL);
for (int i = fullBlock ? 40 : 15; i > 0; i--) {
Vec3d offset = VecHelper.rotate(plane, 360 * world.rand.nextFloat(), direction.getAxis());
Vec3d motion = offset.normalize().scale(1 / 16f);
if (fullBlock)
offset = new Vec3d(MathHelper.clamp(offset.x, -.5, .5), MathHelper.clamp(offset.y, -.5, .5),
MathHelper.clamp(offset.z, -.5, .5));
Vec3d particlePos = facePos.add(offset);
world.addParticle(new ItemParticleData(ParticleTypes.ITEM, stack), particlePos.x, particlePos.y,
particlePos.z, motion.x, motion.y, motion.z);
}
}
}

View file

@ -0,0 +1,123 @@
package com.simibubi.create.modules.contraptions.components.contraptions.glue;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.vertex.IVertexBuilder;
import com.simibubi.create.AllItems;
import com.simibubi.create.Create;
import com.simibubi.create.config.AllConfigs;
import com.simibubi.create.foundation.utility.VecHelper;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.IRenderTypeBuffer;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.entity.EntityRenderer;
import net.minecraft.client.renderer.entity.EntityRendererManager;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
@OnlyIn(Dist.CLIENT)
public class SuperGlueRenderer extends EntityRenderer<SuperGlueEntity> {
private ResourceLocation regular = new ResourceLocation(Create.ID, "textures/entity/super_glue/slime.png");
private ResourceLocation ghostly = new ResourceLocation(Create.ID, "textures/entity/super_glue/ghostly.png");
private Vec3d[] quad1;
private Vec3d[] quad2;
public SuperGlueRenderer(EntityRendererManager renderManager) {
super(renderManager);
initQuads();
}
@Override
public ResourceLocation getEntityTexture(SuperGlueEntity entity) {
return isVisible(entity) ? regular : ghostly;
}
@Override // TODO what are these floats for?
public void render(SuperGlueEntity entity, float p_225623_2_, float p_225623_3_, MatrixStack ms,
IRenderTypeBuffer buffer, int light) {
super.render(entity, p_225623_2_, p_225623_3_, ms, buffer, light);
IVertexBuilder builder = buffer.getBuffer(RenderType.getEntityCutout(getEntityTexture(entity)));
PlayerEntity player = Minecraft.getInstance().player;
boolean visible = isVisible(entity);
boolean holdingGlue = AllItems.SUPER_GLUE.typeOf(player.getHeldItemMainhand())
|| AllItems.SUPER_GLUE.typeOf(player.getHeldItemOffhand());
holdingGlue = holdingGlue && AllConfigs.CLIENT.showHiddenSuperGlue.get();
if (!visible && !holdingGlue)
return;
// GlStateManager.pushMatrix(); TODO find equivalent
// GlStateManager.translated(x, y, z);
// GlStateManager.rotated(AngleHelper.horizontalAngle(facing), 0, 1, 0);
// GlStateManager.rotated(AngleHelper.verticalAngle(facing), 1, 0, 0);
// if (!visible) {
// GlStateManager.color4f(1, 1, 1, 0.375f);
// GlStateManager.enableBlend();
// GlStateManager.disableDepthTest();
// }
// TODO use quad1 & quad2 to render the glue texture
// GlStateManager.disableBlend();
// GlStateManager.enableDepthTest();
// GlStateManager.color4f(1.0F, 1.0F, 1.0F, 1.0F);
// GlStateManager.popMatrix();
}
private boolean isVisible(SuperGlueEntity entity) {
if (!entity.isAlive())
return false;
BlockPos pos = entity.hangingPosition;
BlockPos pos2 = pos.offset(entity.getFacingDirection().getOpposite());
return entity.world.isAirBlock(pos) != entity.world.isAirBlock(pos2);
}
private void initQuads() {
Vec3d diff = new Vec3d(Direction.SOUTH.getDirectionVec());
Vec3d extension = diff.normalize().scale(1 / 32f - 1 / 128f);
Vec3d plane = VecHelper.planeByNormal(diff);
Axis axis = Direction.getFacingFromVector(diff.x, diff.y, diff.z).getAxis();
Vec3d start = Vec3d.ZERO.subtract(extension);
Vec3d end = Vec3d.ZERO.add(extension);
plane = plane.scale(1 / 2f);
Vec3d a1 = plane.add(start);
Vec3d b1 = plane.add(end);
plane = VecHelper.rotate(plane, -90, axis);
Vec3d a2 = plane.add(start);
Vec3d b2 = plane.add(end);
plane = VecHelper.rotate(plane, -90, axis);
Vec3d a3 = plane.add(start);
Vec3d b3 = plane.add(end);
plane = VecHelper.rotate(plane, -90, axis);
Vec3d a4 = plane.add(start);
Vec3d b4 = plane.add(end);
quad1 = new Vec3d[] { a1, a2, a3, a4 };
quad2 = new Vec3d[] { b1, b2, b3, b4 };
// PositionTextureVertex v11 = new PositionTextureVertex(a1, 1, 0);
// PositionTextureVertex v12 = new PositionTextureVertex(a2, 1, 1);
// PositionTextureVertex v13 = new PositionTextureVertex(a3, 0, 1);
// PositionTextureVertex v14 = new PositionTextureVertex(a4, 0, 0);
//
// PositionTextureVertex v21 = new PositionTextureVertex(b1, 1, 0);
// PositionTextureVertex v22 = new PositionTextureVertex(b2, 1, 1);
// PositionTextureVertex v23 = new PositionTextureVertex(b3, 0, 1);
// PositionTextureVertex v24 = new PositionTextureVertex(b4, 0, 0);
//
// quad1 = new TexturedQuad(new PositionTextureVertex[] { v14, v11, v12, v13 }, 0, 0, 16, 16, 16, 16);
// quad2 = new TexturedQuad(new PositionTextureVertex[] { v21, v24, v23, v22 }, 0, 0, 16, 16, 16, 16);
}
}

View file

@ -1,10 +1,11 @@
package com.simibubi.create.modules.contraptions.components.contraptions.mounted; package com.simibubi.create.modules.contraptions.components.contraptions.mounted;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.foundation.block.ITE;
import com.simibubi.create.foundation.block.RenderUtilityBlock; import com.simibubi.create.foundation.block.RenderUtilityBlock;
import com.simibubi.create.foundation.utility.AllShapes; import com.simibubi.create.foundation.utility.AllShapes;
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;
import com.simibubi.create.modules.contraptions.components.contraptions.mounted.CartAssemblerTileEntity.CartMovementMode;
import net.minecraft.block.AbstractRailBlock; import net.minecraft.block.AbstractRailBlock;
import net.minecraft.block.Block; import net.minecraft.block.Block;
@ -12,13 +13,16 @@ 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.minecart.AbstractMinecartEntity; import net.minecraft.entity.item.minecart.AbstractMinecartEntity;
import net.minecraft.entity.item.minecart.FurnaceMinecartEntity;
import net.minecraft.item.BlockItemUseContext; import net.minecraft.item.BlockItemUseContext;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.state.BooleanProperty; import net.minecraft.state.BooleanProperty;
import net.minecraft.state.EnumProperty; import net.minecraft.state.EnumProperty;
import net.minecraft.state.IProperty; import net.minecraft.state.IProperty;
import net.minecraft.state.StateContainer.Builder; import net.minecraft.state.StateContainer.Builder;
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.math.BlockPos; import net.minecraft.util.math.BlockPos;
@ -28,7 +32,7 @@ import net.minecraft.util.math.shapes.VoxelShapes;
import net.minecraft.world.IBlockReader; import net.minecraft.world.IBlockReader;
import net.minecraft.world.World; import net.minecraft.world.World;
public class CartAssemblerBlock extends AbstractRailBlock { public class CartAssemblerBlock extends AbstractRailBlock implements ITE<CartAssemblerTileEntity> {
public static IProperty<RailShape> RAIL_SHAPE = public static IProperty<RailShape> RAIL_SHAPE =
EnumProperty.create("shape", RailShape.class, RailShape.EAST_WEST, RailShape.NORTH_SOUTH); EnumProperty.create("shape", RailShape.class, RailShape.EAST_WEST, RailShape.NORTH_SOUTH);
@ -45,6 +49,16 @@ public class CartAssemblerBlock extends AbstractRailBlock {
super.fillStateContainer(builder); super.fillStateContainer(builder);
} }
@Override
public boolean hasTileEntity(BlockState state) {
return true;
}
@Override
public TileEntity createTileEntity(BlockState state, IBlockReader world) {
return new CartAssemblerTileEntity();
}
@Override @Override
public BlockState getStateForPlacement(BlockItemUseContext context) { public BlockState getStateForPlacement(BlockItemUseContext context) {
boolean alongX = context.getPlacementHorizontalFacing().getAxis() == Axis.X; boolean alongX = context.getPlacementHorizontalFacing().getAxis() == Axis.X;
@ -60,7 +74,7 @@ public class CartAssemblerBlock extends AbstractRailBlock {
@Override @Override
public void onMinecartPass(BlockState state, World world, BlockPos pos, AbstractMinecartEntity cart) { public void onMinecartPass(BlockState state, World world, BlockPos pos, AbstractMinecartEntity cart) {
if (!cart.canBeRidden()) if (!cart.canBeRidden() && !(cart instanceof FurnaceMinecartEntity))
return; return;
if (state.get(POWERED)) if (state.get(POWERED))
disassemble(world, pos, cart); disassemble(world, pos, cart);
@ -72,16 +86,28 @@ public class CartAssemblerBlock extends AbstractRailBlock {
if (!cart.getPassengers().isEmpty()) if (!cart.getPassengers().isEmpty())
return; return;
Contraption contraption = MountedContraption.assembleMinecart(world, pos); MountedContraption contraption = MountedContraption.assembleMinecart(world, pos);
if (contraption == null) if (contraption == null)
return; return;
if (contraption.blocks.size() == 1) if (contraption.blocks.size() == 1)
return; return;
float initialAngle = ContraptionEntity.yawFromVector(cart.getMotion());
int yawFromVector = (int) (ContraptionEntity.yawFromVector(cart.getMotion()) + .5d);
yawFromVector = ((yawFromVector + 45) / 90) * 90;
float initialAngle = yawFromVector;
withTileEntityDo(world, pos, te -> contraption.rotationMode = CartMovementMode.values()[te.movementMode.value]);
ContraptionEntity entity = ContraptionEntity.createMounted(world, contraption, initialAngle); ContraptionEntity entity = ContraptionEntity.createMounted(world, contraption, initialAngle);
entity.setPosition(pos.getX(), pos.getY(), pos.getZ()); entity.setPosition(pos.getX(), pos.getY(), pos.getZ());
world.addEntity(entity); world.addEntity(entity);
entity.startRiding(cart); entity.startRiding(cart);
if (cart instanceof FurnaceMinecartEntity) {
CompoundNBT nbt = cart.serializeNBT();
nbt.putDouble("PushZ", 0);
nbt.putDouble("PushX", 0);
cart.deserializeNBT(nbt);
}
} }
protected void disassemble(World world, BlockPos pos, AbstractMinecartEntity cart) { protected void disassemble(World world, BlockPos pos, AbstractMinecartEntity cart) {
@ -90,6 +116,13 @@ public class CartAssemblerBlock extends AbstractRailBlock {
if (!(cart.getPassengers().get(0) instanceof ContraptionEntity)) if (!(cart.getPassengers().get(0) instanceof ContraptionEntity))
return; return;
cart.removePassengers(); cart.removePassengers();
if (cart instanceof FurnaceMinecartEntity) {
CompoundNBT nbt = cart.serializeNBT();
nbt.putDouble("PushZ", cart.getMotion().x);
nbt.putDouble("PushX", cart.getMotion().z);
cart.deserializeNBT(nbt);
}
} }
@Override @Override
@ -129,7 +162,7 @@ public class CartAssemblerBlock extends AbstractRailBlock {
public PushReaction getPushReaction(BlockState state) { public PushReaction getPushReaction(BlockState state) {
return PushReaction.BLOCK; return PushReaction.BLOCK;
} }
@Override @Override
public boolean isNormalCube(BlockState state, IBlockReader worldIn, BlockPos pos) { public boolean isNormalCube(BlockState state, IBlockReader worldIn, BlockPos pos) {
return false; return false;
@ -142,6 +175,13 @@ public class CartAssemblerBlock extends AbstractRailBlock {
builder.add(BlockStateProperties.HORIZONTAL_AXIS); builder.add(BlockStateProperties.HORIZONTAL_AXIS);
super.fillStateContainer(builder); super.fillStateContainer(builder);
} }
@Override
public VoxelShape getShape(BlockState p_220053_1_, IBlockReader p_220053_2_, BlockPos p_220053_3_,
ISelectionContext p_220053_4_) {
return VoxelShapes.empty();
}
} }
public static BlockState createAnchor(BlockState state) { public static BlockState createAnchor(BlockState state) {
@ -149,4 +189,9 @@ public class CartAssemblerBlock extends AbstractRailBlock {
return AllBlocks.MINECART_ANCHOR.get().getDefaultState().with(BlockStateProperties.HORIZONTAL_AXIS, axis); return AllBlocks.MINECART_ANCHOR.get().getDefaultState().with(BlockStateProperties.HORIZONTAL_AXIS, axis);
} }
@Override
public Class<CartAssemblerTileEntity> getTileEntityClass() {
return CartAssemblerTileEntity.class;
}
} }

View file

@ -0,0 +1,65 @@
package com.simibubi.create.modules.contraptions.components.contraptions.mounted;
import java.util.List;
import com.simibubi.create.AllTileEntities;
import com.simibubi.create.ScreenResources;
import com.simibubi.create.foundation.behaviour.CenteredSideValueBoxTransform;
import com.simibubi.create.foundation.behaviour.ValueBoxTransform;
import com.simibubi.create.foundation.behaviour.base.SmartTileEntity;
import com.simibubi.create.foundation.behaviour.base.TileEntityBehaviour;
import com.simibubi.create.foundation.behaviour.scrollvalue.INamedIconOptions;
import com.simibubi.create.foundation.behaviour.scrollvalue.ScrollOptionBehaviour;
import com.simibubi.create.foundation.utility.Lang;
import net.minecraft.util.Direction;
public class CartAssemblerTileEntity extends SmartTileEntity {
protected ScrollOptionBehaviour<CartMovementMode> movementMode;
public CartAssemblerTileEntity() {
super(AllTileEntities.CART_ASSEMBLER.type);
}
@Override
public void addBehaviours(List<TileEntityBehaviour> behaviours) {
movementMode = new ScrollOptionBehaviour<>(CartMovementMode.class,
Lang.translate("contraptions.cart_movement_mode"), this, getMovementModeSlot());
movementMode.requiresWrench();
behaviours.add(movementMode);
}
protected ValueBoxTransform getMovementModeSlot() {
return new CenteredSideValueBoxTransform((state, d) -> d == Direction.UP);
}
public static enum CartMovementMode implements INamedIconOptions {
ROTATE(ScreenResources.I_CART_ROTATE),
ROTATE_PAUSED(ScreenResources.I_CART_ROTATE_PAUSED),
ROTATION_LOCKED(ScreenResources.I_CART_ROTATE_LOCKED),
;
private String translationKey;
private ScreenResources icon;
private CartMovementMode(ScreenResources icon) {
this.icon = icon;
translationKey = "contraptions.cart_movement_mode." + Lang.asId(name());
}
@Override
public ScreenResources getIcon() {
return icon;
}
@Override
public String getTranslationKey() {
return translationKey;
}
}
}

View file

@ -0,0 +1,215 @@
package com.simibubi.create.modules.contraptions.components.contraptions.mounted;
import java.util.List;
import javax.annotation.Nullable;
import com.simibubi.create.AllItems;
import com.simibubi.create.modules.contraptions.components.contraptions.Contraption;
import com.simibubi.create.modules.contraptions.components.contraptions.ContraptionEntity;
import net.minecraft.block.AbstractRailBlock;
import net.minecraft.block.BlockState;
import net.minecraft.block.DispenserBlock;
import net.minecraft.dispenser.DefaultDispenseItemBehavior;
import net.minecraft.dispenser.IBlockSource;
import net.minecraft.dispenser.IDispenseItemBehavior;
import net.minecraft.entity.Entity;
import net.minecraft.entity.item.minecart.AbstractMinecartEntity;
import net.minecraft.entity.item.minecart.AbstractMinecartEntity.Type;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.Item;
import net.minecraft.item.ItemGroup;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemUseContext;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.state.properties.RailShape;
import net.minecraft.tags.BlockTags;
import net.minecraft.util.ActionResultType;
import net.minecraft.util.Direction;
import net.minecraft.util.NonNullList;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.event.entity.player.PlayerInteractEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
@EventBusSubscriber
public class MinecartContraptionItem extends Item {
private final AbstractMinecartEntity.Type minecartType;
public MinecartContraptionItem(Type minecartTypeIn, Properties builder) {
super(builder);
this.minecartType = minecartTypeIn;
DispenserBlock.registerDispenseBehavior(this, DISPENSER_BEHAVIOR);
}
// Taken and adjusted from MinecartItem
private static final IDispenseItemBehavior DISPENSER_BEHAVIOR = new DefaultDispenseItemBehavior() {
private final DefaultDispenseItemBehavior behaviourDefaultDispenseItem = new DefaultDispenseItemBehavior();
@Override
public ItemStack dispenseStack(IBlockSource source, ItemStack stack) {
Direction direction = source.getBlockState().get(DispenserBlock.FACING);
World world = source.getWorld();
double d0 = source.getX() + (double) direction.getXOffset() * 1.125D;
double d1 = Math.floor(source.getY()) + (double) direction.getYOffset();
double d2 = source.getZ() + (double) direction.getZOffset() * 1.125D;
BlockPos blockpos = source.getBlockPos().offset(direction);
BlockState blockstate = world.getBlockState(blockpos);
RailShape railshape = blockstate.getBlock() instanceof AbstractRailBlock
? ((AbstractRailBlock) blockstate.getBlock()).getRailDirection(blockstate, world, blockpos, null)
: RailShape.NORTH_SOUTH;
double d3;
if (blockstate.isIn(BlockTags.RAILS)) {
if (railshape.isAscending()) {
d3 = 0.6D;
} else {
d3 = 0.1D;
}
} else {
if (!blockstate.isAir(world, blockpos) || !world.getBlockState(blockpos.down()).isIn(BlockTags.RAILS)) {
return this.behaviourDefaultDispenseItem.dispense(source, stack);
}
BlockState blockstate1 = world.getBlockState(blockpos.down());
RailShape railshape1 = blockstate1.getBlock() instanceof AbstractRailBlock
? ((AbstractRailBlock) blockstate1.getBlock()).getRailDirection(blockstate1, world,
blockpos.down(), null)
: RailShape.NORTH_SOUTH;
if (direction != Direction.DOWN && railshape1.isAscending()) {
d3 = -0.4D;
} else {
d3 = -0.9D;
}
}
AbstractMinecartEntity abstractminecartentity = AbstractMinecartEntity.create(world, d0, d1 + d3, d2,
((MinecartContraptionItem) stack.getItem()).minecartType);
if (stack.hasDisplayName())
abstractminecartentity.setCustomName(stack.getDisplayName());
world.addEntity(abstractminecartentity);
addContraptionToMinecart(world, stack, abstractminecartentity, direction);
stack.shrink(1);
return stack;
}
@Override
protected void playDispenseSound(IBlockSource source) {
source.getWorld().playEvent(1000, source.getBlockPos(), 0);
}
};
// Taken and adjusted from MinecartItem
@Override
public ActionResultType onItemUse(ItemUseContext context) {
World world = context.getWorld();
BlockPos blockpos = context.getPos();
BlockState blockstate = world.getBlockState(blockpos);
if (!blockstate.isIn(BlockTags.RAILS)) {
return ActionResultType.FAIL;
} else {
ItemStack itemstack = context.getItem();
if (!world.isRemote) {
RailShape railshape = blockstate.getBlock() instanceof AbstractRailBlock
? ((AbstractRailBlock) blockstate.getBlock()).getRailDirection(blockstate, world, blockpos,
null)
: RailShape.NORTH_SOUTH;
double d0 = 0.0D;
if (railshape.isAscending()) {
d0 = 0.5D;
}
AbstractMinecartEntity abstractminecartentity = AbstractMinecartEntity.create(world,
(double) blockpos.getX() + 0.5D, (double) blockpos.getY() + 0.0625D + d0,
(double) blockpos.getZ() + 0.5D, this.minecartType);
if (itemstack.hasDisplayName())
abstractminecartentity.setCustomName(itemstack.getDisplayName());
PlayerEntity player = context.getPlayer();
world.addEntity(abstractminecartentity);
addContraptionToMinecart(world, itemstack, abstractminecartentity,
player == null ? null : player.getHorizontalFacing());
}
itemstack.shrink(1);
return ActionResultType.SUCCESS;
}
}
public static void addContraptionToMinecart(World world, ItemStack itemstack, AbstractMinecartEntity cart,
@Nullable Direction newFacing) {
CompoundNBT tag = itemstack.getOrCreateTag();
if (tag.contains("Contraption")) {
CompoundNBT contraptionTag = tag.getCompound("Contraption");
float initialAngle = contraptionTag.getFloat("InitialAngle");
Contraption mountedContraption = Contraption.fromNBT(world, contraptionTag);
ContraptionEntity contraption;
if (newFacing != null)
contraption = ContraptionEntity.createMounted(world, mountedContraption, initialAngle, newFacing);
else
contraption = ContraptionEntity.createMounted(world, mountedContraption, initialAngle);
contraption.startRiding(cart);
contraption.setPosition(cart.getX(), cart.getY(), cart.getZ());
world.addEntity(contraption);
}
}
@Override
public String getTranslationKey(ItemStack stack) {
return "item.create.minecart_contraption";
}
@Override
public void fillItemGroup(ItemGroup group, NonNullList<ItemStack> items) {
}
@SubscribeEvent
public static void wrenchCanBeUsedToPickUpMinecartContraptions(PlayerInteractEvent.EntityInteract event) {
Entity entity = event.getTarget();
PlayerEntity player = event.getPlayer();
if (player == null || entity == null)
return;
ItemStack wrench = player.getHeldItem(event.getHand());
if (!AllItems.WRENCH.typeOf(wrench))
return;
if (entity instanceof ContraptionEntity)
entity = entity.getRidingEntity();
if (!(entity instanceof AbstractMinecartEntity))
return;
AbstractMinecartEntity cart = (AbstractMinecartEntity) entity;
Type type = cart.getMinecartType();
if (type != Type.RIDEABLE && type != Type.FURNACE)
return;
List<Entity> passengers = cart.getPassengers();
if (passengers.isEmpty() || !(passengers.get(0) instanceof ContraptionEntity))
return;
ContraptionEntity contraption = (ContraptionEntity) passengers.get(0);
if (!event.getWorld().isRemote) {
player.inventory.placeItemBackInInventory(event.getWorld(), create(type, contraption));
contraption.remove();
entity.remove();
}
event.setCancellationResult(ActionResultType.SUCCESS);
event.setCanceled(true);
}
public static ItemStack create(Type type, ContraptionEntity entity) {
ItemStack stack =
(type == Type.RIDEABLE ? AllItems.MINECART_CONTRAPTION : AllItems.FURNACE_MINECART_CONTRAPTION).asStack();
CompoundNBT tag = entity.getContraption().writeNBT();
tag.remove("UUID");
tag.remove("Pos");
tag.remove("Motion");
tag.putFloat("InitialAngle", entity.getInitialAngle());
stack.getOrCreateTag().put("Contraption", tag);
return stack;
}
}

View file

@ -7,10 +7,14 @@ import java.util.List;
import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.tuple.Pair;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.foundation.utility.NBTHelper;
import com.simibubi.create.modules.contraptions.components.contraptions.AllContraptionTypes; import com.simibubi.create.modules.contraptions.components.contraptions.AllContraptionTypes;
import com.simibubi.create.modules.contraptions.components.contraptions.BlockMovementTraits;
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.mounted.CartAssemblerTileEntity.CartMovementMode;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.nbt.CompoundNBT;
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.tileentity.TileEntity;
@ -25,12 +29,14 @@ import net.minecraft.world.gen.feature.template.Template.BlockInfo;
public class MountedContraption extends Contraption { public class MountedContraption extends Contraption {
public CartMovementMode rotationMode;
@Override @Override
protected AllContraptionTypes getType() { protected AllContraptionTypes getType() {
return AllContraptionTypes.MOUNTED; return AllContraptionTypes.MOUNTED;
} }
public static Contraption assembleMinecart(World world, BlockPos pos) { public static MountedContraption assembleMinecart(World world, BlockPos pos) {
if (isFrozen()) if (isFrozen())
return null; return null;
@ -38,7 +44,7 @@ public class MountedContraption extends Contraption {
if (!state.has(RAIL_SHAPE)) if (!state.has(RAIL_SHAPE))
return null; return null;
Contraption contraption = new MountedContraption(); MountedContraption contraption = new MountedContraption();
if (!contraption.searchMovedStructure(world, pos, null)) if (!contraption.searchMovedStructure(world, pos, null))
return null; return null;
@ -61,8 +67,14 @@ public class MountedContraption extends Contraption {
if (!AllBlocks.CART_ASSEMBLER.typeOf(state)) if (!AllBlocks.CART_ASSEMBLER.typeOf(state))
return false; return false;
Axis axis = state.get(CartAssemblerBlock.RAIL_SHAPE) == RailShape.EAST_WEST ? Axis.Z : Axis.X; Axis axis = state.get(CartAssemblerBlock.RAIL_SHAPE) == RailShape.EAST_WEST ? Axis.Z : Axis.X;
for (AxisDirection axisDirection : AxisDirection.values()) for (AxisDirection axisDirection : AxisDirection.values()) {
frontier.add(pos.offset(Direction.getFacingFromAxis(axisDirection, axis))); Direction facingFromAxis = Direction.getFacingFromAxis(axisDirection, axis);
BlockPos offset = pos.offset(facingFromAxis);
BlockState blockState = world.getBlockState(offset);
if (!BlockMovementTraits.isBrittle(blockState)
|| BlockMovementTraits.isBlockAttachedTowards(blockState, facingFromAxis.getOpposite()))
frontier.add(offset);
}
return true; return true;
} }
@ -76,14 +88,27 @@ public class MountedContraption extends Contraption {
return pair; return pair;
} }
@Override
public CompoundNBT writeNBT() {
CompoundNBT writeNBT = super.writeNBT();
writeNBT.putString("RotationMode", NBTHelper.writeEnum(rotationMode));
return writeNBT;
}
@Override
public void readNBT(World world, CompoundNBT nbt) {
rotationMode = NBTHelper.readEnum(nbt.getString("RotationMode"), CartMovementMode.class);
super.readNBT(world, nbt);
}
@Override @Override
public void removeBlocksFromWorld(IWorld world, BlockPos offset) { public void removeBlocksFromWorld(IWorld world, BlockPos offset) {
super.removeBlocksFromWorld(world, offset, (pos, state) -> pos.equals(anchor)); super.removeBlocksFromWorld(world, offset, (pos, state) -> pos.equals(anchor));
} }
@Override @Override
public void disassemble(World world, BlockPos offset, Vec3d rotation) { public void addBlocksToWorld(World world, BlockPos offset, Vec3d rotation) {
super.disassemble(world, offset, rotation, (pos, state) -> AllBlocks.MINECART_ANCHOR.typeOf(state)); super.addBlocksToWorld(world, offset, rotation, (pos, state) -> AllBlocks.MINECART_ANCHOR.typeOf(state));
} }
} }

View file

@ -293,8 +293,10 @@ public abstract class LinearActuatorTileEntity extends KineticTileEntity impleme
@Override @Override
public void attach(ContraptionEntity contraption) { public void attach(ContraptionEntity contraption) {
this.movedContraption = contraption; this.movedContraption = contraption;
if (!world.isRemote) if (!world.isRemote) {
this.running = true;
sendData(); sendData();
}
} }
@Override @Override

View file

@ -42,6 +42,9 @@ public class MechanicalPistonTileEntity extends LinearActuatorTileEntity {
@Override @Override
public void assemble() { public void assemble() {
if (!(world.getBlockState(pos).getBlock() instanceof MechanicalPistonBlock))
return;
Direction direction = getBlockState().get(BlockStateProperties.FACING); Direction direction = getBlockState().get(BlockStateProperties.FACING);
// Collect Construct // Collect Construct
@ -83,10 +86,11 @@ public class MechanicalPistonTileEntity extends LinearActuatorTileEntity {
@Override @Override
public void disassemble() { public void disassemble() {
if (!running) if (!running && movedContraption == null)
return; return;
if (!removed) if (!removed)
getWorld().setBlockState(pos, getBlockState().with(MechanicalPistonBlock.STATE, PistonState.EXTENDED), 3); getWorld().setBlockState(pos, getBlockState().with(MechanicalPistonBlock.STATE, PistonState.EXTENDED),
3 | 16);
if (movedContraption != null) { if (movedContraption != null) {
applyContraptionPosition(); applyContraptionPosition();
movedContraption.disassemble(); movedContraption.disassemble();

View file

@ -6,7 +6,6 @@ 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 net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher; import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher;
import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.state.properties.BlockStateProperties;

View file

@ -13,9 +13,11 @@ 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.foundation.utility.NBTHelper;
import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.modules.contraptions.components.contraptions.AllContraptionTypes; import com.simibubi.create.modules.contraptions.components.contraptions.AllContraptionTypes;
import com.simibubi.create.modules.contraptions.components.contraptions.BlockMovementTraits; import com.simibubi.create.modules.contraptions.components.contraptions.BlockMovementTraits;
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.glue.SuperGlueEntity;
import com.simibubi.create.modules.contraptions.components.contraptions.piston.MechanicalPistonBlock.PistonState; import com.simibubi.create.modules.contraptions.components.contraptions.piston.MechanicalPistonBlock.PistonState;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
@ -63,17 +65,24 @@ public class PistonContraption extends Contraption {
BlockPos actualStart = pos; BlockPos actualStart = pos;
BlockState nextBlock = world.getBlockState(actualStart.offset(direction)); BlockState nextBlock = world.getBlockState(actualStart.offset(direction));
int extensionsInFront = 0; int extensionsInFront = 0;
boolean sticky = STICKY_MECHANICAL_PISTON.typeOf(world.getBlockState(pos)); BlockState blockState = world.getBlockState(pos);
boolean sticky = STICKY_MECHANICAL_PISTON.typeOf(blockState);
if (world.getBlockState(pos).get(MechanicalPistonBlock.STATE) == PistonState.EXTENDED) { if (!(blockState.getBlock() instanceof MechanicalPistonBlock))
return false;
if (blockState.get(MechanicalPistonBlock.STATE) == PistonState.EXTENDED) {
while (PISTON_POLE.typeOf(nextBlock) && nextBlock.get(FACING).getAxis() == direction.getAxis() while (PISTON_POLE.typeOf(nextBlock) && nextBlock.get(FACING).getAxis() == direction.getAxis()
|| MECHANICAL_PISTON_HEAD.typeOf(nextBlock) && nextBlock.get(FACING) == direction) { || MECHANICAL_PISTON_HEAD.typeOf(nextBlock) && nextBlock.get(FACING) == direction) {
actualStart = actualStart.offset(direction); actualStart = actualStart.offset(direction);
poles.add(new BlockInfo(actualStart, nextBlock.with(FACING, direction), null)); poles.add(new BlockInfo(actualStart, nextBlock.with(FACING, direction), null));
extensionsInFront++; extensionsInFront++;
nextBlock = world.getBlockState(actualStart.offset(direction));
if (MECHANICAL_PISTON_HEAD.typeOf(nextBlock))
break;
nextBlock = world.getBlockState(actualStart.offset(direction));
if (extensionsInFront > MechanicalPistonBlock.maxAllowedPistonPoles()) if (extensionsInFront > MechanicalPistonBlock.maxAllowedPistonPoles())
return false; return false;
} }
@ -122,6 +131,11 @@ public class PistonContraption extends Contraption {
return true; return true;
} }
@Override
protected boolean isAnchoringBlockAt(BlockPos pos) {
return pistonExtensionCollisionBox.contains(VecHelper.getCenterOf(pos.subtract(anchor)));
}
@Override @Override
protected boolean addToInitialFrontier(World world, BlockPos pos, Direction direction, List<BlockPos> frontier) { protected boolean addToInitialFrontier(World world, BlockPos pos, Direction direction, List<BlockPos> frontier) {
frontier.clear(); frontier.clear();
@ -138,6 +152,8 @@ public class PistonContraption extends Contraption {
if (!BlockMovementTraits.movementNecessary(world, currentPos)) if (!BlockMovementTraits.movementNecessary(world, currentPos))
return true; return true;
BlockState state = world.getBlockState(currentPos); BlockState state = world.getBlockState(currentPos);
if (BlockMovementTraits.isBrittle(state))
return true;
if (AllBlocks.MECHANICAL_PISTON_HEAD.typeOf(state) && state.get(FACING) == direction.getOpposite()) if (AllBlocks.MECHANICAL_PISTON_HEAD.typeOf(state) && state.get(FACING) == direction.getOpposite())
return true; return true;
if (!BlockMovementTraits.movementAllowed(world, currentPos)) if (!BlockMovementTraits.movementAllowed(world, currentPos))
@ -146,7 +162,7 @@ public class PistonContraption extends Contraption {
if (BlockMovementTraits.notSupportive(state, orientation)) if (BlockMovementTraits.notSupportive(state, orientation))
return true; return true;
} }
return false; // too many return true;
} }
@Override @Override
@ -155,8 +171,17 @@ public class PistonContraption extends Contraption {
} }
@Override @Override
public void disassemble(World world, BlockPos offset, Vec3d rotation) { public void addGlue(SuperGlueEntity entity) {
super.disassemble(world, offset, rotation, (pos, state) -> { BlockPos pos = entity.getHangingPosition();
Direction direction = entity.getFacingDirection();
BlockPos localPos = pos.subtract(anchor).offset(orientation, -initialExtensionProgress);
this.superglue.add(Pair.of(localPos, direction));
glueToRemove.add(entity);
}
@Override
public void addBlocksToWorld(World world, BlockPos offset, Vec3d rotation) {
super.addBlocksToWorld(world, offset, rotation, (pos, state) -> {
BlockPos pistonPos = anchor.offset(orientation, -1); BlockPos pistonPos = anchor.offset(orientation, -1);
BlockState pistonState = world.getBlockState(pistonPos); BlockState pistonState = world.getBlockState(pistonPos);
TileEntity te = world.getTileEntity(pistonPos); TileEntity te = world.getTileEntity(pistonPos);
@ -165,7 +190,7 @@ public class PistonContraption extends Contraption {
return true; return true;
if (!AllBlocks.PISTON_POLE.typeOf(state) && pistonState.getBlock() instanceof MechanicalPistonBlock) if (!AllBlocks.PISTON_POLE.typeOf(state) && pistonState.getBlock() instanceof MechanicalPistonBlock)
world.setBlockState(pistonPos, pistonState.with(MechanicalPistonBlock.STATE, PistonState.RETRACTED), world.setBlockState(pistonPos, pistonState.with(MechanicalPistonBlock.STATE, PistonState.RETRACTED),
3); 3 | 16);
return true; return true;
} }
return false; return false;
@ -178,7 +203,7 @@ public class PistonContraption extends Contraption {
BlockPos pistonPos = anchor.offset(orientation, -1); BlockPos pistonPos = anchor.offset(orientation, -1);
BlockState blockState = world.getBlockState(pos); BlockState blockState = world.getBlockState(pos);
if (pos.equals(pistonPos) && blockState.getBlock() instanceof MechanicalPistonBlock) { if (pos.equals(pistonPos) && blockState.getBlock() instanceof MechanicalPistonBlock) {
world.setBlockState(pos, blockState.with(MechanicalPistonBlock.STATE, PistonState.MOVING), 66); world.setBlockState(pos, blockState.with(MechanicalPistonBlock.STATE, PistonState.MOVING), 66 | 16);
return true; return true;
} }
return false; return false;

View file

@ -1,6 +1,5 @@
package com.simibubi.create.modules.contraptions.components.contraptions.pulley; package com.simibubi.create.modules.contraptions.components.contraptions.pulley;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.foundation.block.ITE; import com.simibubi.create.foundation.block.ITE;
import com.simibubi.create.foundation.utility.AllShapes; import com.simibubi.create.foundation.utility.AllShapes;
import com.simibubi.create.modules.contraptions.base.HorizontalAxisKineticBlock; import com.simibubi.create.modules.contraptions.base.HorizontalAxisKineticBlock;
@ -8,6 +7,7 @@ import com.simibubi.create.modules.contraptions.base.HorizontalAxisKineticBlock;
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.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.state.EnumProperty; import net.minecraft.state.EnumProperty;
import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.state.properties.BlockStateProperties;
@ -42,6 +42,17 @@ public class PulleyBlock extends HorizontalAxisKineticBlock implements ITE<Pulle
} }
@Override @Override
public void onReplaced(BlockState state, World worldIn, BlockPos pos, BlockState newState, boolean isMoving) {
if (state.hasTileEntity() && state.getBlock() != newState.getBlock()) {
if (!worldIn.isRemote) {
BlockState below = worldIn.getBlockState(pos.down());
if (below.getBlock() instanceof RopeBlockBase)
worldIn.destroyBlock(pos.down(), true);
}
worldIn.removeTileEntity(pos);
}
}
public ActionResultType onUse(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn, public ActionResultType onUse(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn,
BlockRayTraceResult hit) { BlockRayTraceResult hit) {
if (!player.isAllowEdit()) if (!player.isAllowEdit())
@ -76,27 +87,23 @@ public class PulleyBlock extends HorizontalAxisKineticBlock implements ITE<Pulle
} }
@Override @Override
public void neighborChanged(BlockState state, World worldIn, BlockPos pos, Block blockIn, BlockPos fromPos, public PushReaction getPushReaction(BlockState state) {
boolean isMoving) { return PushReaction.BLOCK;
if (isMoving)
return;
if (fromPos.equals(pos.down()) && this != AllBlocks.PULLEY_MAGNET.get())
if (!AllBlocks.ROPE.typeOf(worldIn.getBlockState(fromPos))
&& !AllBlocks.PULLEY_MAGNET.typeOf(worldIn.getBlockState(fromPos))) {
worldIn.destroyBlock(pos, true);
}
if (fromPos.equals(pos.up()))
if (!AllBlocks.ROPE.typeOf(worldIn.getBlockState(fromPos))
&& !AllBlocks.ROPE_PULLEY.typeOf(worldIn.getBlockState(fromPos))) {
worldIn.destroyBlock(pos, true);
}
} }
@Override @Override
public void onReplaced(BlockState state, World worldIn, BlockPos pos, BlockState newState, boolean isMoving) { public void onReplaced(BlockState state, World worldIn, BlockPos pos, BlockState newState, boolean isMoving) {
if (!isMoving) if (!isMoving) {
onRopeBroken(worldIn, pos.up()); onRopeBroken(worldIn, pos.up());
if (!worldIn.isRemote) {
BlockState above = worldIn.getBlockState(pos.up());
BlockState below = worldIn.getBlockState(pos.down());
if (above.getBlock() instanceof RopeBlockBase)
worldIn.destroyBlock(pos.up(), true);
if (below.getBlock() instanceof RopeBlockBase)
worldIn.destroyBlock(pos.down(), true);
}
}
if (state.hasTileEntity() && state.getBlock() != newState.getBlock()) { if (state.hasTileEntity() && state.getBlock() != newState.getBlock()) {
worldIn.removeTileEntity(pos); worldIn.removeTileEntity(pos);
} }

View file

@ -27,6 +27,16 @@ public class PulleyContraption extends Contraption {
return construct; return construct;
} }
@Override
protected boolean isAnchoringBlockAt(BlockPos pos) {
if (pos.getX() != anchor.getX() || pos.getZ() != anchor.getZ())
return false;
int y = pos.getY();
if (y <= anchor.getY() || y > anchor.getY() + initialOffset + 1)
return false;
return true;
}
@Override @Override
public CompoundNBT writeNBT() { public CompoundNBT writeNBT() {
CompoundNBT writeNBT = super.writeNBT(); CompoundNBT writeNBT = super.writeNBT();

View file

@ -37,6 +37,8 @@ public class PulleyTileEntity extends LinearActuatorTileEntity {
@Override @Override
protected void assemble() { protected void assemble() {
if (!(world.getBlockState(pos).getBlock() instanceof PulleyBlock))
return;
if (speed == 0) if (speed == 0)
return; return;
if (offset >= getExtensionRange() && getSpeed() > 0) if (offset >= getExtensionRange() && getSpeed() > 0)
@ -81,7 +83,7 @@ public class PulleyTileEntity extends LinearActuatorTileEntity {
@Override @Override
public void disassemble() { public void disassemble() {
if (!running) if (!running && movedContraption == null)
return; return;
offset = getGridOffset(offset); offset = getGridOffset(offset);
if (movedContraption != null) if (movedContraption != null)
@ -137,6 +139,8 @@ public class PulleyTileEntity extends LinearActuatorTileEntity {
BlockPos posBelow = pos.down((int) (offset + getMovementSpeed()) + 1); BlockPos posBelow = pos.down((int) (offset + getMovementSpeed()) + 1);
if (!BlockMovementTraits.movementNecessary(world, posBelow)) if (!BlockMovementTraits.movementNecessary(world, posBelow))
return; return;
if (BlockMovementTraits.isBrittle(world.getBlockState(posBelow)))
return;
disassemble(); disassemble();
assembleNextTick = true; assembleNextTick = true;

View file

@ -6,6 +6,7 @@ import static com.simibubi.create.modules.contraptions.base.HorizontalKineticBlo
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
@ -137,8 +138,8 @@ public class ConnectedInputHandler {
if (controllerPos1.equals(controllerPos2)) { if (controllerPos1.equals(controllerPos2)) {
MechanicalCrafterTileEntity controller = CrafterHelper.getCrafter(world, controllerPos1); MechanicalCrafterTileEntity controller = CrafterHelper.getCrafter(world, controllerPos1);
Set<BlockPos> positions = controller.input.data.stream().map(l -> controllerPos1.add(l)) Set<BlockPos> positions =
.collect(Collectors.toSet()); controller.input.data.stream().map(l -> controllerPos1.add(l)).collect(Collectors.toSet());
List<BlockPos> frontier = new LinkedList<>(); List<BlockPos> frontier = new LinkedList<>();
List<BlockPos> splitGroup = new ArrayList<>(); List<BlockPos> splitGroup = new ArrayList<>();
@ -198,8 +199,7 @@ public class ConnectedInputHandler {
crafter1.input.data.forEach(offset -> { crafter1.input.data.forEach(offset -> {
BlockPos connectedPos = crafter1.getPos().add(offset); BlockPos connectedPos = crafter1.getPos().add(offset);
modifyAndUpdate(world, connectedPos, input -> { modifyAndUpdate(world, connectedPos, input -> {});
});
}); });
crafter2.input.data.forEach(offset -> { crafter2.input.data.forEach(offset -> {
@ -229,7 +229,7 @@ public class ConnectedInputHandler {
public static class ConnectedInput { public static class ConnectedInput {
boolean isController; boolean isController;
List<BlockPos> data = new ArrayList<>(); List<BlockPos> data = Collections.synchronizedList(new ArrayList<>());
public ConnectedInput() { public ConnectedInput() {
isController = true; isController = true;

View file

@ -20,6 +20,7 @@ import com.simibubi.create.modules.contraptions.components.crafter.MechanicalCra
import com.simibubi.create.modules.contraptions.components.crafter.RecipeGridHandler.GroupedItems; import com.simibubi.create.modules.contraptions.components.crafter.RecipeGridHandler.GroupedItems;
import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity; import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity;
import net.minecraft.block.BlockState;
import net.minecraft.entity.item.ItemEntity; import net.minecraft.entity.item.ItemEntity;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.CompoundNBT;
@ -357,8 +358,10 @@ public class MechanicalCrafterTileEntity extends KineticTileEntity {
} }
public void eject() { public void eject() {
Vec3d ejectPos = VecHelper.getCenterOf(pos) BlockState blockState = getBlockState();
.add(new Vec3d(getBlockState().get(HORIZONTAL_FACING).getDirectionVec()).scale(.75f)); boolean present = AllBlocks.MECHANICAL_CRAFTER.typeOf(blockState);
Vec3d vec = present ? new Vec3d(blockState.get(HORIZONTAL_FACING).getDirectionVec()).scale(.75f) : Vec3d.ZERO;
Vec3d ejectPos = VecHelper.getCenterOf(pos).add(vec);
groupedItems.grid.forEach((pair, stack) -> dropItem(ejectPos, stack)); groupedItems.grid.forEach((pair, stack) -> dropItem(ejectPos, stack));
if (!inventory.getStackInSlot(0).isEmpty()) if (!inventory.getStackInSlot(0).isEmpty())
dropItem(ejectPos, inventory.getStackInSlot(0)); dropItem(ejectPos, inventory.getStackInSlot(0));

Some files were not shown because too many files have changed in this diff Show more