From 788a00efdf7c2916980291382e4105cc5c9d1281 Mon Sep 17 00:00:00 2001 From: simibubi <31564874+simibubi@users.noreply.github.com> Date: Wed, 16 Jun 2021 17:17:55 +0200 Subject: [PATCH 1/9] Breaks in every port - Fixed the schematic hotbar overlay - Goggles overlay is no longer its own eventhandler --- .../goggles/GoggleOverlayRenderer.java | 19 +++++-------------- .../schematics/client/SchematicHandler.java | 3 +-- .../client/SchematicHotbarSlotOverlay.java | 5 ++--- .../simibubi/create/events/ClientEvents.java | 2 ++ .../foundation/gui/ToolSelectionScreen.java | 1 + 5 files changed, 11 insertions(+), 19 deletions(-) diff --git a/src/main/java/com/simibubi/create/content/contraptions/goggles/GoggleOverlayRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/goggles/GoggleOverlayRenderer.java index 3bd7cebd9..2acd72a7a 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/goggles/GoggleOverlayRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/goggles/GoggleOverlayRenderer.java @@ -22,6 +22,7 @@ import com.simibubi.create.foundation.utility.outliner.Outliner.OutlineEntry; import net.minecraft.block.BlockState; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.world.ClientWorld; import net.minecraft.inventory.EquipmentSlotType; import net.minecraft.item.ItemStack; @@ -33,24 +34,15 @@ import net.minecraft.util.math.RayTraceResult; import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.ITextProperties; import net.minecraft.util.text.StringTextComponent; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.client.event.RenderGameOverlayEvent; -import net.minecraftforge.client.event.RenderGameOverlayEvent.ElementType; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.common.Mod.EventBusSubscriber; -@EventBusSubscriber(value = Dist.CLIENT) public class GoggleOverlayRenderer { private static final Map outlines = CreateClient.OUTLINER.getOutlines(); - @SubscribeEvent - public static void lookingAtBlocksThroughGogglesShowsTooltip(RenderGameOverlayEvent.Post event) { - MatrixStack ms = event.getMatrixStack(); - if (event.getType() != ElementType.HOTBAR) - return; - + public static void renderOverlay(MatrixStack ms, IRenderTypeBuffer buffer, int light, int overlay, + float partialTicks) { RayTraceResult objectMouseOver = Minecraft.getInstance().objectMouseOver; + if (!(objectMouseOver instanceof BlockRayTraceResult)) return; @@ -58,9 +50,8 @@ public class GoggleOverlayRenderer { if (!entry.isAlive()) continue; Outline outline = entry.getOutline(); - if (outline instanceof ValueBox && !((ValueBox) outline).isPassive) { + if (outline instanceof ValueBox && !((ValueBox) outline).isPassive) return; - } } BlockRayTraceResult result = (BlockRayTraceResult) objectMouseOver; diff --git a/src/main/java/com/simibubi/create/content/schematics/client/SchematicHandler.java b/src/main/java/com/simibubi/create/content/schematics/client/SchematicHandler.java index d2eaa4595..9bea80f55 100644 --- a/src/main/java/com/simibubi/create/content/schematics/client/SchematicHandler.java +++ b/src/main/java/com/simibubi/create/content/schematics/client/SchematicHandler.java @@ -191,12 +191,11 @@ public class SchematicHandler { return; if (activeSchematicItem != null) this.overlay.renderOn(ms, activeHotbarSlot); - currentTool.getTool() .renderOverlay(ms, buffer); selectionScreen.renderPassive(ms, partialTicks); } - + public void onMouseInput(int button, boolean pressed) { if (!active) return; diff --git a/src/main/java/com/simibubi/create/content/schematics/client/SchematicHotbarSlotOverlay.java b/src/main/java/com/simibubi/create/content/schematics/client/SchematicHotbarSlotOverlay.java index 8b765eca9..33f531cbe 100644 --- a/src/main/java/com/simibubi/create/content/schematics/client/SchematicHotbarSlotOverlay.java +++ b/src/main/java/com/simibubi/create/content/schematics/client/SchematicHotbarSlotOverlay.java @@ -14,11 +14,10 @@ public class SchematicHotbarSlotOverlay extends AbstractGui { MainWindow mainWindow = Minecraft.getInstance().getWindow(); int x = mainWindow.getScaledWidth() / 2 - 88; int y = mainWindow.getScaledHeight() - 19; - RenderSystem.enableAlphaTest(); RenderSystem.enableDepthTest(); - RenderSystem.enableBlend(); + matrixStack.push(); AllGuiTextures.SCHEMATIC_SLOT.draw(matrixStack, this, x + 20 * slot, y); - RenderSystem.disableAlphaTest(); + matrixStack.pop(); } } diff --git a/src/main/java/com/simibubi/create/events/ClientEvents.java b/src/main/java/com/simibubi/create/events/ClientEvents.java index ee0c5d676..32ff48000 100644 --- a/src/main/java/com/simibubi/create/events/ClientEvents.java +++ b/src/main/java/com/simibubi/create/events/ClientEvents.java @@ -21,6 +21,7 @@ import com.simibubi.create.content.contraptions.components.structureMovement.tra import com.simibubi.create.content.contraptions.components.structureMovement.train.CouplingRenderer; import com.simibubi.create.content.contraptions.components.structureMovement.train.capability.CapabilityMinecartController; import com.simibubi.create.content.contraptions.components.turntable.TurntableHandler; +import com.simibubi.create.content.contraptions.goggles.GoggleOverlayRenderer; import com.simibubi.create.content.contraptions.goggles.IHaveGoggleInformation; import com.simibubi.create.content.contraptions.relays.belt.item.BeltConnectorHandler; import com.simibubi.create.content.curiosities.armor.CopperBacktankArmorLayer; @@ -228,6 +229,7 @@ public class ClientEvents { CreateClient.SCHEMATIC_HANDLER.renderOverlay(ms, buffer, light, overlay, partialTicks); LinkedControllerClientHandler.renderOverlay(ms, buffer, light, overlay, partialTicks); BlueprintOverlayRenderer.renderOverlay(ms, buffer, light, overlay, partialTicks); + GoggleOverlayRenderer.renderOverlay(ms, buffer, light, overlay, partialTicks); } @SubscribeEvent diff --git a/src/main/java/com/simibubi/create/foundation/gui/ToolSelectionScreen.java b/src/main/java/com/simibubi/create/foundation/gui/ToolSelectionScreen.java index 5efe5c936..cb77c8b7d 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/ToolSelectionScreen.java +++ b/src/main/java/com/simibubi/create/foundation/gui/ToolSelectionScreen.java @@ -136,6 +136,7 @@ public class ToolSelectionScreen extends Screen { matrixStack.pop(); } + RenderSystem.enableBlend(); matrixStack.pop(); } From 39e467fe1ccb1e98634205380c41efb55198bcb5 Mon Sep 17 00:00:00 2001 From: PepperBell <44146161+PepperCode1@users.noreply.github.com> Date: Wed, 16 Jun 2021 12:20:08 -0700 Subject: [PATCH 2/9] Update mods.toml - Add CurseForge link, issue tracker link, and logo --- src/main/resources/META-INF/mods.toml | 24 ++++++++++++++---------- src/main/resources/logo.png | Bin 0 -> 59444 bytes 2 files changed, 14 insertions(+), 10 deletions(-) create mode 100644 src/main/resources/logo.png diff --git a/src/main/resources/META-INF/mods.toml b/src/main/resources/META-INF/mods.toml index 3c8e798a7..864f01b8f 100644 --- a/src/main/resources/META-INF/mods.toml +++ b/src/main/resources/META-INF/mods.toml @@ -1,20 +1,24 @@ -modLoader="javafml" -loaderVersion="[34,)" -#issueTrackerURL="" +modLoader="javafml" +loaderVersion="[34,)" +issueTrackerURL="https://github.com/Creators-of-Create/Create/issues" license="MIT" -[[mods]] +[[mods]] modId="create" version="${file.jarVersion}" -displayName="Create" +displayName="Create" #updateJSONURL="" -authors="simibubi" +displayURL="https://www.curseforge.com/minecraft/mc-mods/create" +logoFile="logo.png" +#credits="" +authors="simibubi" description=''' -Technology that empowers the player.''' +Technology that empowers the player. +''' -[[dependencies.create]] +[[dependencies.create]] modId="forge" - mandatory=true + mandatory=true versionRange="[35.1.16,)" ordering="NONE" side="BOTH" @@ -24,4 +28,4 @@ Technology that empowers the player.''' mandatory=true versionRange="[1.16.4,1.17)" ordering="NONE" - side="BOTH" \ No newline at end of file + side="BOTH" diff --git a/src/main/resources/logo.png b/src/main/resources/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..beac8a31bba1c6fb9226000990b7c581d630c142 GIT binary patch literal 59444 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 Z{{uSTF^yn|h3x Date: Wed, 16 Jun 2021 21:39:38 +0200 Subject: [PATCH 3/9] Blending in with Entities - Changed blueprint entity and item rendering to be more Optifine friendly (?) - Punching blueprints now clears the slot before breaking it - Fix a dist issue with KTEs - Added recipe for blueprint --- gradle.properties | 2 +- src/generated/resources/.cache/cache | 4 +- .../data/create/advancements/aesthetics.json | 4 +- .../appliances/crafting_blueprint.json | 32 +++ .../appliances/crafting_blueprint.json | 14 ++ .../contraptions/base/KineticTileEntity.java | 13 +- .../curiosities/tools/BlueprintEntity.java | 183 ++++++++++-------- .../curiosities/tools/BlueprintRenderer.java | 60 ++++-- .../data/recipe/StandardRecipeGen.java | 4 + .../foundation/render/SuperByteBuffer.java | 29 ++- 10 files changed, 229 insertions(+), 116 deletions(-) create mode 100644 src/generated/resources/data/create/advancements/recipes/create.base/crafting/appliances/crafting_blueprint.json create mode 100644 src/generated/resources/data/create/recipes/crafting/appliances/crafting_blueprint.json diff --git a/gradle.properties b/gradle.properties index b50c41fc3..179b53901 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,7 +4,7 @@ org.gradle.jvmargs=-Xmx3G org.gradle.daemon=false # mod version info -mod_version=0.3.1c +mod_version=0.3.2 minecraft_version=1.16.5 forge_version=36.0.42 diff --git a/src/generated/resources/.cache/cache b/src/generated/resources/.cache/cache index 2b20bd785..2c2d57364 100644 --- a/src/generated/resources/.cache/cache +++ b/src/generated/resources/.cache/cache @@ -1654,7 +1654,7 @@ d080b1b25e5bc8baf5aee68691b08c7f12ece3b0 assets/create/models/item/windmill_bear a80fb25a0b655e76be986b5b49fcb0f03461a1ab assets/create/models/item/zinc_nugget.json b1689617190c05ef34bd18456b0c7ae09bb3210f assets/create/models/item/zinc_ore.json 6490fa0587db770cf7c794b47f3bcd2b691f4226 assets/create/sounds.json -0f1b4b980afba9bf2caf583b88e261bba8b10313 data/create/advancements/aesthetics.json +5d0cc4c0255dc241e61c173b31ddca70c88d08e4 data/create/advancements/aesthetics.json 187921fa131b06721bfaf63f2623a28c141aae9a data/create/advancements/andesite_alloy.json 0ea2db7173b5be28b289ea7c9a6a0cf5805c60c7 data/create/advancements/andesite_casing.json 83c046bd200623933545c9e4326f782fb02c87fa data/create/advancements/arm_blaze_burner.json @@ -1779,6 +1779,7 @@ c368cadffa9177fefb9e92ff4453b40bc8dd670d data/create/advancements/recipes/create 8fffce2a5c5dd88d52e3b006fa92fb18cf2f1571 data/create/advancements/recipes/create.base/blasting/zinc_ingot_from_crushed.json 4bb60ef5e186f12a9d52e61319db8c78300c64ab data/create/advancements/recipes/create.base/blasting/zinc_ingot_from_ore.json d1d8cf6e1c95b7d99bf873fa6fee033103f995fd data/create/advancements/recipes/create.base/crafting/appliances/copper_backtank.json +f2dc28c600011e6e8e515cb4d56118b1bd45b743 data/create/advancements/recipes/create.base/crafting/appliances/crafting_blueprint.json 46c04e685ab345a80598176f7ac68a044a76cd76 data/create/advancements/recipes/create.base/crafting/appliances/diving_boots.json 5f06b7dcf2af11f30c2e10ade4ac3fd172bc04df data/create/advancements/recipes/create.base/crafting/appliances/diving_helmet.json dd487f98c411f1ff22cb7fc208b8cc24b27deb2f data/create/advancements/recipes/create.base/crafting/appliances/dough.json @@ -2858,6 +2859,7 @@ f7879d404d7a848d818278b4e788f285a9087e63 data/create/recipes/compacting/blaze_ca 7b2ef15dd28d1d8a450ea49a82dfb361d1adde4c data/create/recipes/compacting/diorite_from_flint.json 7657603e95ccf83dd0d4b104635db66e531d092a data/create/recipes/compacting/granite_from_flint.json 30030b15caa11b3a7c0104adb62fe74e8c7c0df1 data/create/recipes/crafting/appliances/copper_backtank.json +c077375d16b4505e52548613fbc9356993556e6b data/create/recipes/crafting/appliances/crafting_blueprint.json 9ad82ac5ce02654b7af7f1a570a6b2c01e140da3 data/create/recipes/crafting/appliances/diving_boots.json 813081c6421b34e161ec44e8e470994c282f76be data/create/recipes/crafting/appliances/diving_helmet.json 19526da3a59fc136654ff1bc93c0251581f397a9 data/create/recipes/crafting/appliances/dough.json diff --git a/src/generated/resources/data/create/advancements/aesthetics.json b/src/generated/resources/data/create/advancements/aesthetics.json index d723cbe38..59a86f429 100644 --- a/src/generated/resources/data/create/advancements/aesthetics.json +++ b/src/generated/resources/data/create/advancements/aesthetics.json @@ -28,8 +28,8 @@ "trigger": "create:bracket_apply", "conditions": { "accepted_entries": [ - "create:cogwheel", - "create:large_cogwheel" + "create:large_cogwheel", + "create:cogwheel" ] } }, diff --git a/src/generated/resources/data/create/advancements/recipes/create.base/crafting/appliances/crafting_blueprint.json b/src/generated/resources/data/create/advancements/recipes/create.base/crafting/appliances/crafting_blueprint.json new file mode 100644 index 000000000..e1d2038ea --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/create.base/crafting/appliances/crafting_blueprint.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "rewards": { + "recipes": [ + "create:crafting/appliances/crafting_blueprint" + ] + }, + "criteria": { + "has_item": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "minecraft:crafting_table" + } + ] + } + }, + "has_the_recipe": { + "trigger": "minecraft:recipe_unlocked", + "conditions": { + "recipe": "create:crafting/appliances/crafting_blueprint" + } + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/appliances/crafting_blueprint.json b/src/generated/resources/data/create/recipes/crafting/appliances/crafting_blueprint.json new file mode 100644 index 000000000..880a71332 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/appliances/crafting_blueprint.json @@ -0,0 +1,14 @@ +{ + "type": "minecraft:crafting_shapeless", + "ingredients": [ + { + "item": "minecraft:painting" + }, + { + "item": "minecraft:crafting_table" + } + ], + "result": { + "item": "create:crafting_blueprint" + } +} \ No newline at end of file diff --git a/src/main/java/com/simibubi/create/content/contraptions/base/KineticTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/base/KineticTileEntity.java index a0fe6a992..832fc2138 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/base/KineticTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/base/KineticTileEntity.java @@ -477,9 +477,13 @@ public abstract class KineticTileEntity extends SmartTileEntity return d.getAxisDirection() == AxisDirection.POSITIVE ? axisSpeed : -axisSpeed; } - public static float convertToLinear(float speed) { return speed / 512f; } + public static float convertToLinear(float speed) { + return speed / 512f; + } - public static float convertToAngular(float speed) { return speed * 3 / 10f; } + public static float convertToAngular(float speed) { + return speed * 3 / 10f; + } public boolean isOverStressed() { return overStressed; @@ -556,9 +560,8 @@ public abstract class KineticTileEntity extends SmartTileEntity @Override public void requestModelDataUpdate() { super.requestModelDataUpdate(); - if (!this.removed) { - FastRenderDispatcher.enqueueUpdate(this); - } + if (!this.removed) + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> FastRenderDispatcher.enqueueUpdate(this)); } protected AxisAlignedBB cachedBoundingBox; diff --git a/src/main/java/com/simibubi/create/content/curiosities/tools/BlueprintEntity.java b/src/main/java/com/simibubi/create/content/curiosities/tools/BlueprintEntity.java index 99d6deae3..344bd3405 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/tools/BlueprintEntity.java +++ b/src/main/java/com/simibubi/create/content/curiosities/tools/BlueprintEntity.java @@ -59,6 +59,7 @@ import net.minecraft.world.World; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.common.ForgeHooks; +import net.minecraftforge.common.ForgeMod; import net.minecraftforge.common.util.FakePlayer; import net.minecraftforge.fml.common.registry.IEntityAdditionalSpawnData; import net.minecraftforge.fml.hooks.BasicEventHooks; @@ -243,6 +244,36 @@ public class BlueprintEntity extends HangingEntity return 16 * size; } + @Override + public boolean hitByEntity(Entity source) { + if (!(source instanceof PlayerEntity) || world.isRemote) + return super.hitByEntity(source); + + PlayerEntity player = (PlayerEntity) source; + double attrib = player.getAttribute(ForgeMod.REACH_DISTANCE.get()) + .getValue() + (player.isCreative() ? 0 : -0.5F); + + Vector3d eyePos = source.getEyePosition(1); + Vector3d look = source.getLook(1); + Vector3d target = eyePos.add(look.scale(attrib)); + + Optional rayTrace = getBoundingBox().rayTrace(eyePos, target); + if (!rayTrace.isPresent()) + return super.hitByEntity(source); + + Vector3d hitVec = rayTrace.get(); + BlueprintSection sectionAt = getSectionAt(hitVec.subtract(getPositionVec())); + ItemStackHandler items = sectionAt.getItems(); + + if (items.getStackInSlot(9) + .isEmpty()) + return super.hitByEntity(source); + for (int i = 0; i < items.getSlots(); i++) + items.setStackInSlot(i, ItemStack.EMPTY); + sectionAt.save(items); + return true; + } + @Override public void onBroken(@Nullable Entity p_110128_1_) { if (!world.getGameRules() @@ -309,98 +340,88 @@ public class BlueprintEntity extends HangingEntity if (player instanceof FakePlayer) return ActionResultType.PASS; + boolean holdingWrench = AllItems.WRENCH.isIn(player.getHeldItem(hand)); BlueprintSection section = getSectionAt(vec); + ItemStackHandler items = section.getItems(); - if (!AllItems.WRENCH.isIn(player.getHeldItem(hand)) && !world.isRemote) { - boolean empty = true; - ItemStackHandler items = section.getItems(); - for (int i = 0; i < 9; i++) { - if (!items.getStackInSlot(i) - .isEmpty()) { - empty = false; + if (!holdingWrench && !world.isRemote && !items.getStackInSlot(9) + .isEmpty()) { + + IItemHandlerModifiable playerInv = new InvWrapper(player.inventory); + boolean firstPass = true; + int amountCrafted = 0; + ForgeHooks.setCraftingPlayer(player); + Optional recipe = Optional.empty(); + + do { + Map stacksTaken = new HashMap<>(); + Map craftingGrid = new HashMap<>(); + boolean success = true; + + Search: for (int i = 0; i < 9; i++) { + ItemStack requestedItem = items.getStackInSlot(i); + if (requestedItem.isEmpty()) { + craftingGrid.put(i, ItemStack.EMPTY); + continue; + } + + for (int slot = 0; slot < playerInv.getSlots(); slot++) { + if (!FilterItem.test(world, playerInv.getStackInSlot(slot), requestedItem)) + continue; + ItemStack currentItem = playerInv.extractItem(slot, 1, false); + if (stacksTaken.containsKey(slot)) + stacksTaken.get(slot) + .grow(1); + else + stacksTaken.put(slot, currentItem.copy()); + craftingGrid.put(i, currentItem); + continue Search; + } + + success = false; break; } - } - if (!empty) { - IItemHandlerModifiable playerInv = new InvWrapper(player.inventory); - boolean firstPass = true; - int amountCrafted = 0; - ForgeHooks.setCraftingPlayer(player); - Optional recipe = Optional.empty(); + if (success) { + CraftingInventory craftingInventory = new BlueprintCraftingInventory(craftingGrid); - do { - Map stacksTaken = new HashMap<>(); - Map craftingGrid = new HashMap<>(); - boolean success = true; - - Search: for (int i = 0; i < 9; i++) { - ItemStack requestedItem = items.getStackInSlot(i); - if (requestedItem.isEmpty()) { - craftingGrid.put(i, ItemStack.EMPTY); - continue; - } - - for (int slot = 0; slot < playerInv.getSlots(); slot++) { - if (!FilterItem.test(world, playerInv.getStackInSlot(slot), requestedItem)) - continue; - ItemStack currentItem = playerInv.extractItem(slot, 1, false); - if (stacksTaken.containsKey(slot)) { - stacksTaken.get(slot) - .grow(1); - } else { - stacksTaken.put(slot, currentItem.copy()); - } - craftingGrid.put(i, currentItem); - continue Search; - } + if (!recipe.isPresent()) + recipe = world.getRecipeManager() + .getRecipe(IRecipeType.CRAFTING, craftingInventory, world); + ItemStack result = recipe.filter(r -> r.matches(craftingInventory, world)) + .map(r -> r.getCraftingResult(craftingInventory)) + .orElse(ItemStack.EMPTY); + if (result.isEmpty()) { success = false; - break; + } else if (result.getCount() + amountCrafted > 64) { + success = false; + } else { + amountCrafted += result.getCount(); + result.onCrafting(player.world, player, 1); + BasicEventHooks.firePlayerCraftingEvent(player, result, craftingInventory); + NonNullList nonnulllist = world.getRecipeManager() + .getRecipeNonNull(IRecipeType.CRAFTING, craftingInventory, world); + + if (firstPass) + world.playSound(null, player.getBlockPos(), SoundEvents.ENTITY_ITEM_PICKUP, + SoundCategory.PLAYERS, .2f, 1f + Create.RANDOM.nextFloat()); + player.inventory.placeItemBackInInventory(world, result); + for (ItemStack itemStack : nonnulllist) + player.inventory.placeItemBackInInventory(world, itemStack); + firstPass = false; } + } - if (success) { - CraftingInventory craftingInventory = new BlueprintCraftingInventory(craftingGrid); + if (!success) { + for (Entry entry : stacksTaken.entrySet()) + playerInv.insertItem(entry.getKey(), entry.getValue(), false); + break; + } - if (!recipe.isPresent()) - recipe = world.getRecipeManager() - .getRecipe(IRecipeType.CRAFTING, craftingInventory, world); - ItemStack result = recipe.filter(r -> r.matches(craftingInventory, world)) - .map(r -> r.getCraftingResult(craftingInventory)) - .orElse(ItemStack.EMPTY); - - if (result.isEmpty()) { - success = false; - } else if (result.getCount() + amountCrafted > 64) { - success = false; - } else { - amountCrafted += result.getCount(); - result.onCrafting(player.world, player, 1); - BasicEventHooks.firePlayerCraftingEvent(player, result, craftingInventory); - NonNullList nonnulllist = world.getRecipeManager() - .getRecipeNonNull(IRecipeType.CRAFTING, craftingInventory, world); - - if (firstPass) - world.playSound(null, player.getBlockPos(), SoundEvents.ENTITY_ITEM_PICKUP, - SoundCategory.PLAYERS, .2f, 1f + Create.RANDOM.nextFloat()); - player.inventory.placeItemBackInInventory(world, result); - for (ItemStack itemStack : nonnulllist) - player.inventory.placeItemBackInInventory(world, itemStack); - firstPass = false; - } - } - - if (!success) { - for (Entry entry : stacksTaken.entrySet()) - playerInv.insertItem(entry.getKey(), entry.getValue(), false); - break; - } - - } while (player.isSneaking()); - ForgeHooks.setCraftingPlayer(null); - - return ActionResultType.SUCCESS; - } + } while (player.isSneaking()); + ForgeHooks.setCraftingPlayer(null); + return ActionResultType.SUCCESS; } int i = section.index; diff --git a/src/main/java/com/simibubi/create/content/curiosities/tools/BlueprintRenderer.java b/src/main/java/com/simibubi/create/content/curiosities/tools/BlueprintRenderer.java index 13825d42c..3cd2bcd82 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/tools/BlueprintRenderer.java +++ b/src/main/java/com/simibubi/create/content/curiosities/tools/BlueprintRenderer.java @@ -17,8 +17,11 @@ import net.minecraft.client.renderer.WorldRenderer; import net.minecraft.client.renderer.entity.EntityRenderer; import net.minecraft.client.renderer.entity.EntityRendererManager; import net.minecraft.client.renderer.model.ItemCameraTransforms.TransformType; +import net.minecraft.client.renderer.texture.OverlayTexture; +import net.minecraft.inventory.container.PlayerContainer; import net.minecraft.item.ItemStack; import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.vector.Matrix3f; public class BlueprintRenderer extends EntityRenderer { @@ -40,15 +43,30 @@ public class BlueprintRenderer extends EntityRenderer { .translate(-.5, -1 / 32f, -.5); if (entity.size == 2) sbb.translate(.5, 0, -.5); - sbb.light(light) - .renderInto(ms, buffer.getBuffer(RenderType.getSolid())); + + RenderType entitySolid = RenderType.getEntitySolid(PlayerContainer.BLOCK_ATLAS_TEXTURE); + sbb.asEntityModel() + .light(light) + .renderInto(ms, buffer.getBuffer(entitySolid)); super.render(entity, yaw, pt, ms, buffer, light); ms.push(); + float fakeNormalXRotation = -15; + int bl = light >> 4 & 0xf; + int sl = light >> 20 & 0xf; + boolean vertical = entity.rotationPitch != 0; + if (entity.rotationPitch == -90) + fakeNormalXRotation = -45; + else if (entity.rotationPitch == 90 || yaw % 180 != 0) { + bl /= 1.35; + sl /= 1.35; + } + int itemLight = MathHelper.floor(sl + .5) << 20 | (MathHelper.floor(bl + .5) & 0xf) << 4; + MatrixStacker.of(ms) - .rotateY(-yaw) - .rotateX(entity.rotationPitch == -90 ? -45 : entity.rotationPitch == 0 ? -15 : -5); + .rotateY(vertical ? 0 : -yaw) + .rotateX(fakeNormalXRotation); Matrix3f copy = ms.peek() .getNormal() .copy(); @@ -60,28 +78,34 @@ public class BlueprintRenderer extends EntityRenderer { .rotateY(-yaw) .rotateX(entity.rotationPitch) .translate(0, 0, 1 / 32f + .001); - + if (entity.size == 3) ms.translate(-1, -1, 0); + MatrixStack squashedMS = new MatrixStack(); + squashedMS.peek() + .getModel() + .multiply(ms.peek() + .getModel()); + for (int x = 0; x < entity.size; x++) { - ms.push(); + squashedMS.push(); for (int y = 0; y < entity.size; y++) { BlueprintSection section = entity.getSection(x * entity.size + y); Couple displayItems = section.getDisplayItems(); - ms.push(); - ms.scale(.5f, .5f, 1 / 1024f); + squashedMS.push(); + squashedMS.scale(.5f, .5f, 1 / 1024f); displayItems.forEachWithContext((stack, primary) -> { if (stack.isEmpty()) return; - ms.push(); + squashedMS.push(); if (!primary) { - ms.translate(0.325f, -0.325f, 1); - ms.scale(.625f, .625f, 1); + squashedMS.translate(0.325f, -0.325f, 1); + squashedMS.scale(.625f, .625f, 1); } - Matrix3f n = ms.peek() + Matrix3f n = squashedMS.peek() .getNormal(); n.a00 = copy.a00; n.a01 = copy.a01; @@ -95,14 +119,14 @@ public class BlueprintRenderer extends EntityRenderer { Minecraft.getInstance() .getItemRenderer() - .renderItem(stack, TransformType.GUI, light, overlay, ms, buffer); - ms.pop(); + .renderItem(stack, TransformType.GUI, itemLight, OverlayTexture.DEFAULT_UV, squashedMS, buffer); + squashedMS.pop(); }); - ms.pop(); - ms.translate(1, 0, 0); + squashedMS.pop(); + squashedMS.translate(1, 0, 0); } - ms.pop(); - ms.translate(0, 1, 0); + squashedMS.pop(); + squashedMS.translate(0, 1, 0); } ms.pop(); diff --git a/src/main/java/com/simibubi/create/foundation/data/recipe/StandardRecipeGen.java b/src/main/java/com/simibubi/create/foundation/data/recipe/StandardRecipeGen.java index 4f6998cc9..f65f63baa 100644 --- a/src/main/java/com/simibubi/create/foundation/data/recipe/StandardRecipeGen.java +++ b/src/main/java/com/simibubi/create/foundation/data/recipe/StandardRecipeGen.java @@ -968,6 +968,10 @@ public class StandardRecipeGen extends CreateRecipeProvider { .patternLine("P P") .patternLine("P P") .patternLine("G G")), + + CRAFTING_BLUEPRINT = create(AllItems.CRAFTING_BLUEPRINT).unlockedBy(() -> Items.CRAFTING_TABLE) + .viaShapeless(b -> b.addIngredient(Items.PAINTING) + .addIngredient(Items.CRAFTING_TABLE)), SLIME_BALL = create(() -> Items.SLIME_BALL).unlockedBy(AllItems.DOUGH::get) .viaShapeless(b -> b.addIngredient(AllItems.DOUGH.get()) diff --git a/src/main/java/com/simibubi/create/foundation/render/SuperByteBuffer.java b/src/main/java/com/simibubi/create/foundation/render/SuperByteBuffer.java index f3ff7ef80..1fa2a55ad 100644 --- a/src/main/java/com/simibubi/create/foundation/render/SuperByteBuffer.java +++ b/src/main/java/com/simibubi/create/foundation/render/SuperByteBuffer.java @@ -13,6 +13,7 @@ import it.unimi.dsi.fastutil.longs.Long2DoubleMap; import it.unimi.dsi.fastutil.longs.Long2DoubleOpenHashMap; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.BufferBuilder; +import net.minecraft.client.renderer.texture.OverlayTexture; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.util.Direction; import net.minecraft.util.math.BlockPos; @@ -37,6 +38,7 @@ public class SuperByteBuffer extends TemplateBuffer { // Vertex Texture Coords private SpriteShiftFunc spriteShiftFunc; + private boolean isEntityModel; // Vertex Lighting private boolean shouldLight; @@ -78,7 +80,6 @@ public class SuperByteBuffer extends TemplateBuffer { Matrix3f normalMat = transforms.peek() .getNormal() .copy(); - // normalMat.multiply(transforms.peek().getNormal()); Matrix4f modelMat = input.peek() .getModel() @@ -119,9 +120,9 @@ public class SuperByteBuffer extends TemplateBuffer { pos.transform(modelMat); builder.vertex(pos.getX(), pos.getY(), pos.getZ()); - // builder.color((byte) Math.max(0, nx * 255), (byte) Math.max(0, ny * 255), (byte) Math.max(0, nz * 255), a); - if (shouldColor) { - // float lum = (r < 0 ? 255 + r : r) / 256f; + if (isEntityModel) { + builder.color(255, 255, 255, 255); + } else if (shouldColor) { int colorR = Math.min(255, (int) (((float) this.r) * instanceDiffuse)); int colorG = Math.min(255, (int) (((float) this.g) * instanceDiffuse)); int colorB = Math.min(255, (int) (((float) this.b) * instanceDiffuse)); @@ -141,7 +142,10 @@ public class SuperByteBuffer extends TemplateBuffer { spriteShiftFunc.shift(builder, u, v); } else builder.texture(u, v); - + + if (isEntityModel) + builder.overlay(OverlayTexture.DEFAULT_UV); + if (shouldLight) { int light = packedLightCoords; if (lightTransform != null) { @@ -158,14 +162,18 @@ public class SuperByteBuffer extends TemplateBuffer { } else builder.light(getLight(buffer, i)); - builder.normal(nx, ny, nz) - .endVertex(); + if (isEntityModel) + builder.normal(input.peek().getNormal(), nx, ny, nz); + else + builder.normal(nx, ny, nz); + builder.endVertex(); } transforms = new MatrixStack(); spriteShiftFunc = null; shouldColor = false; + isEntityModel = false; shouldLight = false; otherBlockLight = -1; } @@ -286,6 +294,11 @@ public class SuperByteBuffer extends TemplateBuffer { a = 255; return this; } + + public SuperByteBuffer asEntityModel() { + isEntityModel = true; + return this; + } private static int getLight(World world, Vector4f lightPos) { BlockPos.Mutable pos = new BlockPos.Mutable(); @@ -295,7 +308,7 @@ public class SuperByteBuffer extends TemplateBuffer { block += blockLightCache.computeIfAbsent(pos.toLong(), $ -> world.getLightLevel(LightType.BLOCK, pos)); return ((int) sky) << 20 | ((int) block) << 4; } - + public boolean isEmpty() { return ((Buffer) template).limit() == 0; } From ee3d359a9a4cb78edb78d311f5c4a020970358b6 Mon Sep 17 00:00:00 2001 From: simibubi <31564874+simibubi@users.noreply.github.com> Date: Wed, 16 Jun 2021 21:58:46 +0200 Subject: [PATCH 4/9] Reorder main menu --- .../foundation/gui/mainMenu/CreateMainMenuScreen.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/simibubi/create/foundation/gui/mainMenu/CreateMainMenuScreen.java b/src/main/java/com/simibubi/create/foundation/gui/mainMenu/CreateMainMenuScreen.java index bda65b052..5e0c7b59a 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/mainMenu/CreateMainMenuScreen.java +++ b/src/main/java/com/simibubi/create/foundation/gui/mainMenu/CreateMainMenuScreen.java @@ -133,9 +133,9 @@ public class CreateMainMenuScreen extends AbstractSimiScreen { int bShortWidth = 98; int bLongWidth = 200; - addButton(new Button(center - 100, yStart + 24 + -16, bLongWidth, bHeight, Lang.translate("menu.return"), + addButton(new Button(center - 100, yStart + 92, bLongWidth, bHeight, Lang.translate("menu.return"), $ -> onClose())); - addButton(new Button(center - 100, yStart + 48 + -16, bShortWidth, bHeight, Lang.translate("menu.configure"), + addButton(new Button(center - 100, yStart + 24 + -16, bLongWidth, bHeight, Lang.translate("menu.configure"), $ -> linkTo(BaseConfigScreen.forCreate(this)))); Button gettingStarted = new Button(center + 2, yStart + 48 + -16, bShortWidth, bHeight, @@ -148,11 +148,11 @@ public class CreateMainMenuScreen extends AbstractSimiScreen { String issueTrackerLink = "https://github.com/Creators-of-Create/Create/issues"; String supportLink = "https://github.com/Creators-of-Create/Create/wiki/Supporting-the-Project"; - addButton(new Button(center - 100, yStart + 68, bShortWidth, bHeight, Lang.translate("menu.project_page"), + addButton(new Button(center - 100, yStart + 48 + -16, bShortWidth, bHeight, Lang.translate("menu.project_page"), $ -> linkTo(projectLink))); addButton(new Button(center + 2, yStart + 68, bShortWidth, bHeight, Lang.translate("menu.report_bugs"), $ -> linkTo(issueTrackerLink))); - addButton(new Button(center - 100, yStart + 92, bLongWidth, bHeight, Lang.translate("menu.support"), + addButton(new Button(center - 100, yStart + 68, bShortWidth, bHeight, Lang.translate("menu.support"), $ -> linkTo(supportLink))); } From bf1c86ed876ad532772c1ba2e2de27e7a96bb9eb Mon Sep 17 00:00:00 2001 From: simibubi <31564874+simibubi@users.noreply.github.com> Date: Wed, 16 Jun 2021 22:32:58 +0200 Subject: [PATCH 5/9] Flow transfer - Fluid pipes no longer reset their contained flows when changed to/from their windowed or encased variant --- .../fluids/FluidTransportBehaviour.java | 22 +++++++++++++++++++ .../fluids/pipes/AxisPipeBlock.java | 3 +++ .../fluids/pipes/EncasedPipeBlock.java | 3 +++ .../fluids/pipes/FluidPipeBlock.java | 13 ++++++++--- .../fluids/pipes/GlassFluidPipeBlock.java | 3 +++ 5 files changed, 41 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/FluidTransportBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/FluidTransportBehaviour.java index 1d5d087fa..9cb460344 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/FluidTransportBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/FluidTransportBehaviour.java @@ -1,6 +1,7 @@ package com.simibubi.create.content.contraptions.fluids; import java.util.Collection; +import java.util.HashMap; import java.util.IdentityHashMap; import java.util.Map; import java.util.function.Predicate; @@ -13,12 +14,14 @@ import com.simibubi.create.foundation.tileEntity.SmartTileEntity; import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; import com.simibubi.create.foundation.tileEntity.behaviour.BehaviourType; import com.simibubi.create.foundation.utility.Iterate; +import com.simibubi.create.foundation.utility.WorldAttached; import net.minecraft.block.BlockState; import net.minecraft.nbt.CompoundNBT; import net.minecraft.util.Direction; import net.minecraft.util.math.BlockPos; import net.minecraft.world.IBlockDisplayReader; +import net.minecraft.world.IWorld; import net.minecraft.world.World; import net.minecraftforge.fluids.FluidStack; @@ -266,4 +269,23 @@ public abstract class FluidTransportBehaviour extends TileEntityBehaviour { return TYPE; } + // for switching TEs, but retaining flows + + public static final WorldAttached>> interfaceTransfer = + new WorldAttached<>(HashMap::new); + + public static void cacheFlows(IWorld world, BlockPos pos) { + FluidTransportBehaviour pipe = TileEntityBehaviour.get(world, pos, FluidTransportBehaviour.TYPE); + if (pipe != null) + interfaceTransfer.get(world) + .put(pos, pipe.interfaces); + } + + public static void loadFlows(IWorld world, BlockPos pos) { + FluidTransportBehaviour newPipe = TileEntityBehaviour.get(world, pos, FluidTransportBehaviour.TYPE); + if (newPipe != null) + newPipe.interfaces = interfaceTransfer.get(world) + .remove(pos); + } + } diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/AxisPipeBlock.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/AxisPipeBlock.java index dde62b1ff..d9410ff54 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/AxisPipeBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/AxisPipeBlock.java @@ -7,6 +7,7 @@ import java.util.Random; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllShapes; import com.simibubi.create.content.contraptions.fluids.FluidPropagator; +import com.simibubi.create.content.contraptions.fluids.FluidTransportBehaviour; import com.simibubi.create.content.contraptions.relays.elementary.BracketedTileEntityBehaviour; import com.simibubi.create.content.contraptions.wrench.IWrenchableWithBracket; import com.simibubi.create.foundation.advancement.AllTriggers; @@ -63,7 +64,9 @@ public class AxisPipeBlock extends RotatedPillarBlock implements IWrenchableWith BlockState newState = AllBlocks.ENCASED_FLUID_PIPE.getDefaultState(); for (Direction d : Iterate.directionsInAxis(getAxis(state))) newState = newState.with(EncasedPipeBlock.FACING_TO_PROPERTY_MAP.get(d), true); + FluidTransportBehaviour.cacheFlows(world, pos); world.setBlockState(pos, newState); + FluidTransportBehaviour.loadFlows(world, pos); } AllTriggers.triggerFor(AllTriggers.CASING_PIPE, player); return ActionResultType.SUCCESS; diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/EncasedPipeBlock.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/EncasedPipeBlock.java index fe75a7c28..6c59b77a7 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/EncasedPipeBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/EncasedPipeBlock.java @@ -13,6 +13,7 @@ import java.util.Random; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllTileEntities; import com.simibubi.create.content.contraptions.fluids.FluidPropagator; +import com.simibubi.create.content.contraptions.fluids.FluidTransportBehaviour; import com.simibubi.create.content.contraptions.wrench.IWrenchable; import com.simibubi.create.content.schematics.ISpecialBlockItemRequirement; import com.simibubi.create.content.schematics.ItemRequirement; @@ -126,8 +127,10 @@ public class EncasedPipeBlock extends Block implements IWrenchable, ISpecialBloc break; } + FluidTransportBehaviour.cacheFlows(world, pos); world.setBlockState(pos, AllBlocks.FLUID_PIPE.get() .updateBlockState(equivalentPipe, firstFound, null, world, pos)); + FluidTransportBehaviour.loadFlows(world, pos); return ActionResultType.SUCCESS; } diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/FluidPipeBlock.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/FluidPipeBlock.java index df762a72d..d906e294e 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/FluidPipeBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/FluidPipeBlock.java @@ -66,9 +66,13 @@ public class FluidPipeBlock extends SixWayBlock implements IWaterLoggable, IWren if (context.getFace() .getAxis() == axis) return ActionResultType.PASS; - if (!world.isRemote) + if (!world.isRemote) { + FluidTransportBehaviour.cacheFlows(world, pos); world.setBlockState(pos, AllBlocks.GLASS_FLUID_PIPE.getDefaultState() - .with(GlassFluidPipeBlock.AXIS, axis).with(BlockStateProperties.WATERLOGGED, state.get(BlockStateProperties.WATERLOGGED))); + .with(GlassFluidPipeBlock.AXIS, axis) + .with(BlockStateProperties.WATERLOGGED, state.get(BlockStateProperties.WATERLOGGED))); + FluidTransportBehaviour.loadFlows(world, pos); + } return ActionResultType.SUCCESS; } @@ -78,9 +82,12 @@ public class FluidPipeBlock extends SixWayBlock implements IWaterLoggable, IWren if (!AllBlocks.COPPER_CASING.isIn(player.getHeldItem(hand))) return ActionResultType.PASS; AllTriggers.triggerFor(AllTriggers.CASING_PIPE, player); - if (!world.isRemote) + if (!world.isRemote) { + FluidTransportBehaviour.cacheFlows(world, pos); world.setBlockState(pos, EncasedPipeBlock.transferSixWayProperties(state, AllBlocks.ENCASED_FLUID_PIPE.getDefaultState())); + FluidTransportBehaviour.loadFlows(world, pos); + } return ActionResultType.SUCCESS; } diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/GlassFluidPipeBlock.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/GlassFluidPipeBlock.java index fffa566df..d85e25e8f 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/GlassFluidPipeBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/GlassFluidPipeBlock.java @@ -4,6 +4,7 @@ import javax.annotation.ParametersAreNonnullByDefault; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllTileEntities; +import com.simibubi.create.content.contraptions.fluids.FluidTransportBehaviour; import com.simibubi.create.content.schematics.ISpecialBlockItemRequirement; import com.simibubi.create.content.schematics.ItemRequirement; @@ -59,8 +60,10 @@ public class GlassFluidPipeBlock extends AxisPipeBlock implements IWaterLoggable BlockState newState; World world = context.getWorld(); BlockPos pos = context.getPos(); + FluidTransportBehaviour.cacheFlows(world, pos); newState = toRegularPipe(world, pos, state).with(BlockStateProperties.WATERLOGGED, state.get(BlockStateProperties.WATERLOGGED)); world.setBlockState(pos, newState, 3); + FluidTransportBehaviour.loadFlows(world, pos); return ActionResultType.SUCCESS; } From 06ca8b0d1ced0f0d0c3d324a65c61b1963534ab0 Mon Sep 17 00:00:00 2001 From: simibubi <31564874+simibubi@users.noreply.github.com> Date: Thu, 17 Jun 2021 00:54:48 +0200 Subject: [PATCH 6/9] What's inside? - Blueprint crafting overlay now attempts to show a list of items matching an ingredient filter in the respective slot - Fixed JEI prematurely transferring the blueprint recipe when viewed --- .../compat/jei/BlueprintTransferHandler.java | 2 + .../tools/BlueprintOverlayRenderer.java | 80 ++++++++++++++++--- .../logistics/item/filter/ItemAttribute.java | 2 +- 3 files changed, 71 insertions(+), 13 deletions(-) diff --git a/src/main/java/com/simibubi/create/compat/jei/BlueprintTransferHandler.java b/src/main/java/com/simibubi/create/compat/jei/BlueprintTransferHandler.java index 47848a981..f499357f9 100644 --- a/src/main/java/com/simibubi/create/compat/jei/BlueprintTransferHandler.java +++ b/src/main/java/com/simibubi/create/compat/jei/BlueprintTransferHandler.java @@ -22,6 +22,8 @@ public class BlueprintTransferHandler implements IRecipeTransferHandler iRecipe = (IRecipe) recipe; // Continued server-side in BlueprintItem.assignCompleteRecipe() AllPackets.channel.sendToServer(new BlueprintAssignCompleteRecipePacket(iRecipe.getId())); diff --git a/src/main/java/com/simibubi/create/content/curiosities/tools/BlueprintOverlayRenderer.java b/src/main/java/com/simibubi/create/content/curiosities/tools/BlueprintOverlayRenderer.java index edb9b3e93..0e90ee67e 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/tools/BlueprintOverlayRenderer.java +++ b/src/main/java/com/simibubi/create/content/curiosities/tools/BlueprintOverlayRenderer.java @@ -2,15 +2,19 @@ package com.simibubi.create.content.curiosities.tools; import java.util.ArrayList; import java.util.HashMap; +import java.util.IdentityHashMap; import java.util.List; import java.util.Map; import java.util.Optional; import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.systems.RenderSystem; +import com.simibubi.create.AllItems; import com.simibubi.create.content.curiosities.tools.BlueprintEntity.BlueprintCraftingInventory; import com.simibubi.create.content.curiosities.tools.BlueprintEntity.BlueprintSection; +import com.simibubi.create.content.logistics.item.filter.AttributeFilterContainer.WhitelistMode; import com.simibubi.create.content.logistics.item.filter.FilterItem; +import com.simibubi.create.content.logistics.item.filter.ItemAttribute; import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.gui.GuiGameElement; import com.simibubi.create.foundation.utility.AnimationTickHolder; @@ -19,14 +23,21 @@ import com.simibubi.create.foundation.utility.Pair; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.inventory.CraftingInventory; +import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; import net.minecraft.item.crafting.ICraftingRecipe; import net.minecraft.item.crafting.IRecipeType; +import net.minecraft.item.crafting.Ingredient; +import net.minecraft.nbt.CompoundNBT; +import net.minecraft.nbt.ListNBT; +import net.minecraft.tags.ITag; +import net.minecraft.tags.TagCollectionManager; import net.minecraft.util.math.EntityRayTraceResult; import net.minecraft.util.math.RayTraceResult; import net.minecraft.util.math.RayTraceResult.Type; import net.minecraft.util.text.TextFormatting; +import net.minecraftforge.common.util.Constants.NBT; import net.minecraftforge.items.ItemHandlerHelper; import net.minecraftforge.items.ItemStackHandler; @@ -37,6 +48,7 @@ public class BlueprintOverlayRenderer { static boolean lastSneakState; static BlueprintSection lastTargetedSection; + static Map cachedRenderedFilters = new IdentityHashMap<>(); static List> ingredients = new ArrayList<>(); static ItemStack result = ItemStack.EMPTY; static boolean resultCraftable = false; @@ -72,6 +84,7 @@ public class BlueprintOverlayRenderer { } public static void rebuild(BlueprintSection sectionAt, boolean sneak) { + cachedRenderedFilters.clear(); ItemStackHandler items = sectionAt.getItems(); boolean empty = true; for (int i = 0; i < 9; i++) { @@ -206,13 +219,9 @@ public class BlueprintOverlayRenderer { RenderSystem.enableBlend(); (pair.getSecond() ? AllGuiTextures.HOTSLOT_ACTIVE : AllGuiTextures.HOTSLOT).draw(ms, x, y); ItemStack itemStack = pair.getFirst(); - GuiGameElement.of(itemStack) - .at(x + 3, y + 3) - .render(ms); - mc.getItemRenderer() - .renderItemOverlayIntoGUI(mc.fontRenderer, itemStack, x + 3, y + 3, - pair.getSecond() || itemStack.getCount() == 1 ? null - : TextFormatting.GOLD.toString() + itemStack.getCount()); + String count = pair.getSecond() || itemStack.getCount() == 1 ? null + : TextFormatting.GOLD.toString() + itemStack.getCount(); + drawItemStack(ms, mc, x, y, itemStack, count); x += 21; } @@ -229,12 +238,59 @@ public class BlueprintOverlayRenderer { } else { (resultCraftable ? AllGuiTextures.HOTSLOT_SUPER_ACTIVE : AllGuiTextures.HOTSLOT).draw(ms, resultCraftable ? x - 1 : x, resultCraftable ? y - 1 : y); - GuiGameElement.of(result) - .at(x + 3, y + 3) - .render(ms); - mc.getItemRenderer() - .renderItemOverlayIntoGUI(mc.fontRenderer, result, x + 3, y + 3, null); + drawItemStack(ms, mc, x, y, result, null); } } + public static void drawItemStack(MatrixStack ms, Minecraft mc, int x, int y, ItemStack itemStack, String count) { + if (itemStack.getItem() instanceof FilterItem) { + int step = AnimationTickHolder.getTicks(mc.world) / 10; + ItemStack[] itemsMatchingFilter = getItemsMatchingFilter(itemStack); + if (itemsMatchingFilter.length > 0) + itemStack = itemsMatchingFilter[step % itemsMatchingFilter.length]; + } + + GuiGameElement.of(itemStack) + .at(x + 3, y + 3) + .render(ms); + mc.getItemRenderer() + .renderItemOverlayIntoGUI(mc.fontRenderer, itemStack, x + 3, y + 3, count); + } + + private static ItemStack[] getItemsMatchingFilter(ItemStack filter) { + return cachedRenderedFilters.computeIfAbsent(filter, itemStack -> { + CompoundNBT tag = itemStack.getOrCreateTag(); + + if (AllItems.FILTER.isIn(itemStack) && !tag.getBoolean("Blacklist")) { + ItemStackHandler filterItems = FilterItem.getFilterItems(itemStack); + List list = new ArrayList<>(); + for (int slot = 0; slot < filterItems.getSlots(); slot++) { + ItemStack stackInSlot = filterItems.getStackInSlot(slot); + if (!stackInSlot.isEmpty()) + list.add(stackInSlot); + } + return list.toArray(new ItemStack[list.size()]); + } + + if (AllItems.ATTRIBUTE_FILTER.isIn(itemStack)) { + WhitelistMode whitelistMode = WhitelistMode.values()[tag.getInt("WhitelistMode")]; + ListNBT attributes = tag.getList("MatchedAttributes", NBT.TAG_COMPOUND); + if (whitelistMode == WhitelistMode.WHITELIST_DISJ && attributes.size() == 1) { + ItemAttribute fromNBT = ItemAttribute.fromNBT((CompoundNBT) attributes.get(0)); + if (fromNBT instanceof ItemAttribute.InTag) { + ItemAttribute.InTag inTag = (ItemAttribute.InTag) fromNBT; + ITag itag = TagCollectionManager.getTagManager() + .getItems() + .get(inTag.tagName); + if (itag != null) + return Ingredient.fromTag(itag) + .getMatchingStacks(); + } + } + } + + return new ItemStack[0]; + }); + } + } diff --git a/src/main/java/com/simibubi/create/content/logistics/item/filter/ItemAttribute.java b/src/main/java/com/simibubi/create/content/logistics/item/filter/ItemAttribute.java index 7e7e1bb15..4f79b0eee 100644 --- a/src/main/java/com/simibubi/create/content/logistics/item/filter/ItemAttribute.java +++ b/src/main/java/com/simibubi/create/content/logistics/item/filter/ItemAttribute.java @@ -222,7 +222,7 @@ public interface ItemAttribute { public static class InTag implements ItemAttribute { - ResourceLocation tagName; + public ResourceLocation tagName; public InTag(ResourceLocation tagName) { this.tagName = tagName; From 1d476160ccad16152079acad4444f581ba7bcad1 Mon Sep 17 00:00:00 2001 From: PepperBell <44146161+PepperCode1@users.noreply.github.com> Date: Wed, 16 Jun 2021 17:17:16 -0700 Subject: [PATCH 7/9] Mechanical arm tweaks - Don't dance if arm speed is zero - Rerender arm after switching back from dancing state (flywheel only) - Formatting --- .../block/mechanicalArm/ArmInstance.java | 17 ++++++------- .../block/mechanicalArm/ArmRenderer.java | 25 +++++++++++-------- 2 files changed, 23 insertions(+), 19 deletions(-) diff --git a/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmInstance.java b/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmInstance.java index 941b35260..fed885fac 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmInstance.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmInstance.java @@ -37,7 +37,7 @@ public class ArmInstance extends SingleRotatingInstance implements IDynamicInsta private final ArmTileEntity arm; private final Boolean ceiling; - private boolean firstTick = true; + private boolean firstRender = true; private float baseAngle = Float.NaN; private float lowerArmAngle = Float.NaN; @@ -69,8 +69,9 @@ public class ArmInstance extends SingleRotatingInstance implements IDynamicInsta @Override public void beginFrame() { - if (arm.phase == ArmTileEntity.Phase.DANCING) { + if (arm.phase == ArmTileEntity.Phase.DANCING && tile.getSpeed() != 0) { animateArm(true); + firstRender = true; return; } @@ -91,20 +92,19 @@ public class ArmInstance extends SingleRotatingInstance implements IDynamicInsta this.upperArmAngle = upperArmAngleNow; this.headAngle = headAngleNow; - if (!settled || firstTick) + if (!settled || firstRender) animateArm(false); - if (settled) - firstTick = false; + if (firstRender) + firstRender = false; } private void animateArm(boolean rave) { - - int color; float baseAngle; float lowerArmAngle; float upperArmAngle; float headAngle; + int color; if (rave) { float renderTick = AnimationTickHolder.getRenderTime(this.arm.getWorld()) + (tile.hashCode() % 64); @@ -112,14 +112,12 @@ public class ArmInstance extends SingleRotatingInstance implements IDynamicInsta lowerArmAngle = MathHelper.lerp((MathHelper.sin(renderTick / 4) + 1) / 2, -45, 15); upperArmAngle = MathHelper.lerp((MathHelper.sin(renderTick / 8) + 1) / 4, -45, 95); headAngle = -lowerArmAngle; - color = ColorHelper.rainbowColor(AnimationTickHolder.getTicks() * 100); } else { baseAngle = this.baseAngle; lowerArmAngle = this.lowerArmAngle - 135; upperArmAngle = this.upperArmAngle - 90; headAngle = this.headAngle; - color = 0xFFFFFF; } @@ -182,4 +180,5 @@ public class ArmInstance extends SingleRotatingInstance implements IDynamicInsta super.remove(); models.forEach(InstanceData::delete); } + } diff --git a/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmRenderer.java b/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmRenderer.java index 2a9a72ac3..135b97261 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmRenderer.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmRenderer.java @@ -40,12 +40,11 @@ public class ArmRenderer extends KineticTileEntityRenderer { protected void renderSafe(KineticTileEntity te, float pt, MatrixStack ms, IRenderTypeBuffer buffer, int light, int overlay) { super.renderSafe(te, pt, ms, buffer, light, overlay); + ArmTileEntity arm = (ArmTileEntity) te; - - boolean usingFlywheel = FastRenderDispatcher.available(te.getWorld()); - ItemStack item = arm.heldItem; boolean hasItem = !item.isEmpty(); + boolean usingFlywheel = FastRenderDispatcher.available(te.getWorld()); if (usingFlywheel && !hasItem) return; @@ -61,21 +60,27 @@ public class ArmRenderer extends KineticTileEntityRenderer { MatrixStack msLocal = new MatrixStack(); MatrixStacker msr = MatrixStacker.of(msLocal); - int color = 0xFFFFFF; - float baseAngle = arm.baseAngle.get(pt); - float lowerArmAngle = arm.lowerArmAngle.get(pt) - 135; - float upperArmAngle = arm.upperArmAngle.get(pt) - 90; - float headAngle = arm.headAngle.get(pt); + float baseAngle; + float lowerArmAngle; + float upperArmAngle; + float headAngle; + int color; - boolean rave = arm.phase == Phase.DANCING; - float renderTick = AnimationTickHolder.getRenderTime(te.getWorld()) + (te.hashCode() % 64); + boolean rave = arm.phase == Phase.DANCING && te.getSpeed() != 0; if (rave) { + float renderTick = AnimationTickHolder.getRenderTime(te.getWorld()) + (te.hashCode() % 64); baseAngle = (renderTick * 10) % 360; lowerArmAngle = MathHelper.lerp((MathHelper.sin(renderTick / 4) + 1) / 2, -45, 15); upperArmAngle = MathHelper.lerp((MathHelper.sin(renderTick / 8) + 1) / 4, -45, 95); headAngle = -lowerArmAngle; color = ColorHelper.rainbowColor(AnimationTickHolder.getTicks() * 100); + } else { + baseAngle = arm.baseAngle.get(pt); + lowerArmAngle = arm.lowerArmAngle.get(pt) - 135; + upperArmAngle = arm.upperArmAngle.get(pt) - 90; + headAngle = arm.headAngle.get(pt); + color = 0xFFFFFF; } msr.centre(); From 761fa2c1e9f8d44f262b3466686b2e3a06c8aa96 Mon Sep 17 00:00:00 2001 From: simibubi <31564874+simibubi@users.noreply.github.com> Date: Thu, 17 Jun 2021 10:00:47 +0200 Subject: [PATCH 8/9] Update README.md --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index a7fc50bd6..70bb55392 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -

Logo

-

Create
- Patreon +

Logo

+

Create
+ Patreon Supported Versions License Discord @@ -13,7 +13,7 @@ The added elements of tech are designed to leave as many design choices to the p 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. -[](https://github.com/simibubi/Create/issues "Report Issues") +[](https://github.com/Creators-of-Create/Create/issues "Report Issues") [](https://www.youtube.com/playlist?list=PLyADkcfPLU8ywCXZPaDbQ_JZJL0CGDN5Z "Watch Videos") [](https://discord.gg/hmaD7Se "Feedback & Help") [](https://www.patreon.com/simibubi "Support Us") From 4265a2855cf6d0e672229b841eeb95ef950786cc Mon Sep 17 00:00:00 2001 From: simibubi <31564874+simibubi@users.noreply.github.com> Date: Thu, 17 Jun 2021 11:28:29 +0200 Subject: [PATCH 9/9] Finally bearable - Entities can now jump on Mechanical Belts - Entities on belts no longer get force-centered while actively moving or strafing --- .../relays/belt/transport/BeltMovementHandler.java | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/BeltMovementHandler.java b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/BeltMovementHandler.java index 9786a30c4..e96ebabdf 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/BeltMovementHandler.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/BeltMovementHandler.java @@ -95,9 +95,8 @@ public class BeltMovementHandler { // Lock entities in place boolean isPlayer = entityIn instanceof PlayerEntity; - if (entityIn instanceof LivingEntity && !isPlayer) { + if (entityIn instanceof LivingEntity && !isPlayer) ((LivingEntity) entityIn).addPotionEffect(new EffectInstance(Effects.SLOWNESS, 10, 1, false, false)); - } final Direction beltFacing = blockState.get(BlockStateProperties.HORIZONTAL_FACING); final BeltSlope slope = blockState.get(BeltBlock.SLOPE); @@ -138,12 +137,14 @@ public class BeltMovementHandler { movement = movement.add(0, -Math.abs(axis.getCoordinate(movement.x, movement.y, movement.z)), 0); Vector3d centering = Vector3d.of(centeringDirection).scale(diffCenter * Math.min(Math.abs(movementSpeed), .1f) * 4); - float step = entityIn.stepHeight; - if (!isPlayer) { + if (!(entityIn instanceof LivingEntity) + || ((LivingEntity) entityIn).moveForward == 0 && ((LivingEntity) entityIn).moveStrafing == 0) movement = movement.add(centering); + + float step = entityIn.stepHeight; + if (!isPlayer) entityIn.stepHeight = 1; - } // Entity Collisions if (Math.abs(movementSpeed) < .5f) { @@ -175,6 +176,8 @@ public class BeltMovementHandler { } else { entityIn.move(SELF, movement); } + + entityIn.onGround = true; if (!isPlayer) entityIn.stepHeight = step; @@ -189,6 +192,7 @@ public class BeltMovementHandler { entityIn.setMotion(movement); entityIn.velocityChanged = true; } + } public static boolean shouldIgnoreBlocking(Entity me, Entity other) {