Merge branch 'master' into mc1.15/dev

This commit is contained in:
simibubi 2020-05-11 00:23:28 +02:00
commit 901c530f62
208 changed files with 4163 additions and 1550 deletions

View file

@ -1,18 +1,23 @@
# Create <p align="center"><img src="https://i.imgur.com/35JmqWB.gif" alt="Logo" width="100"></p>
<h1 align="center">Create<br>
<a href="https://www.patreon.com/simibubi"><img src="https://img.shields.io/badge/Supporters-30-ff5733" alt="Patreon"></a>
<a href="https://www.curseforge.com/minecraft/mc-mods/create/files"><img src="https://img.shields.io/badge/Available%20for-MC%201.14-c70039" alt="Supported Versions"></a>
<a href="https://github.com/Creators-of-Create/Create/blob/master/LICENSE"><img src="https://img.shields.io/github/license/Creators-of-Create/Create?style=flat&color=900c3f" alt="License"></a>
<a href="https://discord.gg/hmaD7Se"><img src="https://img.shields.io/discord/620934202875183104?color=844685&label=Feedback%20%26%20Help&style=flat" alt="Discord"></a>
<a href="https://www.curseforge.com/minecraft/mc-mods/create"><img src="http://cf.way2muchnoise.eu/short_create.svg" alt="Curseforge Downloads"></a><br><br>
</h1>
Welcome to Create, a mod offering a variety of tools and blocks for Building, Decoration and Aesthetic Automation. Welcome to Create, a mod offering a variety of tools and blocks for Building, Decoration and Aesthetic Automation.
The added elements of tech are designed to leave as many design choices to the player as possible, where item processing doesn't happen inside a single block with funny textures, it requires a set of actors working together in many possible arrangements. The added elements of tech are designed to leave as many design choices to the player as possible, where item processing doesn't happen inside a single block with funny textures, it requires a set of actors working together in many possible arrangements.
Check out the wiki and in-game Tool-tips for further info on how to use these features, and stay tuned for an ever-growing selection of possibilities for Creative and Survival Minecraft. Check out the wiki and in-game Tool-tips for further info on how to use these features, and stay tuned for an ever-growing selection of possibilities for Creative and Survival Minecraft.
## Links [<img src="https://i.imgur.com/0lLX9Oy.jpg" width="210">](https://github.com/simibubi/Create/issues "Report Issues")
[<img src="https://i.imgur.com/0lLX9Oy.jpg" width="320">](https://github.com/simibubi/Create/issues "Report Issues") [<img src="https://i.imgur.com/bjEZraY.jpg" width="210">](https://www.youtube.com/playlist?list=PLyADkcfPLU8ywCXZPaDbQ_JZJL0CGDN5Z "Watch Videos")
[<img src="https://i.imgur.com/bjEZraY.jpg" width="320">](https://www.youtube.com/playlist?list=PLyADkcfPLU8ywCXZPaDbQ_JZJL0CGDN5Z "Watch Videos") [<img src="https://i.imgur.com/aWrjfKJ.jpg" width="210">](https://discord.gg/hmaD7Se "Feedback & Help")
[<img src="https://i.imgur.com/aWrjfKJ.jpg" width="320">](https://discord.gg/hmaD7Se "Feedback & Help") [<img src="https://i.imgur.com/xj8o2xC.jpg" width="210">](https://www.patreon.com/simibubi "Support Us")
[<img src="https://i.imgur.com/xj8o2xC.jpg" width="320">](https://www.patreon.com/simibubi "Support Us")
## Current Progress
- Create 0.2.2 is coming soon with more bug-fixes. Thank you for testing Create with us!
- Support for Minecraft 1.12: Not planned - Support for Minecraft 1.12: Not planned
- Support for Minecraft 1.15: Porting work is in Progress! - Support for Minecraft 1.15: Porting work is in Progress!
- Support for Fabric: Not planned - Support for Fabric: Not planned
@ -25,14 +30,4 @@ Check out the wiki and in-game Tool-tips for further info on how to use these fe
- simibubi - Developer & Artist - simibubi - Developer & Artist
- tterrag - Developer & Port-Meister - tterrag - Developer & Port-Meister
## Localization ### For more information, check out our [Project Page](https://www.curseforge.com/minecraft/mc-mods/create)
| Code | Version | Language | Author |
|-------|---------|------------|--------------------------|
| en_us | 0.2.2 | English US | |
| de_de | 0.1 | German | Vexatos & Azratosh |
| nl_nl | 0.1 | Dutch | Prusias |
| fr_fr | 0.2.1 | French | Kiro |
| zh_cn | 0.2.1 | Chinese | noptia & spider_stranger |
| ru_ru | 0.1 | Russian | sirabein |
| pt_br | 0.1 | Brazilian | lucassabreu |

View file

@ -72,6 +72,7 @@ import com.simibubi.create.modules.logistics.block.diodes.ToggleLatchBlock;
import com.simibubi.create.modules.logistics.block.extractor.ExtractorBlock; import com.simibubi.create.modules.logistics.block.extractor.ExtractorBlock;
import com.simibubi.create.modules.logistics.block.extractor.LinkedExtractorBlock; import com.simibubi.create.modules.logistics.block.extractor.LinkedExtractorBlock;
import com.simibubi.create.modules.logistics.block.funnel.FunnelBlock; import com.simibubi.create.modules.logistics.block.funnel.FunnelBlock;
import com.simibubi.create.modules.logistics.block.inventories.CreativeCrateBlock;
import com.simibubi.create.modules.logistics.block.inventories.FlexcrateBlock; import com.simibubi.create.modules.logistics.block.inventories.FlexcrateBlock;
import com.simibubi.create.modules.logistics.block.transposer.LinkedTransposerBlock; import com.simibubi.create.modules.logistics.block.transposer.LinkedTransposerBlock;
import com.simibubi.create.modules.logistics.block.transposer.TransposerBlock; import com.simibubi.create.modules.logistics.block.transposer.TransposerBlock;
@ -185,6 +186,7 @@ public enum AllBlocks implements NonNullSupplier<Block> {
REDSTONE_BRIDGE(RedstoneLinkBlock::new), REDSTONE_BRIDGE(RedstoneLinkBlock::new),
STOCKSWITCH(StockswitchBlock::new), STOCKSWITCH(StockswitchBlock::new),
FLEXCRATE(FlexcrateBlock::new), FLEXCRATE(FlexcrateBlock::new),
CREATIVE_CRATE(() -> new CreativeCrateBlock(Properties.from(Blocks.CHEST))),
EXTRACTOR(ExtractorBlock::new), EXTRACTOR(ExtractorBlock::new),
VERTICAL_EXTRACTOR(ExtractorBlock.Vertical::new, ComesWith.NO_BLOCKITEM), VERTICAL_EXTRACTOR(ExtractorBlock.Vertical::new, ComesWith.NO_BLOCKITEM),
LINKED_EXTRACTOR(LinkedExtractorBlock::new), LINKED_EXTRACTOR(LinkedExtractorBlock::new),

View file

@ -21,11 +21,9 @@ import net.minecraftforge.fml.client.registry.RenderingRegistry;
public enum AllEntities { public enum AllEntities {
CONTRAPTION(ContraptionEntity::new, EntityClassification.MISC, 30, 3, true, CONTRAPTION(ContraptionEntity::new, EntityClassification.MISC, 5, 3, true, ContraptionEntity::build),
ContraptionEntity::build), STATIONARY_CONTRAPTION(ContraptionEntity::new, EntityClassification.MISC, 20, 40, false, ContraptionEntity::build),
STATIONARY_CONTRAPTION(ContraptionEntity::new, EntityClassification.MISC, 30, 40, SUPER_GLUE(SuperGlueEntity::new, EntityClassification.MISC, 10, Integer.MAX_VALUE, false, SuperGlueEntity::build),
false, ContraptionEntity::build),
SUPER_GLUE(SuperGlueEntity::new, EntityClassification.MISC, 30, Integer.MAX_VALUE, false, SuperGlueEntity::build),
; ;
@ -53,8 +51,10 @@ public enum AllEntities {
for (AllEntities entity : values()) { for (AllEntities entity : values()) {
String id = Lang.asId(entity.name()); String id = Lang.asId(entity.name());
ResourceLocation resourceLocation = new ResourceLocation(Create.ID, id); ResourceLocation resourceLocation = new ResourceLocation(Create.ID, id);
Builder<? extends Entity> builder = EntityType.Builder.create(entity.factory, entity.group) Builder<? extends Entity> builder = EntityType.Builder
.setTrackingRange(entity.range).setUpdateInterval(entity.updateFrequency) .create(entity.factory, entity.group)
.setTrackingRange(entity.range)
.setUpdateInterval(entity.updateFrequency)
.setShouldReceiveVelocityUpdates(entity.sendVelocity); .setShouldReceiveVelocityUpdates(entity.sendVelocity);
if (entity.propertyBuilder != null) if (entity.propertyBuilder != null)
builder = entity.propertyBuilder.apply(builder); builder = entity.propertyBuilder.apply(builder);

View file

@ -27,6 +27,7 @@ import com.simibubi.create.modules.curiosities.TreeFertilizerItem;
import com.simibubi.create.modules.curiosities.deforester.DeforesterItem; import com.simibubi.create.modules.curiosities.deforester.DeforesterItem;
import com.simibubi.create.modules.curiosities.symmetry.SymmetryWandItem; import com.simibubi.create.modules.curiosities.symmetry.SymmetryWandItem;
import com.simibubi.create.modules.curiosities.tools.AllToolTiers; import com.simibubi.create.modules.curiosities.tools.AllToolTiers;
import com.simibubi.create.modules.curiosities.tools.BlazingSwordItem;
import com.simibubi.create.modules.curiosities.tools.BlazingToolItem; import com.simibubi.create.modules.curiosities.tools.BlazingToolItem;
import com.simibubi.create.modules.curiosities.tools.RoseQuartzToolItem; import com.simibubi.create.modules.curiosities.tools.RoseQuartzToolItem;
import com.simibubi.create.modules.curiosities.tools.SandPaperItem; import com.simibubi.create.modules.curiosities.tools.SandPaperItem;
@ -123,7 +124,7 @@ public enum AllItems {
BLAZING_PICKAXE(p -> new BlazingToolItem(1, -2.8F, p, PICKAXE)), BLAZING_PICKAXE(p -> new BlazingToolItem(1, -2.8F, p, PICKAXE)),
BLAZING_SHOVEL(p -> new BlazingToolItem(1.5F, -3.0F, p, SHOVEL)), BLAZING_SHOVEL(p -> new BlazingToolItem(1.5F, -3.0F, p, SHOVEL)),
BLAZING_AXE(p -> new BlazingToolItem(5.0F, -3.0F, p, AXE)), BLAZING_AXE(p -> new BlazingToolItem(5.0F, -3.0F, p, AXE)),
BLAZING_SWORD(p -> new SwordItem(AllToolTiers.BLAZING, 3, -2.4F, p)), BLAZING_SWORD(p -> new BlazingSwordItem(AllToolTiers.BLAZING, 3, -2.4F, p)),
ROSE_QUARTZ_PICKAXE(p -> new RoseQuartzToolItem(1, -2.8F, p, PICKAXE)), ROSE_QUARTZ_PICKAXE(p -> new RoseQuartzToolItem(1, -2.8F, p, PICKAXE)),
ROSE_QUARTZ_SHOVEL(p -> new RoseQuartzToolItem(1.5F, -3.0F, p, SHOVEL)), ROSE_QUARTZ_SHOVEL(p -> new RoseQuartzToolItem(1.5F, -3.0F, p, SHOVEL)),

View file

@ -83,6 +83,7 @@ import com.simibubi.create.modules.logistics.block.diodes.FlexpeaterTileEntityRe
import com.simibubi.create.modules.logistics.block.extractor.ExtractorTileEntity; import com.simibubi.create.modules.logistics.block.extractor.ExtractorTileEntity;
import com.simibubi.create.modules.logistics.block.extractor.LinkedExtractorTileEntity; import com.simibubi.create.modules.logistics.block.extractor.LinkedExtractorTileEntity;
import com.simibubi.create.modules.logistics.block.funnel.FunnelTileEntity; import com.simibubi.create.modules.logistics.block.funnel.FunnelTileEntity;
import com.simibubi.create.modules.logistics.block.inventories.CreativeCrateTileEntity;
import com.simibubi.create.modules.logistics.block.inventories.FlexcrateTileEntity; import com.simibubi.create.modules.logistics.block.inventories.FlexcrateTileEntity;
import com.simibubi.create.modules.logistics.block.transposer.LinkedTransposerTileEntity; import com.simibubi.create.modules.logistics.block.transposer.LinkedTransposerTileEntity;
import com.simibubi.create.modules.logistics.block.transposer.TransposerTileEntity; import com.simibubi.create.modules.logistics.block.transposer.TransposerTileEntity;
@ -155,6 +156,7 @@ public enum AllTileEntities {
REDSTONE_BRIDGE(RedstoneLinkTileEntity::new, AllBlocks.REDSTONE_BRIDGE), REDSTONE_BRIDGE(RedstoneLinkTileEntity::new, AllBlocks.REDSTONE_BRIDGE),
STOCKSWITCH(StockswitchTileEntity::new, AllBlocks.STOCKSWITCH), STOCKSWITCH(StockswitchTileEntity::new, AllBlocks.STOCKSWITCH),
FLEXCRATE(FlexcrateTileEntity::new, AllBlocks.FLEXCRATE), FLEXCRATE(FlexcrateTileEntity::new, AllBlocks.FLEXCRATE),
CREATIVE_CRATE(CreativeCrateTileEntity::new, AllBlocks.CREATIVE_CRATE),
EXTRACTOR(ExtractorTileEntity::new, AllBlocks.EXTRACTOR, AllBlocks.VERTICAL_EXTRACTOR), EXTRACTOR(ExtractorTileEntity::new, AllBlocks.EXTRACTOR, AllBlocks.VERTICAL_EXTRACTOR),
LINKED_EXTRACTOR(LinkedExtractorTileEntity::new, AllBlocks.LINKED_EXTRACTOR, AllBlocks.VERTICAL_LINKED_EXTRACTOR), LINKED_EXTRACTOR(LinkedExtractorTileEntity::new, AllBlocks.LINKED_EXTRACTOR, AllBlocks.VERTICAL_LINKED_EXTRACTOR),
TRANSPOSER(TransposerTileEntity::new, AllBlocks.TRANSPOSER, AllBlocks.VERTICAL_TRANSPOSER), TRANSPOSER(TransposerTileEntity::new, AllBlocks.TRANSPOSER, AllBlocks.VERTICAL_TRANSPOSER),
@ -238,6 +240,7 @@ public enum AllTileEntities {
bind(FURNACE_ENGINE, EngineRenderer::new); bind(FURNACE_ENGINE, EngineRenderer::new);
bind(ROTATION_SPEED_CONTROLLER, SpeedControllerRenderer::new); bind(ROTATION_SPEED_CONTROLLER, SpeedControllerRenderer::new);
bind(CREATIVE_CRATE, SmartTileEntityRenderer::new);
bind(REDSTONE_BRIDGE, SmartTileEntityRenderer::new); bind(REDSTONE_BRIDGE, SmartTileEntityRenderer::new);
bind(EXTRACTOR, SmartTileEntityRenderer::new); bind(EXTRACTOR, SmartTileEntityRenderer::new);
bind(LINKED_EXTRACTOR, SmartTileEntityRenderer::new); bind(LINKED_EXTRACTOR, SmartTileEntityRenderer::new);
@ -247,9 +250,6 @@ public enum AllTileEntities {
bind(BELT_TUNNEL, BeltTunnelTileEntityRenderer::new); bind(BELT_TUNNEL, BeltTunnelTileEntityRenderer::new);
bind(ENTITY_DETECTOR, BeltObserverTileEntityRenderer::new); bind(ENTITY_DETECTOR, BeltObserverTileEntityRenderer::new);
bind(FLEXPEATER, FlexpeaterTileEntityRenderer::new); bind(FLEXPEATER, FlexpeaterTileEntityRenderer::new);
// bind(LogisticalController, LogisticalControllerTileEntityRenderer::new);
// bind(LogisticiansTable, LogisticiansTableTileEntityRenderer::new);
} }
@SuppressWarnings("unchecked") // TODO 1.15 this generic stuff is incompatible with the enum system - need strong types @SuppressWarnings("unchecked") // TODO 1.15 this generic stuff is incompatible with the enum system - need strong types

View file

@ -26,6 +26,7 @@ public enum ScreenResources {
SCHEMATICANNON_PROGRESS_2("schematicannon.png", 122, 161, 16, 15), SCHEMATICANNON_PROGRESS_2("schematicannon.png", 122, 161, 16, 15),
SCHEMATICANNON_HIGHLIGHT("schematicannon.png", 0, 182, 28, 28), SCHEMATICANNON_HIGHLIGHT("schematicannon.png", 0, 182, 28, 28),
SCHEMATICANNON_FUEL("schematicannon.png", 0, 215, 82, 4), SCHEMATICANNON_FUEL("schematicannon.png", 0, 215, 82, 4),
SCHEMATICANNON_FUEL_CREATIVE("schematicannon.png", 0, 219, 82, 4),
FLEXCRATE("flex_crate_and_stockpile_switch.png", 125, 129), FLEXCRATE("flex_crate_and_stockpile_switch.png", 125, 129),
FLEXCRATE_DOUBLE("double_flexcrate.png", 197, 129), FLEXCRATE_DOUBLE("double_flexcrate.png", 197, 129),

View file

@ -24,7 +24,6 @@ import com.simibubi.create.compat.jei.category.SawingCategory;
import com.simibubi.create.compat.jei.category.SmokingViaFanCategory; import com.simibubi.create.compat.jei.category.SmokingViaFanCategory;
import com.simibubi.create.compat.jei.category.SplashingCategory; import com.simibubi.create.compat.jei.category.SplashingCategory;
import com.simibubi.create.foundation.utility.Lang; 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.mixer.MixingRecipe;
import com.simibubi.create.modules.contraptions.components.press.MechanicalPressTileEntity; import com.simibubi.create.modules.contraptions.components.press.MechanicalPressTileEntity;
import com.simibubi.create.modules.logistics.block.inventories.FlexcrateScreen; import com.simibubi.create.modules.logistics.block.inventories.FlexcrateScreen;
@ -66,8 +65,7 @@ public class CreateJEI implements IModPlugin {
private PackingCategory packingCategory; private PackingCategory packingCategory;
private PolishingCategory polishingCategory; private PolishingCategory polishingCategory;
private MysteriousItemConversionCategory mysteryConversionCategory; private MysteriousItemConversionCategory mysteryConversionCategory;
private MechanicalCraftingCategory smallMechanicalCraftingCategory; private MechanicalCraftingCategory mechanicalCraftingCategory;
private MechanicalCraftingCategory largeMechanicalCraftingCategory;
@Override @Override
public ResourceLocation getPluginUid() { public ResourceLocation getPluginUid() {
@ -88,8 +86,7 @@ public class CreateJEI implements IModPlugin {
packingCategory = new PackingCategory(); packingCategory = new PackingCategory();
polishingCategory = new PolishingCategory(); polishingCategory = new PolishingCategory();
mysteryConversionCategory = new MysteriousItemConversionCategory(); mysteryConversionCategory = new MysteriousItemConversionCategory();
smallMechanicalCraftingCategory = new MechanicalCraftingCategory(false); mechanicalCraftingCategory = new MechanicalCraftingCategory();
largeMechanicalCraftingCategory = new MechanicalCraftingCategory(true);
} }
@Override @Override
@ -99,10 +96,11 @@ public class CreateJEI implements IModPlugin {
@Override @Override
public void registerCategories(IRecipeCategoryRegistration registration) { public void registerCategories(IRecipeCategoryRegistration registration) {
registration.addRecipeCategories(millingCategory, crushingCategory, splashingCategory, pressingCategory, registration
.addRecipeCategories(millingCategory, crushingCategory, splashingCategory, pressingCategory,
smokingCategory, blastingCategory, blockzapperCategory, mixingCategory, sawingCategory, smokingCategory, blastingCategory, blockzapperCategory, mixingCategory, sawingCategory,
blockCuttingCategory, packingCategory, polishingCategory, mysteryConversionCategory, blockCuttingCategory, packingCategory, polishingCategory, mysteryConversionCategory,
smallMechanicalCraftingCategory, largeMechanicalCraftingCategory); mechanicalCraftingCategory);
} }
@Override @Override
@ -132,32 +130,27 @@ public class CreateJEI implements IModPlugin {
packingCategory.getUid()); packingCategory.getUid());
registration.addRecipes(findRecipes(AllRecipes.SANDPAPER_POLISHING), polishingCategory.getUid()); registration.addRecipes(findRecipes(AllRecipes.SANDPAPER_POLISHING), polishingCategory.getUid());
registration.addRecipes(MysteriousItemConversionCategory.getRecipes(), mysteryConversionCategory.getUid()); registration.addRecipes(MysteriousItemConversionCategory.getRecipes(), mysteryConversionCategory.getUid());
registration.addRecipes(findRecipes(r -> (r.getType() == AllRecipes.MECHANICAL_CRAFTING.type)),
registration.addRecipes(findRecipes( mechanicalCraftingCategory.getUid());
r -> (r instanceof MechanicalCraftingRecipe) && MechanicalCraftingCategory.isSmall((ShapedRecipe) r)), registration.addRecipes(findRecipes(r -> (r.getType() == IRecipeType.CRAFTING
smallMechanicalCraftingCategory.getUid()); && r.getType() != AllRecipes.MECHANICAL_CRAFTING.type) && (r instanceof ShapedRecipe)),
registration.addRecipes( mechanicalCraftingCategory.getUid());
findRecipes(
r -> (r.getType() == IRecipeType.CRAFTING || r.getType() == AllRecipes.MECHANICAL_CRAFTING.type)
&& (r instanceof ShapedRecipe) && !(r instanceof MechanicalCraftingRecipe)
&& MechanicalCraftingCategory.isSmall((ShapedRecipe) r)),
smallMechanicalCraftingCategory.getUid());
registration.addRecipes(findRecipes(
r -> (r.getType() == IRecipeType.CRAFTING || r.getType() == AllRecipes.MECHANICAL_CRAFTING.type)
&& (r instanceof ShapedRecipe) && !MechanicalCraftingCategory.isSmall((ShapedRecipe) r)),
largeMechanicalCraftingCategory.getUid());
} }
@Override @Override
public void registerRecipeCatalysts(IRecipeCatalystRegistration registration) { public void registerRecipeCatalysts(IRecipeCatalystRegistration registration) {
ItemStack fan = new ItemStack(AllBlocks.ENCASED_FAN.get()); ItemStack fan = new ItemStack(AllBlocks.ENCASED_FAN.get());
ItemStack splashingFan = fan.copy() ItemStack splashingFan = fan
.copy()
.setDisplayName(new StringTextComponent(TextFormatting.RESET + Lang.translate("recipe.splashing.fan"))); .setDisplayName(new StringTextComponent(TextFormatting.RESET + Lang.translate("recipe.splashing.fan")));
ItemStack smokingFan = fan.copy().setDisplayName( ItemStack smokingFan = fan
.copy()
.setDisplayName(
new StringTextComponent(TextFormatting.RESET + Lang.translate("recipe.smokingViaFan.fan"))); new StringTextComponent(TextFormatting.RESET + Lang.translate("recipe.smokingViaFan.fan")));
ItemStack blastingFan = fan.copy().setDisplayName( ItemStack blastingFan = fan
.copy()
.setDisplayName(
new StringTextComponent(TextFormatting.RESET + Lang.translate("recipe.blastingViaFan.fan"))); new StringTextComponent(TextFormatting.RESET + Lang.translate("recipe.blastingViaFan.fan")));
registration.addRecipeCatalyst(new ItemStack(AllBlocks.MILLSTONE.get()), millingCategory.getUid()); registration.addRecipeCatalyst(new ItemStack(AllBlocks.MILLSTONE.get()), millingCategory.getUid());
@ -176,10 +169,9 @@ public class CreateJEI implements IModPlugin {
registration.addRecipeCatalyst(new ItemStack(AllBlocks.BASIN.get()), packingCategory.getUid()); registration.addRecipeCatalyst(new ItemStack(AllBlocks.BASIN.get()), packingCategory.getUid());
registration.addRecipeCatalyst(AllItems.SAND_PAPER.asStack(), polishingCategory.getUid()); registration.addRecipeCatalyst(AllItems.SAND_PAPER.asStack(), polishingCategory.getUid());
registration.addRecipeCatalyst(AllItems.RED_SAND_PAPER.asStack(), polishingCategory.getUid()); registration.addRecipeCatalyst(AllItems.RED_SAND_PAPER.asStack(), polishingCategory.getUid());
registration.addRecipeCatalyst(new ItemStack(AllBlocks.MECHANICAL_CRAFTER.get()), registration
smallMechanicalCraftingCategory.getUid()); .addRecipeCatalyst(new ItemStack(AllBlocks.MECHANICAL_CRAFTER.get()),
registration.addRecipeCatalyst(new ItemStack(AllBlocks.MECHANICAL_CRAFTER.get()), mechanicalCraftingCategory.getUid());
largeMechanicalCraftingCategory.getUid());
} }
@Override @Override
@ -193,18 +185,30 @@ public class CreateJEI implements IModPlugin {
} }
private static List<IRecipe<?>> findRecipes(Predicate<IRecipe<?>> pred) { private static List<IRecipe<?>> findRecipes(Predicate<IRecipe<?>> pred) {
return Minecraft.getInstance().world.getRecipeManager().getRecipes().stream().filter(pred) return Minecraft.getInstance().world
.getRecipeManager()
.getRecipes()
.stream()
.filter(pred)
.collect(Collectors.toList()); .collect(Collectors.toList());
} }
private static List<IRecipe<?>> findRecipesByType(IRecipeType<?> type) { private static List<IRecipe<?>> findRecipesByType(IRecipeType<?> type) {
return Minecraft.getInstance().world.getRecipeManager().getRecipes().stream().filter(r -> r.getType() == type) return Minecraft.getInstance().world
.getRecipeManager()
.getRecipes()
.stream()
.filter(r -> r.getType() == type)
.collect(Collectors.toList()); .collect(Collectors.toList());
} }
private static List<IRecipe<?>> findRecipesById(ResourceLocation id) { private static List<IRecipe<?>> findRecipesById(ResourceLocation id) {
return Minecraft.getInstance().world.getRecipeManager().getRecipes().stream() return Minecraft.getInstance().world
.filter(r -> r.getSerializer().getRegistryName().equals(id)).collect(Collectors.toList()); .getRecipeManager()
.getRecipes()
.stream()
.filter(r -> r.getSerializer().getRegistryName().equals(id))
.collect(Collectors.toList());
} }
private static List<IRecipe<?>> findRecipesByTypeExcluding(IRecipeType<?> type, IRecipeType<?> excludingType) { private static List<IRecipe<?>> findRecipesByTypeExcluding(IRecipeType<?> type, IRecipeType<?> excludingType) {

View file

@ -1,39 +1,103 @@
package com.simibubi.create.compat.jei.category; package com.simibubi.create.compat.jei.category;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import com.mojang.blaze3d.platform.GlStateManager;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.ScreenResources; import com.simibubi.create.ScreenResources;
import com.simibubi.create.compat.jei.category.animations.AnimatedCrafter; 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.constants.VanillaTypes;
import mezz.jei.api.gui.IRecipeLayout; import mezz.jei.api.gui.IRecipeLayout;
import mezz.jei.api.gui.ingredient.IGuiItemStackGroup; import mezz.jei.api.gui.ingredient.IGuiItemStackGroup;
import mezz.jei.api.ingredients.IIngredientRenderer;
import mezz.jei.api.ingredients.IIngredients; import mezz.jei.api.ingredients.IIngredients;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.renderer.ItemRenderer;
import net.minecraft.client.renderer.RenderHelper;
import net.minecraft.client.util.ITooltipFlag;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Rarity;
import net.minecraft.item.crafting.Ingredient; import net.minecraft.item.crafting.Ingredient;
import net.minecraft.item.crafting.ShapedRecipe; import net.minecraft.item.crafting.ShapedRecipe;
import net.minecraft.util.NonNullList; import net.minecraft.util.NonNullList;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TextFormatting;
public class MechanicalCraftingCategory extends CreateRecipeCategory<ShapedRecipe> { public class MechanicalCraftingCategory extends CreateRecipeCategory<ShapedRecipe> {
private AnimatedCrafter crafter; private final class CrafterIngredientRenderer implements IIngredientRenderer<ItemStack> {
private boolean large;
public MechanicalCraftingCategory(boolean large) { private ShapedRecipe recipe;
super("mechanical_crafting" + (large ? "_large" : ""), itemIcon(AllBlocks.MECHANICAL_CRAFTER.get()),
emptyBackground(large ? 177 : 177, large ? 235 : 81));
this.large = large;
crafter = new AnimatedCrafter(large);
}
public static boolean isSmall(ShapedRecipe recipe) { public CrafterIngredientRenderer(ShapedRecipe recipe) {
return Math.max((recipe).getWidth(), (recipe).getHeight()) <= 4; this.recipe = recipe;
} }
@Override @Override
public String getTitle() { public void render(int xPosition, int yPosition, ItemStack ingredient) {
return Lang.translate("recipe.mechanical_crafting"); GlStateManager.pushMatrix();
GlStateManager.translated(xPosition, yPosition, 0);
float scale = getScale(recipe);
GlStateManager.scaled(scale, scale, scale);
if (ingredient != null) {
GlStateManager.enableDepthTest();
RenderHelper.enableGUIStandardItemLighting();
Minecraft minecraft = Minecraft.getInstance();
FontRenderer font = getFontRenderer(minecraft, ingredient);
ItemRenderer itemRenderer = minecraft.getItemRenderer();
itemRenderer.renderItemAndEffectIntoGUI(null, ingredient, 0, 0);
itemRenderer.renderItemOverlayIntoGUI(font, ingredient, 0, 0, null);
GlStateManager.disableBlend();
RenderHelper.disableStandardItemLighting();
}
GlStateManager.popMatrix();
}
@Override
public List<String> getTooltip(ItemStack ingredient, ITooltipFlag tooltipFlag) {
Minecraft minecraft = Minecraft.getInstance();
PlayerEntity player = minecraft.player;
List<String> list;
try {
list = ingredient
.getTooltip(player, tooltipFlag)
.stream()
.map(ITextComponent::getFormattedText)
.collect(Collectors.toList());
} catch (RuntimeException | LinkageError e) {
return new ArrayList<>();
}
Rarity rarity;
try {
rarity = ingredient.getRarity();
} catch (RuntimeException | LinkageError e) {
rarity = Rarity.COMMON;
}
for (int k = 0; k < list.size(); ++k) {
if (k == 0) {
list.set(k, rarity.color + list.get(k));
} else {
list.set(k, TextFormatting.GRAY + list.get(k));
}
}
return list;
}
}
private AnimatedCrafter crafter = new AnimatedCrafter();
public MechanicalCraftingCategory() {
super("mechanical_crafting", itemIcon(AllBlocks.MECHANICAL_CRAFTER.get()), emptyBackground(177, 107));
} }
@Override @Override
@ -47,45 +111,79 @@ public class MechanicalCraftingCategory extends CreateRecipeCategory<ShapedRecip
IGuiItemStackGroup itemStacks = recipeLayout.getItemStacks(); IGuiItemStackGroup itemStacks = recipeLayout.getItemStacks();
NonNullList<Ingredient> recipeIngredients = recipe.getIngredients(); NonNullList<Ingredient> recipeIngredients = recipe.getIngredients();
itemStacks.init(0, false, large ? 136 : 141, large ? 196 : 50); itemStacks.init(0, false, 133, 80);
itemStacks.set(0, recipe.getRecipeOutput().getStack()); itemStacks.set(0, recipe.getRecipeOutput().getStack());
int x = getGridX(recipe); int x = getXPadding(recipe);
int y = getGridY(recipe); int y = getYPadding(recipe);
float scale = getScale(recipe);
int size = recipeIngredients.size(); int size = recipeIngredients.size();
IIngredientRenderer<ItemStack> renderer = new CrafterIngredientRenderer(recipe);
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
itemStacks.init(i + 1, true, x + (i % recipe.getWidth()) * 19, y + (i / recipe.getWidth()) * 19); float f = 19 * scale;
int slotSize = (int) (16 * scale);
int xPosition = (int) (x + 1 + (i % recipe.getWidth()) * f);
int yPosition = (int) (y + 1 + (i / recipe.getWidth()) * f);
itemStacks.init(i + 1, true, renderer, xPosition, yPosition, slotSize, slotSize, 0, 0);
itemStacks.set(i + 1, Arrays.asList(recipeIngredients.get(i).getMatchingStacks())); itemStacks.set(i + 1, Arrays.asList(recipeIngredients.get(i).getMatchingStacks()));
} }
} }
public int getGridY(ShapedRecipe recipe) { static int maxSize = 100;
return 3 + (int) (((large ? 9 : 4) - recipe.getRecipeHeight()) * 19 / 2f);
public static float getScale(ShapedRecipe recipe) {
int w = recipe.getWidth();
int h = recipe.getHeight();
return Math.min(1, maxSize / (19f * Math.max(w, h)));
} }
public int getGridX(ShapedRecipe recipe) { public static int getYPadding(ShapedRecipe recipe) {
return 3 + (int) (((large ? 9 : 4) - recipe.getRecipeWidth()) * 19 / 2f); return 3 + 50 - (int) (getScale(recipe) * recipe.getHeight() * 19 * .5);
}
public static int getXPadding(ShapedRecipe recipe) {
return 3 + 50 - (int) (getScale(recipe) * recipe.getWidth() * 19 * .5);
} }
@Override @Override
public void draw(ShapedRecipe recipe, double mouseX, double mouseY) { public void draw(ShapedRecipe recipe, double mouseX, double mouseY) {
int x = getGridX(recipe); GlStateManager.pushMatrix();
int y = getGridY(recipe); float scale = getScale(recipe);
GlStateManager.translated(getXPadding(recipe), getYPadding(recipe), 0);
for (int row = 0; row < recipe.getHeight(); row++) for (int row = 0; row < recipe.getHeight(); row++)
for (int col = 0; col < recipe.getWidth(); col++) for (int col = 0; col < recipe.getWidth(); col++)
if (!recipe.getIngredients().get(row * recipe.getWidth() + col).hasNoMatchingItems()) if (!recipe.getIngredients().get(row * recipe.getWidth() + col).hasNoMatchingItems()) {
ScreenResources.JEI_SLOT.draw(x + col * 19, y + row * 19); GlStateManager.pushMatrix();
GlStateManager.translated((int) col * 19 * scale, (int) row * 19 * scale, 0);
GlStateManager.scaled(scale, scale, scale);
ScreenResources.JEI_SLOT.draw(0, 0);
GlStateManager.popMatrix();
}
ScreenResources.JEI_SLOT.draw(large ? 136 : 141, large ? 196 : 50); GlStateManager.popMatrix();
if (large)
ScreenResources.JEI_ARROW.draw(86, 200);
else
ScreenResources.JEI_DOWN_ARROW.draw(136, 32);
ScreenResources.JEI_SHADOW.draw(large ? 20 : 84, large ? 223 : 68); ScreenResources.JEI_SLOT.draw(133, 80);
crafter.draw(large ? 105 : 185, large ? 189 : -1); ScreenResources.JEI_DOWN_ARROW.draw(128, 59);
ScreenResources.JEI_SHADOW.draw(116, 36);
crafter.draw(219, 8);
GlStateManager.pushMatrix();
GlStateManager.translated(0, 0, 200);
RenderHelper.disableStandardItemLighting();
int amount = 0;
for (Ingredient ingredient : recipe.getIngredients()) {
if (Ingredient.EMPTY == ingredient)
continue;
amount++;
}
Minecraft.getInstance().fontRenderer
.drawStringWithShadow(amount + "", 142, 39, 0xFFFFFF);
RenderHelper.enableStandardItemLighting();
GlStateManager.popMatrix();
} }
@Override @Override

View file

@ -12,12 +12,6 @@ import net.minecraft.util.Direction;
public class AnimatedCrafter extends AnimatedKinetics { public class AnimatedCrafter extends AnimatedKinetics {
boolean four;
public AnimatedCrafter(boolean four) {
this.four = four;
}
@Override @Override
public int getWidth() { public int getWidth() {
return 50; return 50;
@ -40,23 +34,6 @@ public class AnimatedCrafter extends AnimatedKinetics {
ScreenElementRenderer.renderModel(() -> cogwheel(true)); ScreenElementRenderer.renderModel(() -> cogwheel(true));
ScreenElementRenderer.renderBlock(this::body); ScreenElementRenderer.renderBlock(this::body);
RenderSystem.translatef(0, 50, 0);
ScreenElementRenderer.renderModel(() -> cogwheel(false));
ScreenElementRenderer.renderBlock(this::body);
if (four) {
RenderSystem.translatef(50, -50, 0);
ScreenElementRenderer.renderModel(() -> cogwheel(false));
ScreenElementRenderer.renderBlock(this::body);
RenderSystem.translatef(0, 50, 0);
ScreenElementRenderer.renderModel(() -> cogwheel(true));
ScreenElementRenderer.renderBlock(this::body);
} else {
RenderSystem.translatef(0, 50, 0);
ScreenElementRenderer.renderModel(() -> cogwheel(true));
ScreenElementRenderer.renderBlock(this::body);
}
RenderSystem.popMatrix(); RenderSystem.popMatrix();
} }
@ -71,8 +48,10 @@ public class AnimatedCrafter extends AnimatedKinetics {
} }
private BlockState body() { private BlockState body() {
return AllBlocks.MECHANICAL_CRAFTER.get().getDefaultState().with(MechanicalCrafterBlock.HORIZONTAL_FACING, return AllBlocks.MECHANICAL_CRAFTER
Direction.WEST); .get()
.getDefaultState()
.with(MechanicalCrafterBlock.HORIZONTAL_FACING, Direction.WEST);
} }
} }

View file

@ -0,0 +1,359 @@
package com.simibubi.create.data;
import java.io.IOException;
import java.nio.file.Path;
import java.util.Set;
import java.util.function.Consumer;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import com.google.common.collect.Sets;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllItems;
import com.simibubi.create.Create;
import com.simibubi.create.foundation.advancement.AllTriggers;
import com.simibubi.create.foundation.advancement.KineticBlockTrigger;
import com.simibubi.create.modules.curiosities.zapper.blockzapper.BlockzapperItem;
import com.simibubi.create.modules.curiosities.zapper.blockzapper.BlockzapperItem.ComponentTier;
import com.simibubi.create.modules.curiosities.zapper.blockzapper.BlockzapperItem.Components;
import net.minecraft.advancements.Advancement;
import net.minecraft.advancements.Advancement.Builder;
import net.minecraft.advancements.FrameType;
import net.minecraft.advancements.criterion.InventoryChangeTrigger;
import net.minecraft.advancements.criterion.PlacedBlockTrigger;
import net.minecraft.block.Block;
import net.minecraft.block.Blocks;
import net.minecraft.data.DataGenerator;
import net.minecraft.data.DirectoryCache;
import net.minecraft.data.IDataProvider;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.util.IItemProvider;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.text.TranslationTextComponent;
@SuppressWarnings("unused") // dont warn about unused avancements
public class CreateAdvancements implements IDataProvider {
static final String LANG = "advancement." + Create.ID + ".";
public void register(Consumer<Advancement> t) {
String id = Create.ID;
Advancement root = Advancement.Builder
.builder()
.withDisplay(AllItems.BRASS_HAND.asStack(), new TranslationTextComponent(LANG + "root"),
new TranslationTextComponent(LANG + "root.desc"),
new ResourceLocation(Create.ID, "textures/block/scoria_bricks.png"), FrameType.TASK, false,
false, false)
.withCriterion("0", InventoryChangeTrigger.Instance.forItems(new IItemProvider[] {}))
.register(t, id + ":root");
Advancement andesite_alloy = advancement("andesite_alloy", AllItems.ANDESITE_ALLOY.get(), TaskType.NORMAL)
.withParent(root)
.withCriterion("0", itemGathered(AllItems.ANDESITE_ALLOY.get()))
.register(t, id + ":andesite_alloy");
kineticsBranch(t, andesite_alloy);
Advancement water_wheel = advancement("water_wheel", AllBlocks.WATER_WHEEL.get(), TaskType.NORMAL)
.withParent(andesite_alloy)
.withCriterion("0", placeBlock(AllBlocks.WATER_WHEEL.get()))
.withCriterion("1", AllTriggers.WATER_WHEEL.instance())
.register(t, id + ":water_wheel");
Advancement lava_wheel = advancement("lava_wheel", Items.LAVA_BUCKET, TaskType.SECRET)
.withParent(water_wheel)
.withCriterion("0", AllTriggers.LAVA_WHEEL.instance())
.register(t, id + ":lava_wheel");
Advancement millstone = kinecticAdvancement("millstone", AllBlocks.MILLSTONE, TaskType.NORMAL)
.withParent(andesite_alloy)
.register(t, id + ":millstone");
Advancement andesite_casing = advancement("andesite_casing", AllBlocks.ANDESITE_CASING.get(), TaskType.GOAL)
.withParent(andesite_alloy)
.withCriterion("0", itemGathered(AllBlocks.ANDESITE_CASING.get()))
.register(t, id + ":andesite_casing");
andesiteExpertLane(t, andesite_casing);
Advancement drill = kinecticAdvancement("drill", AllBlocks.DRILL, TaskType.NORMAL)
.withParent(andesite_casing)
.register(t, id + ":drill");
Advancement press = advancement("press", AllBlocks.MECHANICAL_PRESS.get(), TaskType.MILESTONE)
.withParent(andesite_casing)
.withCriterion("0", AllTriggers.BONK.instance())
.register(t, id + ":press");
Advancement rose_quartz =
itemAdvancement("polished_rose_quartz", AllItems.POLISHED_ROSE_QUARTZ, TaskType.NORMAL)
.withParent(andesite_casing)
.register(t, id + ":polished_rose_quartz");
Advancement electron_tube = itemAdvancement("electron_tube", AllItems.ELECTRON_TUBE, TaskType.NORMAL)
.withParent(rose_quartz)
.register(t, id + ":electron_tube");
Advancement saw =
kinecticAdvancement("saw", AllBlocks.SAW, TaskType.NORMAL).withParent(press).register(t, id + ":saw");
Advancement basin = advancement("basin", AllBlocks.BASIN.get(), TaskType.NORMAL)
.withParent(press)
.withCriterion("0", placeBlock(AllBlocks.BASIN.get()))
.withCriterion("1", AllTriggers.BASIN_THROW.instance())
.register(t, id + ":basin");
Advancement mixer = advancement("mixer", AllBlocks.MECHANICAL_MIXER.get(), TaskType.MILESTONE)
.withCriterion("0", placeBlock(AllBlocks.MECHANICAL_MIXER.get()))
.withCriterion("1", isPowered(AllBlocks.MECHANICAL_MIXER.get()))
.withCriterion("2", AllTriggers.MIXER_MIX.instance())
.withParent(basin)
.register(t, id + ":mixer");
Advancement compact = advancement("compact", Blocks.IRON_BLOCK, TaskType.NORMAL)
.withCriterion("0", AllTriggers.PRESS_COMPACT.instance())
.withParent(basin)
.register(t, id + ":compact");
Advancement brass = itemAdvancement("brass", AllItems.BRASS_INGOT, TaskType.NORMAL)
.withParent(mixer)
.register(t, id + ":brass");
brassAge(t, brass);
copperAge(t, press);
}
void kineticsBranch(Consumer<Advancement> t, Advancement root) {
String id = Create.ID;
Advancement its_alive = advancement("its_alive", AllBlocks.COGWHEEL.get(), TaskType.NORMAL)
.withParent(root)
.withCriterion("0", AllTriggers.ROTATION.instance())
.register(t, id + ":its_alive");
Advancement belt = advancement("belt", AllItems.BELT_CONNECTOR.get(), TaskType.NORMAL)
.withParent(its_alive)
.withCriterion("0", AllTriggers.CONNECT_BELT.instance())
.register(t, id + ":belt");
Advancement wrench = itemAdvancement("wrench", AllItems.WRENCH, TaskType.NORMAL)
.withParent(its_alive)
.register(t, id + ":wrench");
Advancement goggles = itemAdvancement("goggles", AllItems.GOGGLES, TaskType.NORMAL)
.withParent(its_alive)
.register(t, id + ":goggles");
Advancement speed_gauge = kinecticAdvancement("speed_gauge", AllBlocks.SPEED_GAUGE, TaskType.NORMAL)
.withParent(goggles)
.register(t, id + ":speed_gauge");
Advancement stress_gauge = kinecticAdvancement("stress_gauge", AllBlocks.STRESS_GAUGE, TaskType.NORMAL)
.withParent(goggles)
.register(t, id + ":stress_gauge");
Advancement shifting_gears = advancement("shifting_gears", AllBlocks.LARGE_COGWHEEL.get(), TaskType.NORMAL)
.withParent(its_alive)
.withCriterion("0", AllTriggers.SHIFTING_GEARS.instance())
.register(t, id + ":shifting_gears");
Advancement overstressed = advancement("overstressed", Items.BARRIER, TaskType.SECRET)
.withParent(its_alive)
.withCriterion("0", AllTriggers.OVERSTRESSED.instance())
.register(t, id + ":overstressed");
}
void copperAge(Consumer<Advancement> t, Advancement root) {
String id = Create.ID;
Advancement copper_casing = advancement("copper_casing", AllBlocks.COPPER_CASING.get(), TaskType.GOAL)
.withParent(root)
.withCriterion("0", itemGathered(AllBlocks.COPPER_CASING.get()))
.register(t, id + ":copper_casing");
Advancement copper_end = deadEnd()
.withParent(copper_casing)
.withCriterion("0", itemGathered(AllBlocks.COPPER_CASING.get()))
.register(t, id + ":copper_end");
}
void brassAge(Consumer<Advancement> t, Advancement root) {
String id = Create.ID;
Advancement brass_casing = advancement("brass_casing", AllBlocks.BRASS_CASING.get(), TaskType.GOAL)
.withParent(root)
.withCriterion("0", itemGathered(AllBlocks.BRASS_CASING.get()))
.register(t, id + ":brass_casing");
Advancement crafter = kinecticAdvancement("crafter", AllBlocks.MECHANICAL_CRAFTER, TaskType.MILESTONE)
.withParent(brass_casing)
.register(t, id + ":crafter");
Advancement deployer = kinecticAdvancement("deployer", AllBlocks.DEPLOYER, TaskType.GOAL)
.withParent(brass_casing)
.register(t, id + ":deployer");
Advancement fist_bump = advancement("fist_bump", AllBlocks.DEPLOYER.get(), TaskType.SECRET)
.withParent(deployer)
.withCriterion("0", AllTriggers.DEPLOYER_BOOP.instance())
.register(t, id + ":fist_bump");
Advancement crushing_wheel = advancement("crushing_wheel", AllBlocks.CRUSHING_WHEEL.get(), TaskType.MILESTONE)
.withParent(crafter)
.withCriterion("0", itemGathered(AllBlocks.CRUSHING_WHEEL.get()))
.register(t, id + ":crushing_wheel");
Advancement chromatic_compound =
itemAdvancement("chromatic_compound", AllItems.CHROMATIC_COMPOUND, TaskType.NORMAL)
.withParent(crushing_wheel)
.register(t, id + ":chromatic_compound");
Advancement shadow_steel = itemAdvancement("shadow_steel", AllItems.SHADOW_STEEL, TaskType.GOAL)
.withParent(chromatic_compound)
.register(t, id + ":shadow_steel");
Advancement refined_radiance = itemAdvancement("refined_radiance", AllItems.REFINED_RADIANCE, TaskType.GOAL)
.withParent(chromatic_compound)
.register(t, id + ":refined_radiance");
Advancement deforester = itemAdvancement("deforester", AllItems.DEFORESTER, TaskType.NORMAL)
.withParent(refined_radiance)
.register(t, id + ":deforester");
Advancement zapper = itemAdvancement("zapper", AllItems.PLACEMENT_HANDGUN, TaskType.NORMAL)
.withParent(refined_radiance)
.register(t, id + ":zapper");
ItemStack gunWithPurpurStuff = AllItems.PLACEMENT_HANDGUN.asStack();
for (Components c : Components.values())
BlockzapperItem.setTier(c, ComponentTier.Chromatic, gunWithPurpurStuff);
Advancement upgraded_zapper = advancement("upgraded_zapper", gunWithPurpurStuff, TaskType.CHALLENGE)
.withCriterion("0", AllTriggers.UPGRADED_ZAPPER.instance())
.withParent(zapper)
.register(t, id + ":upgraded_zapper");
Advancement symmetry_wand = itemAdvancement("symmetry_wand", AllItems.SYMMETRY_WAND, TaskType.NORMAL)
.withParent(refined_radiance)
.register(t, id + ":symmetry_wand");
Advancement shadow_end = deadEnd()
.withParent(shadow_steel)
.withCriterion("0", itemGathered(AllItems.SHADOW_STEEL.get()))
.register(t, id + ":shadow_end");
}
private void andesiteExpertLane(Consumer<Advancement> t, Advancement root) {
String id = Create.ID;
}
// Datagen
private static final Logger LOGGER = LogManager.getLogger();
private static final Gson GSON = (new GsonBuilder()).setPrettyPrinting().create();
private final DataGenerator generator;
public CreateAdvancements(DataGenerator generatorIn) {
this.generator = generatorIn;
}
@Override
public void act(DirectoryCache cache) throws IOException {
Path path = this.generator.getOutputFolder();
Set<ResourceLocation> set = Sets.newHashSet();
Consumer<Advancement> consumer = (p_204017_3_) -> {
if (!set.add(p_204017_3_.getId()))
throw new IllegalStateException("Duplicate advancement " + p_204017_3_.getId());
Path path1 = getPath(path, p_204017_3_);
try {
IDataProvider.save(GSON, cache, p_204017_3_.copy().serialize(), path1);
} catch (IOException ioexception) {
LOGGER.error("Couldn't save advancement {}", path1, ioexception);
}
};
register(consumer);
}
private static Path getPath(Path pathIn, Advancement advancementIn) {
return pathIn
.resolve("data/" + advancementIn.getId().getNamespace() + "/advancements/"
+ advancementIn.getId().getPath() + ".json");
}
@Override
public String getName() {
return "CreateAdvancements";
}
public PlacedBlockTrigger.Instance placeBlock(Block block) {
return PlacedBlockTrigger.Instance.placedBlock(block);
}
public KineticBlockTrigger.Instance isPowered(Block block) {
return AllTriggers.KINETIC_BLOCK.forBlock(block);
}
public InventoryChangeTrigger.Instance itemGathered(IItemProvider itemprovider) {
return InventoryChangeTrigger.Instance.forItems(itemprovider);
}
static enum TaskType {
NORMAL(FrameType.TASK, true, false, false),
MILESTONE(FrameType.TASK, true, true, false),
GOAL(FrameType.GOAL, true, true, false),
SECRET(FrameType.GOAL, true, true, true),
SILENT_GATE(FrameType.CHALLENGE, false, false, false),
CHALLENGE(FrameType.CHALLENGE, true, true, false),
;
private FrameType frame;
private boolean toast;
private boolean announce;
private boolean hide;
private TaskType(FrameType frame, boolean toast, boolean announce, boolean hide) {
this.frame = frame;
this.toast = toast;
this.announce = announce;
this.hide = hide;
}
}
public Builder kinecticAdvancement(String name, AllBlocks block, TaskType type) {
return advancement(name, block.get(), type)
.withCriterion("0", placeBlock(block.get()))
.withCriterion("1", isPowered(block.get()));
}
public Builder advancement(String name, IItemProvider icon, TaskType type) {
return advancement(name, new ItemStack(icon), type);
}
public Builder deadEnd() {
return advancement("eob", Items.OAK_SAPLING, TaskType.SILENT_GATE);
}
public Builder advancement(String name, ItemStack icon, TaskType type) {
return Advancement.Builder
.builder()
.withDisplay(icon, new TranslationTextComponent(LANG + name),
new TranslationTextComponent(LANG + name + ".desc"), null, type.frame, type.toast,
type.announce, type.hide);
}
public Builder itemAdvancement(String name, AllItems item, TaskType type) {
return advancement(name, item.get(), type).withCriterion("0", itemGathered(item.get()));
}
}

View file

@ -15,12 +15,23 @@ public class AllTriggers {
private static List<CriterionTriggerBase<?>> triggers = new LinkedList<>(); private static List<CriterionTriggerBase<?>> triggers = new LinkedList<>();
public static SandpaperUseTrigger SANDPAPER_USE = add(new SandpaperUseTrigger("sandpaper_use")); public static KineticBlockTrigger KINETIC_BLOCK = add(new KineticBlockTrigger("kinetic_block"));
public static SimpleTrigger DEPLOYER_BOOP = simple("deployer");
public static SimpleTrigger ABSORBED_LIGHT = simple("light_absorbed"); public static SimpleTrigger
public static SimpleTrigger SPEED_READ = simple("speed_read"); ROTATION = simple("rotation"),
public static SimpleTrigger OVERSTRESSED = simple("overstressed"); OVERSTRESSED = simple("overstressed"),
public static SimpleTrigger ROTATION = simple("rotation"); SHIFTING_GEARS = simple("shifting_gears"),
CONNECT_BELT = simple("connect_belt"),
BONK = simple("bonk"),
WATER_WHEEL = simple("water_wheel"),
LAVA_WHEEL = simple("lava_wheel"),
DEPLOYER_BOOP = simple("deployer"),
ABSORBED_LIGHT = simple("light_absorbed"),
SPEED_READ = simple("speed_read"),
BASIN_THROW = simple("basin"),
PRESS_COMPACT = simple("compact"),
UPGRADED_ZAPPER = simple("upgraded_zapper"),
MIXER_MIX = simple("mixer");
private static SimpleTrigger simple(String id) { private static SimpleTrigger simple(String id) {
return add(new SimpleTrigger(id)); return add(new SimpleTrigger(id));
@ -35,19 +46,29 @@ public class AllTriggers {
triggers.forEach(CriteriaTriggers::register); triggers.forEach(CriteriaTriggers::register);
} }
public static void triggerForNearbyPlayers(SimpleTrigger trigger, World world, BlockPos pos, int range) { public static void triggerFor(ITriggerable trigger, PlayerEntity player) {
if (player instanceof ServerPlayerEntity)
trigger.trigger((ServerPlayerEntity) player);
}
public static void triggerForNearbyPlayers(ITriggerable trigger, World world, BlockPos pos, int range) {
triggerForNearbyPlayers(trigger, world, pos, range, player -> true); triggerForNearbyPlayers(trigger, world, pos, range, player -> true);
} }
public static void triggerForNearbyPlayers(SimpleTrigger trigger, World world, BlockPos pos, int range, public static void triggerForNearbyPlayers(ITriggerable trigger, World world, BlockPos pos, int range,
Predicate<PlayerEntity> playerFilter) { Predicate<PlayerEntity> playerFilter) {
if (world == null) if (world == null)
return; return;
if (world.isRemote) if (world.isRemote)
return; return;
List<ServerPlayerEntity> players = List<ServerPlayerEntity> players = getPlayersInRange(world, pos, range);
world.getEntitiesWithinAABB(ServerPlayerEntity.class, new AxisAlignedBB(pos).grow(range));
players.stream().filter(playerFilter).forEach(trigger::trigger); players.stream().filter(playerFilter).forEach(trigger::trigger);
} }
public static List<ServerPlayerEntity> getPlayersInRange(World world, BlockPos pos, int range) {
List<ServerPlayerEntity> players =
world.getEntitiesWithinAABB(ServerPlayerEntity.class, new AxisAlignedBB(pos).grow(range));
return players;
}
} }

View file

@ -0,0 +1,9 @@
package com.simibubi.create.foundation.advancement;
import net.minecraft.entity.player.ServerPlayerEntity;
public interface ITriggerable {
public void trigger(ServerPlayerEntity player);
}

View file

@ -0,0 +1,76 @@
package com.simibubi.create.foundation.advancement;
import java.util.Arrays;
import java.util.List;
import java.util.function.Supplier;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonSyntaxException;
import com.simibubi.create.Create;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.util.JSONUtils;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.registry.Registry;
public class KineticBlockTrigger extends CriterionTriggerBase<KineticBlockTrigger.Instance> {
private static final ResourceLocation ID = new ResourceLocation(Create.ID, "kinetic_block");
public KineticBlockTrigger(String id) {
super(id);
}
public Instance forBlock(Block block) {
return new Instance(block);
}
@Override
@SuppressWarnings("deprecation")
public Instance deserializeInstance(JsonObject json, JsonDeserializationContext context) {
Block block = null;
if (json.has("block")) {
ResourceLocation resourcelocation = new ResourceLocation(JSONUtils.getString(json, "block"));
block = Registry.BLOCK.getValue(resourcelocation).orElseThrow(() -> {
return new JsonSyntaxException("Unknown block type '" + resourcelocation + "'");
});
}
return new Instance(block);
}
public void trigger(ServerPlayerEntity player, BlockState state) {
trigger(player, Arrays.asList(() -> state.getBlock()));
}
public static class Instance extends CriterionTriggerBase.Instance {
private final Block block;
public Instance(Block block) {
super(KineticBlockTrigger.ID);
this.block = block;
}
@Override
protected boolean test(List<Supplier<Object>> suppliers) {
if (suppliers.isEmpty())
return false;
return block == suppliers.get(0).get();
}
@Override
@SuppressWarnings("deprecation")
public JsonElement serialize() {
JsonObject jsonobject = new JsonObject();
if (this.block != null)
jsonobject.addProperty("block", Registry.BLOCK.getKey(this.block).toString());
return jsonobject;
}
}
}

View file

@ -1,47 +0,0 @@
package com.simibubi.create.foundation.advancement;
import java.util.Arrays;
import java.util.List;
import java.util.function.Supplier;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonObject;
import net.minecraft.advancements.criterion.ItemPredicate;
import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ResourceLocation;
public class SandpaperUseTrigger extends CriterionTriggerBase<SandpaperUseTrigger.Instance> {
public SandpaperUseTrigger(String id) {
super(id);
}
@Override
public Instance deserializeInstance(JsonObject json, JsonDeserializationContext context) {
return new SandpaperUseTrigger.Instance(getId(), ItemPredicate.deserialize(json.get("target")),ItemPredicate.deserialize(json.get("result")));
}
public void trigger(ServerPlayerEntity player, ItemStack target, ItemStack result){
trigger(player, Arrays.asList(() -> target, () -> result));
}
public static class Instance extends CriterionTriggerBase.Instance {
private final ItemPredicate target;
private final ItemPredicate result;
public Instance(ResourceLocation idIn, ItemPredicate target, ItemPredicate result) {
super(idIn);
this.target = target;
this.result = result;
}
@Override
protected boolean test(List<Supplier<Object>> suppliers) {
return this.target.test((ItemStack) suppliers.get(0).get()) &&
this.result.test((ItemStack) suppliers.get(1).get());
}
}
}

View file

@ -9,7 +9,7 @@ import com.google.gson.JsonObject;
import net.minecraft.entity.player.ServerPlayerEntity; import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
public class SimpleTrigger extends CriterionTriggerBase<SimpleTrigger.Instance> { public class SimpleTrigger extends CriterionTriggerBase<SimpleTrigger.Instance> implements ITriggerable {
public SimpleTrigger(String id) { public SimpleTrigger(String id) {
super(id); super(id);
@ -24,6 +24,10 @@ public class SimpleTrigger extends CriterionTriggerBase<SimpleTrigger.Instance>
super.trigger(player, null); super.trigger(player, null);
} }
public Instance instance() {
return new Instance(getId());
}
public static class Instance extends CriterionTriggerBase.Instance { public static class Instance extends CriterionTriggerBase.Instance {
public Instance(ResourceLocation idIn) { public Instance(ResourceLocation idIn) {

View file

@ -1,6 +1,7 @@
package com.simibubi.create.foundation.behaviour.filtering; package com.simibubi.create.foundation.behaviour.filtering;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Supplier;
import com.simibubi.create.AllPackets; import com.simibubi.create.AllPackets;
import com.simibubi.create.foundation.behaviour.ValueBoxTransform; import com.simibubi.create.foundation.behaviour.ValueBoxTransform;
@ -29,6 +30,7 @@ public class FilteringBehaviour extends TileEntityBehaviour {
private ItemStack filter; private ItemStack filter;
public int count; public int count;
private Consumer<ItemStack> callback; private Consumer<ItemStack> callback;
private Supplier<Boolean> isActive;
int scrollableValue; int scrollableValue;
int ticksUntilScrollPacket; int ticksUntilScrollPacket;
@ -40,6 +42,7 @@ public class FilteringBehaviour extends TileEntityBehaviour {
slotPositioning = slot; slotPositioning = slot;
showCount = false; showCount = false;
callback = stack -> {}; callback = stack -> {};
isActive = () -> true;
textShift = Vec3d.ZERO; textShift = Vec3d.ZERO;
count = 0; count = 0;
ticksUntilScrollPacket = -1; ticksUntilScrollPacket = -1;
@ -94,6 +97,11 @@ public class FilteringBehaviour extends TileEntityBehaviour {
return this; return this;
} }
public FilteringBehaviour onlyActiveWhen(Supplier<Boolean> condition) {
isActive = condition;
return this;
}
public FilteringBehaviour showCount() { public FilteringBehaviour showCount() {
showCount = true; showCount = true;
return this; return this;
@ -162,4 +170,8 @@ public class FilteringBehaviour extends TileEntityBehaviour {
return count == 0; return count == 0;
} }
public boolean isActive() {
return isActive.get();
}
} }

View file

@ -41,6 +41,8 @@ public class FilteringHandler {
FilteringBehaviour behaviour = TileEntityBehaviour.get(world, pos, FilteringBehaviour.TYPE); FilteringBehaviour behaviour = TileEntityBehaviour.get(world, pos, FilteringBehaviour.TYPE);
if (behaviour == null) if (behaviour == null)
return; return;
if (!behaviour.isActive())
return;
BlockRayTraceResult ray = RaycastHelper.rayTraceRange(world, player, 10); BlockRayTraceResult ray = RaycastHelper.rayTraceRange(world, player, 10);
if (ray == null) if (ray == null)

View file

@ -43,6 +43,8 @@ public class FilteringRenderer {
FilteringBehaviour behaviour = TileEntityBehaviour.get(world, pos, FilteringBehaviour.TYPE); FilteringBehaviour behaviour = TileEntityBehaviour.get(world, pos, FilteringBehaviour.TYPE);
if (behaviour == null) if (behaviour == null)
return; return;
if (!behaviour.isActive())
return;
if (Minecraft.getInstance().player.isSneaking()) if (Minecraft.getInstance().player.isSneaking())
return; return;
@ -77,6 +79,8 @@ public class FilteringRenderer {
FilteringBehaviour behaviour = TileEntityBehaviour.get(tileEntityIn, FilteringBehaviour.TYPE); FilteringBehaviour behaviour = TileEntityBehaviour.get(tileEntityIn, FilteringBehaviour.TYPE);
if (behaviour == null) if (behaviour == null)
return; return;
if (!behaviour.isActive())
return;
if (behaviour.getFilter().isEmpty()) if (behaviour.getFilter().isEmpty())
return; return;

View file

@ -95,10 +95,11 @@ public class ScreenElementRenderer {
blockRenderer.renderBlock(blockToRender, ms, buffer, 0xF000F0, OverlayTexture.DEFAULT_UV, blockRenderer.renderBlock(blockToRender, ms, buffer, 0xF000F0, OverlayTexture.DEFAULT_UV,
EmptyModelData.INSTANCE); EmptyModelData.INSTANCE);
} else { } else {
if (modelToRender != null) {
RenderSystem.rotatef(90, 0, 1, 0); RenderSystem.rotatef(90, 0, 1, 0);
if (color == -1) { if (color == -1) {
blockRenderer.getBlockModelRenderer().renderModel(ms.peek(), vb, blockToRender, modelToRender, 1, 1, 1, blockRenderer.getBlockModelRenderer().renderModel(ms.peek(), vb, blockToRender, modelToRender, 1, 1,
0xF000F0, OverlayTexture.DEFAULT_UV, EmptyModelData.INSTANCE); 1, 0xF000F0, OverlayTexture.DEFAULT_UV, EmptyModelData.INSTANCE);
} else { } else {
Vec3d rgb = ColorHelper.getRGB(color); Vec3d rgb = ColorHelper.getRGB(color);
blockRenderer.getBlockModelRenderer().renderModel(ms.peek(), vb, blockToRender, modelToRender, blockRenderer.getBlockModelRenderer().renderModel(ms.peek(), vb, blockToRender, modelToRender,
@ -106,6 +107,8 @@ public class ScreenElementRenderer {
EmptyModelData.INSTANCE); EmptyModelData.INSTANCE);
} }
} }
}
RenderSystem.popMatrix(); RenderSystem.popMatrix();
buffer.draw(renderType); buffer.draw(renderType);

View file

@ -127,17 +127,27 @@ public class ItemHelper {
return false; return false;
} }
public static enum ExtractionCountMode {
EXACTLY, UPTO
}
public static ItemStack extract(IItemHandler inv, Predicate<ItemStack> test, boolean simulate) { public static ItemStack extract(IItemHandler inv, Predicate<ItemStack> test, boolean simulate) {
return extract(inv, test, -1, simulate); return extract(inv, test, ExtractionCountMode.UPTO, AllConfigs.SERVER.logistics.extractorAmount.get(),
simulate);
} }
public static ItemStack extract(IItemHandler inv, Predicate<ItemStack> test, int exactAmount, boolean simulate) { public static ItemStack extract(IItemHandler inv, Predicate<ItemStack> test, int exactAmount, boolean simulate) {
return extract(inv, test, ExtractionCountMode.EXACTLY, exactAmount, simulate);
}
public static ItemStack extract(IItemHandler inv, Predicate<ItemStack> test, ExtractionCountMode mode, int amount,
boolean simulate) {
ItemStack extracting = ItemStack.EMPTY; ItemStack extracting = ItemStack.EMPTY;
boolean amountRequired = exactAmount != -1; boolean amountRequired = mode == ExtractionCountMode.EXACTLY;
boolean checkHasEnoughItems = amountRequired; boolean checkHasEnoughItems = amountRequired;
boolean hasEnoughItems = !checkHasEnoughItems; boolean hasEnoughItems = !checkHasEnoughItems;
int maxExtractionCount = hasEnoughItems ? AllConfigs.SERVER.logistics.extractorAmount.get() : exactAmount;
boolean potentialOtherMatch = false; boolean potentialOtherMatch = false;
int maxExtractionCount = amount;
Extraction: do { Extraction: do {
extracting = ItemStack.EMPTY; extracting = ItemStack.EMPTY;
@ -186,7 +196,7 @@ public class ItemHelper {
} while (true); } while (true);
if (amountRequired && extracting.getCount() < exactAmount) if (amountRequired && extracting.getCount() < amount)
return ItemStack.EMPTY; return ItemStack.EMPTY;
return extracting; return extracting;

View file

@ -1,5 +1,7 @@
package com.simibubi.create.foundation.utility.data; package com.simibubi.create.foundation.utility.data;
import com.simibubi.create.data.CreateAdvancements;
import net.minecraft.data.DataGenerator; import net.minecraft.data.DataGenerator;
import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod;
@ -11,8 +13,8 @@ public class Generator {
@SubscribeEvent @SubscribeEvent
public static void gatherData(GatherDataEvent event){ public static void gatherData(GatherDataEvent event){
DataGenerator gen = event.getGenerator(); DataGenerator gen = event.getGenerator();
//gen.addProvider(AllSoundEvents.CUCKOO_PIG);
gen.addProvider(new AllItemsTagProvider(gen)); gen.addProvider(new AllItemsTagProvider(gen));
gen.addProvider(new CreateAdvancements(gen));
} }
} }

View file

@ -10,11 +10,13 @@ import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks; import net.minecraft.block.Blocks;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemUseContext;
import net.minecraft.util.ActionResultType;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IBlockReader; import net.minecraft.world.IBlockReader;
import net.minecraftforge.common.ToolType; import net.minecraftforge.common.ToolType;
public class CasingBlock extends Block implements IHaveConnectedTextures { public class CasingBlock extends Block implements IHaveConnectedTextures, IWrenchable {
String textureFrom; String textureFrom;
@ -23,6 +25,11 @@ public class CasingBlock extends Block implements IHaveConnectedTextures {
this.textureFrom = textureFrom; this.textureFrom = textureFrom;
} }
@Override
public ActionResultType onWrenched(BlockState state, ItemUseContext context) {
return ActionResultType.FAIL;
}
@Override @Override
public ToolType getHarvestTool(BlockState state) { public ToolType getHarvestTool(BlockState state) {
return null; return null;

View file

@ -28,6 +28,8 @@ public interface IWrenchable {
KineticTileEntity.switchToBlockState(world, context.getPos(), updateAfterWrenched(rotated, context)); KineticTileEntity.switchToBlockState(world, context.getPos(), updateAfterWrenched(rotated, context));
TileEntity te = context.getWorld().getTileEntity(context.getPos()); TileEntity te = context.getWorld().getTileEntity(context.getPos());
if (te != null)
te.updateContainingBlockInfo();
if (te instanceof GeneratingKineticTileEntity) { if (te instanceof GeneratingKineticTileEntity) {
((GeneratingKineticTileEntity) te).updateGeneratedRotation(); ((GeneratingKineticTileEntity) te).updateGeneratedRotation();
} }

View file

@ -248,7 +248,8 @@ public class RotationPropagator {
// Do not overpower you own network -> cycle // Do not overpower you own network -> cycle
if (!currentTE.hasNetwork() || currentTE.network.equals(neighbourTE.network)) { if (!currentTE.hasNetwork() || currentTE.network.equals(neighbourTE.network)) {
if (Math.abs(newSpeed) > Math.abs(speedOfNeighbour)) float epsilon = Math.abs(speedOfNeighbour) / 256f / 256f;
if (Math.abs(newSpeed) > Math.abs(speedOfNeighbour) + epsilon)
world.destroyBlock(pos, true); world.destroyBlock(pos, true);
continue; continue;
} }

View file

@ -4,7 +4,6 @@ import com.simibubi.create.foundation.item.ItemDescription.Palette;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.material.PushReaction;
import net.minecraft.entity.LivingEntity; import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
@ -64,11 +63,6 @@ public abstract class KineticBlock extends Block implements IRotate {
return true; return true;
} }
@Override
public PushReaction getPushReaction(BlockState state) {
return PushReaction.BLOCK;
}
@Override @Override
public abstract TileEntity createTileEntity(BlockState state, IBlockReader world); public abstract TileEntity createTileEntity(BlockState state, IBlockReader world);

View file

@ -166,9 +166,13 @@ public abstract class KineticTileEntity extends SmartTileEntity
public void onSpeedChanged(float previousSpeed) { public void onSpeedChanged(float previousSpeed) {
boolean fromOrToZero = (previousSpeed == 0) != (getSpeed() == 0); boolean fromOrToZero = (previousSpeed == 0) != (getSpeed() == 0);
boolean directionSwap = !fromOrToZero && Math.signum(previousSpeed) != Math.signum(getSpeed()); boolean directionSwap = !fromOrToZero && Math.signum(previousSpeed) != Math.signum(getSpeed());
if (fromOrToZero || directionSwap) { if (fromOrToZero || directionSwap)
flickerTally = getFlickerScore() + 5; flickerTally = getFlickerScore() + 5;
}
if (fromOrToZero && previousSpeed == 0 && !world.isRemote)
AllTriggers
.getPlayersInRange(world, pos, 4)
.forEach(p -> AllTriggers.KINETIC_BLOCK.trigger(p, getBlockState()));
} }
@Override @Override
@ -355,8 +359,12 @@ public abstract class KineticTileEntity extends SmartTileEntity
return; return;
TileEntity tileEntityIn = world.getTileEntity(pos); TileEntity tileEntityIn = world.getTileEntity(pos);
if (!(tileEntityIn instanceof KineticTileEntity)) boolean isKinetic = tileEntityIn instanceof KineticTileEntity;
if (!isKinetic) {
world.setBlockState(pos, state, 3);
return; return;
}
KineticTileEntity tileEntity = (KineticTileEntity) tileEntityIn; KineticTileEntity tileEntity = (KineticTileEntity) tileEntityIn;
if (tileEntity.hasNetwork()) if (tileEntity.hasNetwork())
@ -368,8 +376,7 @@ public abstract class KineticTileEntity extends SmartTileEntity
} }
@Override @Override
public void addBehaviours(List<TileEntityBehaviour> behaviours) { public void addBehaviours(List<TileEntityBehaviour> behaviours) {}
}
@Override @Override
public boolean hasFastRenderer() { public boolean hasFastRenderer() {
@ -382,7 +389,8 @@ public abstract class KineticTileEntity extends SmartTileEntity
if (overStressed && AllConfigs.CLIENT.enableOverstressedTooltip.get()) { if (overStressed && AllConfigs.CLIENT.enableOverstressedTooltip.get()) {
tooltip.add(spacing + GOLD + Lang.translate("gui.stress_gauge.overstressed")); tooltip.add(spacing + GOLD + Lang.translate("gui.stress_gauge.overstressed"));
String hint = Lang.translate("gui.contraptions.network_overstressed", String hint = Lang
.translate("gui.contraptions.network_overstressed",
I18n.format(getBlockState().getBlock().getTranslationKey())); I18n.format(getBlockState().getBlock().getTranslationKey()));
List<String> cutString = TooltipHelper.cutString(spacing + hint, GRAY, TextFormatting.WHITE); List<String> cutString = TooltipHelper.cutString(spacing + hint, GRAY, TextFormatting.WHITE);
for (int i = 0; i < cutString.size(); i++) for (int i = 0; i < cutString.size(); i++)
@ -392,7 +400,8 @@ public abstract class KineticTileEntity extends SmartTileEntity
if (notFastEnough) { if (notFastEnough) {
tooltip.add(spacing + GOLD + Lang.translate("tooltip.speedRequirement")); tooltip.add(spacing + GOLD + Lang.translate("tooltip.speedRequirement"));
String hint = Lang.translate("gui.contraptions.not_fast_enough", String hint = Lang
.translate("gui.contraptions.not_fast_enough",
I18n.format(getBlockState().getBlock().getTranslationKey())); I18n.format(getBlockState().getBlock().getTranslationKey()));
List<String> cutString = TooltipHelper.cutString(spacing + hint, GRAY, TextFormatting.WHITE); List<String> cutString = TooltipHelper.cutString(spacing + hint, GRAY, TextFormatting.WHITE);
for (int i = 0; i < cutString.size(); i++) for (int i = 0; i < cutString.size(); i++)
@ -417,9 +426,13 @@ public abstract class KineticTileEntity extends SmartTileEntity
String stressString = String stressString =
spacing + "%s%s" + Lang.translate("generic.unit.stress") + " " + TextFormatting.DARK_GRAY + "%s"; spacing + "%s%s" + Lang.translate("generic.unit.stress") + " " + TextFormatting.DARK_GRAY + "%s";
tooltip.add(String.format(stressString, TextFormatting.AQUA, IHaveGoggleInformation.format(stressAtBase), tooltip
.add(String
.format(stressString, TextFormatting.AQUA, IHaveGoggleInformation.format(stressAtBase),
Lang.translate("gui.goggles.base_value"))); Lang.translate("gui.goggles.base_value")));
tooltip.add(String.format(stressString, TextFormatting.GRAY, IHaveGoggleInformation.format(stressTotal), tooltip
.add(String
.format(stressString, TextFormatting.GRAY, IHaveGoggleInformation.format(stressTotal),
Lang.translate("gui.goggles.at_current_speed"))); Lang.translate("gui.goggles.at_current_speed")));
added = true; added = true;

View file

@ -1,6 +1,7 @@
package com.simibubi.create.modules.contraptions.components.actors; package com.simibubi.create.modules.contraptions.components.actors;
import com.simibubi.create.foundation.utility.AllShapes; import com.simibubi.create.foundation.utility.AllShapes;
import com.simibubi.create.modules.contraptions.IWrenchable;
import com.simibubi.create.modules.contraptions.components.contraptions.IPortableBlock; import com.simibubi.create.modules.contraptions.components.contraptions.IPortableBlock;
import net.minecraft.block.Block; import net.minecraft.block.Block;
@ -8,7 +9,9 @@ import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks; import net.minecraft.block.Blocks;
import net.minecraft.block.HorizontalBlock; import net.minecraft.block.HorizontalBlock;
import net.minecraft.item.BlockItemUseContext; import net.minecraft.item.BlockItemUseContext;
import net.minecraft.item.ItemUseContext;
import net.minecraft.state.StateContainer.Builder; import net.minecraft.state.StateContainer.Builder;
import net.minecraft.util.ActionResultType;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.shapes.ISelectionContext; import net.minecraft.util.math.shapes.ISelectionContext;
@ -16,12 +19,17 @@ import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.world.IBlockReader; import net.minecraft.world.IBlockReader;
import net.minecraft.world.IWorldReader; import net.minecraft.world.IWorldReader;
public abstract class AttachedActorBlock extends HorizontalBlock implements IPortableBlock { public abstract class AttachedActorBlock extends HorizontalBlock implements IPortableBlock, IWrenchable {
public AttachedActorBlock() { public AttachedActorBlock() {
super(Properties.from(Blocks.IRON_BLOCK)); super(Properties.from(Blocks.IRON_BLOCK));
} }
@Override
public ActionResultType onWrenched(BlockState state, ItemUseContext context) {
return ActionResultType.FAIL;
}
@Override @Override
public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) { public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) {
Direction direction = state.get(HORIZONTAL_FACING); Direction direction = state.get(HORIZONTAL_FACING);

View file

@ -12,6 +12,7 @@ import com.simibubi.create.modules.contraptions.components.contraptions.Movement
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks; import net.minecraft.block.Blocks;
import net.minecraft.block.CocoaBlock;
import net.minecraft.block.CropsBlock; import net.minecraft.block.CropsBlock;
import net.minecraft.block.KelpBlock; import net.minecraft.block.KelpBlock;
import net.minecraft.block.SugarCaneBlock; import net.minecraft.block.SugarCaneBlock;
@ -81,7 +82,7 @@ public class HarvesterMovementBehaviour extends MovementBehaviour {
return false; return false;
return true; return true;
} }
if (state.getCollisionShape(world, pos).isEmpty()) { if (state.getCollisionShape(world, pos).isEmpty() || state.getBlock() instanceof CocoaBlock) {
for (IProperty<?> property : state.getProperties()) { for (IProperty<?> property : state.getProperties()) {
if (!(property instanceof IntegerProperty)) if (!(property instanceof IntegerProperty))
continue; continue;
@ -103,7 +104,7 @@ public class HarvesterMovementBehaviour extends MovementBehaviour {
if (state.getBlock() instanceof SugarCaneBlock) if (state.getBlock() instanceof SugarCaneBlock)
return true; return true;
if (state.getCollisionShape(world, pos).isEmpty()) { if (state.getCollisionShape(world, pos).isEmpty() || state.getBlock() instanceof CocoaBlock) {
for (IProperty<?> property : state.getProperties()) { for (IProperty<?> property : state.getProperties()) {
if (!(property instanceof IntegerProperty)) if (!(property instanceof IntegerProperty))
continue; continue;
@ -131,7 +132,7 @@ public class HarvesterMovementBehaviour extends MovementBehaviour {
return Blocks.AIR.getDefaultState(); return Blocks.AIR.getDefaultState();
return state.getFluidState().getBlockState(); return state.getFluidState().getBlockState();
} }
if (state.getCollisionShape(world, pos).isEmpty()) { if (state.getCollisionShape(world, pos).isEmpty() || state.getBlock() instanceof CocoaBlock) {
for (IProperty<?> property : state.getProperties()) { for (IProperty<?> property : state.getProperties()) {
if (!(property instanceof IntegerProperty)) if (!(property instanceof IntegerProperty))
continue; continue;

View file

@ -7,6 +7,7 @@ import com.simibubi.create.modules.contraptions.components.actors.PloughBlock.Pl
import com.simibubi.create.modules.contraptions.components.contraptions.MovementContext; import com.simibubi.create.modules.contraptions.components.contraptions.MovementContext;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.FlowingFluidBlock;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemUseContext; import net.minecraft.item.ItemUseContext;
import net.minecraft.item.Items; import net.minecraft.item.Items;
@ -25,8 +26,8 @@ public class PloughMovementBehaviour extends BlockBreakingMovementBehaviour {
@Override @Override
public boolean isActive(MovementContext context) { public boolean isActive(MovementContext context) {
return !VecHelper.isVecPointingTowards(context.relativeMotion, return !VecHelper
context.state.get(HORIZONTAL_FACING).getOpposite()); .isVecPointingTowards(context.relativeMotion, context.state.get(HORIZONTAL_FACING).getOpposite());
} }
@Override @Override
@ -66,7 +67,8 @@ public class PloughMovementBehaviour extends BlockBreakingMovementBehaviour {
@Override @Override
public boolean canBreak(World world, BlockPos breakingPos, BlockState state) { public boolean canBreak(World world, BlockPos breakingPos, BlockState state) {
return state.getCollisionShape(world, breakingPos).isEmpty(); return state.getCollisionShape(world, breakingPos).isEmpty()
&& !(state.getBlock() instanceof FlowingFluidBlock);
} }
@Override @Override

View file

@ -15,6 +15,9 @@ import com.simibubi.create.modules.contraptions.components.contraptions.pulley.P
import com.simibubi.create.modules.contraptions.components.contraptions.pulley.PulleyBlock.MagnetBlock; 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.PulleyBlock.RopeBlock;
import com.simibubi.create.modules.contraptions.components.contraptions.pulley.PulleyTileEntity; import com.simibubi.create.modules.contraptions.components.contraptions.pulley.PulleyTileEntity;
import com.simibubi.create.modules.contraptions.components.crank.HandCrankBlock;
import com.simibubi.create.modules.contraptions.components.fan.NozzleBlock;
import com.simibubi.create.modules.contraptions.components.flywheel.engine.EngineBlock;
import com.simibubi.create.modules.logistics.block.AttachedLogisticalBlock; import com.simibubi.create.modules.logistics.block.AttachedLogisticalBlock;
import com.simibubi.create.modules.logistics.block.RedstoneLinkBlock; import com.simibubi.create.modules.logistics.block.RedstoneLinkBlock;
import com.simibubi.create.modules.logistics.block.extractor.ExtractorBlock; import com.simibubi.create.modules.logistics.block.extractor.ExtractorBlock;
@ -26,6 +29,7 @@ import net.minecraft.block.AbstractRailBlock;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks; import net.minecraft.block.Blocks;
import net.minecraft.block.CarpetBlock;
import net.minecraft.block.DoorBlock; import net.minecraft.block.DoorBlock;
import net.minecraft.block.FenceGateBlock; import net.minecraft.block.FenceGateBlock;
import net.minecraft.block.FlowerPotBlock; import net.minecraft.block.FlowerPotBlock;
@ -105,6 +109,8 @@ public class BlockMovementTraits {
Block block = state.getBlock(); Block block = state.getBlock();
if (state.has(BlockStateProperties.HANGING)) if (state.has(BlockStateProperties.HANGING))
return true; return true;
if (block instanceof HandCrankBlock)
return true;
if (block instanceof LadderBlock) if (block instanceof LadderBlock)
return true; return true;
if (block instanceof ExtractorBlock) if (block instanceof ExtractorBlock)
@ -131,8 +137,14 @@ public class BlockMovementTraits {
return true; return true;
if (block instanceof RopeBlock) if (block instanceof RopeBlock)
return true; return true;
if (block instanceof NozzleBlock)
return true;
if (block instanceof MagnetBlock) if (block instanceof MagnetBlock)
return true; return true;
if (block instanceof EngineBlock)
return true;
if (block instanceof CarpetBlock)
return true;
return false; return false;
} }
@ -159,6 +171,8 @@ public class BlockMovementTraits {
return direction == Direction.DOWN; return direction == Direction.DOWN;
if (block instanceof RedstoneWireBlock) if (block instanceof RedstoneWireBlock)
return direction == Direction.DOWN; return direction == Direction.DOWN;
if (block instanceof CarpetBlock)
return direction == Direction.DOWN;
if (block instanceof RedstoneWallTorchBlock) if (block instanceof RedstoneWallTorchBlock)
return state.get(RedstoneWallTorchBlock.FACING) == direction.getOpposite(); return state.get(RedstoneWallTorchBlock.FACING) == direction.getOpposite();
if (block instanceof TorchBlock) if (block instanceof TorchBlock)
@ -178,6 +192,12 @@ public class BlockMovementTraits {
return direction == Direction.DOWN; return direction == Direction.DOWN;
if (block instanceof AttachedActorBlock) if (block instanceof AttachedActorBlock)
return direction == state.get(HarvesterBlock.HORIZONTAL_FACING).getOpposite(); return direction == state.get(HarvesterBlock.HORIZONTAL_FACING).getOpposite();
if (block instanceof HandCrankBlock)
return direction == state.get(HandCrankBlock.FACING).getOpposite();
if (block instanceof NozzleBlock)
return direction == state.get(NozzleBlock.FACING).getOpposite();
if (block instanceof EngineBlock)
return direction == state.get(EngineBlock.HORIZONTAL_FACING).getOpposite();
return false; return false;
} }
@ -196,6 +216,8 @@ public class BlockMovementTraits {
return state.get(BlockStateProperties.HORIZONTAL_FACING) == facing; return state.get(BlockStateProperties.HORIZONTAL_FACING) == facing;
if (AllBlocks.ROPE_PULLEY.typeOf(state)) if (AllBlocks.ROPE_PULLEY.typeOf(state))
return facing == Direction.DOWN; return facing == Direction.DOWN;
if (state.getBlock() instanceof CarpetBlock)
return facing == Direction.UP;
return isBrittle(state); return isBrittle(state);
} }

View file

@ -7,6 +7,7 @@ import com.simibubi.create.AllBlocks;
import com.simibubi.create.modules.contraptions.components.actors.BlockBreakingMovementBehaviour; import com.simibubi.create.modules.contraptions.components.actors.BlockBreakingMovementBehaviour;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.CocoaBlock;
import net.minecraft.block.material.PushReaction; import net.minecraft.block.material.PushReaction;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
@ -272,7 +273,8 @@ public class ContraptionCollider {
if (AllBlocks.PULLEY_MAGNET.typeOf(collidedState) && pos.equals(BlockPos.ZERO) if (AllBlocks.PULLEY_MAGNET.typeOf(collidedState) && pos.equals(BlockPos.ZERO)
&& movementDirection == Direction.UP) && movementDirection == Direction.UP)
continue; continue;
if (collidedState.getBlock() instanceof CocoaBlock)
continue;
if (!collidedState.getMaterial().isReplaceable() if (!collidedState.getMaterial().isReplaceable()
&& !collidedState.getCollisionShape(world, colliderPos).isEmpty()) { && !collidedState.getCollisionShape(world, colliderPos).isEmpty()) {
return true; return true;

View file

@ -593,6 +593,12 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
public void setMotion(Vec3d motionIn) { public void setMotion(Vec3d motionIn) {
} }
@Override
public void setPositionAndUpdate(double x, double y, double z) {
if (!stationary)
super.setPositionAndUpdate(x, y, z);
}
@Override @Override
public PushReaction getPushReaction() { public PushReaction getPushReaction() {
return PushReaction.IGNORE; return PushReaction.IGNORE;

View file

@ -9,6 +9,7 @@ import net.minecraft.nbt.CompoundNBT;
import net.minecraft.state.properties.ChestType; import net.minecraft.state.properties.ChestType;
import net.minecraft.tileentity.BarrelTileEntity; import net.minecraft.tileentity.BarrelTileEntity;
import net.minecraft.tileentity.ChestTileEntity; import net.minecraft.tileentity.ChestTileEntity;
import net.minecraft.tileentity.ShulkerBoxTileEntity;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
import net.minecraft.tileentity.TileEntityType; import net.minecraft.tileentity.TileEntityType;
import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.CapabilityItemHandler;
@ -107,6 +108,8 @@ public class MountedStorage {
TileEntityType<?> type = te.getType(); TileEntityType<?> type = te.getType();
if (type == AllTileEntities.FLEXCRATE.type) if (type == AllTileEntities.FLEXCRATE.type)
return true; return true;
if (te instanceof ShulkerBoxTileEntity)
return true;
if (te instanceof ChestTileEntity) if (te instanceof ChestTileEntity)
return true; return true;
if (te instanceof BarrelTileEntity) if (te instanceof BarrelTileEntity)

View file

@ -1,7 +1,9 @@
package com.simibubi.create.modules.contraptions.components.contraptions; package com.simibubi.create.modules.contraptions.components.contraptions;
import static net.minecraft.block.HorizontalFaceBlock.FACE;
import static net.minecraft.state.properties.BlockStateProperties.AXIS; import static net.minecraft.state.properties.BlockStateProperties.AXIS;
import static net.minecraft.state.properties.BlockStateProperties.FACING; import static net.minecraft.state.properties.BlockStateProperties.FACING;
import static net.minecraft.state.properties.BlockStateProperties.HORIZONTAL_FACING;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.foundation.utility.DirectionHelper; import com.simibubi.create.foundation.utility.DirectionHelper;
@ -11,10 +13,13 @@ import com.simibubi.create.modules.contraptions.components.contraptions.chassis.
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock; import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Slope; import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Slope;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.HorizontalFaceBlock;
import net.minecraft.block.SlabBlock; import net.minecraft.block.SlabBlock;
import net.minecraft.block.StairsBlock; import net.minecraft.block.StairsBlock;
import net.minecraft.state.BooleanProperty; import net.minecraft.state.BooleanProperty;
import net.minecraft.state.properties.AttachFace;
import net.minecraft.state.properties.Half; import net.minecraft.state.properties.Half;
import net.minecraft.state.properties.SlabType; import net.minecraft.state.properties.SlabType;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
@ -74,14 +79,45 @@ public class StructureTransform {
* horizontal axes * horizontal axes
*/ */
public BlockState apply(BlockState state) { public BlockState apply(BlockState state) {
if (rotationAxis == Axis.Y) if (rotationAxis == Axis.Y)
state = state.rotate(rotation); return state.rotate(rotation);
else {
if (state.getBlock() instanceof AbstractChassisBlock) Block block = state.getBlock();
if (block instanceof AbstractChassisBlock)
return rotateChassis(state); return rotateChassis(state);
if (state.getBlock() instanceof StairsBlock) { if (block instanceof HorizontalFaceBlock) {
Direction stateFacing = state.get(HorizontalFaceBlock.HORIZONTAL_FACING);
AttachFace stateFace = state.get(FACE);
Direction forcedAxis = rotationAxis == Axis.Z ? Direction.EAST : Direction.SOUTH;
if (stateFacing.getAxis() == rotationAxis && stateFace == AttachFace.WALL)
return state;
for (int i = 0; i < rotation.ordinal(); i++) {
stateFace = state.get(FACE);
stateFacing = state.get(HorizontalFaceBlock.HORIZONTAL_FACING);
boolean b = state.get(FACE) == AttachFace.CEILING;
state = state.with(HORIZONTAL_FACING, b ? forcedAxis : forcedAxis.getOpposite());
if (stateFace != AttachFace.WALL) {
state = state.with(FACE, AttachFace.WALL);
continue;
}
if (stateFacing.getAxisDirection() == AxisDirection.POSITIVE) {
state = state.with(FACE, AttachFace.FLOOR);
continue;
}
state = state.with(FACE, AttachFace.CEILING);
}
return state;
}
if (block instanceof StairsBlock) {
if (state.get(StairsBlock.FACING).getAxis() != rotationAxis) { if (state.get(StairsBlock.FACING).getAxis() != rotationAxis) {
for (int i = 0; i < rotation.ordinal(); i++) { for (int i = 0; i < rotation.ordinal(); i++) {
Direction direction = state.get(StairsBlock.FACING); Direction direction = state.get(StairsBlock.FACING);
@ -110,8 +146,7 @@ public class StructureTransform {
if (slope != Slope.HORIZONTAL && slope != Slope.VERTICAL) { if (slope != Slope.HORIZONTAL && slope != Slope.VERTICAL) {
if (direction.getAxisDirection() == AxisDirection.POSITIVE ^ slope == Slope.DOWNWARD if (direction.getAxisDirection() == AxisDirection.POSITIVE ^ slope == Slope.DOWNWARD
^ direction.getAxis() == Axis.Z) { ^ direction.getAxis() == Axis.Z) {
state = state = state.with(BeltBlock.SLOPE, slope == Slope.UPWARD ? Slope.DOWNWARD : Slope.UPWARD);
state.with(BeltBlock.SLOPE, slope == Slope.UPWARD ? Slope.DOWNWARD : Slope.UPWARD);
} else { } else {
state = state.with(BeltBlock.HORIZONTAL_FACING, direction.getOpposite()); state = state.with(BeltBlock.HORIZONTAL_FACING, direction.getOpposite());
} }
@ -121,8 +156,8 @@ public class StructureTransform {
if (slope == Slope.HORIZONTAL ^ direction.getAxis() == Axis.Z) { if (slope == Slope.HORIZONTAL ^ direction.getAxis() == Axis.Z) {
state = state.with(BeltBlock.HORIZONTAL_FACING, direction.getOpposite()); state = state.with(BeltBlock.HORIZONTAL_FACING, direction.getOpposite());
} }
state = state.with(BeltBlock.SLOPE, state =
slope == Slope.HORIZONTAL ? Slope.VERTICAL : Slope.HORIZONTAL); state.with(BeltBlock.SLOPE, slope == Slope.HORIZONTAL ? Slope.VERTICAL : Slope.HORIZONTAL);
} }
} }
} else { } else {
@ -130,7 +165,8 @@ public class StructureTransform {
Slope slope = state.get(BeltBlock.SLOPE); Slope slope = state.get(BeltBlock.SLOPE);
Direction direction = state.get(BeltBlock.HORIZONTAL_FACING); Direction direction = state.get(BeltBlock.HORIZONTAL_FACING);
if (slope == Slope.UPWARD || slope == Slope.DOWNWARD) { if (slope == Slope.UPWARD || slope == Slope.DOWNWARD) {
state = state.with(BeltBlock.SLOPE, slope == Slope.UPWARD ? Slope.DOWNWARD state = state
.with(BeltBlock.SLOPE, slope == Slope.UPWARD ? Slope.DOWNWARD
: slope == Slope.DOWNWARD ? Slope.UPWARD : slope); : slope == Slope.DOWNWARD ? Slope.UPWARD : slope);
} else if (slope == Slope.VERTICAL) { } else if (slope == Slope.VERTICAL) {
state = state.with(BeltBlock.HORIZONTAL_FACING, direction.getOpposite()); state = state.with(BeltBlock.HORIZONTAL_FACING, direction.getOpposite());
@ -152,12 +188,24 @@ public class StructureTransform {
state = state.with(AXIS, transformAxis(state.get(AXIS))); state = state.with(AXIS, transformAxis(state.get(AXIS)));
} else if (rotation == Rotation.CLOCKWISE_180) { } else if (rotation == Rotation.CLOCKWISE_180) {
state = state.rotate(rotation);
if (state.has(SlabBlock.TYPE) && state.get(SlabBlock.TYPE) != SlabType.DOUBLE) if (state.has(FACING)) {
state = state.with(SlabBlock.TYPE, Direction stateFacing = state.get(FACING);
state.get(SlabBlock.TYPE) == SlabType.BOTTOM ? SlabType.TOP : SlabType.BOTTOM); if (stateFacing.getAxis() == rotationAxis)
return state;
} }
if (state.has(HORIZONTAL_FACING)) {
Direction stateFacing = state.get(HORIZONTAL_FACING);
if (stateFacing.getAxis() == rotationAxis)
return state;
}
state = state.rotate(rotation);
if (state.has(SlabBlock.TYPE) && state.get(SlabBlock.TYPE) != SlabType.DOUBLE)
state = state
.with(SlabBlock.TYPE,
state.get(SlabBlock.TYPE) == SlabType.BOTTOM ? SlabType.TOP : SlabType.BOTTOM);
} }
return state; return state;

View file

@ -1,6 +1,7 @@
package com.simibubi.create.modules.contraptions.components.contraptions.bearing; package com.simibubi.create.modules.contraptions.components.contraptions.bearing;
import com.simibubi.create.foundation.block.ITE; import com.simibubi.create.foundation.block.ITE;
import com.simibubi.create.foundation.utility.WrappedWorld;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
@ -44,15 +45,18 @@ public class MechanicalBearingBlock extends BearingBlock implements ITE<Mechanic
@Override @Override
public void onBlockAdded(BlockState state, World worldIn, BlockPos pos, BlockState oldState, boolean isMoving) { public void onBlockAdded(BlockState state, World worldIn, BlockPos pos, BlockState oldState, boolean isMoving) {
if (worldIn instanceof WrappedWorld)
return;
withTileEntityDo(worldIn, pos, MechanicalBearingTileEntity::neighbourChanged); withTileEntityDo(worldIn, pos, MechanicalBearingTileEntity::neighbourChanged);
} }
@Override @Override
public void neighborChanged(BlockState state, World worldIn, BlockPos pos, Block blockIn, BlockPos fromPos, public void neighborChanged(BlockState state, World worldIn, BlockPos pos, Block blockIn, BlockPos fromPos,
boolean isMoving) { boolean isMoving) {
if (worldIn instanceof WrappedWorld)
return;
if (worldIn.isRemote) if (worldIn.isRemote)
return; return;
withTileEntityDo(worldIn, pos, MechanicalBearingTileEntity::neighbourChanged); withTileEntityDo(worldIn, pos, MechanicalBearingTileEntity::neighbourChanged);
} }

View file

@ -62,6 +62,9 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity imp
} }
public void neighbourChanged() { public void neighbourChanged() {
if (!hasWorld())
return;
boolean shouldWindmill = world.isBlockPowered(pos); boolean shouldWindmill = world.isBlockPowered(pos);
if (shouldWindmill == isWindmill) if (shouldWindmill == isWindmill)
return; return;

View file

@ -1,6 +1,8 @@
package com.simibubi.create.modules.contraptions.components.contraptions.chassis; package com.simibubi.create.modules.contraptions.components.contraptions.chassis;
import com.simibubi.create.AllItems;
import com.simibubi.create.AllSoundEvents; import com.simibubi.create.AllSoundEvents;
import com.simibubi.create.modules.contraptions.IWrenchable;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.RotatedPillarBlock; import net.minecraft.block.RotatedPillarBlock;
@ -22,7 +24,7 @@ import net.minecraft.world.IBlockReader;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraftforge.common.Tags; import net.minecraftforge.common.Tags;
public abstract class AbstractChassisBlock extends RotatedPillarBlock { public abstract class AbstractChassisBlock extends RotatedPillarBlock implements IWrenchable {
public AbstractChassisBlock(Properties properties) { public AbstractChassisBlock(Properties properties) {
super(properties); super(properties);
@ -45,7 +47,7 @@ public abstract class AbstractChassisBlock extends RotatedPillarBlock {
return ActionResultType.PASS; return ActionResultType.PASS;
ItemStack heldItem = player.getHeldItem(handIn); ItemStack heldItem = player.getHeldItem(handIn);
boolean isSlimeBall = heldItem.getItem().isIn(Tags.Items.SLIMEBALLS); boolean isSlimeBall = heldItem.getItem().isIn(Tags.Items.SLIMEBALLS) || AllItems.SUPER_GLUE.typeOf(heldItem);
BooleanProperty affectedSide = getGlueableSide(state, hit.getFace()); BooleanProperty affectedSide = getGlueableSide(state, hit.getFace());
if (affectedSide == null) if (affectedSide == null)

View file

@ -46,7 +46,8 @@ public class ChassisTileEntity extends SmartTileEntity {
te -> ((ChassisTileEntity) te).collectChassisGroup()); te -> ((ChassisTileEntity) te).collectChassisGroup());
range.requiresWrench(); range.requiresWrench();
range.between(1, max); range.between(1, max);
range.withClientCallback( range
.withClientCallback(
i -> DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> ChassisRangeDisplay.display(this))); i -> DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> ChassisRangeDisplay.display(this)));
range.value = max / 2; range.value = max / 2;
behaviours.add(range); behaviours.add(range);
@ -161,7 +162,7 @@ public class ChassisTileEntity extends SmartTileEntity {
BlockPos current = pos.offset(facing, i); BlockPos current = pos.offset(facing, i);
BlockState currentState = world.getBlockState(current); BlockState currentState = world.getBlockState(current);
if (forcedMovement != facing && !visualize && !sticky) if (forcedMovement != facing && !sticky)
break; break;
// Ignore replaceable Blocks and Air-like // Ignore replaceable Blocks and Air-like

View file

@ -9,6 +9,7 @@ import net.minecraft.network.PacketBuffer;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.fml.DistExecutor; import net.minecraftforge.fml.DistExecutor;
import net.minecraftforge.fml.network.NetworkEvent.Context; import net.minecraftforge.fml.network.NetworkEvent.Context;
@ -36,6 +37,7 @@ public class GlueEffectPacket extends SimplePacketBase {
buffer.writeBoolean(fullBlock); buffer.writeBoolean(fullBlock);
} }
@OnlyIn(Dist.CLIENT)
public void handle(Supplier<Context> context) { public void handle(Supplier<Context> context) {
context.get().enqueueWork(() -> DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> { context.get().enqueueWork(() -> DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> {
Minecraft mc = Minecraft.getInstance(); Minecraft mc = Minecraft.getInstance();

View file

@ -8,6 +8,9 @@ import com.simibubi.create.AllEntities;
import com.simibubi.create.AllItems; import com.simibubi.create.AllItems;
import com.simibubi.create.AllPackets; import com.simibubi.create.AllPackets;
import com.simibubi.create.AllSoundEvents; import com.simibubi.create.AllSoundEvents;
import com.simibubi.create.modules.schematics.ISpecialEntityItemRequirement;
import com.simibubi.create.modules.schematics.ItemRequirement;
import com.simibubi.create.modules.schematics.ItemRequirement.ItemUseType;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.player.ClientPlayerEntity; import net.minecraft.client.entity.player.ClientPlayerEntity;
@ -46,7 +49,7 @@ import net.minecraftforge.fml.common.registry.IEntityAdditionalSpawnData;
import net.minecraftforge.fml.network.NetworkHooks; import net.minecraftforge.fml.network.NetworkHooks;
import net.minecraftforge.fml.network.PacketDistributor; import net.minecraftforge.fml.network.PacketDistributor;
public class SuperGlueEntity extends Entity implements IEntityAdditionalSpawnData { public class SuperGlueEntity extends Entity implements IEntityAdditionalSpawnData, ISpecialEntityItemRequirement {
private int validationTimer; private int validationTimer;
protected BlockPos hangingPosition; protected BlockPos hangingPosition;
@ -105,31 +108,32 @@ public class SuperGlueEntity extends Entity implements IEntityAdditionalSpawnDat
protected void updateBoundingBox() { protected void updateBoundingBox() {
if (this.getFacingDirection() != null) { if (this.getFacingDirection() != null) {
double x = hangingPosition.getX() + 0.5 - facingDirection.getXOffset() * 0.5; double offset = 0.5 - 1 / 256d;
double y = hangingPosition.getY() + 0.5 - facingDirection.getYOffset() * 0.5; double x = hangingPosition.getX() + 0.5 - facingDirection.getXOffset() * offset;
double z = hangingPosition.getZ() + 0.5 - facingDirection.getZOffset() * 0.5; double y = hangingPosition.getY() + 0.5 - facingDirection.getYOffset() * offset;
double z = hangingPosition.getZ() + 0.5 - facingDirection.getZOffset() * offset;
this.setPos(x, y, z); this.setPos(x, y, z);
double d1 = (double) this.getWidthPixels(); double w = getWidthPixels();
double d2 = (double) this.getHeightPixels(); double h = getHeightPixels();
double d3 = (double) this.getWidthPixels(); double l = getWidthPixels();
Axis axis = this.getFacingDirection().getAxis(); Axis axis = this.getFacingDirection().getAxis();
double depth = 2 - 1 / 128f; double depth = 2 - 1 / 128f;
switch (axis) { switch (axis) {
case X: case X:
d1 = depth; w = depth;
break; break;
case Y: case Y:
d2 = depth; h = depth;
break; break;
case Z: case Z:
d3 = depth; l = depth;
} }
d1 = d1 / 32.0D; w = w / 32.0D;
d2 = d2 / 32.0D; h = h / 32.0D;
d3 = d3 / 32.0D; l = l / 32.0D;
this.setBoundingBox(new AxisAlignedBB(x - d1, y - d2, z - d3, x + d1, y + d2, z + d3)); this.setBoundingBox(new AxisAlignedBB(x - w, y - h, z - l, x + w, y + h, z + l));
} }
} }
@ -294,13 +298,13 @@ public class SuperGlueEntity extends Entity implements IEntityAdditionalSpawnDat
if (this.getFacingDirection().getAxis() != Direction.Axis.Y) { if (this.getFacingDirection().getAxis() != Direction.Axis.Y) {
switch (transformRotation) { switch (transformRotation) {
case CLOCKWISE_180: case CLOCKWISE_180:
this.facingDirection = this.getFacingDirection().getOpposite(); facingDirection = facingDirection.getOpposite();
break; break;
case COUNTERCLOCKWISE_90: case COUNTERCLOCKWISE_90:
this.facingDirection = this.getFacingDirection().rotateYCCW(); facingDirection = facingDirection.rotateYCCW();
break; break;
case CLOCKWISE_90: case CLOCKWISE_90:
this.facingDirection = this.getFacingDirection().rotateY(); facingDirection = facingDirection.rotateY();
default: default:
break; break;
} }
@ -366,4 +370,10 @@ public class SuperGlueEntity extends Entity implements IEntityAdditionalSpawnDat
public Direction getFacingDirection() { public Direction getFacingDirection() {
return facingDirection; return facingDirection;
} }
@Override
public ItemRequirement getRequiredItems() {
return new ItemRequirement(ItemUseType.DAMAGE, AllItems.SUPER_GLUE.get());
}
} }

View file

@ -4,6 +4,7 @@ import com.simibubi.create.AllBlocks;
import com.simibubi.create.foundation.block.ITE; import com.simibubi.create.foundation.block.ITE;
import com.simibubi.create.foundation.block.RenderUtilityBlock; import com.simibubi.create.foundation.block.RenderUtilityBlock;
import com.simibubi.create.foundation.utility.AllShapes; import com.simibubi.create.foundation.utility.AllShapes;
import com.simibubi.create.modules.contraptions.IWrenchable;
import com.simibubi.create.modules.contraptions.components.contraptions.ContraptionEntity; import com.simibubi.create.modules.contraptions.components.contraptions.ContraptionEntity;
import com.simibubi.create.modules.contraptions.components.contraptions.mounted.CartAssemblerTileEntity.CartMovementMode; import com.simibubi.create.modules.contraptions.components.contraptions.mounted.CartAssemblerTileEntity.CartMovementMode;
@ -32,7 +33,7 @@ import net.minecraft.util.math.shapes.VoxelShapes;
import net.minecraft.world.IBlockReader; import net.minecraft.world.IBlockReader;
import net.minecraft.world.World; import net.minecraft.world.World;
public class CartAssemblerBlock extends AbstractRailBlock implements ITE<CartAssemblerTileEntity> { public class CartAssemblerBlock extends AbstractRailBlock implements ITE<CartAssemblerTileEntity>, IWrenchable {
public static IProperty<RailShape> RAIL_SHAPE = public static IProperty<RailShape> RAIL_SHAPE =
EnumProperty.create("shape", RailShape.class, RailShape.EAST_WEST, RailShape.NORTH_SOUTH); EnumProperty.create("shape", RailShape.class, RailShape.EAST_WEST, RailShape.NORTH_SOUTH);

View file

@ -21,6 +21,7 @@ import com.simibubi.create.modules.contraptions.components.contraptions.glue.Sup
import com.simibubi.create.modules.contraptions.components.contraptions.piston.MechanicalPistonBlock.PistonState; import com.simibubi.create.modules.contraptions.components.contraptions.piston.MechanicalPistonBlock.PistonState;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.CarpetBlock;
import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.CompoundNBT;
import net.minecraft.nbt.ListNBT; import net.minecraft.nbt.ListNBT;
import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.state.properties.BlockStateProperties;
@ -152,7 +153,7 @@ public class PistonContraption extends Contraption {
if (!BlockMovementTraits.movementNecessary(world, currentPos)) if (!BlockMovementTraits.movementNecessary(world, currentPos))
return true; return true;
BlockState state = world.getBlockState(currentPos); BlockState state = world.getBlockState(currentPos);
if (BlockMovementTraits.isBrittle(state)) if (BlockMovementTraits.isBrittle(state) && !(state.getBlock() instanceof CarpetBlock))
return true; return true;
if (AllBlocks.MECHANICAL_PISTON_HEAD.typeOf(state) && state.get(FACING) == direction.getOpposite()) if (AllBlocks.MECHANICAL_PISTON_HEAD.typeOf(state) && state.get(FACING) == direction.getOpposite())
return true; return true;

View file

@ -3,6 +3,7 @@ package com.simibubi.create.modules.contraptions.components.contraptions.piston;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.foundation.block.ProperDirectionalBlock; import com.simibubi.create.foundation.block.ProperDirectionalBlock;
import com.simibubi.create.foundation.utility.AllShapes; import com.simibubi.create.foundation.utility.AllShapes;
import com.simibubi.create.modules.contraptions.IWrenchable;
import com.simibubi.create.modules.contraptions.components.contraptions.piston.MechanicalPistonBlock.PistonState; import com.simibubi.create.modules.contraptions.components.contraptions.piston.MechanicalPistonBlock.PistonState;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
@ -20,7 +21,7 @@ import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.world.IBlockReader; import net.minecraft.world.IBlockReader;
import net.minecraft.world.World; import net.minecraft.world.World;
public class PistonPoleBlock extends ProperDirectionalBlock { public class PistonPoleBlock extends ProperDirectionalBlock implements IWrenchable {
public PistonPoleBlock() { public PistonPoleBlock() {
super(Properties.from(Blocks.PISTON_HEAD)); super(Properties.from(Blocks.PISTON_HEAD));

View file

@ -217,10 +217,12 @@ public class MechanicalCrafterTileEntity extends KineticTileEntity {
}); });
groupedItems = new GroupedItems(result); groupedItems = new GroupedItems(result);
containers.forEach(stack -> { for (int i = 0; i < containers.size(); i++) {
GroupedItems container = new GroupedItems(stack); ItemStack stack = containers.get(i);
GroupedItems container = new GroupedItems();
container.grid.put(Pair.of(i, 0), stack);
container.mergeOnto(groupedItems, Pointing.LEFT); container.mergeOnto(groupedItems, Pointing.LEFT);
}); }
phase = Phase.CRAFTING; phase = Phase.CRAFTING;
countDown = 2000; countDown = 2000;

View file

@ -58,7 +58,8 @@ public class DeployerItemHandler implements IItemHandlerModifiable {
return stack; return stack;
int space = held.getMaxStackSize() - held.getCount(); int space = held.getMaxStackSize() - held.getCount();
ItemStack split = stack.copy().split(space); ItemStack remainder = stack.copy();
ItemStack split = remainder.split(space);
if (space == 0) if (space == 0)
return stack; return stack;
@ -68,7 +69,7 @@ public class DeployerItemHandler implements IItemHandlerModifiable {
set(held); set(held);
} }
return split; return remainder;
} }
@Override @Override

View file

@ -51,8 +51,11 @@ import net.minecraftforge.items.ItemHandlerHelper;
public class DeployerTileEntity extends KineticTileEntity { public class DeployerTileEntity extends KineticTileEntity {
private static final List<Pair<BlockPos, Direction>> EXTRACTING_LOCATIONS = Arrays.asList(Direction.values()) private static final List<Pair<BlockPos, Direction>> EXTRACTING_LOCATIONS = Arrays
.stream().map(d -> Pair.of(BlockPos.ZERO.offset(d), d.getOpposite())).collect(Collectors.toList()); .asList(Direction.values())
.stream()
.map(d -> Pair.of(BlockPos.ZERO.offset(d), d.getOpposite()))
.collect(Collectors.toList());
private FilteringBehaviour filtering; private FilteringBehaviour filtering;
private ExtractingBehaviour extracting; private ExtractingBehaviour extracting;
@ -373,7 +376,8 @@ public class DeployerTileEntity extends KineticTileEntity {
reach = tag.getFloat("Reach"); reach = tag.getFloat("Reach");
if (tag.contains("Particle")) { if (tag.contains("Particle")) {
ItemStack particleStack = ItemStack.read(tag.getCompound("Particle")); ItemStack particleStack = ItemStack.read(tag.getCompound("Particle"));
SandPaperItem.spawnParticles(VecHelper.getCenterOf(pos).add(getMovementVector().scale(2f)), particleStack, SandPaperItem
.spawnParticles(VecHelper.getCenterOf(pos).add(getMovementVector().scale(2f)), particleStack,
this.world); this.world);
} }
@ -402,6 +406,7 @@ public class DeployerTileEntity extends KineticTileEntity {
@Override @Override
public void remove() { public void remove() {
super.remove(); super.remove();
if (invHandler != null)
invHandler.invalidate(); invHandler.invalidate();
} }

View file

@ -1,6 +1,7 @@
package com.simibubi.create.modules.contraptions.components.fan; package com.simibubi.create.modules.contraptions.components.fan;
import com.simibubi.create.foundation.block.ITE; import com.simibubi.create.foundation.block.ITE;
import com.simibubi.create.foundation.utility.WrappedWorld;
import com.simibubi.create.modules.contraptions.base.DirectionalKineticBlock; import com.simibubi.create.modules.contraptions.base.DirectionalKineticBlock;
import net.minecraft.block.Block; import net.minecraft.block.Block;
@ -49,6 +50,8 @@ public class EncasedFanBlock extends DirectionalKineticBlock implements ITE<Enca
} }
protected void blockUpdate(BlockState state, World worldIn, BlockPos pos) { protected void blockUpdate(BlockState state, World worldIn, BlockPos pos) {
if (worldIn instanceof WrappedWorld)
return;
notifyFanTile(worldIn, pos); notifyFanTile(worldIn, pos);
if (worldIn.isRemote) if (worldIn.isRemote)
return; return;

View file

@ -3,11 +3,14 @@ package com.simibubi.create.modules.contraptions.components.fan;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.foundation.block.ProperDirectionalBlock; import com.simibubi.create.foundation.block.ProperDirectionalBlock;
import com.simibubi.create.foundation.utility.AllShapes; import com.simibubi.create.foundation.utility.AllShapes;
import com.simibubi.create.modules.contraptions.IWrenchable;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.item.BlockItemUseContext; import net.minecraft.item.BlockItemUseContext;
import net.minecraft.item.ItemUseContext;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.ActionResultType;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.shapes.ISelectionContext; import net.minecraft.util.math.shapes.ISelectionContext;
@ -16,7 +19,7 @@ import net.minecraft.world.IBlockReader;
import net.minecraft.world.IWorldReader; import net.minecraft.world.IWorldReader;
import net.minecraft.world.World; import net.minecraft.world.World;
public class NozzleBlock extends ProperDirectionalBlock { public class NozzleBlock extends ProperDirectionalBlock implements IWrenchable {
public NozzleBlock() { public NozzleBlock() {
super(Properties.from(AllBlocks.ENCASED_FAN.get())); super(Properties.from(AllBlocks.ENCASED_FAN.get()));
@ -27,6 +30,11 @@ public class NozzleBlock extends ProperDirectionalBlock {
return true; return true;
} }
@Override
public ActionResultType onWrenched(BlockState state, ItemUseContext context) {
return ActionResultType.FAIL;
}
@Override @Override
public TileEntity createTileEntity(BlockState state, IBlockReader world) { public TileEntity createTileEntity(BlockState state, IBlockReader world) {
return new NozzleTileEntity(); return new NozzleTileEntity();

View file

@ -3,14 +3,16 @@ package com.simibubi.create.modules.contraptions.components.flywheel.engine;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import com.simibubi.create.AllBlockPartials; import com.simibubi.create.AllBlockPartials;
import com.simibubi.create.modules.contraptions.IWrenchable;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.HorizontalBlock; import net.minecraft.block.HorizontalBlock;
import net.minecraft.block.material.PushReaction;
import net.minecraft.item.BlockItemUseContext; import net.minecraft.item.BlockItemUseContext;
import net.minecraft.item.ItemUseContext;
import net.minecraft.state.StateContainer.Builder; import net.minecraft.state.StateContainer.Builder;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.ActionResultType;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IBlockReader; import net.minecraft.world.IBlockReader;
@ -19,7 +21,7 @@ import net.minecraft.world.World;
import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.api.distmarker.OnlyIn;
public abstract class EngineBlock extends HorizontalBlock { public abstract class EngineBlock extends HorizontalBlock implements IWrenchable {
protected EngineBlock(Properties builder) { protected EngineBlock(Properties builder) {
super(builder); super(builder);
@ -36,8 +38,8 @@ public abstract class EngineBlock extends HorizontalBlock {
} }
@Override @Override
public PushReaction getPushReaction(BlockState state) { public ActionResultType onWrenched(BlockState state, ItemUseContext context) {
return PushReaction.BLOCK; return ActionResultType.FAIL;
} }
@Override @Override

View file

@ -4,6 +4,7 @@ import com.simibubi.create.AllBlockPartials;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.foundation.block.ITE; import com.simibubi.create.foundation.block.ITE;
import com.simibubi.create.foundation.utility.AllShapes; import com.simibubi.create.foundation.utility.AllShapes;
import com.simibubi.create.foundation.utility.WrappedWorld;
import net.minecraft.block.AbstractFurnaceBlock; import net.minecraft.block.AbstractFurnaceBlock;
import net.minecraft.block.Block; import net.minecraft.block.Block;
@ -53,6 +54,8 @@ public class FurnaceEngineBlock extends EngineBlock implements ITE<FurnaceEngine
public void neighborChanged(BlockState state, World worldIn, BlockPos pos, Block blockIn, BlockPos fromPos, public void neighborChanged(BlockState state, World worldIn, BlockPos pos, Block blockIn, BlockPos fromPos,
boolean isMoving) { boolean isMoving) {
super.neighborChanged(state, worldIn, pos, blockIn, fromPos, isMoving); super.neighborChanged(state, worldIn, pos, blockIn, fromPos, isMoving);
if (worldIn instanceof WrappedWorld)
return;
if (worldIn.isRemote) if (worldIn.isRemote)
return; return;

View file

@ -7,6 +7,7 @@ import java.util.Optional;
import com.simibubi.create.AllRecipes; import com.simibubi.create.AllRecipes;
import com.simibubi.create.AllSoundEvents; import com.simibubi.create.AllSoundEvents;
import com.simibubi.create.AllTileEntities; import com.simibubi.create.AllTileEntities;
import com.simibubi.create.foundation.advancement.AllTriggers;
import com.simibubi.create.foundation.item.ItemHelper; import com.simibubi.create.foundation.item.ItemHelper;
import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.modules.contraptions.processing.BasinOperatingTileEntity; import com.simibubi.create.modules.contraptions.processing.BasinOperatingTileEntity;
@ -163,8 +164,10 @@ public class MechanicalPressTileEntity extends BasinOperatingTileEntity {
pressedItems.add(itemEntity.getItem()); pressedItems.add(itemEntity.getItem());
sendData(); sendData();
Optional<PressingRecipe> recipe = getRecipe(itemEntity.getItem()); Optional<PressingRecipe> recipe = getRecipe(itemEntity.getItem());
if (recipe.isPresent()) if (recipe.isPresent()) {
InWorldProcessing.applyRecipeOn(itemEntity, recipe.get()); InWorldProcessing.applyRecipeOn(itemEntity, recipe.get());
AllTriggers.triggerForNearbyPlayers(AllTriggers.BONK, world, pos, 4);
}
} }
} }
} }

View file

@ -2,11 +2,14 @@ package com.simibubi.create.modules.contraptions.components.waterwheel;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.config.AllConfigs; import com.simibubi.create.config.AllConfigs;
import com.simibubi.create.foundation.advancement.AllTriggers;
import com.simibubi.create.foundation.block.ITE; import com.simibubi.create.foundation.block.ITE;
import com.simibubi.create.foundation.utility.WrappedWorld;
import com.simibubi.create.modules.contraptions.base.HorizontalKineticBlock; import com.simibubi.create.modules.contraptions.base.HorizontalKineticBlock;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks; import net.minecraft.block.Blocks;
import net.minecraft.fluid.Fluids;
import net.minecraft.fluid.IFluidState; import net.minecraft.fluid.IFluidState;
import net.minecraft.item.BlockItemUseContext; import net.minecraft.item.BlockItemUseContext;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
@ -60,7 +63,7 @@ public class WaterWheelBlock extends HorizontalKineticBlock implements ITE<Water
public BlockState updatePostPlacement(BlockState stateIn, Direction facing, BlockState facingState, IWorld worldIn, public BlockState updatePostPlacement(BlockState stateIn, Direction facing, BlockState facingState, IWorld worldIn,
BlockPos currentPos, BlockPos facingPos) { BlockPos currentPos, BlockPos facingPos) {
World world = worldIn.getWorld(); World world = worldIn.getWorld();
if (world == null) if (world == null || worldIn instanceof WrappedWorld)
return stateIn; return stateIn;
updateFlowAt(stateIn, world, currentPos, facing); updateFlowAt(stateIn, world, currentPos, facing);
updateWheelSpeed(worldIn, currentPos); updateWheelSpeed(worldIn, currentPos);
@ -109,6 +112,12 @@ public class WaterWheelBlock extends HorizontalKineticBlock implements ITE<Water
flowStrength = flow.y > 0 ^ !clockwise ? -flow.y * clockwiseMultiplier : -flow.y; flowStrength = flow.y > 0 ^ !clockwise ? -flow.y * clockwiseMultiplier : -flow.y;
} }
if (te.getSpeed() == 0 && flowStrength != 0 && !world.isRemote) {
AllTriggers.triggerForNearbyPlayers(AllTriggers.WATER_WHEEL, world, pos, 5);
if (fluid.getFluid() == Fluids.FLOWING_LAVA || fluid.getFluid() == Fluids.LAVA)
AllTriggers.triggerForNearbyPlayers(AllTriggers.LAVA_WHEEL, world, pos, 5);
}
te.setFlow(f, (float) (flowStrength * AllConfigs.SERVER.kinetics.waterWheelSpeed.get() / 2f)); te.setFlow(f, (float) (flowStrength * AllConfigs.SERVER.kinetics.waterWheelSpeed.get() / 2f));
}); });
} }
@ -126,7 +135,6 @@ public class WaterWheelBlock extends HorizontalKineticBlock implements ITE<Water
if (facing.getAxis().isHorizontal()) if (facing.getAxis().isHorizontal())
return getDefaultState().with(HORIZONTAL_FACING, return getDefaultState().with(HORIZONTAL_FACING,
context.getPlayer().isSneaking() ? facing.getOpposite() : facing); context.getPlayer().isSneaking() ? facing.getOpposite() : facing);
return super.getStateForPlacement(context); return super.getStateForPlacement(context);
} }

View file

@ -1,18 +1,20 @@
package com.simibubi.create.modules.contraptions.processing; package com.simibubi.create.modules.contraptions.processing;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.foundation.advancement.AllTriggers;
import com.simibubi.create.foundation.block.ITE; import com.simibubi.create.foundation.block.ITE;
import com.simibubi.create.foundation.item.ItemHelper; import com.simibubi.create.foundation.item.ItemHelper;
import com.simibubi.create.foundation.utility.AllShapes; import com.simibubi.create.foundation.utility.AllShapes;
import com.simibubi.create.modules.contraptions.IWrenchable;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks; import net.minecraft.block.Blocks;
import net.minecraft.block.material.PushReaction;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.item.ItemEntity; import net.minecraft.entity.item.ItemEntity;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemUseContext;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.ActionResultType; import net.minecraft.util.ActionResultType;
import net.minecraft.util.Hand; import net.minecraft.util.Hand;
@ -26,7 +28,7 @@ import net.minecraftforge.items.IItemHandlerModifiable;
import net.minecraftforge.items.ItemHandlerHelper; import net.minecraftforge.items.ItemHandlerHelper;
import net.minecraftforge.items.ItemStackHandler; import net.minecraftforge.items.ItemStackHandler;
public class BasinBlock extends Block implements ITE<BasinTileEntity> { public class BasinBlock extends Block implements ITE<BasinTileEntity>, IWrenchable {
public BasinBlock() { public BasinBlock() {
super(Properties.from(Blocks.ANDESITE)); super(Properties.from(Blocks.ANDESITE));
@ -43,8 +45,8 @@ public class BasinBlock extends Block implements ITE<BasinTileEntity> {
} }
@Override @Override
public PushReaction getPushReaction(BlockState state) { public ActionResultType onWrenched(BlockState state, ItemUseContext context) {
return PushReaction.BLOCK; return ActionResultType.FAIL;
} }
@Override @Override
@ -81,6 +83,11 @@ public class BasinBlock extends Block implements ITE<BasinTileEntity> {
if (insertItem.isEmpty()) { if (insertItem.isEmpty()) {
itemEntity.remove(); itemEntity.remove();
if (!itemEntity.world.isRemote)
AllTriggers
.triggerForNearbyPlayers(AllTriggers.BASIN_THROW, itemEntity.world,
itemEntity.getPosition(), 3);
return; return;
} }

View file

@ -5,6 +5,9 @@ import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import com.simibubi.create.AllTileEntities;
import com.simibubi.create.foundation.advancement.AllTriggers;
import com.simibubi.create.foundation.advancement.SimpleTrigger;
import com.simibubi.create.foundation.behaviour.base.TileEntityBehaviour; import com.simibubi.create.foundation.behaviour.base.TileEntityBehaviour;
import com.simibubi.create.foundation.behaviour.simple.DeferralBehaviour; import com.simibubi.create.foundation.behaviour.simple.DeferralBehaviour;
import com.simibubi.create.foundation.utility.recipe.RecipeFinder; import com.simibubi.create.foundation.utility.recipe.RecipeFinder;
@ -150,6 +153,13 @@ public abstract class BasinOperatingTileEntity extends KineticTileEntity {
return; return;
} }
if (!world.isRemote) {
SimpleTrigger trigger = AllTriggers.MIXER_MIX;
if (getType() == AllTileEntities.MECHANICAL_PRESS.type)
trigger = AllTriggers.PRESS_COMPACT;
AllTriggers.triggerForNearbyPlayers(trigger, world, pos, 4);
}
ItemHandlerHelper.insertItemStacked(outputs, lastRecipe.getRecipeOutput().copy(), false); ItemHandlerHelper.insertItemStacked(outputs, lastRecipe.getRecipeOutput().copy(), false);
containers.forEach(stack -> ItemHandlerHelper.insertItemStacked(outputs, stack, false)); containers.forEach(stack -> ItemHandlerHelper.insertItemStacked(outputs, stack, false));
catalysts.forEach(c -> ItemHandlerHelper.insertItemStacked(outputs, c, false)); catalysts.forEach(c -> ItemHandlerHelper.insertItemStacked(outputs, c, false));

View file

@ -28,8 +28,14 @@ public class ProcessingRecipeSerializer<T extends ProcessingRecipe<?>>
List<ProcessingIngredient> ingredients = new ArrayList<>(); List<ProcessingIngredient> ingredients = new ArrayList<>();
for (JsonElement e : JSONUtils.getJsonArray(json, "ingredients")) { for (JsonElement e : JSONUtils.getJsonArray(json, "ingredients")) {
int count = 1;
if (JSONUtils.hasField((JsonObject) e, "count")) {
count = JSONUtils.getInt(e.getAsJsonObject().get("count"), "count");
}
for(int i = 0; i < count; i++) {
ingredients.add(ProcessingIngredient.parse(e.getAsJsonObject())); ingredients.add(ProcessingIngredient.parse(e.getAsJsonObject()));
} }
}
List<ProcessingOutput> results = new ArrayList<>(); List<ProcessingOutput> results = new ArrayList<>();
for (JsonElement e : JSONUtils.getJsonArray(json, "results")) { for (JsonElement e : JSONUtils.getJsonArray(json, "results")) {

View file

@ -4,6 +4,7 @@ import java.util.Random;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.foundation.block.ProperDirectionalBlock; import com.simibubi.create.foundation.block.ProperDirectionalBlock;
import com.simibubi.create.modules.contraptions.IWrenchable;
import com.simibubi.create.modules.contraptions.components.contraptions.IPortableBlock; import com.simibubi.create.modules.contraptions.components.contraptions.IPortableBlock;
import com.simibubi.create.modules.contraptions.components.contraptions.MovementBehaviour; import com.simibubi.create.modules.contraptions.components.contraptions.MovementBehaviour;
@ -21,7 +22,7 @@ import net.minecraft.world.IWorld;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraft.world.server.ServerWorld; import net.minecraft.world.server.ServerWorld;
public class ContactBlock extends ProperDirectionalBlock implements IPortableBlock { public class ContactBlock extends ProperDirectionalBlock implements IPortableBlock, IWrenchable {
public static final BooleanProperty POWERED = BlockStateProperties.POWERED; public static final BooleanProperty POWERED = BlockStateProperties.POWERED;
public static MovementBehaviour MOVEMENT = new ContactMovementBehaviour(); public static MovementBehaviour MOVEMENT = new ContactMovementBehaviour();

View file

@ -59,10 +59,25 @@ public class SpeedControllerTileEntity extends KineticTileEntity {
boolean targetingController) { boolean targetingController) {
if (!(speedControllerIn instanceof SpeedControllerTileEntity)) if (!(speedControllerIn instanceof SpeedControllerTileEntity))
return 0; return 0;
SpeedControllerTileEntity speedController = (SpeedControllerTileEntity) speedControllerIn;
float speed = speedControllerIn.getTheoreticalSpeed();
float wheelSpeed = cogWheel.getTheoreticalSpeed();
float desiredOutputSpeed = getDesiredOutputSpeed(cogWheel, speedControllerIn, targetingController);
float compareSpeed = targetingController ? speed : wheelSpeed;
if (desiredOutputSpeed >= 0 && compareSpeed >= 0)
return Math.max(desiredOutputSpeed, compareSpeed);
if (desiredOutputSpeed < 0 && compareSpeed < 0)
return Math.min(desiredOutputSpeed, compareSpeed);
return desiredOutputSpeed;
}
public static float getDesiredOutputSpeed(KineticTileEntity cogWheel, KineticTileEntity speedControllerIn,
boolean targetingController) {
SpeedControllerTileEntity speedController = (SpeedControllerTileEntity) speedControllerIn;
float targetSpeed = speedController.targetSpeed.getValue(); float targetSpeed = speedController.targetSpeed.getValue();
float speed = speedControllerIn.getSpeed(); float speed = speedControllerIn.getTheoreticalSpeed();
float wheelSpeed = cogWheel.getTheoreticalSpeed(); float wheelSpeed = cogWheel.getTheoreticalSpeed();
if (targetSpeed == 0) if (targetSpeed == 0)

View file

@ -1,5 +1,6 @@
package com.simibubi.create.modules.contraptions.relays.belt; package com.simibubi.create.modules.contraptions.relays.belt;
import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
@ -16,6 +17,9 @@ import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.modules.contraptions.base.HorizontalKineticBlock; import com.simibubi.create.modules.contraptions.base.HorizontalKineticBlock;
import com.simibubi.create.modules.contraptions.relays.belt.transport.BeltMovementHandler.TransportedEntityInfo; import com.simibubi.create.modules.contraptions.relays.belt.transport.BeltMovementHandler.TransportedEntityInfo;
import com.simibubi.create.modules.logistics.block.belts.tunnel.BeltTunnelBlock; import com.simibubi.create.modules.logistics.block.belts.tunnel.BeltTunnelBlock;
import com.simibubi.create.modules.schematics.ISpecialBlockItemRequirement;
import com.simibubi.create.modules.schematics.ItemRequirement;
import com.simibubi.create.modules.schematics.ItemRequirement.ItemUseType;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockRenderType; import net.minecraft.block.BlockRenderType;
@ -45,12 +49,14 @@ import net.minecraft.util.Direction.Axis;
import net.minecraft.util.Direction.AxisDirection; import net.minecraft.util.Direction.AxisDirection;
import net.minecraft.util.Hand; import net.minecraft.util.Hand;
import net.minecraft.util.IStringSerializable; import net.minecraft.util.IStringSerializable;
import net.minecraft.util.Rotation;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult; import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.RayTraceResult; import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.shapes.ISelectionContext; import net.minecraft.util.math.shapes.ISelectionContext;
import net.minecraft.util.math.shapes.VoxelShape; import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.util.math.shapes.VoxelShapes;
import net.minecraft.world.IBlockReader; import net.minecraft.world.IBlockReader;
import net.minecraft.world.IWorldReader; import net.minecraft.world.IWorldReader;
import net.minecraft.world.World; import net.minecraft.world.World;
@ -62,7 +68,7 @@ import net.minecraftforge.common.Tags;
import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.IItemHandler;
public class BeltBlock extends HorizontalKineticBlock implements ITE<BeltTileEntity>, IHaveColorHandler { public class BeltBlock extends HorizontalKineticBlock implements ITE<BeltTileEntity>, IHaveColorHandler, ISpecialBlockItemRequirement {
public static final IProperty<Slope> SLOPE = EnumProperty.create("slope", Slope.class); public static final IProperty<Slope> SLOPE = EnumProperty.create("slope", Slope.class);
public static final IProperty<Part> PART = EnumProperty.create("part", Part.class); public static final IProperty<Part> PART = EnumProperty.create("part", Part.class);
@ -338,7 +344,8 @@ public class BeltBlock extends HorizontalKineticBlock implements ITE<BeltTileEnt
double d7 = d4 * d1 + x1; double d7 = d4 * d1 + x1;
double d8 = d5 * d2 + y1; double d8 = d5 * d2 + y1;
double d9 = d6 * d3 + z1; double d9 = d6 * d3 + z1;
manager.addEffect( manager
.addEffect(
(new DiggingParticle(world, (double) pos.getX() + d7, (double) pos.getY() + d8, (new DiggingParticle(world, (double) pos.getX() + d7, (double) pos.getY() + d8,
(double) pos.getZ() + d9, d4 - 0.5D, d5 - 0.5D, d6 - 0.5D, state)) (double) pos.getZ() + d9, d4 - 0.5D, d5 - 0.5D, d6 - 0.5D, state))
.setBlockPos(pos)); .setBlockPos(pos));
@ -358,6 +365,9 @@ public class BeltBlock extends HorizontalKineticBlock implements ITE<BeltTileEnt
@Override @Override
public VoxelShape getCollisionShape(BlockState state, IBlockReader worldIn, BlockPos pos, public VoxelShape getCollisionShape(BlockState state, IBlockReader worldIn, BlockPos pos,
ISelectionContext context) { ISelectionContext context) {
if (state.getBlock() != this)
return VoxelShapes.empty();
VoxelShape shape = getShape(state, worldIn, pos, context); VoxelShape shape = getShape(state, worldIn, pos, context);
try { try {
if (context.getEntity() == null) if (context.getEntity() == null)
@ -427,7 +437,9 @@ public class BeltBlock extends HorizontalKineticBlock implements ITE<BeltTileEnt
for (BlockPos beltPos : beltChain) { for (BlockPos beltPos : beltChain) {
TileEntity tileEntity = world.getTileEntity(beltPos); TileEntity tileEntity = world.getTileEntity(beltPos);
if (tileEntity instanceof BeltTileEntity) { BlockState currentState = world.getBlockState(beltPos);
if (tileEntity instanceof BeltTileEntity && AllBlocks.BELT.typeOf(currentState)) {
BeltTileEntity te = (BeltTileEntity) tileEntity; BeltTileEntity te = (BeltTileEntity) tileEntity;
te.setController(currentPos); te.setController(currentPos);
te.beltLength = beltChain.size(); te.beltLength = beltChain.size();
@ -436,7 +448,6 @@ public class BeltBlock extends HorizontalKineticBlock implements ITE<BeltTileEnt
te.markDirty(); te.markDirty();
te.sendData(); te.sendData();
BlockState currentState = world.getBlockState(beltPos);
boolean isVertical = currentState.get(BeltBlock.SLOPE) == Slope.VERTICAL; boolean isVertical = currentState.get(BeltBlock.SLOPE) == Slope.VERTICAL;
if (currentState.get(CASING) && isVertical) { if (currentState.get(CASING) && isVertical) {
@ -537,10 +548,10 @@ public class BeltBlock extends HorizontalKineticBlock implements ITE<BeltTileEnt
int limit = 1000; int limit = 1000;
BlockPos current = controllerPos; BlockPos current = controllerPos;
while (limit-- > 0 && current != null) { while (limit-- > 0 && current != null) {
positions.add(current);
BlockState state = world.getBlockState(current); BlockState state = world.getBlockState(current);
if (!AllBlocks.BELT.typeOf(state)) if (!AllBlocks.BELT.typeOf(state))
break; break;
positions.add(current);
current = nextSegmentPosition(state, current, true); current = nextSegmentPosition(state, current, true);
} }
@ -605,4 +616,34 @@ public class BeltBlock extends HorizontalKineticBlock implements ITE<BeltTileEnt
return BeltTileEntity.class; return BeltTileEntity.class;
} }
@Override
public ItemRequirement getRequiredItems(BlockState state) {
List<ItemStack> required = new ArrayList<>();
if (state.get(PART) != Part.MIDDLE)
required.add(new ItemStack(AllBlocksNew.SHAFT.get()));
if (state.get(CASING))
required.add(new ItemStack(AllBlocks.BRASS_CASING.get()));
if (state.get(PART) == Part.START)
required.add(AllItems.BELT_CONNECTOR.asStack());
if (required.isEmpty())
return ItemRequirement.NONE;
return new ItemRequirement(ItemUseType.CONSUME, required);
}
@Override
public BlockState rotate(BlockState state, Rotation rot) {
BlockState rotate = super.rotate(state, rot);
if (state.get(SLOPE) != Slope.VERTICAL)
return rotate;
if (state.get(HORIZONTAL_FACING).getAxisDirection() != rotate.get(HORIZONTAL_FACING).getAxisDirection()) {
if (state.get(PART) == Part.START)
return rotate.with(PART, Part.END);
if (state.get(PART) == Part.END)
return rotate.with(PART, Part.START);
}
return rotate;
}
} }

View file

@ -73,6 +73,8 @@ public class BeltTileEntity extends KineticTileEntity {
// Init belt // Init belt
if (beltLength == 0) if (beltLength == 0)
BeltBlock.initBelt(world, pos); BeltBlock.initBelt(world, pos);
if (!AllBlocks.BELT.typeOf(world.getBlockState(pos)))
return;
// Initialize Belt Attachments // Initialize Belt Attachments
if (world != null && trackerUpdateTag != null) { if (world != null && trackerUpdateTag != null) {
@ -131,7 +133,10 @@ public class BeltTileEntity extends KineticTileEntity {
TileEntity te = world.getTileEntity(controller); TileEntity te = world.getTileEntity(controller);
if (te == null || !(te instanceof BeltTileEntity)) if (te == null || !(te instanceof BeltTileEntity))
return; return;
IItemHandler handler = ((BeltTileEntity) te).getInventory().createHandlerForSegment(index); BeltInventory inventory = ((BeltTileEntity) te).getInventory();
if (inventory == null)
return;
IItemHandler handler = inventory.createHandlerForSegment(index);
itemHandler = LazyOptional.of(() -> handler); itemHandler = LazyOptional.of(() -> handler);
} }
@ -306,8 +311,8 @@ public class BeltTileEntity extends KineticTileEntity {
public Direction getMovementFacing() { public Direction getMovementFacing() {
Axis axis = getBeltFacing().getAxis(); Axis axis = getBeltFacing().getAxis();
return Direction.getFacingFromAxisDirection(axis, return Direction
getBeltMovementSpeed() < 0 ^ axis == Axis.X ? NEGATIVE : POSITIVE); .getFacingFromAxisDirection(axis, getBeltMovementSpeed() < 0 ^ axis == Axis.X ? NEGATIVE : POSITIVE);
} }
protected Direction getBeltFacing() { protected Direction getBeltFacing() {
@ -344,7 +349,7 @@ public class BeltTileEntity extends KineticTileEntity {
if (simulate) if (simulate)
return true; return true;
transportedStack.beltPosition = index + .5f - Math.signum(getSpeed()) / 16f; transportedStack.beltPosition = index + .5f - Math.signum(getDirectionAwareBeltMovementSpeed()) / 16f;
Direction movementFacing = getMovementFacing(); Direction movementFacing = getMovementFacing();
if (!side.getAxis().isVertical()) { if (!side.getAxis().isVertical()) {

View file

@ -5,6 +5,7 @@ import java.util.List;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.config.AllConfigs; import com.simibubi.create.config.AllConfigs;
import com.simibubi.create.foundation.advancement.AllTriggers;
import com.simibubi.create.foundation.item.IAddedByOther; import com.simibubi.create.foundation.item.IAddedByOther;
import com.simibubi.create.modules.contraptions.base.KineticTileEntity; import com.simibubi.create.modules.contraptions.base.KineticTileEntity;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock; import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock;
@ -71,9 +72,9 @@ public class BeltConnectorItem extends BlockItem implements IAddedByOther {
if (!canConnect(world, firstPulley, pos)) if (!canConnect(world, firstPulley, pos))
return ActionResultType.FAIL; return ActionResultType.FAIL;
if (firstPulley != null && !firstPulley.equals(pos)) { if (firstPulley != null && !firstPulley.equals(pos) && !world.isRemote) {
createBelts(world, firstPulley, pos); createBelts(world, firstPulley, pos);
AllTriggers.triggerFor(AllTriggers.CONNECT_BELT, context.getPlayer());
if (!context.getPlayer().isCreative()) if (!context.getPlayer().isCreative())
context.getItem().shrink(1); context.getItem().shrink(1);
} }
@ -91,14 +92,15 @@ public class BeltConnectorItem extends BlockItem implements IAddedByOther {
return ActionResultType.SUCCESS; return ActionResultType.SUCCESS;
} }
private void createBelts(World world, BlockPos start, BlockPos end) { public static void createBelts(World world, BlockPos start, BlockPos end) {
BeltBlock.Slope slope = getSlopeBetween(start, end); BeltBlock.Slope slope = getSlopeBetween(start, end);
Direction facing = getFacingFromTo(start, end); Direction facing = getFacingFromTo(start, end);
BlockPos diff = end.subtract(start); BlockPos diff = end.subtract(start);
if (diff.getX() == diff.getZ()) if (diff.getX() == diff.getZ())
facing = Direction.getFacingFromAxis(facing.getAxisDirection(), facing = Direction
.getFacingFromAxis(facing.getAxisDirection(),
world.getBlockState(start).get(BlockStateProperties.AXIS) == Axis.X ? Axis.Z : Axis.X); world.getBlockState(start).get(BlockStateProperties.AXIS) == Axis.X ? Axis.Z : Axis.X);
List<BlockPos> beltsToCreate = getBeltChainBetween(start, end, slope, facing); List<BlockPos> beltsToCreate = getBeltChainBetween(start, end, slope, facing);
@ -109,12 +111,17 @@ public class BeltConnectorItem extends BlockItem implements IAddedByOther {
boolean pulley = ShaftBlock.isShaft(world.getBlockState(pos)); boolean pulley = ShaftBlock.isShaft(world.getBlockState(pos));
if (part == Part.MIDDLE && pulley) if (part == Part.MIDDLE && pulley)
part = Part.PULLEY; part = Part.PULLEY;
world.setBlockState(pos, beltBlock.with(BeltBlock.SLOPE, slope).with(BeltBlock.PART, part) world
.with(BeltBlock.HORIZONTAL_FACING, facing), 3); .setBlockState(pos,
beltBlock
.with(BeltBlock.SLOPE, slope)
.with(BeltBlock.PART, part)
.with(BeltBlock.HORIZONTAL_FACING, facing),
3);
} }
} }
private Direction getFacingFromTo(BlockPos start, BlockPos end) { private static Direction getFacingFromTo(BlockPos start, BlockPos end) {
Axis beltAxis = start.getX() == end.getX() ? Axis.Z : Axis.X; Axis beltAxis = start.getX() == end.getX() ? Axis.Z : Axis.X;
BlockPos diff = end.subtract(start); BlockPos diff = end.subtract(start);
AxisDirection axisDirection = AxisDirection.POSITIVE; AxisDirection axisDirection = AxisDirection.POSITIVE;
@ -128,7 +135,7 @@ public class BeltConnectorItem extends BlockItem implements IAddedByOther {
return Direction.getFacingFromAxis(axisDirection, beltAxis); return Direction.getFacingFromAxis(axisDirection, beltAxis);
} }
private Slope getSlopeBetween(BlockPos start, BlockPos end) { private static Slope getSlopeBetween(BlockPos start, BlockPos end) {
BlockPos diff = end.subtract(start); BlockPos diff = end.subtract(start);
if (diff.getY() != 0) { if (diff.getY() != 0) {
@ -139,7 +146,7 @@ public class BeltConnectorItem extends BlockItem implements IAddedByOther {
return Slope.HORIZONTAL; return Slope.HORIZONTAL;
} }
private List<BlockPos> getBeltChainBetween(BlockPos start, BlockPos end, Slope slope, Direction direction) { private static List<BlockPos> getBeltChainBetween(BlockPos start, BlockPos end, Slope slope, Direction direction) {
List<BlockPos> positions = new LinkedList<>(); List<BlockPos> positions = new LinkedList<>();
int limit = 1000; int limit = 1000;
BlockPos current = start; BlockPos current = start;

View file

@ -118,11 +118,11 @@ public class BeltInventory {
float diffToEnd = beltMovementPositive ? belt.beltLength - currentPos : -currentPos; float diffToEnd = beltMovementPositive ? belt.beltLength - currentPos : -currentPos;
float limitedMovement = float limitedMovement =
beltMovementPositive ? Math.min(movement, diffToEnd) : Math.max(movement, diffToEnd); beltMovementPositive ? Math.min(movement, diffToEnd) : Math.max(movement, diffToEnd);
float nextOffset = current.beltPosition + limitedMovement; float nextOffset = current.beltPosition + limitedMovement;
if (!onClient) {
if (!onClient && segmentBefore != -1) {
// Don't move if belt attachments want to continue processing // Don't move if belt attachments want to continue processing
if (segmentBefore != -1 && current.locked) { if (current.locked) {
BeltTileEntity beltSegment = BeltHelper.getBeltAtSegment(belt, segmentBefore); BeltTileEntity beltSegment = BeltHelper.getBeltAtSegment(belt, segmentBefore);
if (beltSegment != null) { if (beltSegment != null) {
@ -146,10 +146,11 @@ public class BeltInventory {
} }
// See if any new belt processing catches the item // See if any new belt processing catches the item
int upcomingSegment = (int) (current.beltPosition + (beltMovementPositive ? .5f : -.5f)); if (current.beltPosition > .5f || beltMovementPositive) {
for (int segment = upcomingSegment; beltMovementPositive ? segment + .5f <= nextOffset int firstUpcomingSegment = (int) (current.beltPosition + (beltMovementPositive ? .5f : -.5f));
for (int segment = firstUpcomingSegment; beltMovementPositive ? segment + .5f <= nextOffset
: segment + .5f >= nextOffset; segment += beltMovementPositive ? 1 : -1) { : segment + .5f >= nextOffset; segment += beltMovementPositive ? 1 : -1) {
BeltTileEntity beltSegment = BeltHelper.getBeltAtSegment(belt, segmentBefore); BeltTileEntity beltSegment = BeltHelper.getBeltAtSegment(belt, segment);
if (beltSegment == null) if (beltSegment == null)
break; break;
for (BeltAttachmentState attachmentState : beltSegment.attachmentTracker.attachments) { for (BeltAttachmentState attachmentState : beltSegment.attachmentTracker.attachments) {
@ -165,6 +166,7 @@ public class BeltInventory {
} }
} }
} }
}
// Belt tunnels // Belt tunnels
{ {
@ -202,7 +204,8 @@ public class BeltInventory {
if (segment == -1) if (segment == -1)
continue; continue;
if (!world.isRemote) if (!world.isRemote)
world.updateComparatorOutputLevel(BeltHelper.getPositionForOffset(belt, segment), world
.updateComparatorOutputLevel(BeltHelper.getPositionForOffset(belt, segment),
belt.getBlockState().getBlock()); belt.getBlockState().getBlock());
} }
} }
@ -392,7 +395,8 @@ public class BeltInventory {
public void read(CompoundNBT nbt) { public void read(CompoundNBT nbt) {
getItems().clear(); getItems().clear();
nbt.getList("Items", NBT.TAG_COMPOUND) nbt
.getList("Items", NBT.TAG_COMPOUND)
.forEach(inbt -> getItems().add(TransportedItemStack.read((CompoundNBT) inbt))); .forEach(inbt -> getItems().add(TransportedItemStack.read((CompoundNBT) inbt)));
beltMovementPositive = nbt.getBoolean("PositiveOrder"); beltMovementPositive = nbt.getBoolean("PositiveOrder");
} }

View file

@ -1,8 +1,12 @@
package com.simibubi.create.modules.contraptions.relays.elementary; package com.simibubi.create.modules.contraptions.relays.elementary;
import com.simibubi.create.AllBlocksNew;
import com.simibubi.create.foundation.advancement.AllTriggers;
import com.simibubi.create.foundation.utility.Iterate;
import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.utility.VecHelper;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.BlockItem; import net.minecraft.item.BlockItem;
import net.minecraft.item.BlockItemUseContext; import net.minecraft.item.BlockItemUseContext;
import net.minecraft.util.ActionResultType; import net.minecraft.util.ActionResultType;
@ -11,6 +15,7 @@ import net.minecraft.util.Direction.Axis;
import net.minecraft.util.Direction.AxisDirection; import net.minecraft.util.Direction.AxisDirection;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
public class CogwheelBlockItem extends BlockItem { public class CogwheelBlockItem extends BlockItem {
@ -52,8 +57,8 @@ public class CogwheelBlockItem extends BlockItem {
hitVec = hitVec hitVec = hitVec
.mul(new Vec3d(Direction.getFacingFromAxis(AxisDirection.POSITIVE, offsetAxis).getDirectionVec())); .mul(new Vec3d(Direction.getFacingFromAxis(AxisDirection.POSITIVE, offsetAxis).getDirectionVec()));
BlockPos correctPos = context.getPos().add(Math.signum(hitVec.x), Math.signum(hitVec.y), BlockPos correctPos =
Math.signum(hitVec.z)); context.getPos().add(Math.signum(hitVec.x), Math.signum(hitVec.y), Math.signum(hitVec.z));
if (context.getWorld().getBlockState(correctPos).getMaterial().isReplaceable()) if (context.getWorld().getBlockState(correctPos).getMaterial().isReplaceable())
context = BlockItemUseContext.func_221536_a(context, correctPos, largeOnLarge ? face context = BlockItemUseContext.func_221536_a(context, correctPos, largeOnLarge ? face
@ -65,4 +70,41 @@ public class CogwheelBlockItem extends BlockItem {
return super.tryPlace(context); return super.tryPlace(context);
} }
@Override
// Trigger cogwheel criterion
protected boolean placeBlock(BlockItemUseContext context, BlockState state) {
World world = context.getWorld();
PlayerEntity player = context.getPlayer();
if (!world.isRemote && player != null) {
Axis axis = state.get(CogWheelBlock.AXIS);
for (Axis perpendicular1 : Iterate.axes) {
if (perpendicular1 == axis)
continue;
Direction d1 = Direction.getFacingFromAxis(AxisDirection.POSITIVE, perpendicular1);
for (Axis perpendicular2 : Iterate.axes) {
if (perpendicular1 == perpendicular2)
continue;
if (axis == perpendicular2)
continue;
Direction d2 = Direction.getFacingFromAxis(AxisDirection.POSITIVE, perpendicular2);
for (int offset1 : Iterate.positiveAndNegative) {
for (int offset2 : Iterate.positiveAndNegative) {
BlockPos connectedPos = context.getPos().offset(d1, offset1).offset(d2, offset2);
BlockState blockState = world.getBlockState(connectedPos);
if (!(blockState.getBlock() instanceof CogWheelBlock))
continue;
if (blockState.get(CogWheelBlock.AXIS) != axis)
continue;
if (AllBlocksNew.equals(AllBlocksNew.LARGE_COGWHEEL, blockState) == large)
continue;
AllTriggers.triggerFor(AllTriggers.SHIFTING_GEARS, player);
}
}
}
}
}
return super.placeBlock(context, state);
}
} }

View file

@ -33,6 +33,8 @@ public class AdjustablePulleyTileEntity extends KineticTileEntity {
} }
public void neighborChanged() { public void neighborChanged() {
if (!hasWorld())
return;
int power = world.getRedstonePowerFromNeighbors(pos); int power = world.getRedstonePowerFromNeighbors(pos);
if (power != signal) if (power != signal)
signalChanged = true; signalChanged = true;

View file

@ -5,6 +5,7 @@ import java.util.Random;
import com.simibubi.create.foundation.utility.ColorHelper; import com.simibubi.create.foundation.utility.ColorHelper;
import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.foundation.utility.WrappedWorld;
import com.simibubi.create.modules.contraptions.base.DirectionalAxisKineticBlock; import com.simibubi.create.modules.contraptions.base.DirectionalAxisKineticBlock;
import com.simibubi.create.modules.contraptions.base.IRotate; import com.simibubi.create.modules.contraptions.base.IRotate;
@ -79,13 +80,16 @@ public class GaugeBlock extends DirectionalAxisKineticBlock {
Direction nearestLookingDirection = context.getNearestLookingDirection(); Direction nearestLookingDirection = context.getNearestLookingDirection();
boolean lookPositive = nearestLookingDirection.getAxisDirection() == AxisDirection.POSITIVE; boolean lookPositive = nearestLookingDirection.getAxisDirection() == AxisDirection.POSITIVE;
if (face.getAxis() == Axis.X) { if (face.getAxis() == Axis.X) {
toPlace = toPlace.with(FACING, lookPositive ? Direction.NORTH : Direction.SOUTH) toPlace = toPlace
.with(FACING, lookPositive ? Direction.NORTH : Direction.SOUTH)
.with(AXIS_ALONG_FIRST_COORDINATE, true); .with(AXIS_ALONG_FIRST_COORDINATE, true);
} else if (face.getAxis() == Axis.Y) { } else if (face.getAxis() == Axis.Y) {
toPlace = toPlace.with(FACING, horizontalFacing.getOpposite()).with(AXIS_ALONG_FIRST_COORDINATE, toPlace = toPlace
horizontalFacing.getAxis() == Axis.X); .with(FACING, horizontalFacing.getOpposite())
.with(AXIS_ALONG_FIRST_COORDINATE, horizontalFacing.getAxis() == Axis.X);
} else { } else {
toPlace = toPlace.with(FACING, lookPositive ? Direction.WEST : Direction.EAST) toPlace = toPlace
.with(FACING, lookPositive ? Direction.WEST : Direction.EAST)
.with(AXIS_ALONG_FIRST_COORDINATE, false); .with(AXIS_ALONG_FIRST_COORDINATE, false);
} }
@ -119,8 +123,8 @@ public class GaugeBlock extends DirectionalAxisKineticBlock {
if (getRotationAxis(state) == Axis.Y && face != state.get(FACING)) if (getRotationAxis(state) == Axis.Y && face != state.get(FACING))
return false; return false;
BlockState blockState = world.getBlockState(pos.offset(face)); BlockState blockState = world.getBlockState(pos.offset(face));
if (Block.hasSolidSide(blockState, world, pos, face.getOpposite()) if (Block.hasSolidSide(blockState, world, pos, face.getOpposite()) && blockState.getMaterial() != Material.GLASS
&& blockState.getMaterial() != Material.GLASS) && !(world instanceof WrappedWorld))
return false; return false;
return true; return true;
} }
@ -149,10 +153,14 @@ public class GaugeBlock extends DirectionalAxisKineticBlock {
continue; continue;
for (int i = 0; i < particleCount; i++) { for (int i = 0; i < particleCount; i++) {
Vec3d mul = VecHelper.offsetRandomly(Vec3d.ZERO, rand, .25f) Vec3d mul = VecHelper
.mul(new Vec3d(1, 1, 1).subtract(positiveFaceVec)).normalize().scale(.3f); .offsetRandomly(Vec3d.ZERO, rand, .25f)
.mul(new Vec3d(1, 1, 1).subtract(positiveFaceVec))
.normalize()
.scale(.3f);
Vec3d offset = VecHelper.getCenterOf(pos).add(faceVec.scale(.55)).add(mul); Vec3d offset = VecHelper.getCenterOf(pos).add(faceVec.scale(.55)).add(mul);
worldIn.addParticle(new RedstoneParticleData((float) rgb.x, (float) rgb.y, (float) rgb.z, 1), offset.x, worldIn
.addParticle(new RedstoneParticleData((float) rgb.x, (float) rgb.y, (float) rgb.z, 1), offset.x,
offset.y, offset.z, mul.x, mul.y, mul.z); offset.y, offset.z, mul.x, mul.y, mul.z);
} }

View file

@ -0,0 +1,26 @@
package com.simibubi.create.modules.curiosities.tools;
import net.minecraft.entity.LivingEntity;
import net.minecraft.item.IItemTier;
import net.minecraft.item.ItemStack;
import net.minecraft.item.SwordItem;
public class BlazingSwordItem extends SwordItem {
public BlazingSwordItem(IItemTier tier, int attackDamageIn, float attackSpeedIn, Properties builder) {
super(tier, attackDamageIn, attackSpeedIn, builder);
}
@Override
public boolean hitEntity(ItemStack stack, LivingEntity target, LivingEntity attacker) {
target.setFire(2);
return BlazingToolItem.shouldTakeDamage(attacker.world, stack) ? super.hitEntity(stack, target, attacker)
: true;
}
@Override
public int getBurnTime(ItemStack itemStack) {
return itemStack.getMaxDamage() - itemStack.getDamage() + 1;
}
}

View file

@ -55,7 +55,7 @@ public class BlazingToolItem extends AbstractToolItem {
return shouldTakeDamage(attacker.world, stack) ? super.hitEntity(stack, target, attacker) : true; return shouldTakeDamage(attacker.world, stack) ? super.hitEntity(stack, target, attacker) : true;
} }
protected boolean shouldTakeDamage(World world, ItemStack stack) { static boolean shouldTakeDamage(World world, ItemStack stack) {
return world.getDimension().getType() != DimensionType.THE_NETHER; return world.getDimension().getType() != DimensionType.THE_NETHER;
} }

View file

@ -1,10 +1,8 @@
package com.simibubi.create.modules.curiosities.tools; package com.simibubi.create.modules.curiosities.tools;
import com.simibubi.create.foundation.advancement.AllTriggers;
import com.simibubi.create.foundation.block.render.CustomRenderedItemModel; import com.simibubi.create.foundation.block.render.CustomRenderedItemModel;
import com.simibubi.create.foundation.item.IHaveCustomItemModel; import com.simibubi.create.foundation.item.IHaveCustomItemModel;
import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.modules.contraptions.components.deployer.DeployerFakePlayer;
import com.simibubi.create.modules.curiosities.tools.SandPaperItemRenderer.SandPaperModel; import com.simibubi.create.modules.curiosities.tools.SandPaperItemRenderer.SandPaperModel;
import net.minecraft.client.renderer.model.IBakedModel; import net.minecraft.client.renderer.model.IBakedModel;
@ -12,7 +10,6 @@ import net.minecraft.enchantment.Enchantment;
import net.minecraft.entity.LivingEntity; import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.item.ItemEntity; import net.minecraft.entity.item.ItemEntity;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.item.Item; import net.minecraft.item.Item;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemUseContext; import net.minecraft.item.ItemUseContext;
@ -31,6 +28,7 @@ import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.common.util.FakePlayer;
public class SandPaperItem extends Item implements IHaveCustomItemModel { public class SandPaperItem extends Item implements IHaveCustomItemModel {
@ -136,11 +134,9 @@ public class SandPaperItem extends Item implements IHaveCustomItemModel {
} }
if (!polished.isEmpty()) { if (!polished.isEmpty()) {
if (player instanceof DeployerFakePlayer) { if (player instanceof FakePlayer) {
player.dropItem(polished, false, false); player.dropItem(polished, false, false);
} else { } else {
AllTriggers.SANDPAPER_USE.trigger((ServerPlayerEntity) player, toPolish, polished);
player.inventory.placeItemBackInInventory(worldIn, polished); player.inventory.placeItemBackInInventory(worldIn, polished);
} }
} }

View file

@ -7,6 +7,7 @@ import java.util.Set;
import com.simibubi.create.AllItems; import com.simibubi.create.AllItems;
import com.simibubi.create.Create; import com.simibubi.create.Create;
import com.simibubi.create.foundation.advancement.AllTriggers;
import com.simibubi.create.foundation.block.render.CustomRenderedItemModel; import com.simibubi.create.foundation.block.render.CustomRenderedItemModel;
import com.simibubi.create.foundation.gui.ScreenOpener; import com.simibubi.create.foundation.gui.ScreenOpener;
import com.simibubi.create.foundation.item.IHaveCustomItemModel; import com.simibubi.create.foundation.item.IHaveCustomItemModel;
@ -110,8 +111,10 @@ public class BlockzapperItem extends ZapperItem implements IHaveCustomItemModel
continue; continue;
if (!player.isCreative() && BlockHelper.findAndRemoveInInventory(selectedState, player, 1) == 0) { if (!player.isCreative() && BlockHelper.findAndRemoveInInventory(selectedState, player, 1) == 0) {
player.getCooldownTracker().setCooldown(stack.getItem(), 20); player.getCooldownTracker().setCooldown(stack.getItem(), 20);
player.sendStatusMessage( player
new StringTextComponent(TextFormatting.RED + Lang.translate("blockzapper.empty")), true); .sendStatusMessage(
new StringTextComponent(TextFormatting.RED + Lang.translate("blockzapper.empty")),
true);
return false; return false;
} }
@ -119,9 +122,9 @@ public class BlockzapperItem extends ZapperItem implements IHaveCustomItemModel
dropBlocks(world, player, stack, face, placed); dropBlocks(world, player, stack, face, placed);
for (Direction updateDirection : Direction.values()) for (Direction updateDirection : Direction.values())
selectedState = selectedState.updatePostPlacement(updateDirection, selectedState = selectedState
world.getBlockState(placed.offset(updateDirection)), world, placed, .updatePostPlacement(updateDirection, world.getBlockState(placed.offset(updateDirection)),
placed.offset(updateDirection)); world, placed, placed.offset(updateDirection));
BlockSnapshot blocksnapshot = BlockSnapshot.getBlockSnapshot(world, placed); BlockSnapshot blocksnapshot = BlockSnapshot.getBlockSnapshot(world, placed);
IFluidState ifluidstate = world.getFluidState(placed); IFluidState ifluidstate = world.getFluidState(placed);
@ -132,9 +135,20 @@ public class BlockzapperItem extends ZapperItem implements IHaveCustomItemModel
return false; return false;
} }
if (player instanceof ServerPlayerEntity) if (player instanceof ServerPlayerEntity && world instanceof ServerWorld) {
CriteriaTriggers.PLACED_BLOCK.trigger((ServerPlayerEntity) player, placed, ServerPlayerEntity serverPlayer = (ServerPlayerEntity) player;
new ItemStack(selectedState.getBlock())); CriteriaTriggers.PLACED_BLOCK.trigger(serverPlayer, placed, new ItemStack(selectedState.getBlock()));
boolean fullyUpgraded = true;
for (Components c : Components.values()) {
if (getTier(c, stack) != ComponentTier.Chromatic) {
fullyUpgraded = false;
break;
}
}
if (fullyUpgraded)
AllTriggers.UPGRADED_ZAPPER.trigger(serverPlayer);
}
} }
return true; return true;
@ -179,7 +193,8 @@ public class BlockzapperItem extends ZapperItem implements IHaveCustomItemModel
Vec3d start = player.getPositionVec().add(0, player.getEyeHeight(), 0); Vec3d start = player.getPositionVec().add(0, player.getEyeHeight(), 0);
Vec3d range = player.getLookVec().scale(getRange(stack)); Vec3d range = player.getLookVec().scale(getRange(stack));
BlockRayTraceResult raytrace = player.world.rayTraceBlocks( BlockRayTraceResult raytrace = player.world
.rayTraceBlocks(
new RayTraceContext(start, start.add(range), BlockMode.COLLIDER, FluidMode.NONE, player)); new RayTraceContext(start, start.add(range), BlockMode.COLLIDER, FluidMode.NONE, player));
BlockPos pos = raytrace.getPos().toImmutable(); BlockPos pos = raytrace.getPos().toImmutable();
@ -318,8 +333,8 @@ public class BlockzapperItem extends ZapperItem implements IHaveCustomItemModel
Block.spawnDrops(worldIn.getBlockState(placed), worldIn, playerIn.getPosition(), tileentity); Block.spawnDrops(worldIn.getBlockState(placed), worldIn, playerIn.getPosition(), tileentity);
if (getTier(Components.Retriever, item) == ComponentTier.Chromatic) if (getTier(Components.Retriever, item) == ComponentTier.Chromatic)
for (ItemStack stack : Block.getDrops(worldIn.getBlockState(placed), (ServerWorld) worldIn, placed, for (ItemStack stack : Block
tileentity)) .getDrops(worldIn.getBlockState(placed), (ServerWorld) worldIn, placed, tileentity))
if (!playerIn.inventory.addItemStackToInventory(stack)) if (!playerIn.inventory.addItemStackToInventory(stack))
Block.spawnAsEntity(worldIn, placed, stack); Block.spawnAsEntity(worldIn, placed, stack);
} }

View file

@ -153,6 +153,9 @@ public class InWorldProcessing {
return null; return null;
List<ItemStack> stacks = process(transported.stack, type, belt.getWorld()); List<ItemStack> stacks = process(transported.stack, type, belt.getWorld());
if (stacks == null)
return null;
List<TransportedItemStack> transportedStacks = new ArrayList<>(); List<TransportedItemStack> transportedStacks = new ArrayList<>();
for (ItemStack additional : stacks) { for (ItemStack additional : stacks) {
TransportedItemStack newTransported = transported.getSimilar(); TransportedItemStack newTransported = transported.getSimilar();

View file

@ -1,6 +1,7 @@
package com.simibubi.create.modules.logistics.block; package com.simibubi.create.modules.logistics.block;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.modules.contraptions.IWrenchable;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock; import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock;
import com.simibubi.create.modules.logistics.block.transposer.TransposerBlock; import com.simibubi.create.modules.logistics.block.transposer.TransposerBlock;
@ -12,8 +13,10 @@ import net.minecraft.block.material.PushReaction;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.BlockItemUseContext; import net.minecraft.item.BlockItemUseContext;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemUseContext;
import net.minecraft.state.BooleanProperty; import net.minecraft.state.BooleanProperty;
import net.minecraft.state.StateContainer.Builder; import net.minecraft.state.StateContainer.Builder;
import net.minecraft.util.ActionResultType;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
@ -22,7 +25,7 @@ import net.minecraft.world.IBlockReader;
import net.minecraft.world.IWorldReader; import net.minecraft.world.IWorldReader;
import net.minecraft.world.World; import net.minecraft.world.World;
public abstract class AttachedLogisticalBlock extends HorizontalBlock { public abstract class AttachedLogisticalBlock extends HorizontalBlock implements IWrenchable {
public static final BooleanProperty UPWARD = BooleanProperty.create("upward"); public static final BooleanProperty UPWARD = BooleanProperty.create("upward");
@ -30,6 +33,11 @@ public abstract class AttachedLogisticalBlock extends HorizontalBlock {
super(Properties.from(Blocks.ANDESITE)); super(Properties.from(Blocks.ANDESITE));
} }
@Override
public ActionResultType onWrenched(BlockState state, ItemUseContext context) {
return ActionResultType.FAIL;
}
protected abstract boolean isVertical(); protected abstract boolean isVertical();
protected abstract BlockState getVerticalDefaultState(); protected abstract BlockState getVerticalDefaultState();

View file

@ -1,13 +1,14 @@
package com.simibubi.create.modules.logistics.block; package com.simibubi.create.modules.logistics.block;
import com.simibubi.create.AllItems;
import com.simibubi.create.foundation.block.ITE; import com.simibubi.create.foundation.block.ITE;
import com.simibubi.create.foundation.gui.ScreenOpener; import com.simibubi.create.foundation.gui.ScreenOpener;
import com.simibubi.create.modules.contraptions.IWrenchable;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks; import net.minecraft.block.Blocks;
import net.minecraft.block.HorizontalBlock; import net.minecraft.block.HorizontalBlock;
import net.minecraft.block.material.PushReaction;
import net.minecraft.client.entity.player.ClientPlayerEntity; import net.minecraft.client.entity.player.ClientPlayerEntity;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.BlockItemUseContext; import net.minecraft.item.BlockItemUseContext;
@ -27,7 +28,7 @@ import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.fml.DistExecutor; import net.minecraftforge.fml.DistExecutor;
import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.CapabilityItemHandler;
public class StockswitchBlock extends HorizontalBlock implements ITE<StockswitchTileEntity> { public class StockswitchBlock extends HorizontalBlock implements ITE<StockswitchTileEntity>, IWrenchable {
public static final IntegerProperty INDICATOR = IntegerProperty.create("indicator", 0, 6); public static final IntegerProperty INDICATOR = IntegerProperty.create("indicator", 0, 6);
@ -85,6 +86,8 @@ public class StockswitchBlock extends HorizontalBlock implements ITE<Stockswitch
@Override @Override
public ActionResultType onUse(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn, public ActionResultType onUse(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn,
BlockRayTraceResult hit) { BlockRayTraceResult hit) {
if (player != null && AllItems.WRENCH.typeOf(player.getHeldItem(handIn)))
return false;
DistExecutor.runWhenOn(Dist.CLIENT, DistExecutor.runWhenOn(Dist.CLIENT,
() -> () -> withTileEntityDo(worldIn, pos, te -> this.displayScreen(te, player))); () -> () -> withTileEntityDo(worldIn, pos, te -> this.displayScreen(te, player)));
return ActionResultType.SUCCESS; return ActionResultType.SUCCESS;
@ -136,11 +139,6 @@ public class StockswitchBlock extends HorizontalBlock implements ITE<Stockswitch
return new StockswitchTileEntity(); return new StockswitchTileEntity();
} }
@Override
public PushReaction getPushReaction(BlockState state) {
return PushReaction.BLOCK;
}
@Override @Override
public Class<StockswitchTileEntity> getTileEntityClass() { public Class<StockswitchTileEntity> getTileEntityClass() {
return StockswitchTileEntity.class; return StockswitchTileEntity.class;

View file

@ -1,7 +1,10 @@
package com.simibubi.create.modules.logistics.block; package com.simibubi.create.modules.logistics.block;
import java.util.List;
import com.simibubi.create.AllTileEntities; import com.simibubi.create.AllTileEntities;
import com.simibubi.create.foundation.block.SyncedTileEntity; import com.simibubi.create.foundation.behaviour.base.SmartTileEntity;
import com.simibubi.create.foundation.behaviour.base.TileEntityBehaviour;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
@ -15,7 +18,7 @@ import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.IItemHandler;
public class StockswitchTileEntity extends SyncedTileEntity { public class StockswitchTileEntity extends SmartTileEntity {
public float onWhenAbove; public float onWhenAbove;
public float offWhenBelow; public float offWhenBelow;
@ -34,6 +37,7 @@ public class StockswitchTileEntity extends SyncedTileEntity {
currentLevel = -1; currentLevel = -1;
powered = false; powered = false;
observedInventory = LazyOptional.empty(); observedInventory = LazyOptional.empty();
setLazyTickRate(10);
} }
@Override @Override
@ -107,7 +111,17 @@ public class StockswitchTileEntity extends SyncedTileEntity {
world.notifyNeighbors(pos, getBlockState().getBlock()); world.notifyNeighbors(pos, getBlockState().getBlock());
} }
@Override
public void lazyTick() {
super.lazyTick();
if (world.isRemote)
return;
findNewInventory();
updateCurrentLevel();
}
private boolean findNewInventory() { private boolean findNewInventory() {
observedInventory = LazyOptional.empty();
BlockPos invPos = getPos().offset(getBlockState().get(BlockStateProperties.HORIZONTAL_FACING)); BlockPos invPos = getPos().offset(getBlockState().get(BlockStateProperties.HORIZONTAL_FACING));
if (!world.isBlockPresent(invPos)) if (!world.isBlockPresent(invPos))
@ -117,6 +131,8 @@ public class StockswitchTileEntity extends SyncedTileEntity {
if (!invState.hasTileEntity()) if (!invState.hasTileEntity())
return false; return false;
TileEntity invTE = world.getTileEntity(invPos); TileEntity invTE = world.getTileEntity(invPos);
if (invTE == null)
return false;
observedInventory = invTE.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY); observedInventory = invTE.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY);
if (observedInventory.isPresent()) { if (observedInventory.isPresent()) {
@ -127,4 +143,9 @@ public class StockswitchTileEntity extends SyncedTileEntity {
return false; return false;
} }
@Override
public void addBehaviours(List<TileEntityBehaviour> behaviours) {
}
} }

View file

@ -7,6 +7,7 @@ import java.util.List;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.foundation.block.ITE; import com.simibubi.create.foundation.block.ITE;
import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.foundation.utility.WrappedWorld;
import com.simibubi.create.modules.contraptions.IWrenchable; import com.simibubi.create.modules.contraptions.IWrenchable;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock; import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Slope; import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Slope;
@ -104,6 +105,7 @@ public class BeltTunnelBlock extends Block implements ITE<BeltTunnelTileEntity>,
@Override @Override
public BlockState updatePostPlacement(BlockState state, Direction facing, BlockState facingState, IWorld worldIn, public BlockState updatePostPlacement(BlockState state, Direction facing, BlockState facingState, IWorld worldIn,
BlockPos currentPos, BlockPos facingPos) { BlockPos currentPos, BlockPos facingPos) {
if (!(worldIn instanceof WrappedWorld))
withTileEntityDo(worldIn, currentPos, BeltTunnelTileEntity::initFlaps); withTileEntityDo(worldIn, currentPos, BeltTunnelTileEntity::initFlaps);
BlockState tunnelState = getTunnelState(worldIn, currentPos); BlockState tunnelState = getTunnelState(worldIn, currentPos);
@ -160,11 +162,11 @@ public class BeltTunnelBlock extends Block implements ITE<BeltTunnelTileEntity>,
// T and Cross // T and Cross
Direction left = Direction.getFacingFromAxis(AxisDirection.POSITIVE, axis).rotateY(); Direction left = Direction.getFacingFromAxis(AxisDirection.POSITIVE, axis).rotateY();
BlockState leftState = reader.getBlockState(pos.offset(left).down()); BlockState leftState = reader.getBlockState(pos.offset(left).down());
boolean onLeft = AllBlocks.BELT.typeOf(leftState) boolean onLeft =
&& leftState.get(BeltBlock.HORIZONTAL_FACING).getAxis() != axis; AllBlocks.BELT.typeOf(leftState) && leftState.get(BeltBlock.HORIZONTAL_FACING).getAxis() != axis;
BlockState rightState = reader.getBlockState(pos.offset(left.getOpposite()).down()); BlockState rightState = reader.getBlockState(pos.offset(left.getOpposite()).down());
boolean onRight = AllBlocks.BELT.typeOf(rightState) boolean onRight =
&& rightState.get(BeltBlock.HORIZONTAL_FACING).getAxis() != axis; AllBlocks.BELT.typeOf(rightState) && rightState.get(BeltBlock.HORIZONTAL_FACING).getAxis() != axis;
if (onLeft && onRight) if (onLeft && onRight)
state = state.with(SHAPE, Shape.CROSS); state = state.with(SHAPE, Shape.CROSS);

View file

@ -0,0 +1,13 @@
package com.simibubi.create.modules.logistics.block.diodes;
import com.simibubi.create.modules.contraptions.IWrenchable;
import net.minecraft.block.RedstoneDiodeBlock;
public abstract class AbstractDiodeBlock extends RedstoneDiodeBlock implements IWrenchable {
public AbstractDiodeBlock(Properties builder) {
super(builder);
}
}

View file

@ -5,7 +5,6 @@ import com.simibubi.create.AllBlocks;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks; import net.minecraft.block.Blocks;
import net.minecraft.block.RedstoneDiodeBlock;
import net.minecraft.state.BooleanProperty; import net.minecraft.state.BooleanProperty;
import net.minecraft.state.StateContainer.Builder; import net.minecraft.state.StateContainer.Builder;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
@ -13,7 +12,7 @@ import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IBlockReader; import net.minecraft.world.IBlockReader;
public class FlexpeaterBlock extends RedstoneDiodeBlock { public class FlexpeaterBlock extends AbstractDiodeBlock {
public static BooleanProperty POWERING = BooleanProperty.create("powering"); public static BooleanProperty POWERING = BooleanProperty.create("powering");

View file

@ -4,6 +4,8 @@ import java.util.Random;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.RedstoneWireBlock;
import net.minecraft.state.BooleanProperty; import net.minecraft.state.BooleanProperty;
import net.minecraft.state.StateContainer.Builder; import net.minecraft.state.StateContainer.Builder;
import net.minecraft.util.ActionResultType; import net.minecraft.util.ActionResultType;
@ -30,13 +32,9 @@ public class LatchBlock extends ToggleLatchBlock {
@Override @Override
protected void updateState(World worldIn, BlockPos pos, BlockState state) { protected void updateState(World worldIn, BlockPos pos, BlockState state) {
boolean back = state.get(POWERED); boolean back = state.get(POWERED);
boolean shouldBack = this.shouldBePowered(worldIn, pos, state); boolean shouldBack = shouldBePowered(worldIn, pos, state);
boolean side = state.get(POWERED_SIDE); boolean side = state.get(POWERED_SIDE);
boolean shouldSide = isPoweredOnSides(worldIn, pos, state);
Direction direction = state.get(HORIZONTAL_FACING);
Direction left = direction.rotateY();
Direction right = direction.rotateYCCW();
boolean shouldSide = worldIn.isBlockPowered(pos.offset(left)) || worldIn.isBlockPowered(pos.offset(right));
TickPriority tickpriority = TickPriority.HIGH; TickPriority tickpriority = TickPriority.HIGH;
if (this.isFacingTowardsRepeater(worldIn, pos, state)) if (this.isFacingTowardsRepeater(worldIn, pos, state))
@ -50,16 +48,29 @@ public class LatchBlock extends ToggleLatchBlock {
worldIn.getPendingBlockTicks().scheduleTick(pos, this, this.getDelay(state), tickpriority); worldIn.getPendingBlockTicks().scheduleTick(pos, this, this.getDelay(state), tickpriority);
} }
protected boolean isPoweredOnSides(World worldIn, BlockPos pos, BlockState state) {
Direction direction = state.get(HORIZONTAL_FACING);
Direction left = direction.rotateY();
Direction right = direction.rotateYCCW();
for (Direction d : new Direction[] { left, right }) {
BlockPos blockpos = pos.offset(d);
int i = worldIn.getRedstonePower(blockpos, d);
if (i > 0)
return true;
BlockState blockstate = worldIn.getBlockState(blockpos);
if (blockstate.getBlock() == Blocks.REDSTONE_WIRE && blockstate.get(RedstoneWireBlock.POWER) > 0)
return true;
}
return false;
}
@Override @Override
public void scheduledTick(BlockState state, ServerWorld worldIn, BlockPos pos, Random random) { public void scheduledTick(BlockState state, ServerWorld worldIn, BlockPos pos, Random random) {
boolean back = state.get(POWERED); boolean back = state.get(POWERED);
boolean shouldBack = this.shouldBePowered(worldIn, pos, state); boolean shouldBack = this.shouldBePowered(worldIn, pos, state);
boolean side = state.get(POWERED_SIDE); boolean side = state.get(POWERED_SIDE);
boolean shouldSide = isPoweredOnSides(worldIn, pos, state);
Direction direction = state.get(HORIZONTAL_FACING);
Direction left = direction.rotateY();
Direction right = direction.rotateYCCW();
boolean shouldSide = worldIn.isBlockPowered(pos.offset(left)) || worldIn.isBlockPowered(pos.offset(right));
BlockState stateIn = state; BlockState stateIn = state;
if (back != shouldBack) { if (back != shouldBack) {

View file

@ -5,7 +5,6 @@ import java.util.Random;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks; import net.minecraft.block.Blocks;
import net.minecraft.block.RedstoneDiodeBlock;
import net.minecraft.state.BooleanProperty; import net.minecraft.state.BooleanProperty;
import net.minecraft.state.StateContainer.Builder; import net.minecraft.state.StateContainer.Builder;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
@ -14,7 +13,7 @@ import net.minecraft.world.IBlockReader;
import net.minecraft.world.TickPriority; import net.minecraft.world.TickPriority;
import net.minecraft.world.server.ServerWorld; import net.minecraft.world.server.ServerWorld;
public class PulseRepeaterBlock extends RedstoneDiodeBlock { public class PulseRepeaterBlock extends AbstractDiodeBlock {
public static BooleanProperty PULSING = BooleanProperty.create("pulsing"); public static BooleanProperty PULSING = BooleanProperty.create("pulsing");

View file

@ -2,10 +2,11 @@ package com.simibubi.create.modules.logistics.block.diodes;
import java.util.Random; import java.util.Random;
import com.simibubi.create.AllItems;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks; import net.minecraft.block.Blocks;
import net.minecraft.block.RedstoneDiodeBlock;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.state.BooleanProperty; import net.minecraft.state.BooleanProperty;
import net.minecraft.state.StateContainer.Builder; import net.minecraft.state.StateContainer.Builder;
@ -18,7 +19,7 @@ import net.minecraft.world.IBlockReader;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraft.world.server.ServerWorld; import net.minecraft.world.server.ServerWorld;
public class ToggleLatchBlock extends RedstoneDiodeBlock { public class ToggleLatchBlock extends AbstractDiodeBlock {
public static BooleanProperty POWERING = BooleanProperty.create("powering"); public static BooleanProperty POWERING = BooleanProperty.create("powering");
@ -49,6 +50,8 @@ public class ToggleLatchBlock extends RedstoneDiodeBlock {
return ActionResultType.PASS; return ActionResultType.PASS;
if (player.isSneaking()) if (player.isSneaking())
return ActionResultType.PASS; return ActionResultType.PASS;
if (AllItems.WRENCH.typeOf(player.getHeldItem(handIn)))
return ActionResultType.PASS;
return activated(worldIn, pos, state); return activated(worldIn, pos, state);
} }

View file

@ -0,0 +1,82 @@
package com.simibubi.create.modules.logistics.block.inventories;
import com.simibubi.create.foundation.block.ProperDirectionalBlock;
import com.simibubi.create.foundation.utility.AllShapes;
import com.simibubi.create.modules.contraptions.IWrenchable;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.item.BlockItemUseContext;
import net.minecraft.state.BooleanProperty;
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.IWorld;
import net.minecraft.world.World;
public class CrateBlock extends ProperDirectionalBlock implements IWrenchable {
public static final BooleanProperty DOUBLE = BooleanProperty.create("double");
public CrateBlock(Properties p_i48415_1_) {
super(p_i48415_1_);
setDefaultState(getDefaultState().with(FACING, Direction.UP).with(DOUBLE, false));
}
@Override
public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) {
return AllShapes.CRATE_BLOCK_SHAPE;
}
@Override
public BlockState updatePostPlacement(BlockState stateIn, Direction facing, BlockState facingState, IWorld worldIn,
BlockPos currentPos, BlockPos facingPos) {
boolean isDouble = stateIn.get(DOUBLE);
Direction blockFacing = stateIn.get(FACING);
boolean isFacingOther = facingState.getBlock() == this && facingState.get(DOUBLE)
&& facingState.get(FACING) == facing.getOpposite();
if (!isDouble) {
if (!isFacingOther)
return stateIn;
return stateIn.with(DOUBLE, true).with(FACING, facing);
}
if (facing != blockFacing)
return stateIn;
if (!isFacingOther)
return stateIn.with(DOUBLE, false);
return stateIn;
}
@Override
public BlockState getStateForPlacement(BlockItemUseContext context) {
BlockPos pos = context.getPos();
World world = context.getWorld();
if (!context.isPlacerSneaking()) {
for (Direction d : Direction.values()) {
BlockState state = world.getBlockState(pos.offset(d));
if (state.getBlock() == this && !state.get(DOUBLE))
return getDefaultState().with(FACING, d).with(DOUBLE, true);
}
}
Direction placedOnFace = context.getFace().getOpposite();
BlockState state = world.getBlockState(pos.offset(placedOnFace));
if (state.getBlock() == this && !state.get(DOUBLE))
return getDefaultState().with(FACING, placedOnFace).with(DOUBLE, true);
return getDefaultState();
}
@Override
protected void fillStateContainer(Builder<Block, BlockState> builder) {
super.fillStateContainer(builder.add(DOUBLE));
}
}

View file

@ -0,0 +1,37 @@
package com.simibubi.create.modules.logistics.block.inventories;
import java.util.List;
import com.simibubi.create.foundation.behaviour.base.SmartTileEntity;
import com.simibubi.create.foundation.behaviour.base.TileEntityBehaviour;
import net.minecraft.tileentity.TileEntityType;
import net.minecraft.util.Direction;
import net.minecraft.util.Direction.AxisDirection;
public abstract class CrateTileEntity extends SmartTileEntity {
public CrateTileEntity(TileEntityType<?> tileEntityTypeIn) {
super(tileEntityTypeIn);
}
@Override
public void addBehaviours(List<TileEntityBehaviour> behaviours) {}
public boolean isDoubleCrate() {
return getBlockState().get(FlexcrateBlock.DOUBLE);
}
public boolean isSecondaryCrate() {
if (!hasWorld())
return false;
if (!(getBlockState().getBlock() instanceof CrateBlock))
return false;
return isDoubleCrate() && getFacing().getAxisDirection() == AxisDirection.NEGATIVE;
}
public Direction getFacing() {
return getBlockState().get(FlexcrateBlock.FACING);
}
}

View file

@ -0,0 +1,36 @@
package com.simibubi.create.modules.logistics.block.inventories;
import com.simibubi.create.foundation.block.ITE;
import net.minecraft.block.BlockState;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.World;
public class CreativeCrateBlock extends CrateBlock implements ITE<CreativeCrateTileEntity> {
public CreativeCrateBlock(Properties p_i48415_1_) {
super(p_i48415_1_);
}
@Override
public boolean hasTileEntity(BlockState state) {
return true;
}
@Override
public TileEntity createTileEntity(BlockState state, IBlockReader world) {
return new CreativeCrateTileEntity();
}
@Override
public void onBlockAdded(BlockState state, World worldIn, BlockPos pos, BlockState oldState, boolean isMoving) {
withTileEntityDo(worldIn, pos, CreativeCrateTileEntity::onPlaced);
}
@Override
public Class<CreativeCrateTileEntity> getTileEntityClass() {
return CreativeCrateTileEntity.class;
}
}

View file

@ -0,0 +1,52 @@
package com.simibubi.create.modules.logistics.block.inventories;
import net.minecraft.item.ItemStack;
import net.minecraftforge.items.IItemHandler;
public class CreativeCrateInventory implements IItemHandler {
private CreativeCrateTileEntity te;
public CreativeCrateInventory(CreativeCrateTileEntity te) {
this.te = te;
}
@Override
public int getSlots() {
return 2;
}
@Override
public ItemStack getStackInSlot(int slot) {
if (slot == 1)
return ItemStack.EMPTY;
ItemStack filter = te.filter.getFilter().copy();
if (!filter.isEmpty())
filter.setCount(filter.getMaxStackSize());
return filter;
}
@Override
public ItemStack insertItem(int slot, ItemStack stack, boolean simulate) {
return ItemStack.EMPTY;
}
@Override
public ItemStack extractItem(int slot, int amount, boolean simulate) {
ItemStack filter = te.filter.getFilter().copy();
if (!filter.isEmpty())
filter.setCount(amount);
return filter;
}
@Override
public int getSlotLimit(int slot) {
return getStackInSlot(slot).getMaxStackSize();
}
@Override
public boolean isItemValid(int slot, ItemStack stack) {
return true;
}
}

View file

@ -0,0 +1,106 @@
package com.simibubi.create.modules.logistics.block.inventories;
import java.util.List;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllTileEntities;
import com.simibubi.create.foundation.behaviour.ValueBoxTransform;
import com.simibubi.create.foundation.behaviour.base.TileEntityBehaviour;
import com.simibubi.create.foundation.behaviour.filtering.FilteringBehaviour;
import net.minecraft.block.BlockState;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction;
import net.minecraft.util.math.Vec3d;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
public class CreativeCrateTileEntity extends CrateTileEntity {
public CreativeCrateTileEntity() {
super(AllTileEntities.CREATIVE_CRATE.type);
inv = new CreativeCrateInventory(this);
itemHandler = LazyOptional.of(() -> inv);
}
FilteringBehaviour filter;
LazyOptional<IItemHandler> itemHandler;
private CreativeCrateInventory inv;
@Override
public void addBehaviours(List<TileEntityBehaviour> behaviours) {
filter = createFilter();
filter.onlyActiveWhen(this::filterVisible);
filter.withCallback(this::filterChanged);
behaviours.add(filter);
}
private boolean filterVisible() {
if (!hasWorld() || isDoubleCrate() && !isSecondaryCrate())
return false;
return true;
}
private void filterChanged(ItemStack filter) {
if (!filterVisible())
return;
CreativeCrateTileEntity otherCrate = getOtherCrate();
if (otherCrate == null)
return;
if (ItemStack.areItemsEqual(filter, otherCrate.filter.getFilter()))
return;
otherCrate.filter.setFilter(filter);
}
private CreativeCrateTileEntity getOtherCrate() {
if (!AllBlocks.CREATIVE_CRATE.typeOf(getBlockState()))
return null;
TileEntity tileEntity = world.getTileEntity(pos.offset(getFacing()));
if (tileEntity instanceof CreativeCrateTileEntity)
return (CreativeCrateTileEntity) tileEntity;
return null;
}
public void onPlaced() {
if (!isDoubleCrate())
return;
CreativeCrateTileEntity otherCrate = getOtherCrate();
if (otherCrate == null)
return;
filter.withCallback($ -> {});
filter.setFilter(otherCrate.filter.getFilter());
filter.withCallback(this::filterChanged);
}
@Override
public <T> LazyOptional<T> getCapability(Capability<T> cap, Direction side) {
if (cap == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY)
return itemHandler.cast();
return super.getCapability(cap, side);
}
public FilteringBehaviour createFilter() {
return new FilteringBehaviour(this, new ValueBoxTransform() {
@Override
protected Vec3d getOrientation(BlockState state) {
return new Vec3d(0, 0, 90);
}
@Override
protected Vec3d getLocation(BlockState state) {
return new Vec3d(0.5, 13 / 16d, 0.5);
}
protected float getScale() {
return super.getScale() * 1.5f;
};
});
}
}

View file

@ -1,50 +1,27 @@
package com.simibubi.create.modules.logistics.block.inventories; package com.simibubi.create.modules.logistics.block.inventories;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.foundation.block.ProperDirectionalBlock;
import com.simibubi.create.foundation.item.ItemHelper; import com.simibubi.create.foundation.item.ItemHelper;
import com.simibubi.create.foundation.utility.AllShapes;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks; import net.minecraft.block.Blocks;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.ServerPlayerEntity; import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.item.BlockItemUseContext;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.state.BooleanProperty;
import net.minecraft.state.StateContainer.Builder;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.ActionResultType; import net.minecraft.util.ActionResultType;
import net.minecraft.util.Direction;
import net.minecraft.util.Direction.AxisDirection; import net.minecraft.util.Direction.AxisDirection;
import net.minecraft.util.Hand; import net.minecraft.util.Hand;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult; import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.util.math.shapes.ISelectionContext;
import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.world.IBlockReader; import net.minecraft.world.IBlockReader;
import net.minecraft.world.IWorld;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraftforge.fml.network.NetworkHooks; import net.minecraftforge.fml.network.NetworkHooks;
public class FlexcrateBlock extends ProperDirectionalBlock { public class FlexcrateBlock extends CrateBlock {
public static final BooleanProperty DOUBLE = BooleanProperty.create("double");
public FlexcrateBlock() { public FlexcrateBlock() {
super(Properties.from(Blocks.ANDESITE)); super(Properties.from(Blocks.ANDESITE));
setDefaultState(getDefaultState().with(FACING, Direction.UP).with(DOUBLE, false));
}
@Override
public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) {
return AllShapes.CRATE_BLOCK_SHAPE;
}
@Override
protected void fillStateContainer(Builder<Block, BlockState> builder) {
super.fillStateContainer(builder.add(DOUBLE));
} }
@Override @Override
@ -53,23 +30,8 @@ public class FlexcrateBlock extends ProperDirectionalBlock {
} }
@Override @Override
public BlockState getStateForPlacement(BlockItemUseContext context) { public TileEntity createTileEntity(BlockState state, IBlockReader world) {
BlockPos pos = context.getPos(); return new FlexcrateTileEntity();
World world = context.getWorld();
if (!context.getPlayer().isSneaking()) {
for (Direction d : Direction.values()) {
BlockState state = world.getBlockState(pos.offset(d));
if (AllBlocks.FLEXCRATE.typeOf(state) && !state.get(DOUBLE))
return getDefaultState().with(FACING, d).with(DOUBLE, true);
}
}
Direction placedOnFace = context.getFace().getOpposite();
BlockState state = world.getBlockState(pos.offset(placedOnFace));
if (AllBlocks.FLEXCRATE.typeOf(state) && !state.get(DOUBLE))
return getDefaultState().with(FACING, placedOnFace).with(DOUBLE, true);
return getDefaultState();
} }
@Override @Override
@ -94,29 +56,6 @@ public class FlexcrateBlock extends ProperDirectionalBlock {
} }
} }
@Override
public BlockState updatePostPlacement(BlockState stateIn, Direction facing, BlockState facingState, IWorld worldIn,
BlockPos currentPos, BlockPos facingPos) {
boolean isDouble = stateIn.get(DOUBLE);
Direction blockFacing = stateIn.get(FACING);
boolean isFacingOther = AllBlocks.FLEXCRATE.typeOf(facingState) && facingState.get(DOUBLE)
&& facingState.get(FACING) == facing.getOpposite();
if (!isDouble) {
if (!isFacingOther)
return stateIn;
return stateIn.with(DOUBLE, true).with(FACING, facing);
}
if (facing != blockFacing)
return stateIn;
if (!isFacingOther)
return stateIn.with(DOUBLE, false);
return stateIn;
}
@Override @Override
public ActionResultType onUse(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn, public ActionResultType onUse(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn,
BlockRayTraceResult hit) { BlockRayTraceResult hit) {
@ -134,11 +73,6 @@ public class FlexcrateBlock extends ProperDirectionalBlock {
} }
} }
@Override
public TileEntity createTileEntity(BlockState state, IBlockReader world) {
return new FlexcrateTileEntity();
}
public static void splitCrate(World world, BlockPos pos) { public static void splitCrate(World world, BlockPos pos) {
BlockState state = world.getBlockState(pos); BlockState state = world.getBlockState(pos);
if (!AllBlocks.FLEXCRATE.typeOf(state)) if (!AllBlocks.FLEXCRATE.typeOf(state))

View file

@ -2,7 +2,6 @@ package com.simibubi.create.modules.logistics.block.inventories;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllTileEntities; import com.simibubi.create.AllTileEntities;
import com.simibubi.create.foundation.block.SyncedTileEntity;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory; import net.minecraft.entity.player.PlayerInventory;
@ -15,7 +14,6 @@ import net.minecraft.network.PacketBuffer;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
import net.minecraft.tileentity.TileEntityType; import net.minecraft.tileentity.TileEntityType;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.Direction.AxisDirection;
import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.StringTextComponent; import net.minecraft.util.text.StringTextComponent;
import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.Capability;
@ -24,7 +22,7 @@ import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.ItemStackHandler; import net.minecraftforge.items.ItemStackHandler;
public class FlexcrateTileEntity extends SyncedTileEntity implements INamedContainerProvider { public class FlexcrateTileEntity extends CrateTileEntity implements INamedContainerProvider {
public class Inv extends ItemStackHandler { public class Inv extends ItemStackHandler {
public Inv() { public Inv() {
@ -81,20 +79,6 @@ public class FlexcrateTileEntity extends SyncedTileEntity implements INamedConta
return new FlexcrateContainer(id, inventory, this); return new FlexcrateContainer(id, inventory, this);
} }
public boolean isDoubleCrate() {
return getBlockState().get(FlexcrateBlock.DOUBLE);
}
public FlexcrateTileEntity getMainCrate() {
if (isSecondaryCrate())
return getOtherCrate();
return this;
}
public boolean isSecondaryCrate() {
return isDoubleCrate() && getFacing().getAxisDirection() == AxisDirection.NEGATIVE;
}
public FlexcrateTileEntity getOtherCrate() { public FlexcrateTileEntity getOtherCrate() {
if (!AllBlocks.FLEXCRATE.typeOf(getBlockState())) if (!AllBlocks.FLEXCRATE.typeOf(getBlockState()))
return null; return null;
@ -104,8 +88,10 @@ public class FlexcrateTileEntity extends SyncedTileEntity implements INamedConta
return null; return null;
} }
public Direction getFacing() { public FlexcrateTileEntity getMainCrate() {
return getBlockState().get(FlexcrateBlock.FACING); if (isSecondaryCrate())
return getOtherCrate();
return this;
} }
public void onSplit() { public void onSplit() {
@ -195,7 +181,7 @@ public class FlexcrateTileEntity extends SyncedTileEntity implements INamedConta
public <T> LazyOptional<T> getCapability(Capability<T> capability, Direction facing) { public <T> LazyOptional<T> getCapability(Capability<T> capability, Direction facing) {
if (capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) { if (capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) {
FlexcrateTileEntity mainCrate = getMainCrate(); FlexcrateTileEntity mainCrate = getMainCrate();
if (mainCrate != null && mainCrate.invHandler.isPresent()) if (mainCrate != null && mainCrate.invHandler != null && mainCrate.invHandler.isPresent())
return mainCrate.invHandler.cast(); return mainCrate.invHandler.cast();
} }
return super.getCapability(capability, facing); return super.getCapability(capability, facing);

View file

@ -2,7 +2,6 @@ package com.simibubi.create.modules.logistics.block.transposer;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.foundation.utility.AllShapes; import com.simibubi.create.foundation.utility.AllShapes;
import com.simibubi.create.modules.contraptions.IWrenchable;
import com.simibubi.create.modules.logistics.block.belts.BeltAttachableLogisticalBlock; import com.simibubi.create.modules.logistics.block.belts.BeltAttachableLogisticalBlock;
import net.minecraft.block.Block; import net.minecraft.block.Block;
@ -23,7 +22,7 @@ import net.minecraft.world.IBlockReader;
import net.minecraft.world.IWorldReader; import net.minecraft.world.IWorldReader;
import net.minecraft.world.World; import net.minecraft.world.World;
public class TransposerBlock extends BeltAttachableLogisticalBlock implements IWrenchable { public class TransposerBlock extends BeltAttachableLogisticalBlock {
public static BooleanProperty POWERED = BlockStateProperties.POWERED; public static BooleanProperty POWERED = BlockStateProperties.POWERED;

View file

@ -0,0 +1,11 @@
package com.simibubi.create.modules.schematics;
import net.minecraft.block.BlockState;
public interface ISpecialBlockItemRequirement {
default ItemRequirement getRequiredItems(BlockState state) {
return ItemRequirement.INVALID;
}
}

View file

@ -0,0 +1,9 @@
package com.simibubi.create.modules.schematics;
public interface ISpecialEntityItemRequirement {
default ItemRequirement getRequiredItems() {
return ItemRequirement.INVALID;
}
}

View file

@ -0,0 +1,125 @@
package com.simibubi.create.modules.schematics;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.item.ArmorStandEntity;
import net.minecraft.entity.item.BoatEntity;
import net.minecraft.entity.item.ItemFrameEntity;
import net.minecraft.entity.item.minecart.AbstractMinecartEntity;
import net.minecraft.item.BlockItem;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.state.properties.SlabType;
public class ItemRequirement {
public enum ItemUseType {
CONSUME, DAMAGE
}
ItemUseType usage;
List<ItemStack> requiredItems;
public static ItemRequirement INVALID = new ItemRequirement();
public static ItemRequirement NONE = new ItemRequirement();
private ItemRequirement() {
}
public ItemRequirement(ItemUseType usage, Item item) {
this(usage, Arrays.asList(new ItemStack(item)));
}
public ItemRequirement(ItemUseType usage, List<ItemStack> requiredItems) {
this.usage = usage;
this.requiredItems = requiredItems;
}
public static ItemRequirement of(BlockState state) {
Block block = state.getBlock();
if (block == Blocks.AIR)
return NONE;
if (block instanceof ISpecialBlockItemRequirement)
return ((ISpecialBlockItemRequirement) block).getRequiredItems(state);
Item item = BlockItem.BLOCK_TO_ITEM.getOrDefault(state.getBlock(), Items.AIR);
// double slab needs two items
if (state.has(BlockStateProperties.SLAB_TYPE) && state.get(BlockStateProperties.SLAB_TYPE) == SlabType.DOUBLE)
return new ItemRequirement(ItemUseType.CONSUME, Arrays.asList(new ItemStack(item, 2)));
return item == Items.AIR ? INVALID : new ItemRequirement(ItemUseType.CONSUME, item);
}
public static ItemRequirement of(Entity entity) {
EntityType<?> type = entity.getType();
if (entity instanceof ISpecialEntityItemRequirement)
return ((ISpecialEntityItemRequirement) entity).getRequiredItems();
if (type == EntityType.ITEM_FRAME) {
ItemFrameEntity ife = (ItemFrameEntity) entity;
ItemStack frame = new ItemStack(Items.ITEM_FRAME);
ItemStack displayedItem = ife.getDisplayedItem();
if (displayedItem.isEmpty())
return new ItemRequirement(ItemUseType.CONSUME, Items.ITEM_FRAME);
return new ItemRequirement(ItemUseType.CONSUME, Arrays.asList(frame, displayedItem));
}
if (type == EntityType.PAINTING)
return new ItemRequirement(ItemUseType.CONSUME, Items.PAINTING);
if (type == EntityType.ARMOR_STAND) {
List<ItemStack> requirements = new ArrayList<>();
ArmorStandEntity armorStandEntity = (ArmorStandEntity) entity;
armorStandEntity.getEquipmentAndArmor().forEach(requirements::add);
requirements.add(new ItemStack(Items.ARMOR_STAND));
return new ItemRequirement(ItemUseType.CONSUME, requirements);
}
if (entity instanceof AbstractMinecartEntity) {
AbstractMinecartEntity minecartEntity = (AbstractMinecartEntity) entity;
return new ItemRequirement(ItemUseType.CONSUME, minecartEntity.getCartItem().getItem());
}
if (entity instanceof BoatEntity) {
BoatEntity boatEntity = (BoatEntity) entity;
return new ItemRequirement(ItemUseType.CONSUME, boatEntity.getItemBoat().getItem());
}
if (type == EntityType.END_CRYSTAL)
return new ItemRequirement(ItemUseType.CONSUME, Items.END_CRYSTAL);
return INVALID;
}
public boolean isEmpty() {
return NONE == this;
}
public boolean isInvalid() {
return INVALID == this;
}
public List<ItemStack> getRequiredItems() {
return requiredItems;
}
public ItemUseType getUsage() {
return usage;
}
public static boolean validate(ItemStack required, ItemStack present) {
return required.isEmpty() || required.getItem() == present.getItem();
}
}

View file

@ -7,6 +7,9 @@ import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
import com.google.common.collect.Sets;
import com.simibubi.create.modules.schematics.ItemRequirement.ItemUseType;
import net.minecraft.item.Item; import net.minecraft.item.Item;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.item.Items; import net.minecraft.item.Items;
@ -21,10 +24,12 @@ public class MaterialChecklist {
public Map<Item, Integer> gathered; public Map<Item, Integer> gathered;
public Map<Item, Integer> required; public Map<Item, Integer> required;
public Map<Item, Integer> damageRequired;
public boolean blocksNotLoaded; public boolean blocksNotLoaded;
public MaterialChecklist() { public MaterialChecklist() {
required = new HashMap<>(); required = new HashMap<>();
damageRequired = new HashMap<>();
gathered = new HashMap<>(); gathered = new HashMap<>();
} }
@ -32,16 +37,33 @@ public class MaterialChecklist {
blocksNotLoaded = true; blocksNotLoaded = true;
} }
public void require(Item item) { public void require(ItemRequirement requirement) {
if (required.containsKey(item)) if (requirement.isEmpty())
required.put(item, required.get(item) + 1); return;
if (requirement.isInvalid())
return;
for (ItemStack stack : requirement.requiredItems) {
if (requirement.getUsage() == ItemUseType.DAMAGE)
putOrIncrement(damageRequired, stack);
if (requirement.getUsage() == ItemUseType.CONSUME)
putOrIncrement(required, stack);
}
}
private void putOrIncrement(Map<Item, Integer> map, ItemStack stack) {
Item item = stack.getItem();
if (item == Items.AIR)
return;
if (map.containsKey(item))
map.put(item, map.get(item) + stack.getCount());
else else
required.put(item, 1); map.put(item, stack.getCount());
} }
public void collect(ItemStack stack) { public void collect(ItemStack stack) {
Item item = stack.getItem(); Item item = stack.getItem();
if (required.containsKey(item)) if (required.containsKey(item) || damageRequired.containsKey(item))
if (gathered.containsKey(item)) if (gathered.containsKey(item))
gathered.put(item, gathered.get(item) + stack.getCount()); gathered.put(item, gathered.get(item) + stack.getCount());
else else
@ -65,19 +87,19 @@ public class MaterialChecklist {
string = new StringBuilder("{\"text\":\""); string = new StringBuilder("{\"text\":\"");
} }
List<Item> keys = new ArrayList<>(required.keySet()); List<Item> keys = new ArrayList<>(Sets.union(required.keySet(), damageRequired.keySet()));
Collections.sort(keys, (item1, item2) -> { Collections.sort(keys, (item1, item2) -> {
Locale locale = Locale.ENGLISH; Locale locale = Locale.ENGLISH;
String name1 = new TranslationTextComponent(((Item) item1).getTranslationKey()).getFormattedText() String name1 =
.toLowerCase(locale); new TranslationTextComponent(((Item) item1).getTranslationKey()).getFormattedText().toLowerCase(locale);
String name2 = new TranslationTextComponent(((Item) item2).getTranslationKey()).getFormattedText() String name2 =
.toLowerCase(locale); new TranslationTextComponent(((Item) item2).getTranslationKey()).getFormattedText().toLowerCase(locale);
return name1.compareTo(name2); return name1.compareTo(name2);
}); });
List<Item> completed = new ArrayList<>(); List<Item> completed = new ArrayList<>();
for (Item item : keys) { for (Item item : keys) {
int amount = required.get(item); int amount = getRequiredAmount(item);
if (gathered.containsKey(item)) if (gathered.containsKey(item))
amount -= gathered.get(item); amount -= gathered.get(item);
@ -106,7 +128,7 @@ public class MaterialChecklist {
} }
itemsWritten++; itemsWritten++;
string.append(gatheredEntry(new ItemStack(item), required.get(item))); string.append(gatheredEntry(new ItemStack(item), getRequiredAmount(item)));
} }
string.append("\"}"); string.append("\"}");
@ -120,6 +142,13 @@ public class MaterialChecklist {
return book; return book;
} }
public Integer getRequiredAmount(Item item) {
int amount = required.getOrDefault(item, 0);
if (damageRequired.containsKey(item))
amount += Math.ceil(damageRequired.get(item) / (float) new ItemStack(item).getMaxDamage());
return amount;
}
private String gatheredEntry(ItemStack item, int amount) { private String gatheredEntry(ItemStack item, int amount) {
int stacks = amount / 64; int stacks = amount / 64;
int remainder = amount % 64; int remainder = amount % 64;

View file

@ -1,5 +1,6 @@
package com.simibubi.create.modules.schematics; package com.simibubi.create.modules.schematics;
import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
@ -14,6 +15,8 @@ import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks; import net.minecraft.block.Blocks;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.item.ArmorStandEntity;
import net.minecraft.entity.item.ItemFrameEntity;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.fluid.Fluid; import net.minecraft.fluid.Fluid;
import net.minecraft.fluid.IFluidState; import net.minecraft.fluid.IFluidState;
@ -31,6 +34,7 @@ public class SchematicWorld extends WrappedWorld {
private Map<BlockPos, BlockState> blocks; private Map<BlockPos, BlockState> blocks;
private Map<BlockPos, TileEntity> tileEntities; private Map<BlockPos, TileEntity> tileEntities;
private List<Entity> entities;
private Cuboid bounds; private Cuboid bounds;
public BlockPos anchor; public BlockPos anchor;
public boolean renderMode; public boolean renderMode;
@ -41,12 +45,29 @@ public class SchematicWorld extends WrappedWorld {
this.tileEntities = new HashMap<>(); this.tileEntities = new HashMap<>();
this.bounds = new Cuboid(); this.bounds = new Cuboid();
this.anchor = anchor; this.anchor = anchor;
this.entities = new ArrayList<>();
} }
public Set<BlockPos> getAllPositions() { public Set<BlockPos> getAllPositions() {
return blocks.keySet(); return blocks.keySet();
} }
@Override
public boolean addEntity(Entity entityIn) {
if (entityIn instanceof ItemFrameEntity)
((ItemFrameEntity) entityIn).getDisplayedItem().setTag(null);
if (entityIn instanceof ArmorStandEntity) {
ArmorStandEntity armorStandEntity = (ArmorStandEntity) entityIn;
armorStandEntity.getEquipmentAndArmor().forEach(stack -> stack.setTag(null));
}
return entities.add(entityIn);
}
public List<Entity> getEntities() {
return entities;
}
@Override @Override
public TileEntity getTileEntity(BlockPos pos) { public TileEntity getTileEntity(BlockPos pos) {
if (isOutsideBuildHeight(pos)) if (isOutsideBuildHeight(pos))

View file

@ -25,7 +25,6 @@ import com.simibubi.create.modules.schematics.item.SchematicItem;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.entity.player.ServerPlayerEntity; import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.text.StringTextComponent; import net.minecraft.util.text.StringTextComponent;
import net.minecraft.util.text.TranslationTextComponent; import net.minecraft.util.text.TranslationTextComponent;
@ -234,7 +233,6 @@ public class ServerSchematicLoader {
if (table == null) if (table == null)
return; return;
table.finishUpload(); table.finishUpload();
table.inventory.setStackInSlot(0, ItemStack.EMPTY);
table.inventory.setStackInSlot(1, SchematicItem.create(schematic, player.getName().getFormattedText())); table.inventory.setStackInSlot(1, SchematicItem.create(schematic, player.getName().getFormattedText()));
} catch (IOException e) { } catch (IOException e) {

View file

@ -1,30 +0,0 @@
package com.simibubi.create.modules.schematics.block;
import com.simibubi.create.foundation.utility.AllShapes;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.item.ItemGroup;
import net.minecraft.item.ItemStack;
import net.minecraft.util.NonNullList;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.shapes.ISelectionContext;
import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.world.IBlockReader;
public class CreativeCrateBlock extends Block {
public CreativeCrateBlock(Properties properties) {
super(properties);
}
@Override
public void fillItemGroup(ItemGroup group, NonNullList<ItemStack> items) {
}
@Override
public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) {
return AllShapes.CRATE_BLOCK_SHAPE;
}
}

View file

@ -1,36 +0,0 @@
package com.simibubi.create.modules.schematics.block;
import net.minecraft.block.BlockState;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
public class LaunchedBlock {
private final SchematicannonTileEntity te;
public int totalTicks;
public int ticksRemaining;
public BlockPos target;
public BlockState state;
public LaunchedBlock(SchematicannonTileEntity schematicannonTileEntity, BlockPos target, BlockState state) {
te = schematicannonTileEntity;
this.target = target;
this.state = state;
totalTicks = (int) (Math.max(10, MathHelper.sqrt(MathHelper.sqrt(target.distanceSq(te.getPos()))) * 4f));
ticksRemaining = totalTicks;
}
public LaunchedBlock(SchematicannonTileEntity schematicannonTileEntity, BlockPos target, BlockState state,
int ticksLeft, int total) {
te = schematicannonTileEntity;
this.target = target;
this.state = state;
this.totalTicks = total;
this.ticksRemaining = ticksLeft;
}
public void update() {
if (ticksRemaining > 0)
ticksRemaining--;
}
}

View file

@ -0,0 +1,210 @@
package com.simibubi.create.modules.schematics.block;
import java.util.Optional;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Part;
import com.simibubi.create.modules.contraptions.relays.belt.item.BeltConnectorItem;
import com.simibubi.create.modules.contraptions.relays.elementary.ShaftBlock;
import net.minecraft.block.BlockState;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.nbt.NBTUtil;
import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.World;
public abstract class LaunchedItem {
public int totalTicks;
public int ticksRemaining;
public BlockPos target;
public ItemStack stack;
private LaunchedItem(BlockPos start, BlockPos target, ItemStack stack) {
this(target, stack, ticksForDistance(start, target), ticksForDistance(start, target));
}
private static int ticksForDistance(BlockPos start, BlockPos target) {
return (int) (Math.max(10, MathHelper.sqrt(MathHelper.sqrt(target.distanceSq(start))) * 4f));
}
LaunchedItem() {}
private LaunchedItem(BlockPos target, ItemStack stack, int ticksLeft, int total) {
this.target = target;
this.stack = stack;
this.totalTicks = total;
this.ticksRemaining = ticksLeft;
}
public boolean update(World world) {
if (ticksRemaining > 0) {
ticksRemaining--;
return false;
}
if (world.isRemote)
return false;
place(world);
return true;
}
public CompoundNBT serializeNBT() {
CompoundNBT c = new CompoundNBT();
c.putInt("TotalTicks", totalTicks);
c.putInt("TicksLeft", ticksRemaining);
c.put("Stack", stack.serializeNBT());
c.put("Target", NBTUtil.writeBlockPos(target));
return c;
}
public static LaunchedItem fromNBT(CompoundNBT c) {
LaunchedItem launched = c.contains("Length") ? new LaunchedItem.ForBelt()
: c.contains("BlockState") ? new LaunchedItem.ForBlockState() : new LaunchedItem.ForEntity();
launched.readNBT(c);
return launched;
}
abstract void place(World world);
void readNBT(CompoundNBT c) {
target = NBTUtil.readBlockPos(c.getCompound("Target"));
ticksRemaining = c.getInt("TicksLeft");
totalTicks = c.getInt("TotalTicks");
stack = ItemStack.read(c.getCompound("Stack"));
}
public static class ForBlockState extends LaunchedItem {
public BlockState state;
ForBlockState() {}
public ForBlockState(BlockPos start, BlockPos target, ItemStack stack, BlockState state) {
super(start, target, stack);
this.state = state;
}
@Override
public CompoundNBT serializeNBT() {
CompoundNBT serializeNBT = super.serializeNBT();
serializeNBT.put("BlockState", NBTUtil.writeBlockState(state));
return serializeNBT;
}
@Override
void readNBT(CompoundNBT nbt) {
super.readNBT(nbt);
state = NBTUtil.readBlockState(nbt.getCompound("BlockState"));
}
@Override
void place(World world) {
// Piston
if (state.has(BlockStateProperties.EXTENDED))
state = state.with(BlockStateProperties.EXTENDED, false);
if (AllBlocks.BELT.typeOf(state)) {
world.setBlockState(target, state, 2);
return;
}
world.setBlockState(target, state, 18);
state.getBlock().onBlockPlacedBy(world, target, state, null, stack);
}
}
public static class ForBelt extends ForBlockState {
public int length;
public ForBelt() {}
@Override
public CompoundNBT serializeNBT() {
CompoundNBT serializeNBT = super.serializeNBT();
serializeNBT.putInt("Length", length);
return serializeNBT;
}
@Override
void readNBT(CompoundNBT nbt) {
length = nbt.getInt("Length");
super.readNBT(nbt);
}
public ForBelt(BlockPos start, BlockPos target, ItemStack stack, BlockState state, int length) {
super(start, target, stack, state);
this.length = length;
}
@Override
void place(World world) {
// todo place belt
boolean isStart = state.get(BeltBlock.PART) == Part.START;
BlockPos offset = BeltBlock.nextSegmentPosition(state, BlockPos.ZERO, isStart);
int i = length - 1;
Axis axis = state.get(BeltBlock.HORIZONTAL_FACING).rotateY().getAxis();
world.setBlockState(target, AllBlocks.SHAFT.getDefault().with(ShaftBlock.AXIS, axis));
BeltConnectorItem
.createBelts(world, target, target.add(offset.getX() * i, offset.getY() * i, offset.getZ() * i));
}
}
public static class ForEntity extends LaunchedItem {
public Entity entity;
private CompoundNBT deferredTag;
ForEntity() {}
public ForEntity(BlockPos start, BlockPos target, ItemStack stack, Entity entity) {
super(start, target, stack);
this.entity = entity;
}
@Override
public boolean update(World world) {
if (deferredTag != null && entity == null) {
try {
Optional<Entity> loadEntityUnchecked = EntityType.loadEntityUnchecked(deferredTag, world);
if (!loadEntityUnchecked.isPresent())
return true;
entity = loadEntityUnchecked.get();
} catch (Exception var3) {
return true;
}
deferredTag = null;
}
return super.update(world);
}
@Override
public CompoundNBT serializeNBT() {
CompoundNBT serializeNBT = super.serializeNBT();
if (entity != null)
serializeNBT.put("Entity", entity.serializeNBT());
return serializeNBT;
}
@Override
void readNBT(CompoundNBT nbt) {
super.readNBT(nbt);
if (nbt.contains("Entity"))
deferredTag = nbt.getCompound("Entity");
}
@Override
void place(World world) {
world.addEntity(entity);
}
}
}

View file

@ -7,6 +7,7 @@ import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory; import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.inventory.container.Container; import net.minecraft.inventory.container.Container;
import net.minecraft.inventory.container.INamedContainerProvider; import net.minecraft.inventory.container.INamedContainerProvider;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.CompoundNBT;
import net.minecraft.network.PacketBuffer; import net.minecraft.network.PacketBuffer;
import net.minecraft.tileentity.ITickableTileEntity; import net.minecraft.tileentity.ITickableTileEntity;
@ -102,6 +103,7 @@ public class SchematicTableTileEntity extends SyncedTileEntity implements ITicka
uploadingProgress = 0; uploadingProgress = 0;
uploadingSchematic = schematic; uploadingSchematic = schematic;
sendUpdate = true; sendUpdate = true;
inventory.setStackInSlot(0, ItemStack.EMPTY);
} }
public void finishUpload() { public void finishUpload() {

View file

@ -17,7 +17,6 @@ import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.util.math.shapes.ISelectionContext; import net.minecraft.util.math.shapes.ISelectionContext;
import net.minecraft.util.math.shapes.VoxelShape; import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.world.IBlockReader; import net.minecraft.world.IBlockReader;
import net.minecraft.world.IWorldReader;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraftforge.fml.network.NetworkHooks; import net.minecraftforge.fml.network.NetworkHooks;
@ -47,17 +46,11 @@ public class SchematicannonBlock extends Block implements ITE<SchematicannonTile
return AllShapes.SCHEMATICANNON_SHAPE; return AllShapes.SCHEMATICANNON_SHAPE;
} }
@Override
public void onNeighborChange(BlockState state, IWorldReader world, BlockPos pos, BlockPos neighbor) {
withTileEntityDo(world, pos, SchematicannonTileEntity::findInventories);
}
@Override @Override
public ActionResultType onUse(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn, public ActionResultType onUse(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn,
BlockRayTraceResult hit) { BlockRayTraceResult hit) {
if (worldIn.isRemote) if (worldIn.isRemote)
return ActionResultType.SUCCESS; return ActionResultType.SUCCESS;
withTileEntityDo(worldIn, pos, withTileEntityDo(worldIn, pos,
te -> NetworkHooks.openGui((ServerPlayerEntity) player, te, te::sendToContainer)); te -> NetworkHooks.openGui((ServerPlayerEntity) player, te, te::sendToContainer));
return ActionResultType.SUCCESS; return ActionResultType.SUCCESS;

View file

@ -3,10 +3,13 @@ package com.simibubi.create.modules.schematics.block;
import java.util.Random; import java.util.Random;
import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.platform.GlStateManager;
import com.mojang.blaze3d.vertex.IVertexBuilder; import com.mojang.blaze3d.vertex.IVertexBuilder;
import com.simibubi.create.AllBlockPartials; import com.simibubi.create.AllBlockPartials;
import com.simibubi.create.foundation.block.SafeTileEntityRenderer; import com.simibubi.create.foundation.block.SafeTileEntityRenderer;
import com.simibubi.create.foundation.utility.SuperByteBuffer; import com.simibubi.create.foundation.utility.SuperByteBuffer;
import com.simibubi.create.modules.schematics.block.LaunchedItem.ForBlockState;
import com.simibubi.create.modules.schematics.block.LaunchedItem.ForEntity;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
@ -14,6 +17,7 @@ import net.minecraft.client.renderer.IRenderTypeBuffer;
import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.Vector3f; import net.minecraft.client.renderer.Vector3f;
import net.minecraft.client.renderer.WorldRenderer; import net.minecraft.client.renderer.WorldRenderer;
import net.minecraft.client.renderer.model.ItemCameraTransforms.TransformType;
import net.minecraft.client.renderer.texture.AtlasTexture; import net.minecraft.client.renderer.texture.AtlasTexture;
import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher; import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher;
import net.minecraft.particles.ParticleTypes; import net.minecraft.particles.ParticleTypes;
@ -23,6 +27,7 @@ import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
import net.minecraftforge.client.model.data.EmptyModelData; import net.minecraftforge.client.model.data.EmptyModelData;
@SuppressWarnings("deprecation")
public class SchematicannonRenderer extends SafeTileEntityRenderer<SchematicannonTileEntity> { public class SchematicannonRenderer extends SafeTileEntityRenderer<SchematicannonTileEntity> {
public SchematicannonRenderer(TileEntityRendererDispatcher dispatcher) { public SchematicannonRenderer(TileEntityRendererDispatcher dispatcher) {
@ -30,8 +35,8 @@ public class SchematicannonRenderer extends SafeTileEntityRenderer<Schematicanno
} }
@Override @Override
protected void renderSafe(SchematicannonTileEntity tileEntityIn, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer, protected void renderSafe(SchematicannonTileEntity tileEntityIn, float partialTicks, MatrixStack ms,
int light, int overlay) { IRenderTypeBuffer buffer, int light, int overlay) {
Minecraft.getInstance().getTextureManager().bindTexture(AtlasTexture.LOCATION_BLOCKS_TEXTURE); Minecraft.getInstance().getTextureManager().bindTexture(AtlasTexture.LOCATION_BLOCKS_TEXTURE);
@ -63,14 +68,14 @@ public class SchematicannonRenderer extends SafeTileEntityRenderer<Schematicanno
} }
if (!tileEntityIn.flyingBlocks.isEmpty()) { if (!tileEntityIn.flyingBlocks.isEmpty()) {
for (LaunchedBlock block : tileEntityIn.flyingBlocks) { for (LaunchedItem launched : tileEntityIn.flyingBlocks) {
if (block.ticksRemaining == 0) if (launched.ticksRemaining == 0)
continue; continue;
// Calculate position of flying block // Calculate position of flying block
Vec3d start = new Vec3d(tileEntityIn.getPos().add(.5f, 1, .5f)); Vec3d start = new Vec3d(tileEntityIn.getPos().add(.5f, 1, .5f));
Vec3d target = new Vec3d(block.target).add(-.5, 0, 1); Vec3d target = new Vec3d(launched.target).add(-.5, 0, 1);
Vec3d distance = target.subtract(start); Vec3d distance = target.subtract(start);
double targetY = target.y - start.y; double targetY = target.y - start.y;
@ -78,10 +83,9 @@ public class SchematicannonRenderer extends SafeTileEntityRenderer<Schematicanno
Vec3d cannonOffset = distance.add(0, throwHeight, 0).normalize().scale(2); Vec3d cannonOffset = distance.add(0, throwHeight, 0).normalize().scale(2);
start = start.add(cannonOffset); start = start.add(cannonOffset);
float progress = ((float) block.totalTicks - (block.ticksRemaining + 1 - partialTicks)) float progress =
/ block.totalTicks; ((float) launched.totalTicks - (launched.ticksRemaining + 1 - partialTicks)) / launched.totalTicks;
Vec3d blockLocationXZ = new Vec3d(.5, .5, .5) Vec3d blockLocationXZ = new Vec3d(.5, .5, .5).add(target.subtract(start).scale(progress).mul(1, 0, 1));
.add(target.subtract(start).scale(progress).mul(1, 0, 1));
// Height is determined through a bezier curve // Height is determined through a bezier curve
float t = progress; float t = progress;
@ -93,21 +97,33 @@ public class SchematicannonRenderer extends SafeTileEntityRenderer<Schematicanno
ms.translate(blockLocation.x, blockLocation.y, blockLocation.z); ms.translate(blockLocation.x, blockLocation.y, blockLocation.z);
// Rotation and Scaling effects // Rotation and Scaling effects
float scale = .3f;
ms.multiply(new Vector3f(1, 1, 0).getDegreesQuaternion(360 * t * 2)); ms.multiply(new Vector3f(1, 1, 0).getDegreesQuaternion(360 * t * 2));
ms.scale(scale, scale, scale);
// Render the Block // Render the Block
Minecraft.getInstance().getBlockRendererDispatcher().renderBlock(block.state, ms, buffer, light, overlay, EmptyModelData.INSTANCE); if (launched instanceof ForBlockState) {
float scale = .3f;
ms.scale(scale, scale, scale);
Minecraft.getInstance().getBlockRendererDispatcher().renderBlock(((ForBlockState) launched).state,
ms, buffer, light, overlay, EmptyModelData.INSTANCE);
}
// Render the item
if (launched instanceof ForEntity) {
double scale = 1.2f;
GlStateManager.scaled(scale, scale, scale);
Minecraft.getInstance().getItemRenderer().renderItem(launched.stack, TransformType.GROUND, light,
overlay, ms, buffer);
}
ms.pop(); ms.pop();
// Apply Recoil if block was just launched // Apply Recoil if block was just launched
if ((block.ticksRemaining + 1 - partialTicks) > block.totalTicks - 10) { if ((launched.ticksRemaining + 1 - partialTicks) > launched.totalTicks - 10) {
recoil = Math.max(recoil, (block.ticksRemaining + 1 - partialTicks) - block.totalTicks + 10); recoil = Math.max(recoil, (launched.ticksRemaining + 1 - partialTicks) - launched.totalTicks + 10);
} }
// Render particles for launch // Render particles for launch
if (block.ticksRemaining == block.totalTicks && tileEntityIn.firstRenderTick) { if (launched.ticksRemaining == launched.totalTicks && tileEntityIn.firstRenderTick) {
tileEntityIn.firstRenderTick = false; tileEntityIn.firstRenderTick = false;
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
Random r = tileEntityIn.getWorld().getRandom(); Random r = tileEntityIn.getWorld().getRandom();

View file

@ -26,7 +26,6 @@ import net.minecraft.client.gui.widget.Widget;
import net.minecraft.client.renderer.Rectangle2d; import net.minecraft.client.renderer.Rectangle2d;
import net.minecraft.client.renderer.RenderHelper; import net.minecraft.client.renderer.RenderHelper;
import net.minecraft.entity.player.PlayerInventory; import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.item.BlockItem;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TextFormatting; import net.minecraft.util.text.TextFormatting;
@ -83,16 +82,17 @@ public class SchematicannonScreen extends AbstractSimiContainerScreen<Schematica
resetButton = new IconButton(x + 106, y + 55, ScreenResources.I_STOP); resetButton = new IconButton(x + 106, y + 55, ScreenResources.I_STOP);
resetIndicator = new Indicator(x + 106, y + 50, ""); resetIndicator = new Indicator(x + 106, y + 50, "");
resetIndicator.state = State.RED; resetIndicator.state = State.RED;
Collections.addAll(widgets, playButton, playIndicator, pauseButton, pauseIndicator, resetButton, Collections
resetIndicator); .addAll(widgets, playButton, playIndicator, pauseButton, pauseIndicator, resetButton, resetIndicator);
// Replace settings // Replace settings
replaceLevelButtons = new Vector<>(4); replaceLevelButtons = new Vector<>(4);
replaceLevelIndicators = new Vector<>(4); replaceLevelIndicators = new Vector<>(4);
List<ScreenResources> icons = ImmutableList.of(ScreenResources.I_DONT_REPLACE, List<ScreenResources> icons = ImmutableList
ScreenResources.I_REPLACE_SOLID, ScreenResources.I_REPLACE_ANY, .of(ScreenResources.I_DONT_REPLACE, ScreenResources.I_REPLACE_SOLID, ScreenResources.I_REPLACE_ANY,
ScreenResources.I_REPLACE_EMPTY); ScreenResources.I_REPLACE_EMPTY);
List<String> toolTips = ImmutableList.of(Lang.translate("gui.schematicannon.option.dontReplaceSolid"), List<String> toolTips = ImmutableList
.of(Lang.translate("gui.schematicannon.option.dontReplaceSolid"),
Lang.translate("gui.schematicannon.option.replaceWithSolid"), Lang.translate("gui.schematicannon.option.replaceWithSolid"),
Lang.translate("gui.schematicannon.option.replaceWithAny"), Lang.translate("gui.schematicannon.option.replaceWithAny"),
Lang.translate("gui.schematicannon.option.replaceWithEmpty")); Lang.translate("gui.schematicannon.option.replaceWithEmpty"));
@ -191,8 +191,10 @@ public class SchematicannonScreen extends AbstractSimiContainerScreen<Schematica
boolean enabled = indicator.state == State.ON; boolean enabled = indicator.state == State.ON;
List<String> tip = button.getToolTip(); List<String> tip = button.getToolTip();
tip.add(TextFormatting.BLUE + (enabled ? optionEnabled : optionDisabled)); tip.add(TextFormatting.BLUE + (enabled ? optionEnabled : optionDisabled));
tip.addAll(TooltipHelper.cutString(Lang.translate("gui.schematicannon.option." + tooltipKey + ".description"), tip
GRAY, GRAY)); .addAll(TooltipHelper
.cutString(Lang.translate("gui.schematicannon.option." + tooltipKey + ".description"), GRAY,
GRAY));
} }
@Override @Override
@ -215,21 +217,22 @@ public class SchematicannonScreen extends AbstractSimiContainerScreen<Schematica
String msg = Lang.translate("schematicannon.status." + te.statusMsg); String msg = Lang.translate("schematicannon.status." + te.statusMsg);
int stringWidth = font.getStringWidth(msg); int stringWidth = font.getStringWidth(msg);
if (te.missingBlock != null) { if (te.missingItem != null) {
stringWidth += 15; stringWidth += 15;
itemRenderer.renderItemIntoGUI(new ItemStack(BlockItem.BLOCK_TO_ITEM.get(te.missingBlock.getBlock())), itemRenderer.renderItemIntoGUI(te.missingItem, guiLeft + 145, guiTop + 25);
guiLeft + 145, guiTop + 25);
} }
font.drawStringWithShadow(msg, guiLeft + 20 + 96 - stringWidth / 2, guiTop + 30, 0xCCDDFF); font.drawStringWithShadow(msg, guiLeft + 20 + 96 - stringWidth / 2, guiTop + 30, 0xCCDDFF);
font.drawString(settingsTitle, guiLeft + 20 + 13, guiTop + 84, ScreenResources.FONT_COLOR); font.drawString(settingsTitle, guiLeft + 20 + 13, guiTop + 84, ScreenResources.FONT_COLOR);
font.drawString(playerInventory.getDisplayName().getFormattedText(), guiLeft - 10 + 7, guiTop + 145 + 6, font
.drawString(playerInventory.getDisplayName().getFormattedText(), guiLeft - 10 + 7, guiTop + 145 + 6,
0x666666); 0x666666);
//to see or debug the bounds of the extra area uncomment the following lines // to see or debug the bounds of the extra area uncomment the following lines
//Rectangle2d r = extraAreas.get(0); // Rectangle2d r = extraAreas.get(0);
//fill(r.getX() + r.getWidth(), r.getY() + r.getHeight(), r.getX(), r.getY(), 0xd3d3d3d3); // fill(r.getX() + r.getWidth(), r.getY() + r.getHeight(), r.getX(), r.getY(),
// 0xd3d3d3d3);
} }
protected void renderCannon() { protected void renderCannon() {
@ -270,6 +273,10 @@ public class SchematicannonScreen extends AbstractSimiContainerScreen<Schematica
protected void renderFuelBar(float amount) { protected void renderFuelBar(float amount) {
ScreenResources sprite = ScreenResources.SCHEMATICANNON_FUEL; ScreenResources sprite = ScreenResources.SCHEMATICANNON_FUEL;
if (container.getTileEntity().hasCreativeCrate) {
ScreenResources.SCHEMATICANNON_FUEL_CREATIVE.draw(this, guiLeft + 20 + 73, guiTop + 135);
return;
}
minecraft.getTextureManager().bindTexture(sprite.location); minecraft.getTextureManager().bindTexture(sprite.location);
blit(guiLeft + 20 + 73, guiTop + 135, sprite.startX, sprite.startY, (int) (sprite.width * amount), blit(guiLeft + 20 + 73, guiTop + 135, sprite.startX, sprite.startY, (int) (sprite.width * amount),
sprite.height); sprite.height);
@ -282,21 +289,30 @@ public class SchematicannonScreen extends AbstractSimiContainerScreen<Schematica
if (mouseX >= fuelX && mouseY >= fuelY && mouseX <= fuelX + ScreenResources.SCHEMATICANNON_FUEL.width if (mouseX >= fuelX && mouseY >= fuelY && mouseX <= fuelX + ScreenResources.SCHEMATICANNON_FUEL.width
&& mouseY <= fuelY + ScreenResources.SCHEMATICANNON_FUEL.height) { && mouseY <= fuelY + ScreenResources.SCHEMATICANNON_FUEL.height) {
container.getTileEntity(); container.getTileEntity();
double fuelUsageRate = te.getFuelUsageRate(); double fuelUsageRate = te.getFuelUsageRate();
int shotsLeft = (int) (te.fuelLevel / fuelUsageRate); int shotsLeft = (int) (te.fuelLevel / fuelUsageRate);
int shotsLeftWithItems = (int) (shotsLeft int shotsLeftWithItems = (int) (shotsLeft
+ te.inventory.getStackInSlot(4).getCount() * (te.getFuelAddedByGunPowder() / fuelUsageRate)); + te.inventory.getStackInSlot(4).getCount() * (te.getFuelAddedByGunPowder() / fuelUsageRate));
renderTooltip(ImmutableList.of(Lang.translate(_gunpowderLevel, "" + (int) (te.fuelLevel * 100)),
GRAY + Lang.translate(_shotsRemaining, "" + TextFormatting.BLUE + shotsLeft), List<String> tooltip = new ArrayList<>();
GRAY + Lang.translate(_shotsRemainingWithBackup, "" + TextFormatting.BLUE + shotsLeftWithItems)), float f = te.hasCreativeCrate ? 100 : te.fuelLevel * 100;
mouseX, mouseY); tooltip.add(Lang.translate(_gunpowderLevel, "" + (int) f));
if (!te.hasCreativeCrate)
tooltip.add(GRAY + Lang.translate(_shotsRemaining, "" + TextFormatting.BLUE + shotsLeft));
if (shotsLeftWithItems != shotsLeft)
tooltip
.add(GRAY + Lang
.translate(_shotsRemainingWithBackup, "" + TextFormatting.BLUE + shotsLeftWithItems));
renderTooltip(tooltip, mouseX, mouseY);
} }
if (te.missingBlock != null) { if (te.missingItem != null) {
int missingBlockX = guiLeft + 145, missingBlockY = guiTop + 25; int missingBlockX = guiLeft + 145, missingBlockY = guiTop + 25;
if (mouseX >= missingBlockX && mouseY >= missingBlockY && mouseX <= missingBlockX + 16 if (mouseX >= missingBlockX && mouseY >= missingBlockY && mouseX <= missingBlockX + 16
&& mouseY <= missingBlockY + 16) { && mouseY <= missingBlockY + 16) {
renderTooltip(new ItemStack(BlockItem.BLOCK_TO_ITEM.get(te.missingBlock.getBlock())), mouseX, mouseY); renderTooltip(te.missingItem, mouseX, mouseY);
} }
} }

View file

@ -11,6 +11,15 @@ import com.simibubi.create.config.AllConfigs;
import com.simibubi.create.config.CSchematics; import com.simibubi.create.config.CSchematics;
import com.simibubi.create.foundation.behaviour.base.SmartTileEntity; import com.simibubi.create.foundation.behaviour.base.SmartTileEntity;
import com.simibubi.create.foundation.behaviour.base.TileEntityBehaviour; import com.simibubi.create.foundation.behaviour.base.TileEntityBehaviour;
import com.simibubi.create.foundation.item.ItemHelper;
import com.simibubi.create.foundation.item.ItemHelper.ExtractionCountMode;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Part;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Slope;
import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity;
import com.simibubi.create.modules.contraptions.relays.elementary.ShaftBlock;
import com.simibubi.create.modules.schematics.ItemRequirement;
import com.simibubi.create.modules.schematics.ItemRequirement.ItemUseType;
import com.simibubi.create.modules.schematics.MaterialChecklist; import com.simibubi.create.modules.schematics.MaterialChecklist;
import com.simibubi.create.modules.schematics.SchematicWorld; import com.simibubi.create.modules.schematics.SchematicWorld;
import com.simibubi.create.modules.schematics.item.SchematicItem; import com.simibubi.create.modules.schematics.item.SchematicItem;
@ -18,6 +27,7 @@ import com.simibubi.create.modules.schematics.item.SchematicItem;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks; import net.minecraft.block.Blocks;
import net.minecraft.block.PistonHeadBlock; import net.minecraft.block.PistonHeadBlock;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory; import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.inventory.container.Container; import net.minecraft.inventory.container.Container;
@ -33,21 +43,23 @@ import net.minecraft.network.PacketBuffer;
import net.minecraft.state.properties.BedPart; import net.minecraft.state.properties.BedPart;
import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.state.properties.DoubleBlockHalf; import net.minecraft.state.properties.DoubleBlockHalf;
import net.minecraft.state.properties.SlabType;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
import net.minecraft.tileentity.TileEntityType; import net.minecraft.tileentity.TileEntityType;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.Direction.AxisDirection;
import net.minecraft.util.SoundCategory; import net.minecraft.util.SoundCategory;
import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.StringTextComponent; import net.minecraft.util.text.StringTextComponent;
import net.minecraft.world.gen.feature.template.PlacementSettings;
import net.minecraft.world.gen.feature.template.Template; import net.minecraft.world.gen.feature.template.Template;
import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.ItemHandlerHelper;
public class SchematicannonTileEntity extends SmartTileEntity implements INamedContainerProvider { public class SchematicannonTileEntity extends SmartTileEntity implements INamedContainerProvider {
@ -71,17 +83,18 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
public BlockPos currentPos; public BlockPos currentPos;
public BlockPos schematicAnchor; public BlockPos schematicAnchor;
public boolean schematicLoaded; public boolean schematicLoaded;
public BlockState missingBlock; public ItemStack missingItem;
public boolean blockNotLoaded; public boolean positionNotLoaded;
public boolean hasCreativeCrate; public boolean hasCreativeCrate;
private int printerCooldown; private int printerCooldown;
private int skipsLeft; private int skipsLeft;
private boolean blockSkipped; private boolean blockSkipped;
private int printingEntityIndex;
public BlockPos target; public BlockPos target;
public BlockPos previousTarget; public BlockPos previousTarget;
public List<IItemHandler> attachedInventories; public List<IItemHandler> attachedInventories;
public List<LaunchedBlock> flyingBlocks; public List<LaunchedItem> flyingBlocks;
public MaterialChecklist checklist; public MaterialChecklist checklist;
// Gui information // Gui information
@ -124,6 +137,7 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
inventory = new SchematicannonInventory(this); inventory = new SchematicannonInventory(this);
statusMsg = "idle"; statusMsg = "idle";
state = State.STOPPED; state = State.STOPPED;
printingEntityIndex = -1;
replaceMode = 2; replaceMode = 2;
neighbourCheckCooldown = NEIGHBOUR_CHECKING; neighbourCheckCooldown = NEIGHBOUR_CHECKING;
checklist = new MaterialChecklist(); checklist = new MaterialChecklist();
@ -143,8 +157,8 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
TileEntity tileEntity = world.getTileEntity(pos.offset(facing)); TileEntity tileEntity = world.getTileEntity(pos.offset(facing));
if (tileEntity != null) { if (tileEntity != null) {
LazyOptional<IItemHandler> capability = tileEntity LazyOptional<IItemHandler> capability =
.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, facing.getOpposite()); tileEntity.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, facing.getOpposite());
if (capability.isPresent()) { if (capability.isPresent()) {
attachedInventories.add(capability.orElse(null)); attachedInventories.add(capability.orElse(null));
} }
@ -156,7 +170,7 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
public void read(CompoundNBT compound) { public void read(CompoundNBT compound) {
inventory.deserializeNBT(compound.getCompound("Inventory")); inventory.deserializeNBT(compound.getCompound("Inventory"));
if (compound.contains("Running")) if (compound.contains("CurrentPos"))
currentPos = NBTUtil.readBlockPos(compound.getCompound("CurrentPos")); currentPos = NBTUtil.readBlockPos(compound.getCompound("CurrentPos"));
readClientUpdate(compound); readClientUpdate(compound);
@ -174,11 +188,11 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
state = State.valueOf(compound.getString("State")); state = State.valueOf(compound.getString("State"));
blocksPlaced = compound.getInt("AmountPlaced"); blocksPlaced = compound.getInt("AmountPlaced");
blocksToPlace = compound.getInt("AmountToPlace"); blocksToPlace = compound.getInt("AmountToPlace");
printingEntityIndex = compound.getInt("EntityProgress");
if (compound.contains("MissingBlock")) missingItem = null;
missingBlock = NBTUtil.readBlockState(compound.getCompound("MissingBlock")); if (compound.contains("MissingItem"))
else missingItem = ItemStack.read(compound.getCompound("MissingItem"));
missingBlock = null;
// Settings // Settings
CompoundNBT options = compound.getCompound("Options"); CompoundNBT options = compound.getCompound("Options");
@ -203,15 +217,12 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
for (int i = 0; i < tagBlocks.size(); i++) { for (int i = 0; i < tagBlocks.size(); i++) {
CompoundNBT c = tagBlocks.getCompound(i); CompoundNBT c = tagBlocks.getCompound(i);
LaunchedItem launched = LaunchedItem.fromNBT(c);
BlockPos readBlockPos = NBTUtil.readBlockPos(c.getCompound("Target")); BlockPos readBlockPos = launched.target;
BlockState readBlockState = NBTUtil.readBlockState(c.getCompound("Block"));
int int1 = c.getInt("TicksLeft");
int int2 = c.getInt("TotalTicks");
// Always write to Server tile // Always write to Server tile
if (world == null || !world.isRemote) { if (world == null || !world.isRemote) {
flyingBlocks.add(new LaunchedBlock(this, readBlockPos, readBlockState, int1, int2)); flyingBlocks.add(launched);
continue; continue;
} }
@ -224,7 +235,7 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
// Add new server side blocks // Add new server side blocks
if (i >= flyingBlocks.size()) { if (i >= flyingBlocks.size()) {
flyingBlocks.add(new LaunchedBlock(this, readBlockPos, readBlockState, int1, int2)); flyingBlocks.add(launched);
continue; continue;
} }
@ -238,6 +249,7 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
if (state == State.RUNNING) { if (state == State.RUNNING) {
compound.putBoolean("Running", true); compound.putBoolean("Running", true);
if (currentPos != null)
compound.put("CurrentPos", NBTUtil.writeBlockPos(currentPos)); compound.put("CurrentPos", NBTUtil.writeBlockPos(currentPos));
} }
@ -256,9 +268,10 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
compound.putString("State", state.name()); compound.putString("State", state.name());
compound.putInt("AmountPlaced", blocksPlaced); compound.putInt("AmountPlaced", blocksPlaced);
compound.putInt("AmountToPlace", blocksToPlace); compound.putInt("AmountToPlace", blocksToPlace);
compound.putInt("EntityProgress", printingEntityIndex);
if (missingBlock != null) if (missingItem != null)
compound.put("MissingBlock", NBTUtil.writeBlockState(missingBlock)); compound.put("MissingItem", missingItem.serializeNBT());
// Settings // Settings
CompoundNBT options = new CompoundNBT(); CompoundNBT options = new CompoundNBT();
@ -271,14 +284,8 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
if (target != null) if (target != null)
compound.put("Target", NBTUtil.writeBlockPos(target)); compound.put("Target", NBTUtil.writeBlockPos(target));
ListNBT tagBlocks = new ListNBT(); ListNBT tagBlocks = new ListNBT();
for (LaunchedBlock b : flyingBlocks) { for (LaunchedItem b : flyingBlocks)
CompoundNBT c = new CompoundNBT(); tagBlocks.add(b.serializeNBT());
c.putInt("TotalTicks", b.totalTicks);
c.putInt("TicksLeft", b.ticksRemaining);
c.put("Target", NBTUtil.writeBlockPos(b.target));
c.put("Block", NBTUtil.writeBlockState(b.state));
tagBlocks.add(c);
}
compound.put("FlyingBlocks", tagBlocks); compound.put("FlyingBlocks", tagBlocks);
return compound; return compound;
@ -344,7 +351,7 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
return; return;
} }
if (state == State.PAUSED && !blockNotLoaded && missingBlock == null && fuelLevel > getFuelUsageRate()) if (state == State.PAUSED && !positionNotLoaded && missingItem == null && fuelLevel > getFuelUsageRate())
return; return;
// Initialize Printer // Initialize Printer
@ -360,7 +367,7 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
} }
// Check Fuel // Check Fuel
if (fuelLevel <= 0) { if (fuelLevel <= 0 && !hasCreativeCrate) {
fuelLevel = 0; fuelLevel = 0;
state = State.PAUSED; state = State.PAUSED;
statusMsg = "noGunpowder"; statusMsg = "noGunpowder";
@ -370,13 +377,13 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
// Update Target // Update Target
if (hasCreativeCrate) { if (hasCreativeCrate) {
if (missingBlock != null) { if (missingItem != null) {
missingBlock = null; missingItem = null;
state = State.RUNNING; state = State.RUNNING;
} }
} }
if (missingBlock == null && !blockNotLoaded) { if (missingItem == null && !positionNotLoaded) {
advanceCurrentPos(); advanceCurrentPos();
// End reached // End reached
@ -387,65 +394,121 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
target = schematicAnchor.add(currentPos); target = schematicAnchor.add(currentPos);
} }
boolean entityMode = printingEntityIndex >= 0;
// Check block // Check block
if (!getWorld().isAreaLoaded(target, 0)) { if (!getWorld().isAreaLoaded(target, 0)) {
blockNotLoaded = true; positionNotLoaded = true;
statusMsg = "targetNotLoaded"; statusMsg = "targetNotLoaded";
state = State.PAUSED; state = State.PAUSED;
return; return;
} else { } else {
if (blockNotLoaded) { if (positionNotLoaded) {
blockNotLoaded = false; positionNotLoaded = false;
state = State.RUNNING; state = State.RUNNING;
} }
} }
BlockState blockState = blockReader.getBlockState(target); boolean shouldSkip = false;
ItemStack requiredItem = getItemForBlock(blockState); BlockState blockState = Blocks.AIR.getDefaultState();
ItemRequirement requirement;
if (!shouldPlace(target, blockState) || requiredItem.isEmpty()) { if (entityMode) {
requirement = ItemRequirement.of(blockReader.getEntities().get(printingEntityIndex));
} else {
blockState = blockReader.getBlockState(target);
requirement = ItemRequirement.of(blockState);
shouldSkip = !shouldPlace(target, blockState);
}
if (shouldSkip || requirement.isInvalid()) {
statusMsg = "searching"; statusMsg = "searching";
blockSkipped = true; blockSkipped = true;
return; return;
} }
// Find item // Find item
if (blockState.has(BlockStateProperties.SLAB_TYPE) List<ItemStack> requiredItems = requirement.getRequiredItems();
&& blockState.get(BlockStateProperties.SLAB_TYPE) == SlabType.DOUBLE) if (!requirement.isEmpty()) {
requiredItem.setCount(2); for (ItemStack required : requiredItems) {
if (!grabItemsFromAttachedInventories(required, requirement.getUsage(), true)) {
if (!findItemInAttachedInventories(requiredItem)) {
if (skipMissing) { if (skipMissing) {
statusMsg = "skipping"; statusMsg = "skipping";
blockSkipped = true; blockSkipped = true;
if (missingBlock != null) { if (missingItem != null) {
missingBlock = null; missingItem = null;
state = State.RUNNING; state = State.RUNNING;
} }
return; return;
} }
missingBlock = blockState; missingItem = required;
state = State.PAUSED; state = State.PAUSED;
statusMsg = "missingBlock"; statusMsg = "missingBlock";
return; return;
} }
}
for (ItemStack required : requiredItems)
grabItemsFromAttachedInventories(required, requirement.getUsage(), false);
}
// Success // Success
state = State.RUNNING; state = State.RUNNING;
if (blockState.getBlock() != Blocks.AIR) if (blockState.getBlock() != Blocks.AIR || entityMode)
statusMsg = "placing"; statusMsg = "placing";
else else
statusMsg = "clearing"; statusMsg = "clearing";
launchBlock(target, blockState);
ItemStack icon = requirement.isEmpty() || requiredItems.isEmpty() ? ItemStack.EMPTY : requiredItems.get(0);
if (entityMode)
launchEntity(target, icon, blockReader.getEntities().get(printingEntityIndex));
else if (AllBlocks.BELT.typeOf(blockState)) {
TileEntity te = blockReader.getTileEntity(currentPos.add(schematicAnchor));
blockState = stripBeltIfNotLast(blockState);
if (te instanceof BeltTileEntity && AllBlocks.BELT.typeOf(blockState))
launchBelt(target, blockState, ((BeltTileEntity) te).beltLength);
else
launchBlock(target, icon, blockState);
} else
launchBlock(target, icon, blockState);
printerCooldown = config().schematicannonDelay.get(); printerCooldown = config().schematicannonDelay.get();
fuelLevel -= getFuelUsageRate(); fuelLevel -= getFuelUsageRate();
sendUpdate = true; sendUpdate = true;
missingBlock = null; missingItem = null;
}
public BlockState stripBeltIfNotLast(BlockState blockState) {
// is highest belt?
boolean isLastSegment = false;
Direction facing = blockState.get(BeltBlock.HORIZONTAL_FACING);
Slope slope = blockState.get(BeltBlock.SLOPE);
boolean positive = facing.getAxisDirection() == AxisDirection.POSITIVE;
boolean start = blockState.get(BeltBlock.PART) == Part.START;
boolean end = blockState.get(BeltBlock.PART) == Part.END;
switch (slope) {
case DOWNWARD:
isLastSegment = start;
break;
case UPWARD:
isLastSegment = end;
break;
case HORIZONTAL:
case VERTICAL:
default:
isLastSegment = positive && end || !positive && start;
}
if (!isLastSegment)
blockState = (blockState.get(BeltBlock.PART) == Part.MIDDLE) ? Blocks.AIR.getDefaultState()
: AllBlocks.SHAFT.getDefault().with(ShaftBlock.AXIS, facing.rotateY().getAxis());
return blockState;
} }
public double getFuelUsageRate() { public double getFuelUsageRate() {
return config().schematicannonFuelUsage.get() / 100f; return hasCreativeCrate ? 0 : config().schematicannonFuelUsage.get() / 100f;
} }
protected void initializePrinter(ItemStack blueprint) { protected void initializePrinter(ItemStack blueprint) {
@ -483,10 +546,12 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
schematicAnchor = anchor; schematicAnchor = anchor;
blockReader = new SchematicWorld(schematicAnchor, world); blockReader = new SchematicWorld(schematicAnchor, world);
activeTemplate.addBlocksToWorld(blockReader, schematicAnchor, SchematicItem.getSettings(blueprint)); PlacementSettings settings = SchematicItem.getSettings(blueprint);
activeTemplate.addBlocksToWorld(blockReader, schematicAnchor, settings);
schematicLoaded = true; schematicLoaded = true;
state = State.PAUSED; state = State.PAUSED;
statusMsg = "ready"; statusMsg = "ready";
printingEntityIndex = -1;
updateChecklist(); updateChecklist();
sendUpdate = true; sendUpdate = true;
blocksToPlace += blocksPlaced; blocksToPlace += blocksPlaced;
@ -498,44 +563,86 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
return item == Items.AIR ? ItemStack.EMPTY : new ItemStack(item); return item == Items.AIR ? ItemStack.EMPTY : new ItemStack(item);
} }
protected boolean findItemInAttachedInventories(ItemStack requiredItem) { protected boolean grabItemsFromAttachedInventories(ItemStack required, ItemUseType usage, boolean simulate) {
if (hasCreativeCrate) if (hasCreativeCrate)
return true; return true;
boolean two = requiredItem.getCount() == 2; // Find and apply damage
int lastSlot = -1; if (usage == ItemUseType.DAMAGE) {
for (IItemHandler iItemHandler : attachedInventories) { for (IItemHandler iItemHandler : attachedInventories) {
for (int slot = 0; slot < iItemHandler.getSlots(); slot++) { for (int slot = 0; slot < iItemHandler.getSlots(); slot++) {
ItemStack stackInSlot = iItemHandler.getStackInSlot(slot); ItemStack extractItem = iItemHandler.extractItem(slot, 1, true);
if (!stackInSlot.isItemEqual(requiredItem)) if (!ItemRequirement.validate(required, extractItem))
continue;
if (!extractItem.isDamageable())
continue; continue;
if (!two && !iItemHandler.extractItem(slot, 1, false).isEmpty())
return true;
// Two Items required (Double slabs) if (!simulate) {
if (two) { ItemStack stack = iItemHandler.extractItem(slot, 1, false);
int count = iItemHandler.extractItem(slot, 2, true).getCount(); stack.setDamage(stack.getDamage() + 1);
if (count == 2) { if (stack.getDamage() <= stack.getMaxDamage()) {
iItemHandler.extractItem(slot, 2, false); if (iItemHandler.getStackInSlot(slot).isEmpty())
return true; iItemHandler.insertItem(slot, stack, false);
} else if (count == 1) { else
if (lastSlot == -1) ItemHandlerHelper.insertItem(iItemHandler, stack, false);
lastSlot = slot; }
else { }
iItemHandler.extractItem(lastSlot, 1, false);
iItemHandler.extractItem(slot, 1, false);
return true; return true;
} }
} }
} }
// Find and remove
boolean success = false;
if (usage == ItemUseType.CONSUME) {
int amountFound = 0;
for (IItemHandler iItemHandler : attachedInventories) {
amountFound += ItemHelper
.extract(iItemHandler, s -> ItemRequirement.validate(required, s), ExtractionCountMode.UPTO,
required.getCount(), true)
.getCount();
if (amountFound < required.getCount())
continue;
success = true;
break;
} }
} }
return false;
if (!simulate && success) {
int amountFound = 0;
for (IItemHandler iItemHandler : attachedInventories) {
amountFound += ItemHelper
.extract(iItemHandler, s -> ItemRequirement.validate(required, s), ExtractionCountMode.UPTO,
required.getCount(), false)
.getCount();
if (amountFound < required.getCount())
continue;
break;
}
}
return success;
} }
protected void advanceCurrentPos() { protected void advanceCurrentPos() {
List<Entity> entities = blockReader.getEntities();
if (printingEntityIndex != -1) {
printingEntityIndex++;
// End of entities reached
if (printingEntityIndex >= entities.size()) {
finishedPrinting();
return;
}
currentPos = entities.get(printingEntityIndex).getPosition().subtract(schematicAnchor);
return;
}
BlockPos size = blockReader.getBounds().getSize(); BlockPos size = blockReader.getBounds().getSize();
currentPos = currentPos.offset(Direction.EAST); currentPos = currentPos.offset(Direction.EAST);
BlockPos posInBounds = currentPos.subtract(blockReader.getBounds().getOrigin()); BlockPos posInBounds = currentPos.subtract(blockReader.getBounds().getOrigin());
@ -545,20 +652,30 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
if (posInBounds.getZ() > size.getZ()) if (posInBounds.getZ() > size.getZ())
currentPos = new BlockPos(currentPos.getX(), currentPos.getY() + 1, blockReader.getBounds().z).west(); currentPos = new BlockPos(currentPos.getX(), currentPos.getY() + 1, blockReader.getBounds().z).west();
// End reached // End of blocks reached
if (currentPos.getY() > size.getY()) { if (currentPos.getY() > size.getY()) {
printingEntityIndex = 0;
if (entities.isEmpty()) {
finishedPrinting();
return;
}
currentPos = entities.get(0).getPosition().subtract(schematicAnchor);
}
}
public void finishedPrinting() {
inventory.setStackInSlot(0, ItemStack.EMPTY); inventory.setStackInSlot(0, ItemStack.EMPTY);
inventory.setStackInSlot(1, inventory
.setStackInSlot(1,
new ItemStack(AllItems.EMPTY_BLUEPRINT.get(), inventory.getStackInSlot(1).getCount() + 1)); new ItemStack(AllItems.EMPTY_BLUEPRINT.get(), inventory.getStackInSlot(1).getCount() + 1));
state = State.STOPPED; state = State.STOPPED;
statusMsg = "finished"; statusMsg = "finished";
resetPrinter(); resetPrinter();
target = getPos().add(1, 0, 0); target = getPos().add(1, 0, 0);
world.playSound(null, pos.getX(), pos.getY(), pos.getZ(), AllSoundEvents.SCHEMATICANNON_FINISH.get(), world
.playSound(null, pos.getX(), pos.getY(), pos.getZ(), AllSoundEvents.SCHEMATICANNON_FINISH.get(),
SoundCategory.BLOCKS, 1, .7f); SoundCategory.BLOCKS, 1, .7f);
sendUpdate = true; sendUpdate = true;
return;
}
} }
protected void resetPrinter() { protected void resetPrinter() {
@ -566,8 +683,9 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
schematicAnchor = null; schematicAnchor = null;
currentPos = null; currentPos = null;
blockReader = null; blockReader = null;
missingBlock = null; missingItem = null;
sendUpdate = true; sendUpdate = true;
printingEntityIndex = -1;
schematicProgress = 0; schematicProgress = 0;
blocksPlaced = 0; blocksPlaced = 0;
blocksToPlace = 0; blocksToPlace = 0;
@ -577,6 +695,10 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
BlockState toReplace = world.getBlockState(pos); BlockState toReplace = world.getBlockState(pos);
boolean placingAir = state.getBlock() == Blocks.AIR; boolean placingAir = state.getBlock() == Blocks.AIR;
if (!world.isBlockPresent(pos))
return false;
if (!world.getWorldBorder().contains(pos))
return false;
if (toReplace == state) if (toReplace == state)
return false; return false;
if (toReplace.getBlockHardness(world, pos) == -1) if (toReplace.getBlockHardness(world, pos) == -1)
@ -622,25 +744,16 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
} }
protected void tickFlyingBlocks() { protected void tickFlyingBlocks() {
List<LaunchedBlock> toRemove = new LinkedList<>(); List<LaunchedItem> toRemove = new LinkedList<>();
for (LaunchedBlock b : flyingBlocks) { for (LaunchedItem b : flyingBlocks)
b.update(); if (b.update(world))
if (b.ticksRemaining <= 0 && !world.isRemote) {
// Piston
if (b.state.has(BlockStateProperties.EXTENDED)) {
b.state = b.state.with(BlockStateProperties.EXTENDED, false);
}
world.setBlockState(b.target, b.state, 18);
b.state.getBlock().onBlockPlacedBy(world, b.target, b.state, null, getItemForBlock(b.state));
toRemove.add(b); toRemove.add(b);
}
}
flyingBlocks.removeAll(toRemove); flyingBlocks.removeAll(toRemove);
} }
protected void refillFuelIfPossible() { protected void refillFuelIfPossible() {
if (hasCreativeCrate)
return;
if (1 - fuelLevel + 1 / 128f < getFuelAddedByGunPowder()) if (1 - fuelLevel + 1 / 128f < getFuelAddedByGunPowder())
return; return;
if (inventory.getStackInSlot(4).isEmpty()) if (inventory.getStackInSlot(4).isEmpty())
@ -696,11 +809,29 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
sendUpdate = true; sendUpdate = true;
} }
protected void launchBlock(BlockPos target, BlockState state) { protected void launchBelt(BlockPos target, BlockState state, int length) {
blocksPlaced++;
ItemStack connector = AllItems.BELT_CONNECTOR.asStack();
flyingBlocks.add(new LaunchedItem.ForBelt(this.getPos(), target, connector, state, length));
playFiringSound();
}
protected void launchBlock(BlockPos target, ItemStack stack, BlockState state) {
if (state.getBlock() != Blocks.AIR) if (state.getBlock() != Blocks.AIR)
blocksPlaced++; blocksPlaced++;
flyingBlocks.add(new LaunchedBlock(this, target, state)); flyingBlocks.add(new LaunchedItem.ForBlockState(this.getPos(), target, stack, state));
world.playSound(null, pos.getX(), pos.getY(), pos.getZ(), AllSoundEvents.SCHEMATICANNON_LAUNCH_BLOCK.get(), playFiringSound();
}
protected void launchEntity(BlockPos target, ItemStack stack, Entity entity) {
blocksPlaced++;
flyingBlocks.add(new LaunchedItem.ForEntity(this.getPos(), target, stack, entity));
playFiringSound();
}
public void playFiringSound() {
world
.playSound(null, pos.getX(), pos.getY(), pos.getZ(), AllSoundEvents.SCHEMATICANNON_LAUNCH_BLOCK.get(),
SoundCategory.BLOCKS, .1f, 1.1f); SoundCategory.BLOCKS, .1f, 1.1f);
} }
@ -721,6 +852,7 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
public void updateChecklist() { public void updateChecklist() {
checklist.required.clear(); checklist.required.clear();
checklist.damageRequired.clear();
checklist.blocksNotLoaded = false; checklist.blocksNotLoaded = false;
if (schematicLoaded) { if (schematicLoaded) {
@ -734,18 +866,22 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
} }
if (!shouldPlace(pos.add(schematicAnchor), required)) if (!shouldPlace(pos.add(schematicAnchor), required))
continue; continue;
ItemStack requiredItem = getItemForBlock(required); ItemRequirement requirement = ItemRequirement.of(required);
if (requiredItem.isEmpty()) if (requirement.isEmpty())
continue; continue;
if (requirement.isInvalid())
// Two items for double slabs continue;
if (required.has(BlockStateProperties.SLAB_TYPE) checklist.require(requirement);
&& required.get(BlockStateProperties.SLAB_TYPE) == SlabType.DOUBLE)
checklist.require(requiredItem.getItem());
checklist.require(requiredItem.getItem());
blocksToPlace++; blocksToPlace++;
} }
for (Entity entity : blockReader.getEntities()) {
ItemRequirement requirement = ItemRequirement.of(entity);
if (requirement.isEmpty())
continue;
if (requirement.isInvalid())
continue;
checklist.require(requirement);
}
} }
checklist.gathered.clear(); checklist.gathered.clear();
for (IItemHandler inventory : attachedInventories) { for (IItemHandler inventory : attachedInventories) {
@ -760,8 +896,7 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
} }
@Override @Override
public void addBehaviours(List<TileEntityBehaviour> behaviours) { public void addBehaviours(List<TileEntityBehaviour> behaviours) {}
}
@Override @Override
public void lazyTick() { public void lazyTick() {

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