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.components.actors.DrillBlock;
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.clock.CuckooClockBlock;
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.ScoriaBlock;
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.ItemBuilder;
import com.tterrag.registrate.providers.ProviderType;
@ -172,9 +170,10 @@ public enum AllBlocks implements NonNullSupplier<Block> {
ROTATION_CHASSIS(RadialChassisBlock::new),
DRILL(DrillBlock::new),
SAW(SawBlock::new),
HARVESTER(HarvesterBlock::new),
DEPLOYER(DeployerBlock::new),
PORTABLE_STORAGE_INTERFACE(PortableStorageInterfaceBlock::new),
HARVESTER(HarvesterBlock::new),
PLOUGH(PloughBlock::new),
ANALOG_LEVER(AnalogLeverBlock::new),
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.tterrag.registrate.util.RegistryEntry;
import net.minecraftforge.client.model.generators.ModelFile.UncheckedModelFile;
public class AllBlocksNew {
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.modules.contraptions.components.contraptions.ContraptionEntity;
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.EntityClassification;
@ -23,6 +25,8 @@ public enum AllEntities {
ContraptionEntity::build),
STATIONARY_CONTRAPTION(ContraptionEntity::new, EntityClassification.MISC, 30, 40,
false, ContraptionEntity::build),
SUPER_GLUE(SuperGlueEntity::new, EntityClassification.MISC, 30, Integer.MAX_VALUE, false, SuperGlueEntity::build),
;
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
@OnlyIn(value = Dist.CLIENT)
public static void registerRenderers() {
// RenderingRegistry.registerEntityRenderingHandler(CardboardBoxEntity.class, CardboardBoxEntityRenderer::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.contraptions.GogglesItem;
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.gearbox.VerticalGearboxItem;
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.renderer.color.ItemColors;
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.Properties;
import net.minecraft.item.ItemStack;
@ -75,8 +78,8 @@ public enum AllItems {
ZINC_INGOT((TaggedItem) new TaggedItem().withForgeTags("ingots/zinc")),
BRASS_INGOT((TaggedItem) new TaggedItem().withForgeTags("ingots/brass")),
SAND_PAPER(SandPaperItem::new),
RED_SAND_PAPER(SandPaperItem::new),
FLOUR,
DOUGH,
OBSIDIAN_DUST,
ROSE_QUARTZ,
POLISHED_ROSE_QUARTZ,
@ -86,23 +89,20 @@ public enum AllItems {
ELECTRON_TUBE,
INTEGRATED_CIRCUIT,
__SCHEMATICS__(module()),
EMPTY_BLUEPRINT(Item::new, stackSize(1)),
BLUEPRINT_AND_QUILL(SchematicAndQuillItem::new, stackSize(1)),
BLUEPRINT(SchematicItem::new),
__CONTRAPTIONS__(module()),
BELT_CONNECTOR(BeltConnectorItem::new),
VERTICAL_GEARBOX(VerticalGearboxItem::new),
FLOUR,
DOUGH,
PROPELLER,
WHISK,
BRASS_HAND,
SLOT_COVER,
ZINC_HANDLE,
SUPER_GLUE(SuperGlueItem::new),
SAND_PAPER(SandPaperItem::new),
RED_SAND_PAPER(SandPaperItem::new),
WRENCH(WrenchItem::new),
GOGGLES(GogglesItem::new),
MINECART_CONTRAPTION(p -> new MinecartContraptionItem(Type.RIDEABLE, p)),
FURNACE_MINECART_CONTRAPTION(p -> new MinecartContraptionItem(Type.FURNACE, p)),
__LOGISTICS__(module()),
FILTER(FilterItem::new),
@ -114,6 +114,7 @@ public enum AllItems {
TERRAIN_ZAPPER(TerrainzapperItem::new),
DEFORESTER(DeforesterItem::new),
SYMMETRY_WAND(SymmetryWandItem::new),
ZINC_HANDLE,
BLAZING_PICKAXE(p -> new BlazingToolItem(1, -2.8F, p, PICKAXE)),
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_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 {
@ -197,7 +203,8 @@ public enum AllItems {
continue;
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()));
registry.register(entry.item);
}
@ -224,11 +231,11 @@ public enum AllItems {
private Set<ResourceLocation> tagSetItem = new HashSet<>();
private Function<Properties, Item> itemSupplier;
public TaggedItem(){
public TaggedItem() {
this(Item::new);
}
public TaggedItem(Function<Properties, Item> itemSupplierIn){
public TaggedItem(Function<Properties, Item> 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.modules.contraptions.components.contraptions.CancelPlayerFallPacket;
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.curiosities.symmetry.SymmetryEffectPacket;
import com.simibubi.create.modules.curiosities.zapper.ZapperBeamPacket;
@ -51,6 +52,7 @@ public enum AllPackets {
CONFIGURE_CONFIG(ConfigureConfigPacket.class, ConfigureConfigPacket::new),
CONTRAPTION_STALL(ContraptionStallPacket.class, ContraptionStallPacket::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)
public enum AllSpecialTextures {
BLANK("blank.png"),
CHECKERED("checkerboard.png"),
HIGHLIGHT_CHECKERED("highlighted_checkerboard.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.MechanicalBearingTileEntity;
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.MechanicalPistonTileEntityRenderer;
import com.simibubi.create.modules.contraptions.components.contraptions.pulley.PulleyRenderer;
@ -148,6 +149,7 @@ public enum AllTileEntities {
SPEED_GAUGE(SpeedGaugeTileEntity::new, AllBlocks.SPEED_GAUGE),
STRESS_GAUGE(StressGaugeTileEntity::new, AllBlocks.STRESS_GAUGE),
ANALOG_LEVER(AnalogLeverTileEntity::new, AllBlocks.ANALOG_LEVER),
CART_ASSEMBLER(CartAssemblerTileEntity::new, AllBlocks.CART_ASSEMBLER),
// Logistics
REDSTONE_BRIDGE(RedstoneLinkTileEntity::new, AllBlocks.REDSTONE_BRIDGE),

View file

@ -80,8 +80,6 @@ public class ClientEvents {
IRenderTypeBuffer.Impl buffer = Minecraft.getInstance().getBufferBuilders().getEntityVertexConsumers();
CreateClient.schematicHandler.render(ms, buffer, 0xF000F0, OverlayTexture.DEFAULT_UV);
CreateClient.schematicAndQuillHandler.render(ms, buffer);
CreateClient.schematicHologram.render(ms, buffer);
KineticDebugger.renderSourceOutline(ms, buffer);
ChassisRangeDisplay.renderOutlines(event.getPartialTicks(), 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.client.SchematicAndQuillHandler;
import com.simibubi.create.modules.schematics.client.SchematicHandler;
import com.simibubi.create.modules.schematics.client.SchematicHologram;
import net.minecraft.block.Block;
import net.minecraft.client.Minecraft;
@ -41,10 +40,8 @@ public class CreateClient {
public static ClientSchematicLoader schematicSender;
public static SchematicHandler schematicHandler;
public static SchematicHologram schematicHologram;
public static SchematicAndQuillHandler schematicAndQuillHandler;
public static SuperByteBufferCache bufferCache;
public static int renderTicks;
public static void addListeners(IEventBus modEventBus) {
DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> {
@ -59,7 +56,6 @@ public class CreateClient {
public static void clientInit(FMLClientSetupEvent event) {
schematicSender = new ClientSchematicLoader();
schematicHandler = new SchematicHandler();
schematicHologram = new SchematicHologram();
schematicAndQuillHandler = new SchematicAndQuillHandler();
bufferCache = new SuperByteBufferCache();
@ -82,7 +78,6 @@ public class CreateClient {
schematicSender.tick();
schematicAndQuillHandler.tick();
schematicHandler.tick();
schematicHologram.tick();
ChassisRangeDisplay.clientTick();
}

View file

@ -41,7 +41,7 @@ public enum ScreenResources {
FILTER("filter.png", 200, 100),
ATTRIBUTE_FILTER("filter.png", 0, 100, 200, 86),
SEQUENCER("sequencer.png", 156, 128),
SEQUENCER_INSTRUCTION("sequencer.png", 14, 47, 131, 18),
SEQUENCER_WAIT("sequencer.png", 14, 65, 131, 18),
@ -79,6 +79,7 @@ public enum ScreenResources {
// JEI
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_ARROW("jei/widgets.png", 19, 10, 42, 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_RETURNED(10, 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_REPLACE_SOLID(1, 2),

View file

@ -1,7 +1,6 @@
package com.simibubi.create.compat.jei;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
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.mixer.MixingRecipe;
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.schematics.block.SchematicannonScreen;
import mezz.jei.api.IModPlugin;
import mezz.jei.api.JeiPlugin;
import mezz.jei.api.gui.ingredient.IGuiItemStackGroup;
import mezz.jei.api.registration.IGuiHandlerRegistration;
import mezz.jei.api.registration.IRecipeCatalystRegistration;
import mezz.jei.api.registration.IRecipeCategoryRegistration;
@ -226,28 +223,4 @@ public class CreateJEI implements IModPlugin {
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.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.utility.Lang;
import mezz.jei.api.gui.drawable.IDrawable;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.FlowingFluidBlock;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.item.crafting.AbstractCookingRecipe;
import net.minecraft.util.ResourceLocation;
public class BlastingViaFanCategory extends ProcessingViaFanCategory<AbstractCookingRecipe> {
private static ResourceLocation ID = new ResourceLocation(Create.ID, "blasting_via_fan");
private IDrawable icon;
public BlastingViaFanCategory() {
icon = new DoubleItemIcon(() -> new ItemStack(AllItems.PROPELLER.get()),
() -> new ItemStack(Items.LAVA_BUCKET));
}
@Override
public IDrawable getIcon() {
return icon;
}
@Override
public ResourceLocation getUid() {
return ID;
super("blasting_via_fan", doubleItemIcon(AllItems.PROPELLER.get(), Items.LAVA_BUCKET));
}
@Override
@ -41,11 +21,6 @@ public class BlastingViaFanCategory extends ProcessingViaFanCategory<AbstractCoo
return AbstractCookingRecipe.class;
}
@Override
public String getTitle() {
return Lang.translate("recipe.blastingViaFan");
}
@Override
public void renderAttachedBlock() {
BlockState state = Blocks.LAVA.getDefaultState().with(FlowingFluidBlock.LEVEL, 8);

View file

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

View file

@ -9,8 +9,6 @@ import java.util.stream.Collectors;
import com.mojang.blaze3d.systems.RenderSystem;
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.foundation.gui.ScreenElementRenderer;
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.gui.IRecipeLayout;
import mezz.jei.api.gui.drawable.IDrawable;
import mezz.jei.api.gui.ingredient.IGuiItemStackGroup;
import mezz.jei.api.ingredients.IIngredients;
import mezz.jei.api.recipe.category.IRecipeCategory;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.util.ITooltipFlag;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.Ingredient;
import net.minecraft.item.crafting.ShapedRecipe;
import net.minecraft.util.NonNullList;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.text.ITextComponent;
public class BlockzapperUpgradeCategory implements IRecipeCategory<BlockzapperUpgradeRecipe> {
private static ResourceLocation ID = new ResourceLocation(Create.ID, "blockzapper_upgrade");
private IDrawable icon;
public class BlockzapperUpgradeCategory extends CreateRecipeCategory<BlockzapperUpgradeRecipe> {
public BlockzapperUpgradeCategory() {
icon = new DoubleItemIcon(() -> new ItemStack(AllItems.PLACEMENT_HANDGUN.get()),
() -> ItemStack.EMPTY); // replace with uparrow when available
}
@Override
public IDrawable getIcon() {
return icon;
}
@Override
public ResourceLocation getUid() {
return ID;
super("blockzapper_upgrade", itemIcon(AllItems.PLACEMENT_HANDGUN.get()),
new ScreenResourceWrapper(BLOCKZAPPER_UPGRADE_RECIPE));
}
@Override
@ -57,16 +38,6 @@ public class BlockzapperUpgradeCategory implements IRecipeCategory<BlockzapperUp
return BlockzapperUpgradeRecipe.class;
}
@Override
public String getTitle() {
return Lang.translate("recipe.blockzapperUpgrade");
}
@Override
public IDrawable getBackground() {
return new ScreenResourceWrapper(BLOCKZAPPER_UPGRADE_RECIPE);
}
@Override
public void setIngredients(BlockzapperUpgradeRecipe recipe, IIngredients ingredients) {
ingredients.setInputIngredients(recipe.getIngredients());
@ -90,8 +61,6 @@ public class BlockzapperUpgradeCategory implements IRecipeCategory<BlockzapperUp
i++;
}
}
// itemStacks.init(9, false, BLOCKZAPPER_UPGRADE_RECIPE.width / 2 - 9, BLOCKZAPPER_UPGRADE_RECIPE.height - 18 - 10);
// itemStacks.set(9, recipe.getRecipeOutput());
}
@Override
@ -110,11 +79,11 @@ public class BlockzapperUpgradeCategory implements IRecipeCategory<BlockzapperUp
@Override
public void draw(BlockzapperUpgradeRecipe recipe, double mouseX, double mouseY) {
FontRenderer font = Minecraft.getInstance().fontRenderer;
String componentName = Lang
.translate("blockzapper.component." + Lang.asId(recipe.getUpgradedComponent().name()));
String componentName =
Lang.translate("blockzapper.component." + Lang.asId(recipe.getUpgradedComponent().name()));
String text = "+ " + recipe.getTier().color + componentName;
font.drawStringWithShadow(text,
(BLOCKZAPPER_UPGRADE_RECIPE.width - font.getStringWidth(text)) / 2, 57, 0x8B8B8B);
font.drawStringWithShadow(text, (BLOCKZAPPER_UPGRADE_RECIPE.width - font.getStringWidth(text)) / 2, 57,
0x8B8B8B);
RenderSystem.pushMatrix();
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.AllItems;
import com.simibubi.create.Create;
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.foundation.utility.Lang;
import com.simibubi.create.modules.contraptions.components.crusher.AbstractCrushingRecipe;
import com.simibubi.create.modules.contraptions.processing.ProcessingOutput;
import mezz.jei.api.constants.VanillaTypes;
import mezz.jei.api.gui.IRecipeLayout;
import mezz.jei.api.gui.drawable.IDrawable;
import mezz.jei.api.gui.ingredient.IGuiItemStackGroup;
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 IDrawable icon;
private IDrawable background = new EmptyBackground(177, 100);
public CrushingCategory() {
icon = new DoubleItemIcon(() -> new ItemStack(AllBlocks.CRUSHING_WHEEL.get()),
() -> new ItemStack(AllItems.CRUSHED_GOLD.get()));
}
@Override
public IDrawable getBackground() {
return background;
}
@Override
public ResourceLocation getUid() {
return ID;
super("crushing", doubleItemIcon(AllBlocks.CRUSHING_WHEEL.get(), AllItems.CRUSHED_GOLD.get()),
emptyBackground(177, 100));
}
@Override
@ -51,16 +29,6 @@ public class CrushingCategory implements IRecipeCategory<AbstractCrushingRecipe>
return AbstractCrushingRecipe.class;
}
@Override
public String getTitle() {
return Lang.translate("recipe.crushing");
}
@Override
public IDrawable getIcon() {
return icon;
}
@Override
public void setIngredients(AbstractCrushingRecipe recipe, IIngredients ingredients) {
ingredients.setInputIngredients(recipe.getIngredients());
@ -81,7 +49,7 @@ public class CrushingCategory implements IRecipeCategory<AbstractCrushingRecipe>
itemStacks.set(outputIndex + 1, results.get(outputIndex).getStack());
}
CreateJEI.addStochasticTooltip(itemStacks, results);
addStochasticTooltip(itemStacks, results);
}
@Override
@ -93,7 +61,7 @@ public class CrushingCategory implements IRecipeCategory<AbstractCrushingRecipe>
int size = results.size();
int offset = -size * 19 / 2;
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);
}

View file

@ -3,65 +3,39 @@ package com.simibubi.create.compat.jei.category;
import java.util.Arrays;
import com.simibubi.create.AllBlocks;
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.compat.jei.category.animations.AnimatedCrafter;
import com.simibubi.create.foundation.utility.Lang;
import mezz.jei.api.constants.VanillaTypes;
import mezz.jei.api.gui.IRecipeLayout;
import mezz.jei.api.gui.drawable.IDrawable;
import mezz.jei.api.gui.ingredient.IGuiItemStackGroup;
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.ShapedRecipe;
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 ResourceLocation id;
private IDrawable icon;
private IDrawable background;
private 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;
icon = new DoubleItemIcon(() -> new ItemStack(AllBlocks.MECHANICAL_CRAFTER.get()), () -> ItemStack.EMPTY);
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) {
return Math.max((recipe).getWidth(), (recipe).getHeight()) <= 4;
}
@Override
public IDrawable getIcon() {
return icon;
}
@Override
public ResourceLocation getUid() {
return id;
}
@Override
public String getTitle() {
return Lang.translate("recipe.mechanical_crafting");
}
@Override
public IDrawable getBackground() {
return background;
}
@Override
public void setIngredients(ShapedRecipe recipe, IIngredients ingredients) {
ingredients.setInputIngredients(recipe.getIngredients());

View file

@ -5,45 +5,22 @@ import java.util.List;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllItems;
import com.simibubi.create.Create;
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.foundation.utility.Lang;
import com.simibubi.create.modules.contraptions.components.crusher.AbstractCrushingRecipe;
import com.simibubi.create.modules.contraptions.processing.ProcessingOutput;
import mezz.jei.api.constants.VanillaTypes;
import mezz.jei.api.gui.IRecipeLayout;
import mezz.jei.api.gui.drawable.IDrawable;
import mezz.jei.api.gui.ingredient.IGuiItemStackGroup;
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 IDrawable icon;
private IDrawable background = new EmptyBackground(177, 53);
public MillingCategory() {
icon = new DoubleItemIcon(() -> new ItemStack(AllBlocks.MILLSTONE.get()),
() -> new ItemStack(AllItems.FLOUR.get()));
}
@Override
public IDrawable getBackground() {
return background;
}
@Override
public ResourceLocation getUid() {
return ID;
super("milling", doubleItemIcon(AllBlocks.MILLSTONE.get(), AllItems.FLOUR.get()), emptyBackground(177, 53));
}
@Override
@ -51,16 +28,6 @@ public class MillingCategory implements IRecipeCategory<AbstractCrushingRecipe>
return AbstractCrushingRecipe.class;
}
@Override
public String getTitle() {
return Lang.translate("recipe.milling");
}
@Override
public IDrawable getIcon() {
return icon;
}
@Override
public void setIngredients(AbstractCrushingRecipe recipe, IIngredients ingredients) {
ingredients.setInputIngredients(recipe.getIngredients());
@ -83,7 +50,7 @@ public class MillingCategory implements IRecipeCategory<AbstractCrushingRecipe>
itemStacks.set(outputIndex + 1, results.get(outputIndex).getStack());
}
CreateJEI.addStochasticTooltip(itemStacks, results);
addStochasticTooltip(itemStacks, results);
}
@Override
@ -95,17 +62,19 @@ public class MillingCategory implements IRecipeCategory<AbstractCrushingRecipe>
ScreenResources.JEI_ARROW.draw(85, 32);
ScreenResources.JEI_DOWN_ARROW.draw(43, 4);
if (size > 1) {
for (int i = 0; i < size; i++) {
int xOffset = i % 2 == 0 ? 0 : 19;
int yOffset = (i / 2) * -19;
ScreenResources.JEI_SLOT.draw(133 + xOffset, 27 + yOffset);
}
} else {
ScreenResources.JEI_SLOT.draw(139, 27);
millstone.draw(57, 27);
if (size == 1) {
getRenderedSlot(recipe, 0).draw(139, 27);
return;
}
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 com.simibubi.create.AllBlocks;
import com.simibubi.create.Create;
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.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.processing.ProcessingIngredient;
import mezz.jei.api.constants.VanillaTypes;
import mezz.jei.api.gui.IRecipeLayout;
import mezz.jei.api.gui.drawable.IDrawable;
import mezz.jei.api.gui.ingredient.IGuiItemStackGroup;
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.util.NonNullList;
import net.minecraft.util.ResourceLocation;
public class MixingCategory implements IRecipeCategory<MixingRecipe> {
public class MixingCategory extends CreateRecipeCategory<MixingRecipe> {
private AnimatedMixer mixer;
private static ResourceLocation ID = new ResourceLocation(Create.ID, "mixing");
private IDrawable icon;
private IDrawable background = new EmptyBackground(177, 70);
private AnimatedMixer mixer = new AnimatedMixer();
public MixingCategory() {
icon = new DoubleItemIcon(() -> new ItemStack(AllBlocks.MECHANICAL_MIXER.get()),
() -> new ItemStack(AllBlocks.BASIN.get()));
mixer = new AnimatedMixer();
super("mixing", doubleItemIcon(AllBlocks.MECHANICAL_MIXER.get(), AllBlocks.BASIN.get()),
emptyBackground(177, 70));
}
@Override
public IDrawable getIcon() {
return icon;
}
@Override
public ResourceLocation getUid() {
return ID;
}
@Override
public String getTitle() {
return Lang.translate("recipe.mixing");
}
@Override
public IDrawable getBackground() {
return background;
public Class<? extends MixingRecipe> getRecipeClass() {
return MixingRecipe.class;
}
@Override
@ -77,7 +50,7 @@ public class MixingCategory implements IRecipeCategory<MixingRecipe> {
NonNullList<Ingredient> recipeIngredients = recipe.getIngredients();
List<Pair<Ingredient, MutableInt>> actualIngredients = ItemHelper.condenseIngredients(recipeIngredients);
Map<Integer, Float> catalystIndices = new HashMap<>(9);
for (int i = 0; i < actualIngredients.size(); i++) {
for (ProcessingIngredient processingIngredient : recipe.getRollableIngredients()) {
@ -107,13 +80,11 @@ public class MixingCategory implements IRecipeCategory<MixingRecipe> {
itemStacks.init(i, false, 141, 50);
itemStacks.set(i, recipe.getRecipeOutput().getStack());
CreateJEI.addCatalystTooltip(itemStacks, catalystIndices);
addCatalystTooltip(itemStacks, catalystIndices);
}
@Override
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());
int size = actualIngredients.size();
@ -135,9 +106,4 @@ public class MixingCategory implements IRecipeCategory<MixingRecipe> {
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 com.simibubi.create.AllItems;
import com.simibubi.create.Create;
import com.simibubi.create.ScreenResources;
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 mezz.jei.api.constants.VanillaTypes;
import mezz.jei.api.gui.IRecipeLayout;
import mezz.jei.api.gui.drawable.IDrawable;
import mezz.jei.api.gui.ingredient.IGuiItemStackGroup;
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> {
private static ResourceLocation ID = new ResourceLocation(Create.ID, "mystery_conversion");
private IDrawable icon;
private IDrawable background = new EmptyBackground(177, 50);
public class MysteriousItemConversionCategory extends CreateRecipeCategory<ConversionRecipe> {
public static List<ConversionRecipe> getRecipes() {
List<ConversionRecipe> recipes = new ArrayList<>();
@ -37,17 +24,7 @@ public class MysteriousItemConversionCategory implements IRecipeCategory<Convers
}
public MysteriousItemConversionCategory() {
icon = new DoubleItemIcon(() -> AllItems.CHROMATIC_COMPOUND.asStack(), () -> ItemStack.EMPTY);
}
@Override
public IDrawable getIcon() {
return icon;
}
@Override
public ResourceLocation getUid() {
return ID;
super("mystery_conversion", itemIcon(AllItems.CHROMATIC_COMPOUND.get()), emptyBackground(177, 50));
}
@Override
@ -55,16 +32,6 @@ public class MysteriousItemConversionCategory implements IRecipeCategory<Convers
return ConversionRecipe.class;
}
@Override
public String getTitle() {
return Lang.translate("recipe.mystery_conversion");
}
@Override
public IDrawable getBackground() {
return background;
}
@Override
public void setIngredients(ConversionRecipe recipe, IIngredients ingredients) {
ingredients.setInputIngredients(recipe.getIngredients());
@ -75,13 +42,10 @@ public class MysteriousItemConversionCategory implements IRecipeCategory<Convers
public void setRecipe(IRecipeLayout recipeLayout, ConversionRecipe recipe, IIngredients ingredients) {
IGuiItemStackGroup itemStacks = recipeLayout.getItemStacks();
List<ProcessingOutput> results = recipe.getRollableResults();
itemStacks.init(0, true, 26, 16);
itemStacks.set(0, Arrays.asList(recipe.getIngredients().get(0).getMatchingStacks()));
itemStacks.init(1, false, 131, 16);
itemStacks.set(1, results.get(0).getStack());
CreateJEI.addStochasticTooltip(itemStacks, results);
}
@Override

View file

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

View file

@ -5,66 +5,35 @@ import java.util.List;
import com.mojang.blaze3d.systems.RenderSystem;
import com.simibubi.create.AllItems;
import com.simibubi.create.Create;
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.curiosities.tools.SandPaperPolishingRecipe;
import mezz.jei.api.constants.VanillaTypes;
import mezz.jei.api.gui.IRecipeLayout;
import mezz.jei.api.gui.drawable.IDrawable;
import mezz.jei.api.gui.ingredient.IGuiItemStackGroup;
import mezz.jei.api.ingredients.IIngredients;
import mezz.jei.api.recipe.category.IRecipeCategory;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.ItemRenderer;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.Ingredient;
import net.minecraft.nbt.CompoundNBT;
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;
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();
}
@Override
public IDrawable getIcon() {
return icon;
}
@Override
public ResourceLocation getUid() {
return ID;
}
@Override
public Class<? extends SandPaperPolishingRecipe> getRecipeClass() {
return SandPaperPolishingRecipe.class;
}
@Override
public String getTitle() {
return Lang.translate("recipe.sandpaper_polishing");
}
@Override
public IDrawable getBackground() {
return background;
}
@Override
public void setIngredients(SandPaperPolishingRecipe recipe, IIngredients ingredients) {
ingredients.setInputIngredients(recipe.getIngredients());
@ -81,13 +50,13 @@ public class PolishingCategory implements IRecipeCategory<SandPaperPolishingReci
itemStacks.init(1, false, 131, 28);
itemStacks.set(1, results.get(0).getStack());
CreateJEI.addStochasticTooltip(itemStacks, results);
addStochasticTooltip(itemStacks, results);
}
@Override
public void draw(SandPaperPolishingRecipe recipe, double mouseX, double mouseY) {
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_LONG_ARROW.draw(52, 32);

View file

@ -5,46 +5,23 @@ import java.util.List;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllItems;
import com.simibubi.create.Create;
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.foundation.utility.Lang;
import com.simibubi.create.modules.contraptions.components.press.PressingRecipe;
import com.simibubi.create.modules.contraptions.processing.ProcessingOutput;
import mezz.jei.api.constants.VanillaTypes;
import mezz.jei.api.gui.IRecipeLayout;
import mezz.jei.api.gui.drawable.IDrawable;
import mezz.jei.api.gui.ingredient.IGuiItemStackGroup;
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 static ResourceLocation ID = new ResourceLocation(Create.ID, "pressing");
private IDrawable icon;
private IDrawable background = new EmptyBackground(177, 70);
private AnimatedPress press = new AnimatedPress(false);
public PressingCategory() {
icon = new DoubleItemIcon(() -> new ItemStack(AllBlocks.MECHANICAL_PRESS.get()),
() -> new ItemStack(AllItems.IRON_SHEET.get()));
press = new AnimatedPress(false);
}
@Override
public IDrawable getIcon() {
return icon;
}
@Override
public ResourceLocation getUid() {
return ID;
super("pressing", doubleItemIcon(AllBlocks.MECHANICAL_PRESS.get(), AllItems.IRON_SHEET.get()),
emptyBackground(177, 70));
}
@Override
@ -52,16 +29,6 @@ public class PressingCategory implements IRecipeCategory<PressingRecipe> {
return PressingRecipe.class;
}
@Override
public String getTitle() {
return Lang.translate("recipe.pressing");
}
@Override
public IDrawable getBackground() {
return background;
}
@Override
public void setIngredients(PressingRecipe recipe, IIngredients ingredients) {
ingredients.setInputIngredients(recipe.getIngredients());
@ -79,16 +46,16 @@ public class PressingCategory implements IRecipeCategory<PressingRecipe> {
itemStacks.init(outputIndex + 1, false, 131 + 19 * outputIndex, 50);
itemStacks.set(outputIndex + 1, results.get(outputIndex).getStack());
}
CreateJEI.addStochasticTooltip(itemStacks, results);
addStochasticTooltip(itemStacks, results);
}
@Override
public void draw(PressingRecipe recipe, double mouseX, double mouseY) {
ScreenResources.JEI_SLOT.draw(26, 50);
ScreenResources.JEI_SLOT.draw(131, 50);
getRenderedSlot(recipe, 0).draw(131, 50);
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_LONG_ARROW.draw(52, 54);
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.AllBlocks;
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.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.ingredient.IGuiItemStackGroup;
import mezz.jei.api.ingredients.IIngredients;
import mezz.jei.api.recipe.category.IRecipeCategory;
import net.minecraft.block.BlockState;
import net.minecraft.client.renderer.model.IBakedModel;
import net.minecraft.item.crafting.IRecipe;
import net.minecraft.state.properties.BlockStateProperties;
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);
@Override
public IDrawable getBackground() {
return background;
public ProcessingViaFanCategory(String name, IDrawable icon) {
super(name, icon, emptyBackground(177, 70));
}
@Override
public void setIngredients(T recipe, IIngredients ingredients) {
ingredients.setInputIngredients(recipe.getIngredients());

View file

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

View file

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

View file

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

View file

@ -12,6 +12,8 @@ public class CClient extends ConfigBase {
public ConfigFloat fanParticleDensity = f(.5f, 0, 1, "fanParticleDensity");
public ConfigBool rainbowDebug =
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
public String getName() {

View file

@ -5,9 +5,9 @@ public class CDamageControl extends ConfigBase {
public ConfigBool freezeCrushing = b(false, "freezeCrushing", Comments.freezeCrushing);
public ConfigBool freezeExtractors = b(false, "freezeExtractors", Comments.freezeExtractors);
public ConfigBool freezeInWorldProcessing = b(false, "freezeInWorldProcessing", Comments.freezeInWorldProcessing);
public ConfigBool freezeRotationPropagator = b(false, "freezeRotationPropagator", Comments.freezeRotationPropagator);
public ConfigBool freezeBearingConstructs = b(false, "freezeBearingConstructs", Comments.freezeBearingConstructs);
public ConfigBool freezePistonConstructs = b(false, "freezePistonConstructs", Comments.freezePistonConstructs);
public ConfigBool freezeRotationPropagator =
b(false, "freezeRotationPropagator", Comments.freezeRotationPropagator);
public ConfigBool freezeContraptions = b(false, "freezeContraptions", Comments.freezeContraptions);
@Override
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 freezeRotationPropagator =
"Pauses rotation logic altogether - Use if crash mentions RotationPropagators.";
static String freezeBearingConstructs = "In case Mechanical Bearings turned against you.";
static String freezePistonConstructs = "In case Mechanical Pistons pushed it too far.";
static String freezeContraptions = "In case Moving contraptions pushed it too far.";
}
}

View file

@ -75,6 +75,8 @@ public class ValueBoxRenderer {
}
box.render(highlighted);
RenderSystem.disableBlend();
RenderSystem.disableAlphaTest();
}
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));
}
forEachBehaviour(tb -> tb.readNBT(compound));
super.read(compound);
forEachBehaviour(tb -> tb.readNBT(compound));
if (world != null && world.isRemote)
updateClient(compound);
}
@ -106,7 +107,7 @@ public abstract class SmartTileEntity extends SyncedTileEntity implements ITicka
public void lazyTick() {
}
protected void forEachBehaviour(Consumer<TileEntityBehaviour> action) {
behaviours.values().forEach(tb -> {
if (!tb.isPaused())

View file

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

View file

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

View file

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

View file

@ -1,5 +1,7 @@
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.simibubi.create.AllItems;
import com.simibubi.create.AllKeys;
@ -60,7 +62,10 @@ public class ScrollValueRenderer {
}
} else
render(world, pos, face, behaviour, highlight);
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,

View file

@ -3,12 +3,9 @@ package com.simibubi.create.foundation.block.render;
import java.util.List;
import java.util.Random;
import org.apache.commons.lang3.tuple.Pair;
import com.mojang.blaze3d.matrix.MatrixStack;
import net.minecraft.block.BlockState;
import net.minecraft.client.renderer.Matrix4f;
import net.minecraft.client.renderer.model.BakedQuad;
import net.minecraft.client.renderer.model.IBakedModel;
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 org.lwjgl.opengl.GL11;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.platform.GlStateManager.DestFactor;
import com.mojang.blaze3d.platform.GlStateManager.SourceFactor;
@ -16,15 +14,13 @@ import net.minecraft.block.Blocks;
import net.minecraft.block.FireBlock;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.BlockRendererDispatcher;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.IRenderTypeBuffer;
import net.minecraft.client.renderer.RenderHelper;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.RenderTypeLookup;
import net.minecraft.client.renderer.Tessellator;
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.vertex.DefaultVertexFormats;
import net.minecraft.item.ItemStack;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
@ -79,7 +75,7 @@ public class ScreenElementRenderer {
boolean stateMode = transformsAndModel == null;
boolean fire = false;
if (stateMode) {
if (transformsAndModel == null) {
blockToRender = transformsAndState.get();
fire = (blockToRender.getBlock() instanceof FireBlock);
modelToRender = blockRenderer.getModelForState(blockToRender);
@ -92,7 +88,8 @@ public class ScreenElementRenderer {
RenderType renderType = RenderTypeLookup.getEntityBlockLayer(blockToRender);
IVertexBuilder vb = buffer.getBuffer(renderType);
MatrixStack ms = new MatrixStack();
mc.getTextureManager().bindTexture(AtlasTexture.LOCATION_BLOCKS_TEXTURE);
RenderSystem.pushMatrix();
if (fire) {
blockRenderer.renderBlock(blockToRender, ms, buffer, 0xF000F0, OverlayTexture.DEFAULT_UV,
@ -111,7 +108,7 @@ public class ScreenElementRenderer {
}
RenderSystem.popMatrix();
if (stateMode && !blockToRender.getFluidState().isEmpty()) {
if (blockToRender != null && !blockToRender.getFluidState().isEmpty()) {
RenderHelper.disableStandardItemLighting();
RenderSystem.translatef(0, -300, 0);
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;
public void tick() {
float diff = target - value;
float diff = getCurrentDiff();
if (Math.abs(diff) < eps)
return;
set(value + (diff) * speed);
}
protected float getCurrentDiff() {
return getTarget() - value;
}
public InterpolatedChasingValue withSpeed(float speed) {
this.speed = speed;
@ -22,5 +26,15 @@ public class InterpolatedChasingValue extends InterpolatedValue {
this.target = target;
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) {
return (float) (angle / 180 * Math.PI);
}
public static float deg(float angle) {
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;
}
public static float getShortestAngleDiff(double current, double target) {
public static float getShortestAngleDiff(double current, double target) {
current = current % 360;
target = target % 360;
return (float) (((((target - current) % 360) + 540) % 360) - 180);

View file

@ -1,6 +1,11 @@
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;

View file

@ -1,5 +1,7 @@
package com.simibubi.create.foundation.utility;
import org.lwjgl.opengl.GL11;
import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.util.math.Vec3d;
@ -20,4 +22,14 @@ public class GlHelper {
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.RenderType;
import net.minecraft.client.renderer.texture.OverlayTexture;
import net.minecraft.entity.MobEntity;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;

View file

@ -10,6 +10,7 @@ import net.minecraft.util.math.BlockPos;
public class Iterate {
public static final boolean[] trueAndFalse = { true, false };
public static final int[] zeroAndOne = { 1, -1 };
public static final int[] positiveAndNegative = { 1, -1 };
public static final Direction[] directions = Direction.values();
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);
}
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 target = getTraceTarget(playerIn, range, origin);
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 f1 = playerIn.rotationYaw;
float f2 = MathHelper.cos(-f1 * 0.017453292F - (float) Math.PI);
@ -42,7 +43,7 @@ public class RaycastHelper {
return vec3d1;
}
private static Vec3d getTraceOrigin(PlayerEntity playerIn) {
public static Vec3d getTraceOrigin(PlayerEntity playerIn) {
double d0 = playerIn.getX();
double d1 = playerIn.getY() + (double) playerIn.getEyeHeight();
double d2 = playerIn.getZ();
@ -50,7 +51,7 @@ public class RaycastHelper {
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))
return null;
if (Double.isNaN(end.x) || Double.isNaN(end.y) || Double.isNaN(end.z))
@ -174,7 +175,7 @@ public class RaycastHelper {
this.pos = pos;
this.facing = facing;
}
public PredicateTraceResult() {
// missed, no result
}
@ -186,7 +187,7 @@ public class RaycastHelper {
public BlockPos getPos() {
return pos;
}
public boolean missed() {
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.DrawState;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.GLAllocation;
import net.minecraft.client.renderer.Matrix4f;
import net.minecraft.client.renderer.Vector4f;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;

View file

@ -27,9 +27,7 @@ public class TessellatorHelper {
RenderSystem.pushMatrix();
RenderSystem.pushLightingAttributes();
RenderSystem.enableBlend();
RenderSystem.enableAlphaTest();
RenderSystem.color4f(1, 1, 1, 1);
ActiveRenderInfo renderInfo = mc.gameRenderer.getActiveRenderInfo();
Vec3d view = renderInfo.getProjectedView();
RenderSystem.translated(-view.x, -view.y, -view.z);
@ -83,10 +81,9 @@ public class TessellatorHelper {
}
public static void cleanUpAfterDrawing() {
RenderSystem.disableAlphaTest();
RenderSystem.disableBlend();
RenderSystem.popAttributes();
RenderSystem.popMatrix();
RenderSystem.disableBlend();
}
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;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
@ -8,8 +9,16 @@ import java.util.Set;
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.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.SugarCaneBlock;
import net.minecraft.tags.BlockTags;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
@ -40,6 +49,41 @@ public class TreeCutter {
Set<BlockPos> visited = new HashSet<>();
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))
return null;
@ -94,6 +138,25 @@ public class TreeCutter {
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
* 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.List;
import java.util.function.Predicate;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
@ -11,6 +12,7 @@ import net.minecraft.fluid.Fluid;
import net.minecraft.item.crafting.RecipeManager;
import net.minecraft.scoreboard.Scoreboard;
import net.minecraft.tags.NetworkTagManager;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.SoundCategory;
import net.minecraft.util.SoundEvent;
import net.minecraft.util.math.BlockPos;
@ -34,6 +36,26 @@ public class WrappedWorld extends 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
public int getLight(BlockPos pos) {
return 15;
@ -55,8 +77,7 @@ public class WrappedWorld extends World {
}
@Override
public void playEvent(PlayerEntity player, int type, BlockPos pos, int data) {
}
public void playEvent(PlayerEntity player, int type, BlockPos pos, int data) {}
@Override
public List<? extends PlayerEntity> getPlayers() {
@ -65,13 +86,11 @@ public class WrappedWorld extends World {
@Override
public void playSound(PlayerEntity player, double x, double y, double z, SoundEvent soundIn, SoundCategory category,
float volume, float pitch) {
}
float volume, float pitch) {}
@Override
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
public Entity getEntityByID(int id) {
@ -90,8 +109,7 @@ public class WrappedWorld extends World {
}
@Override
public void registerMapData(MapData mapDataIn) {
}
public void registerMapData(MapData mapDataIn) {}
@Override
public int getNextMapId() {
@ -99,8 +117,7 @@ public class WrappedWorld extends World {
}
@Override
public void sendBlockBreakProgress(int breakerId, BlockPos pos, int progress) {
}
public void sendBlockBreakProgress(int breakerId, BlockPos pos, int progress) {}
@Override
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;
import java.util.Optional;
import java.util.function.Supplier;
import javax.annotation.Nonnull;
import org.apache.commons.lang3.tuple.Pair;

View file

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

View file

@ -1,7 +1,6 @@
package com.simibubi.create.modules.contraptions.base;
import com.simibubi.create.foundation.item.ItemDescription.Palette;
import com.simibubi.create.modules.contraptions.RotationPropagator;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
@ -45,7 +44,10 @@ public abstract class KineticBlock extends Block implements IRotate {
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
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;
}
// Block
@Override
public boolean hasTileEntity(BlockState state) {
return true;
@ -72,8 +72,8 @@ public abstract class KineticBlock extends Block implements IRotate {
@Override
public abstract TileEntity createTileEntity(BlockState state, IBlockReader world);
@SuppressWarnings("deprecation")
@Override
@SuppressWarnings("deprecation")
public void updateNeighbors(BlockState stateIn, IWorld worldIn, BlockPos pos, int flags) {
super.updateNeighbors(stateIn, worldIn, pos, flags);
if (worldIn.isRemote())
@ -83,8 +83,11 @@ public abstract class KineticBlock extends Block implements IRotate {
if (!(tileEntity instanceof KineticTileEntity))
return;
// Remove previous information when block is added
KineticTileEntity kte = (KineticTileEntity) tileEntity;
RotationPropagator.handleAdded(worldIn.getWorld(), pos, kte);
kte.warnOfMovement();
kte.clearKineticInformation();
kte.updateSpeed = true;
}
// @Override // TODO 1.15 register layer

View file

@ -41,12 +41,14 @@ public abstract class KineticTileEntity extends SmartTileEntity
public @Nullable Long network;
public @Nullable BlockPos source;
public boolean networkDirty;
public boolean updateSpeed;
protected KineticEffectHandler effects;
protected float speed;
protected float capacity;
protected float stress;
protected boolean overStressed;
protected boolean wasMoved;
private int flickerTally;
private int networkSize;
@ -57,6 +59,7 @@ public abstract class KineticTileEntity extends SmartTileEntity
public KineticTileEntity(TileEntityType<?> typeIn) {
super(typeIn);
effects = new KineticEffectHandler(this);
updateSpeed = true;
}
@Override
@ -73,6 +76,9 @@ public abstract class KineticTileEntity extends SmartTileEntity
@Override
public void tick() {
if (!world.isRemote && needsSpeedUpdate())
attachKinetics();
super.tick();
effects.tick();
@ -179,6 +185,9 @@ public abstract class KineticTileEntity extends SmartTileEntity
public CompoundNBT write(CompoundNBT compound) {
compound.putFloat("Speed", speed);
if (needsSpeedUpdate())
compound.putBoolean("NeedsSpeedUpdate", true);
if (hasSource())
compound.put("Source", NBTUtil.writeBlockPos(source));
@ -188,7 +197,7 @@ public abstract class KineticTileEntity extends SmartTileEntity
networkTag.putFloat("Stress", stress);
networkTag.putFloat("Capacity", capacity);
networkTag.putInt("Size", networkSize);
if (lastStressApplied != 0)
networkTag.putFloat("AddedStress", lastStressApplied);
if (lastCapacityProvided != 0)
@ -200,16 +209,21 @@ public abstract class KineticTileEntity extends SmartTileEntity
return super.write(compound);
}
public boolean needsSpeedUpdate() {
return updateSpeed;
}
@Override
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");
source = null;
network = null;
overStressed = false;
stress = 0;
capacity = 0;
lastStressApplied = 0;
lastCapacityProvided = 0;
if (compound.contains("Source"))
source = NBTUtil.readBlockPos(compound.getCompound("Source"));
@ -313,6 +327,7 @@ public abstract class KineticTileEntity extends SmartTileEntity
}
public void attachKinetics() {
updateSpeed = false;
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() {
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 net.minecraft.block.BlockState;
import net.minecraft.block.FallingBlock;
import net.minecraft.entity.Entity;
import net.minecraft.entity.item.ItemEntity;
import net.minecraft.entity.item.minecart.AbstractMinecartEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.nbt.NBTUtil;
import net.minecraft.util.DamageSource;
@ -32,30 +34,10 @@ public class BlockBreakingMovementBehaviour extends MovementBehaviour {
World world = context.world;
BlockState stateVisited = world.getBlockState(pos);
if (!stateVisited.isNormalCube(world, pos))
damageEntities(context, pos, world);
if (world.isRemote)
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))
return;
@ -63,10 +45,44 @@ public class BlockBreakingMovementBehaviour extends MovementBehaviour {
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() {
return null;
}
protected boolean throwsEntities() {
return getDamageSource() != null;
}
@Override
public void stopMoving(MovementContext context) {
CompoundNBT data = context.data;
@ -89,6 +105,27 @@ public class BlockBreakingMovementBehaviour extends MovementBehaviour {
@Override
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;
if (context.world.isRemote)
return;
@ -128,14 +165,24 @@ public class BlockBreakingMovementBehaviour extends MovementBehaviour {
destroyProgress += MathHelper.clamp((int) (breakSpeed / blockHardness), 1, 10 - destroyProgress);
if (destroyProgress >= 10) {
BlockHelper.destroyBlock(context.world, breakingPos, 1f, stack -> this.dropItem(context, stack));
onBlockBroken(context, breakingPos);
ticksUntilNextProgress = -1;
world.sendBlockBreakProgress(id, breakingPos, -1);
// 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("TicksUntilNextProgress");
data.remove("BreakingPos");
context.stall = false;
return;
}
@ -150,7 +197,15 @@ public class BlockBreakingMovementBehaviour extends MovementBehaviour {
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.modules.contraptions.components.contraptions.MovementContext;
import net.minecraft.block.BlockState;
import net.minecraft.util.DamageSource;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
@ -27,10 +30,15 @@ public class DrillMovementBehaviour extends BlockBreakingMovementBehaviour {
public SuperByteBuffer renderInContraption(MovementContext context) {
return DrillTileEntityRenderer.renderInContraption(context);
}
@Override
protected DamageSource getDamageSource() {
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;
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.MovementBehaviour;
import net.minecraft.block.Block;
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.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 class HarvesterBlock extends HorizontalBlock implements IPortableBlock {
public class HarvesterBlock extends AttachedActorBlock implements IPortableBlock {
public static MovementBehaviour MOVEMENT = new HarvesterMovementBehaviour();
public HarvesterBlock() {
super(Properties.from(Blocks.IRON_BLOCK));
}
@Override
public boolean hasTileEntity(BlockState state) {
return true;
@ -38,51 +21,11 @@ public class HarvesterBlock extends HorizontalBlock implements IPortableBlock {
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
// public BlockRenderLayer getRenderLayer() {
// 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
public MovementBehaviour getMovementBehaviour() {
return MOVEMENT;

View file

@ -42,7 +42,7 @@ public class HarvesterMovementBehaviour extends MovementBehaviour {
@Override
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

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.modules.contraptions.components.contraptions.MovementContext;
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.entity.item.ItemEntity;
@ -31,12 +32,13 @@ public class SawMovementBehaviour extends BlockBreakingMovementBehaviour {
@Override
public boolean canBreak(World world, BlockPos breakingPos, BlockState state) {
return super.canBreak(world, breakingPos, state)
&& (state.isIn(BlockTags.LOGS) || state.isIn(BlockTags.LEAVES));
return super.canBreak(world, breakingPos, state) && SawTileEntity.isSawable(state);
}
@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);
if (tree != null) {
for (BlockPos log : tree.logs)

View file

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

View file

@ -10,18 +10,19 @@ import java.util.Map;
import java.util.Set;
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.SourceFactor;
import com.mojang.blaze3d.systems.RenderSystem;
import com.simibubi.create.AllItems;
import com.simibubi.create.AllKeys;
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 net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.IRenderTypeBuffer;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.BlockPos;
@ -35,13 +36,15 @@ public class ChassisRangeDisplay {
private static GroupEntry lastHoveredGroup = null;
private static class Entry {
Set<BlockPos> includedPositions;
BlockClusterOutline outline;
OutlineParticle<Outline> particle;
ChassisTileEntity te;
int timer;
public Entry(ChassisTileEntity te) {
this.te = te;
includedPositions = createSelection(te);
outline = new BlockClusterOutline(createSelection(te));
particle = OutlineParticle.create(outline);
timer = DISPLAY_TIME;
}
@ -85,14 +88,19 @@ public class ChassisRangeDisplay {
World world = Minecraft.getInstance().world;
boolean hasWrench = AllItems.WRENCH.typeOf(player.getHeldItemMainhand());
for (Iterator<BlockPos> iterator = entries.keySet().iterator(); iterator.hasNext();)
if (tickEntry(entries.get(iterator.next()), hasWrench))
for (Iterator<BlockPos> iterator = entries.keySet().iterator(); iterator.hasNext();) {
Entry entry = entries.get(iterator.next());
if (tickEntry(entry, hasWrench)) {
entry.particle.remove();
iterator.remove();
}
}
for (Iterator<GroupEntry> iterator = groupEntries.iterator(); iterator.hasNext();) {
GroupEntry group = iterator.next();
if (tickEntry(group, hasWrench)) {
iterator.remove();
group.particle.remove();
if (group == lastHoveredGroup)
lastHoveredGroup = null;
}
@ -118,8 +126,11 @@ public class ChassisRangeDisplay {
if (ctrl) {
GroupEntry existingGroupForPos = getExistingGroupForPos(pos);
if (existingGroupForPos != null) {
for (ChassisTileEntity included : existingGroupForPos.includedTEs)
entries.remove(included.getPos());
for (ChassisTileEntity included : existingGroupForPos.includedTEs) {
Entry removed = entries.remove(included.getPos());
if (removed != null)
removed.particle.remove();
}
existingGroupForPos.timer = DISPLAY_TIME;
return;
}
@ -167,13 +178,19 @@ public class ChassisRangeDisplay {
public static void display(ChassisTileEntity chassis) {
deselect();
if (AllKeys.ctrlDown()) {
groupEntries.forEach(e -> e.particle.remove());
groupEntries.clear();
GroupEntry hoveredGroup = new GroupEntry(chassis);
for (ChassisTileEntity included : hoveredGroup.includedTEs)
entries.remove(included.getPos());
for (ChassisTileEntity included : hoveredGroup.includedTEs) {
Entry remove = entries.remove(included.getPos());
if (remove != null)
remove.particle.remove();
}
groupEntries.add(hoveredGroup);
} 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) {
TessellatorHelper.begin();
BlockPos size = new BlockPos(1, 1, 1);
// GlStateManager.pushMatrix();
// 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 alpha = timer > 20 ? .5f : timer / 40f;
RenderSystem.color4f(1, .7f, 0, alpha);
Set<BlockPos> includedPositions = entry.includedPositions;
GlStateManager.depthMask(false);
for (BlockPos pos : includedPositions)
TessellatorHelper.cube(Tessellator.getInstance().getBuffer(), pos, size, 1 / 16f - 1 / 64f, true, false);
TessellatorHelper.draw();
GlStateManager.depthMask(true);
float alpha = timer > 20 ? 1 : timer / 20f;
entry.outline.setAlpha(alpha);
// entry.outline.render(Tessellator.getInstance().getBuffer());
//
// GlStateManager.disableBlend();
// GlStateManager.depthMask(true);
// GlStateManager.popMatrix();
}
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.components.contraptions.chassis.AbstractChassisBlock;
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.PistonPoleBlock;
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.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.redstone.ContactBlock;
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 net.minecraft.block.AbstractButtonBlock;
@ -54,6 +59,7 @@ import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.Direction.AxisDirection;
import net.minecraft.util.Rotation;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
@ -71,6 +77,7 @@ public abstract class Contraption {
public List<MutablePair<BlockInfo, MovementContext>> actors;
public CombinedInvWrapper inventory;
public List<TileEntity> customRenderTEs;
public Set<Pair<BlockPos, Direction>> superglue;
public AxisAlignedBB bounds;
public boolean stalled;
@ -80,13 +87,16 @@ public abstract class Contraption {
protected BlockPos anchor;
List<BlockPos> renderOrder;
protected List<SuperGlueEntity> glueToRemove;
public Contraption() {
blocks = new HashMap<>();
storage = new HashMap<>();
actors = new ArrayList<>();
superglue = new HashSet<>();
renderOrder = new ArrayList<>();
customRenderTEs = new ArrayList<>();
glueToRemove = new ArrayList<>();
}
public Set<BlockPos> getColliders(World world, Direction movementDirection) {
@ -118,7 +128,8 @@ public abstract class Contraption {
if (bounds == null)
bounds = new AxisAlignedBB(BlockPos.ZERO);
frontier.add(pos);
if (!BlockMovementTraits.isBrittle(world.getBlockState(pos)))
frontier.add(pos);
if (!addToInitialFrontier(world, pos, forcedDirection, frontier))
return false;
for (int limit = 100000; limit > 0; limit--) {
@ -148,6 +159,8 @@ public abstract class Contraption {
if (!world.isBlockPresent(pos))
return false;
if (isAnchoringBlockAt(pos))
return true;
if (!BlockMovementTraits.movementNecessary(world, pos))
return true;
if (!BlockMovementTraits.movementAllowed(world, pos))
@ -155,6 +168,7 @@ public abstract class Contraption {
BlockState state = world.getBlockState(pos);
if (isChassis(state) && !moveChassis(world, pos, forcedDirection, frontier, visited))
return false;
if (AllBlocks.FLEXCRATE.typeOf(state))
FlexcrateBlock.splitCrate(world, pos);
if (AllBlocks.BELT.typeOf(state)) {
@ -165,7 +179,27 @@ public abstract class Contraption {
if (prevPos != null && !visited.contains(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) {
int limit = AllConfigs.SERVER.kinetics.maxPistonPoles.get();
Direction direction = state.get(MechanicalPistonBlock.FACING);
@ -189,7 +223,7 @@ public abstract class Contraption {
if (limit <= -1)
return false;
}
BlockPos searchPos = pos;
while (limit-- >= 0) {
searchPos = searchPos.offset(direction.getOpposite());
@ -203,17 +237,21 @@ public abstract class Contraption {
}
break;
}
if (limit <= -1)
return false;
}
// Doors try to stay whole
if (state.getBlock() instanceof DoorBlock) {
BlockPos otherPartPos = pos.up(state.get(DoorBlock.HALF) == DoubleBlockHalf.LOWER ? 1 : -1);
if (!visited.contains(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;
for (Direction offset : Direction.values()) {
BlockPos offsetPos = pos.offset(offset);
@ -225,14 +263,24 @@ public abstract class Contraption {
return false;
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);
if (faceHasGlue)
addGlue(superglue.get(offset));
}
add(pos, capture(world, pos));
if (blocks.size() > AllConfigs.SERVER.kinetics.maxBlocksMoved.get())
return false;
return true;
}
@ -295,6 +343,14 @@ public abstract class Contraption {
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) {
BlockInfo captured = pair.getKey();
BlockPos localPos = pos.subtract(anchor);
@ -371,6 +427,13 @@ public abstract class Contraption {
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();
nbt.getList("Storage", 10).forEach(c -> {
CompoundNBT comp = (CompoundNBT) c;
@ -409,6 +472,14 @@ public abstract class Contraption {
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();
for (BlockPos pos : storage.keySet()) {
CompoundNBT c = new CompoundNBT();
@ -422,6 +493,7 @@ public abstract class Contraption {
nbt.put("Blocks", blocksNBT);
nbt.put("Actors", actorsNBT);
nbt.put("Superglue", superglueNBT);
nbt.put("Storage", storageNBT);
nbt.put("Anchor", NBTUtil.writeBlockPos(anchor));
nbt.putBoolean("Stalled", stalled);
@ -435,11 +507,7 @@ public abstract class Contraption {
}
public static boolean isFrozen() {
return AllConfigs.SERVER.control.freezePistonConstructs.get();
}
public void disassemble(World world, BlockPos offset, Vec3d rotation) {
disassemble(world, offset, rotation, (pos, state) -> false);
return AllConfigs.SERVER.control.freezeContraptions.get();
}
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) {
storage.values().forEach(MountedStorage::empty);
glueToRemove.forEach(SuperGlueEntity::remove);
for (boolean brittles : Iterate.trueAndFalse) {
for (BlockInfo block : blocks.values()) {
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) {
stop(world);
@ -497,8 +571,16 @@ public abstract class Contraption {
&& !blockState.getCollisionShape(world, targetPos).isEmpty())
continue;
world.destroyBlock(targetPos, blockState.getCollisionShape(world, targetPos).isEmpty());
world.destroyBlock(targetPos, true);
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);
CompoundNBT tag = block.nbt;
if (tileEntity != null && tag != null) {
@ -506,32 +588,34 @@ public abstract class Contraption {
tag.putInt("y", targetPos.getY());
tag.putInt("z", targetPos.getZ());
if (tileEntity instanceof BeltTileEntity) {
tag.remove("Length");
tag.remove("Index");
tag.putBoolean("DontClearAttachments", true);
if (verticalRotation && tileEntity instanceof PulleyTileEntity) {
tag.remove("Offset");
tag.remove("InitialOffset");
}
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)) {
MountedStorage mountedStorage = storage.get(block.pos);
if (mountedStorage.isWorking())
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) {

View file

@ -12,16 +12,24 @@ import org.apache.commons.lang3.tuple.MutablePair;
import com.google.common.collect.ImmutableSet;
import com.simibubi.create.AllEntities;
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.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 net.minecraft.block.BlockState;
import net.minecraft.block.material.PushReaction;
import net.minecraft.client.Minecraft;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
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.ListNBT;
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.DataSerializers;
import net.minecraft.network.datasync.EntityDataManager;
import net.minecraft.tags.BlockTags;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.DamageSource;
import net.minecraft.util.Direction;
import net.minecraft.util.ReuseableStream;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.shapes.IBooleanFunction;
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.world.World;
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.OnlyIn;
import net.minecraftforge.fml.common.registry.IEntityAdditionalSpawnData;
@ -53,12 +63,14 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
protected Contraption contraption;
protected float initialAngle;
protected float forcedAngle;
protected BlockPos controllerPos;
protected Vec3d motionBeforeStall;
protected boolean stationary;
final List<Entity> collidingEntities = new ArrayList<>();
private static final Ingredient FUEL_ITEMS = Ingredient.fromItems(Items.COAL, Items.CHARCOAL);
private static final DataParameter<Boolean> STALLED =
EntityDataManager.createKey(ContraptionEntity.class, DataSerializers.BOOLEAN);
@ -78,20 +90,27 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
super(entityTypeIn, worldIn);
motionBeforeStall = Vec3d.ZERO;
stationary = entityTypeIn == AllEntities.STATIONARY_CONTRAPTION.type;
forcedAngle = -1;
}
public static ContraptionEntity createMounted(World world, Contraption contraption, float initialAngle) {
ContraptionEntity entity = new ContraptionEntity(AllEntities.CONTRAPTION.type, world);
entity.contraption = contraption;
entity.initialAngle = initialAngle;
entity.prevYaw = initialAngle;
entity.yaw = initialAngle;
entity.targetYaw = initialAngle;
entity.forceYaw(initialAngle);
if (contraption != null)
contraption.gatherStoredItems();
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) {
ContraptionEntity entity = new ContraptionEntity(AllEntities.STATIONARY_CONTRAPTION.type, world);
entity.contraption = contraption;
@ -156,6 +175,14 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
}
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;
while (riding.getRidingEntity() != null)
riding = riding.getRidingEntity();
@ -163,20 +190,28 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
if (riding instanceof BoatEntity)
movementVector = getPositionVec().subtract(prevPosX, prevPosY, prevPosZ);
Vec3d motion = movementVector.normalize();
boolean rotating = false;
if (motion.length() > 0) {
targetYaw = yawFromVector(motion);
if (targetYaw < 0)
targetYaw += 360;
if (yaw < 0)
yaw += 360;
if (!rotationLock) {
if (motion.length() > 0) {
targetYaw = yawFromVector(motion);
if (targetYaw < 0)
targetYaw += 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();
tickActors(movementVector);
if (!rotating || !pauseWhileRotating)
tickActors(movementVector);
if (isStalled()) {
if (!wasStalled)
motionBeforeStall = riding.getMotion();
@ -188,6 +223,39 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
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();
}
@ -210,12 +278,12 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
Vec3d actorPosition = new Vec3d(blockInfo.pos);
actorPosition = actorPosition.add(actor.getActiveAreaOffset(context));
actorPosition = VecHelper.rotate(actorPosition, angleRoll, angleYaw, anglePitch);
actorPosition = actorPosition.add(rotationOffset).add(getPositionVec());
actorPosition = actorPosition.add(rotationOffset).add(getAnchorVec());
boolean newPosVisited = false;
BlockPos gridPosition = new BlockPos(actorPosition);
if (!stalledPreviously) {
if (!context.stall) {
Vec3d previousPosition = context.position;
if (previousPosition != null) {
context.motion = actorPosition.subtract(previousPosition);
@ -245,13 +313,11 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
}
}
}
}
}
context.rotation = rotationVec;
context.position = actorPosition;
if (actor.isActive(context)) {
if (newPosVisited && !context.stall) {
actor.visitNewPosition(context, gridPosition);
@ -280,6 +346,12 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
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) {
rotate(getShortestAngleDiff(this.roll, roll), getShortestAngleDiff(this.yaw, yaw),
getShortestAngleDiff(this.pitch, pitch));
@ -298,23 +370,13 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
@Override
public void setPosition(double x, double y, double z) {
Entity e = getRidingEntity();
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.
super.setPosition(x, y, z);
if (contraption != null) {
AxisAlignedBB cbox = contraption.getBoundingBox();
if (cbox != null)
this.setBoundingBox(cbox.offset(x, y, z));
if (cbox != null) {
Vec3d actualVec = getAnchorVec();
this.setBoundingBox(cbox.offset(actualVec));
}
}
}
@ -362,7 +424,7 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
protected void readAdditional(CompoundNBT compound) {
contraption = Contraption.fromNBT(world, compound.getCompound("Contraption"));
initialAngle = compound.getFloat("InitialAngle");
targetYaw = yaw = prevYaw = initialAngle;
forceYaw(compound.contains("ForcedYaw") ? compound.getFloat("ForcedYaw") : initialAngle);
dataManager.set(STALLED, compound.getBoolean("Stalled"));
ListNBT vecNBT = compound.getList("CachedMotion", 6);
if (!vecNBT.isEmpty()) {
@ -375,6 +437,10 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
controllerPos = NBTUtil.readBlockPos(compound.getCompound("Controller"));
}
public void forceYaw(float forcedYaw) {
targetYaw = yaw = prevYaw = forcedYaw;
}
public void checkController() {
if (controllerPos == null)
return;
@ -394,14 +460,18 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
@Override
protected void writeAdditional(CompoundNBT compound) {
compound.put("Contraption", getContraption().writeNBT());
compound.putFloat("InitialAngle", initialAngle);
if (!stationary)
if (contraption != null)
compound.put("Contraption", contraption.writeNBT());
if (!stationary && motionBeforeStall != null)
compound.put("CachedMotion",
newDoubleNBTList(motionBeforeStall.x, motionBeforeStall.y, motionBeforeStall.z));
compound.putBoolean("Stalled", isStalled());
if (controllerPos != null)
compound.put("Controller", NBTUtil.writeBlockPos(controllerPos));
if (forcedAngle != -1)
compound.putFloat("ForcedYaw", forcedAngle);
compound.putFloat("InitialAngle", initialAngle);
compound.putBoolean("Stalled", isStalled());
}
@Override
@ -423,14 +493,14 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
public void disassemble() {
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));
getContraption().disassemble(world, offset, rotation);
getContraption().addBlocksToWorld(world, offset, rotation);
preventMovedEntitiesFromGettingStuck();
}
remove();
}
@Override
protected void doWaterSplashEffect() {
}
@ -532,4 +602,18 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
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;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.platform.GlStateManager;
import com.mojang.blaze3d.systems.RenderSystem;
import com.simibubi.create.foundation.utility.TessellatorHelper;
import com.simibubi.create.foundation.utility.VecHelper;
@ -37,6 +38,8 @@ public class ContraptionEntityRenderer extends EntityRenderer<ContraptionEntity>
return;
if (entity.getContraption() == null)
return;
if (entity.getContraption().getType() == AllContraptionTypes.MOUNTED && entity.getRidingEntity() == null)
return;
// TODO 1.15 buffered render
RenderSystem.pushMatrix();
@ -78,6 +81,7 @@ public class ContraptionEntityRenderer extends EntityRenderer<ContraptionEntity>
RenderSystem.translatef((float) cartX, (float) cartY, (float) cartZ);
}
GlStateManager.translatef(-.5f, 0, -.5f);
}
Vec3d rotationOffset = VecHelper.getCenterOf(BlockPos.ZERO);

View file

@ -1,23 +1,17 @@
package com.simibubi.create.modules.contraptions.components.contraptions;
import java.util.Iterator;
import java.util.Random;
import java.util.function.Consumer;
import org.apache.commons.lang3.tuple.Pair;
import org.lwjgl.opengl.GL11;
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.CreateClient;
import com.simibubi.create.config.AllConfigs;
import com.simibubi.create.foundation.utility.PlacementSimulationWorld;
import com.simibubi.create.foundation.utility.SuperByteBuffer;
import com.simibubi.create.foundation.utility.SuperByteBufferCache.Compartment;
import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.foundation.utility.WrappedWorld;
import com.simibubi.create.foundation.utility.render.StructureRenderer;
import net.minecraft.block.BlockRenderType;
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.BufferBuilder;
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.texture.OverlayTexture;
import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher;
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.Vec3d;
import net.minecraft.world.LightType;
@ -46,59 +34,19 @@ public class ContraptionRenderer {
public static final Compartment<Contraption> CONTRAPTION = new Compartment<>();
protected static PlacementSimulationWorld renderWorld;
protected static LightingWorld lightingWorld;
public static void render(World world, Contraption c, Consumer<SuperByteBuffer> transform, MatrixStack ms, BufferBuilder buffer) {
SuperByteBuffer contraptionBuffer = CreateClient.bufferCache.get(CONTRAPTION, c, () -> renderContraption(c, ms));
public static void render(World world, Contraption c, Consumer<SuperByteBuffer> transform, MatrixStack ms,
BufferBuilder buffer) {
SuperByteBuffer contraptionBuffer =
CreateClient.bufferCache.get(CONTRAPTION, c, () -> renderContraption(c, ms));
transform.accept(contraptionBuffer);
contraptionBuffer.light((lx, ly, lz) -> getLight(world, lx, ly, lz)).renderInto(ms, buffer);
renderActors(world, c, transform, ms, buffer);
}
public static void renderTEsWithGL(World world, Contraption c, Vec3d position, Vec3d rotation, 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 = 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;
}
}
public static void renderTEsWithGL(World world, Contraption c, Vec3d position, Vec3d rotation, MatrixStack ms,
IRenderTypeBuffer buffer) {
StructureRenderer.renderTileEntities(world, position, rotation, c.customRenderTEs, ms, buffer);
}
private static SuperByteBuffer renderContraption(Contraption c, MatrixStack ms) {
@ -130,8 +78,8 @@ public class ContraptionRenderer {
return new SuperByteBuffer(builder);
}
private static void renderActors(World world, Contraption c, Consumer<SuperByteBuffer> transform,
MatrixStack ms, BufferBuilder buffer) {
private static void renderActors(World world, Contraption c, Consumer<SuperByteBuffer> transform, MatrixStack ms,
BufferBuilder buffer) {
for (Pair<BlockInfo, MovementContext> actor : c.getActors()) {
MovementContext context = actor.getRight();
if (context == null)
@ -171,36 +119,4 @@ public class ContraptionRenderer {
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;
}
protected Axis transformAxis(Axis axisIn) {
public Axis transformAxis(Axis axisIn) {
Direction facing = Direction.getFacingFromAxis(AxisDirection.POSITIVE, axisIn);
facing = transformFacing(facing);
Axis axis = facing.getAxis();
return axis;
}
protected Direction transformFacing(Direction facing) {
public Direction transformFacing(Direction facing) {
for (int i = 0; i < rotation.ordinal(); i++)
facing = DirectionHelper.rotateAround(facing, rotationAxis);
return facing;

View file

@ -36,6 +36,11 @@ public class BearingContraption extends Contraption {
return construct;
}
@Override
protected boolean isAnchoringBlockAt(BlockPos pos) {
return pos.equals(anchor.offset(facing.getOpposite()));
}
@Override
public void add(BlockPos pos, Pair<BlockInfo, TileEntity> capture) {
BlockPos localPos = pos.subtract(anchor);
@ -62,7 +67,7 @@ public class BearingContraption extends Contraption {
public int getSailBlocks() {
return sailBlocks;
}
public Direction getFacing() {
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.KineticTileEntityRenderer;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.IRenderTypeBuffer;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher;

View file

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

View file

@ -32,6 +32,11 @@ public class ClockworkContraption extends Contraption {
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,
Direction direction) {
if (isFrozen())

View file

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

View file

@ -167,11 +167,7 @@ public class ChassisTileEntity extends SmartTileEntity {
// Ignore replaceable Blocks and Air-like
if (!BlockMovementTraits.movementNecessary(world, current))
break;
if (AllBlocks.MECHANICAL_PISTON_HEAD.typeOf(currentState))
break;
if (AllBlocks.MECHANICAL_PISTON.typeOf(currentState))
break;
if (AllBlocks.STICKY_MECHANICAL_PISTON.typeOf(currentState))
if (BlockMovementTraits.isBrittle(currentState))
break;
positions.add(current);
@ -212,6 +208,8 @@ public class ChassisTileEntity extends SmartTileEntity {
continue;
if (!BlockMovementTraits.movementNecessary(world, searchPos))
continue;
if (BlockMovementTraits.isBrittle(searchedState))
continue;
localVisited.add(searchPos);
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;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.foundation.block.ITE;
import com.simibubi.create.foundation.block.RenderUtilityBlock;
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.mounted.CartAssemblerTileEntity.CartMovementMode;
import net.minecraft.block.AbstractRailBlock;
import net.minecraft.block.Block;
@ -12,13 +13,16 @@ import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.material.PushReaction;
import net.minecraft.entity.item.minecart.AbstractMinecartEntity;
import net.minecraft.entity.item.minecart.FurnaceMinecartEntity;
import net.minecraft.item.BlockItemUseContext;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.state.BooleanProperty;
import net.minecraft.state.EnumProperty;
import net.minecraft.state.IProperty;
import net.minecraft.state.StateContainer.Builder;
import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.state.properties.RailShape;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;
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.World;
public class CartAssemblerBlock extends AbstractRailBlock {
public class CartAssemblerBlock extends AbstractRailBlock implements ITE<CartAssemblerTileEntity> {
public static IProperty<RailShape> RAIL_SHAPE =
EnumProperty.create("shape", RailShape.class, RailShape.EAST_WEST, RailShape.NORTH_SOUTH);
@ -45,6 +49,16 @@ public class CartAssemblerBlock extends AbstractRailBlock {
super.fillStateContainer(builder);
}
@Override
public boolean hasTileEntity(BlockState state) {
return true;
}
@Override
public TileEntity createTileEntity(BlockState state, IBlockReader world) {
return new CartAssemblerTileEntity();
}
@Override
public BlockState getStateForPlacement(BlockItemUseContext context) {
boolean alongX = context.getPlacementHorizontalFacing().getAxis() == Axis.X;
@ -60,7 +74,7 @@ public class CartAssemblerBlock extends AbstractRailBlock {
@Override
public void onMinecartPass(BlockState state, World world, BlockPos pos, AbstractMinecartEntity cart) {
if (!cart.canBeRidden())
if (!cart.canBeRidden() && !(cart instanceof FurnaceMinecartEntity))
return;
if (state.get(POWERED))
disassemble(world, pos, cart);
@ -72,16 +86,28 @@ public class CartAssemblerBlock extends AbstractRailBlock {
if (!cart.getPassengers().isEmpty())
return;
Contraption contraption = MountedContraption.assembleMinecart(world, pos);
MountedContraption contraption = MountedContraption.assembleMinecart(world, pos);
if (contraption == null)
return;
if (contraption.blocks.size() == 1)
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);
entity.setPosition(pos.getX(), pos.getY(), pos.getZ());
world.addEntity(entity);
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) {
@ -90,6 +116,13 @@ public class CartAssemblerBlock extends AbstractRailBlock {
if (!(cart.getPassengers().get(0) instanceof ContraptionEntity))
return;
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
@ -129,7 +162,7 @@ public class CartAssemblerBlock extends AbstractRailBlock {
public PushReaction getPushReaction(BlockState state) {
return PushReaction.BLOCK;
}
@Override
public boolean isNormalCube(BlockState state, IBlockReader worldIn, BlockPos pos) {
return false;
@ -142,6 +175,13 @@ public class CartAssemblerBlock extends AbstractRailBlock {
builder.add(BlockStateProperties.HORIZONTAL_AXIS);
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) {
@ -149,4 +189,9 @@ public class CartAssemblerBlock extends AbstractRailBlock {
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 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.BlockMovementTraits;
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.nbt.CompoundNBT;
import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.state.properties.RailShape;
import net.minecraft.tileentity.TileEntity;
@ -25,12 +29,14 @@ import net.minecraft.world.gen.feature.template.Template.BlockInfo;
public class MountedContraption extends Contraption {
public CartMovementMode rotationMode;
@Override
protected AllContraptionTypes getType() {
return AllContraptionTypes.MOUNTED;
}
public static Contraption assembleMinecart(World world, BlockPos pos) {
public static MountedContraption assembleMinecart(World world, BlockPos pos) {
if (isFrozen())
return null;
@ -38,7 +44,7 @@ public class MountedContraption extends Contraption {
if (!state.has(RAIL_SHAPE))
return null;
Contraption contraption = new MountedContraption();
MountedContraption contraption = new MountedContraption();
if (!contraption.searchMovedStructure(world, pos, null))
return null;
@ -61,8 +67,14 @@ public class MountedContraption extends Contraption {
if (!AllBlocks.CART_ASSEMBLER.typeOf(state))
return false;
Axis axis = state.get(CartAssemblerBlock.RAIL_SHAPE) == RailShape.EAST_WEST ? Axis.Z : Axis.X;
for (AxisDirection axisDirection : AxisDirection.values())
frontier.add(pos.offset(Direction.getFacingFromAxis(axisDirection, axis)));
for (AxisDirection axisDirection : AxisDirection.values()) {
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;
}
@ -76,14 +88,27 @@ public class MountedContraption extends Contraption {
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
public void removeBlocksFromWorld(IWorld world, BlockPos offset) {
super.removeBlocksFromWorld(world, offset, (pos, state) -> pos.equals(anchor));
}
@Override
public void disassemble(World world, BlockPos offset, Vec3d rotation) {
super.disassemble(world, offset, rotation, (pos, state) -> AllBlocks.MINECART_ANCHOR.typeOf(state));
public void addBlocksToWorld(World world, BlockPos offset, Vec3d rotation) {
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
public void attach(ContraptionEntity contraption) {
this.movedContraption = contraption;
if (!world.isRemote)
if (!world.isRemote) {
this.running = true;
sendData();
}
}
@Override

View file

@ -42,6 +42,9 @@ public class MechanicalPistonTileEntity extends LinearActuatorTileEntity {
@Override
public void assemble() {
if (!(world.getBlockState(pos).getBlock() instanceof MechanicalPistonBlock))
return;
Direction direction = getBlockState().get(BlockStateProperties.FACING);
// Collect Construct
@ -83,10 +86,11 @@ public class MechanicalPistonTileEntity extends LinearActuatorTileEntity {
@Override
public void disassemble() {
if (!running)
if (!running && movedContraption == null)
return;
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) {
applyContraptionPosition();
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 net.minecraft.block.BlockState;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher;
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.config.AllConfigs;
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.BlockMovementTraits;
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 net.minecraft.block.BlockState;
@ -63,17 +65,24 @@ public class PistonContraption extends Contraption {
BlockPos actualStart = pos;
BlockState nextBlock = world.getBlockState(actualStart.offset(direction));
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()
|| MECHANICAL_PISTON_HEAD.typeOf(nextBlock) && nextBlock.get(FACING) == direction) {
actualStart = actualStart.offset(direction);
poles.add(new BlockInfo(actualStart, nextBlock.with(FACING, direction), null));
extensionsInFront++;
nextBlock = world.getBlockState(actualStart.offset(direction));
if (MECHANICAL_PISTON_HEAD.typeOf(nextBlock))
break;
nextBlock = world.getBlockState(actualStart.offset(direction));
if (extensionsInFront > MechanicalPistonBlock.maxAllowedPistonPoles())
return false;
}
@ -122,6 +131,11 @@ public class PistonContraption extends Contraption {
return true;
}
@Override
protected boolean isAnchoringBlockAt(BlockPos pos) {
return pistonExtensionCollisionBox.contains(VecHelper.getCenterOf(pos.subtract(anchor)));
}
@Override
protected boolean addToInitialFrontier(World world, BlockPos pos, Direction direction, List<BlockPos> frontier) {
frontier.clear();
@ -138,6 +152,8 @@ public class PistonContraption extends Contraption {
if (!BlockMovementTraits.movementNecessary(world, currentPos))
return true;
BlockState state = world.getBlockState(currentPos);
if (BlockMovementTraits.isBrittle(state))
return true;
if (AllBlocks.MECHANICAL_PISTON_HEAD.typeOf(state) && state.get(FACING) == direction.getOpposite())
return true;
if (!BlockMovementTraits.movementAllowed(world, currentPos))
@ -146,7 +162,7 @@ public class PistonContraption extends Contraption {
if (BlockMovementTraits.notSupportive(state, orientation))
return true;
}
return false; // too many
return true;
}
@Override
@ -155,8 +171,17 @@ public class PistonContraption extends Contraption {
}
@Override
public void disassemble(World world, BlockPos offset, Vec3d rotation) {
super.disassemble(world, offset, rotation, (pos, state) -> {
public void addGlue(SuperGlueEntity entity) {
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);
BlockState pistonState = world.getBlockState(pistonPos);
TileEntity te = world.getTileEntity(pistonPos);
@ -165,7 +190,7 @@ public class PistonContraption extends Contraption {
return true;
if (!AllBlocks.PISTON_POLE.typeOf(state) && pistonState.getBlock() instanceof MechanicalPistonBlock)
world.setBlockState(pistonPos, pistonState.with(MechanicalPistonBlock.STATE, PistonState.RETRACTED),
3);
3 | 16);
return true;
}
return false;
@ -178,7 +203,7 @@ public class PistonContraption extends Contraption {
BlockPos pistonPos = anchor.offset(orientation, -1);
BlockState blockState = world.getBlockState(pos);
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 false;

View file

@ -1,6 +1,5 @@
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.utility.AllShapes;
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.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.material.PushReaction;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.state.EnumProperty;
import net.minecraft.state.properties.BlockStateProperties;
@ -42,6 +42,17 @@ public class PulleyBlock extends HorizontalAxisKineticBlock implements ITE<Pulle
}
@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,
BlockRayTraceResult hit) {
if (!player.isAllowEdit())
@ -76,27 +87,23 @@ public class PulleyBlock extends HorizontalAxisKineticBlock implements ITE<Pulle
}
@Override
public void neighborChanged(BlockState state, World worldIn, BlockPos pos, Block blockIn, BlockPos fromPos,
boolean isMoving) {
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);
}
public PushReaction getPushReaction(BlockState state) {
return PushReaction.BLOCK;
}
@Override
public void onReplaced(BlockState state, World worldIn, BlockPos pos, BlockState newState, boolean isMoving) {
if (!isMoving)
if (!isMoving) {
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()) {
worldIn.removeTileEntity(pos);
}

View file

@ -27,6 +27,16 @@ public class PulleyContraption extends Contraption {
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
public CompoundNBT writeNBT() {
CompoundNBT writeNBT = super.writeNBT();

View file

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

View file

@ -6,6 +6,7 @@ import static com.simibubi.create.modules.contraptions.base.HorizontalKineticBlo
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
@ -137,8 +138,8 @@ public class ConnectedInputHandler {
if (controllerPos1.equals(controllerPos2)) {
MechanicalCrafterTileEntity controller = CrafterHelper.getCrafter(world, controllerPos1);
Set<BlockPos> positions = controller.input.data.stream().map(l -> controllerPos1.add(l))
.collect(Collectors.toSet());
Set<BlockPos> positions =
controller.input.data.stream().map(l -> controllerPos1.add(l)).collect(Collectors.toSet());
List<BlockPos> frontier = new LinkedList<>();
List<BlockPos> splitGroup = new ArrayList<>();
@ -198,8 +199,7 @@ public class ConnectedInputHandler {
crafter1.input.data.forEach(offset -> {
BlockPos connectedPos = crafter1.getPos().add(offset);
modifyAndUpdate(world, connectedPos, input -> {
});
modifyAndUpdate(world, connectedPos, input -> {});
});
crafter2.input.data.forEach(offset -> {
@ -229,7 +229,7 @@ public class ConnectedInputHandler {
public static class ConnectedInput {
boolean isController;
List<BlockPos> data = new ArrayList<>();
List<BlockPos> data = Collections.synchronizedList(new ArrayList<>());
public ConnectedInput() {
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.relays.belt.BeltTileEntity;
import net.minecraft.block.BlockState;
import net.minecraft.entity.item.ItemEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT;
@ -357,8 +358,10 @@ public class MechanicalCrafterTileEntity extends KineticTileEntity {
}
public void eject() {
Vec3d ejectPos = VecHelper.getCenterOf(pos)
.add(new Vec3d(getBlockState().get(HORIZONTAL_FACING).getDirectionVec()).scale(.75f));
BlockState blockState = getBlockState();
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));
if (!inventory.getStackInSlot(0).isEmpty())
dropItem(ejectPos, inventory.getStackInSlot(0));

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