diff --git a/src/main/java/com/simibubi/create/AllItems.java b/src/main/java/com/simibubi/create/AllItems.java index f8412edc1..1c1fef701 100644 --- a/src/main/java/com/simibubi/create/AllItems.java +++ b/src/main/java/com/simibubi/create/AllItems.java @@ -6,6 +6,8 @@ import com.simibubi.create.item.ItemWandSymmetry; import net.minecraft.item.Item; import net.minecraft.item.Item.Properties; import net.minecraft.item.ItemStack; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.registries.IForgeRegistry; public enum AllItems { @@ -39,6 +41,7 @@ public enum AllItems { return stack.getItem() == item; } + @OnlyIn(Dist.CLIENT) public static void initColorHandlers() { } diff --git a/src/main/java/com/simibubi/create/AllTileEntities.java b/src/main/java/com/simibubi/create/AllTileEntities.java index 45fb8105a..177b04e0b 100644 --- a/src/main/java/com/simibubi/create/AllTileEntities.java +++ b/src/main/java/com/simibubi/create/AllTileEntities.java @@ -10,6 +10,8 @@ import net.minecraft.client.renderer.tileentity.TileEntityRenderer; import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntityType; import net.minecraft.util.ResourceLocation; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.event.RegistryEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.client.registry.ClientRegistry; @@ -42,10 +44,12 @@ public enum AllTileEntities { } } + @OnlyIn(Dist.CLIENT) public static void registerRenderers() { bind(SchematicannonTileEntity.class, new SchematicannonRenderer()); } + @OnlyIn(Dist.CLIENT) private static void bind(Class clazz, TileEntityRenderer renderer) { ClientRegistry.bindTileEntitySpecialRenderer(clazz, renderer); } diff --git a/src/main/java/com/simibubi/create/Create.java b/src/main/java/com/simibubi/create/Create.java index 6d43e6173..b6b08b98c 100644 --- a/src/main/java/com/simibubi/create/Create.java +++ b/src/main/java/com/simibubi/create/Create.java @@ -3,10 +3,13 @@ package com.simibubi.create; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import com.simibubi.create.gui.Keyboard; import com.simibubi.create.networking.Packets; +import com.simibubi.create.schematic.BlueprintHandler; import com.simibubi.create.schematic.SchematicHologram; import net.minecraft.block.Block; +import net.minecraft.client.settings.KeyBinding; import net.minecraft.item.Item; import net.minecraft.item.ItemGroup; import net.minecraftforge.api.distmarker.Dist; @@ -15,6 +18,7 @@ import net.minecraftforge.event.RegistryEvent; import net.minecraftforge.eventbus.api.IEventBus; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.DistExecutor; +import net.minecraftforge.fml.client.registry.ClientRegistry; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod.EventBusSubscriber; import net.minecraftforge.fml.common.Mod.EventBusSubscriber.Bus; @@ -37,6 +41,8 @@ public class Create { @OnlyIn(Dist.CLIENT) public static ClientSchematicLoader cSchematicLoader; + @OnlyIn(Dist.CLIENT) + public static KeyBinding TOOL_MENU; public static ServerSchematicLoader sSchematicLoader; @@ -47,17 +53,24 @@ public class Create { } private void clientInit(FMLClientSetupEvent event) { - AllItems.initColorHandlers(); - AllTileEntities.registerRenderers(); - cSchematicLoader = new ClientSchematicLoader(); - sSchematicLoader = new ServerSchematicLoader(); - new SchematicHologram(); -// ScrollFixer.init(); + DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> { + AllItems.initColorHandlers(); + AllTileEntities.registerRenderers(); + cSchematicLoader = new ClientSchematicLoader(); + new SchematicHologram(); + new BlueprintHandler(); + ScrollFixer.init(); + ScrollFixer.addMouseWheelListener(BlueprintHandler.instance::onScroll); + + TOOL_MENU = new KeyBinding("Tool Menu (Hold)", Keyboard.LALT, NAME); + ClientRegistry.registerKeyBinding(TOOL_MENU); + }); } private void init(final FMLCommonSetupEvent event) { Packets.registerPackets(); DistExecutor.runWhenOn(Dist.CLIENT, () -> AllContainers::registerScreenFactories); + sSchematicLoader = new ServerSchematicLoader(); } @OnlyIn(Dist.CLIENT) diff --git a/src/main/java/com/simibubi/create/ServerSchematicLoader.java b/src/main/java/com/simibubi/create/ServerSchematicLoader.java index 28930408c..e8c614573 100644 --- a/src/main/java/com/simibubi/create/ServerSchematicLoader.java +++ b/src/main/java/com/simibubi/create/ServerSchematicLoader.java @@ -10,14 +10,13 @@ import java.util.Map; import com.simibubi.create.block.SchematicTableContainer; import com.simibubi.create.block.SchematicTableTileEntity; +import com.simibubi.create.item.ItemBlueprint; import com.simibubi.create.networking.PacketSchematicUpload.DimensionPos; import com.simibubi.create.utility.FilesHelper; import net.minecraft.block.BlockState; import net.minecraft.entity.player.ServerPlayerEntity; import net.minecraft.item.ItemStack; -import net.minecraft.util.text.StringTextComponent; -import net.minecraft.util.text.TextFormatting; public class ServerSchematicLoader { @@ -111,13 +110,7 @@ public class ServerSchematicLoader { return; tileEntity.inputStack = ItemStack.EMPTY; - ItemStack blueprint = new ItemStack(AllItems.BLUEPRINT.get()); - blueprint.setDisplayName(new StringTextComponent(TextFormatting.RESET + "" + TextFormatting.WHITE - + "Blueprint (" + TextFormatting.GOLD + schematic + TextFormatting.WHITE + ")")); - blueprint.getTag().putString("Owner", player.getName().getFormattedText()); - blueprint.getTag().putString("File", schematic); - - tileEntity.outputStack = blueprint; + tileEntity.outputStack = ItemBlueprint.create(schematic, player.getName().getFormattedText()); dimpos.world.notifyBlockUpdate(dimpos.pos, blockState, blockState, 3); diff --git a/src/main/java/com/simibubi/create/block/SchematicTableBlock.java b/src/main/java/com/simibubi/create/block/SchematicTableBlock.java index 39904510d..dc030606d 100644 --- a/src/main/java/com/simibubi/create/block/SchematicTableBlock.java +++ b/src/main/java/com/simibubi/create/block/SchematicTableBlock.java @@ -1,12 +1,9 @@ package com.simibubi.create.block; -import javax.annotation.Nullable; - import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; import net.minecraft.block.HorizontalBlock; -import net.minecraft.block.ITileEntityProvider; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.inventory.InventoryHelper; import net.minecraft.inventory.container.INamedContainerProvider; @@ -19,8 +16,7 @@ import net.minecraft.util.math.BlockRayTraceResult; import net.minecraft.world.IBlockReader; import net.minecraft.world.World; -@SuppressWarnings("deprecation") -public class SchematicTableBlock extends HorizontalBlock implements ITileEntityProvider { +public class SchematicTableBlock extends HorizontalBlock { public SchematicTableBlock() { super(Properties.from(Blocks.OAK_PLANKS)); @@ -43,17 +39,18 @@ public class SchematicTableBlock extends HorizontalBlock implements ITileEntityP } @Override - public boolean hasTileEntity() { + public boolean hasTileEntity(BlockState state) { return true; } @Override public boolean onBlockActivated(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn, BlockRayTraceResult hit) { + if (worldIn.isRemote) { return true; } else { - INamedContainerProvider inamedcontainerprovider = this.getContainer(state, worldIn, pos); + INamedContainerProvider inamedcontainerprovider = (INamedContainerProvider) worldIn.getTileEntity(pos); if (inamedcontainerprovider != null) { player.openContainer(inamedcontainerprovider); } @@ -61,9 +58,9 @@ public class SchematicTableBlock extends HorizontalBlock implements ITileEntityP return true; } } - + @Override - public TileEntity createNewTileEntity(IBlockReader worldIn) { + public TileEntity createTileEntity(BlockState state, IBlockReader world) { return new SchematicTableTileEntity(); } @@ -80,16 +77,4 @@ public class SchematicTableBlock extends HorizontalBlock implements ITileEntityP } - public boolean eventReceived(BlockState state, World worldIn, BlockPos pos, int id, int param) { - super.eventReceived(state, worldIn, pos, id, param); - TileEntity tileentity = worldIn.getTileEntity(pos); - return tileentity == null ? false : tileentity.receiveClientEvent(id, param); - } - - @Nullable - public INamedContainerProvider getContainer(BlockState state, World worldIn, BlockPos pos) { - TileEntity tileentity = worldIn.getTileEntity(pos); - return tileentity instanceof INamedContainerProvider ? (INamedContainerProvider) tileentity : null; - } - } diff --git a/src/main/java/com/simibubi/create/block/SchematicTableContainer.java b/src/main/java/com/simibubi/create/block/SchematicTableContainer.java index e614a8f5e..71cf7d17f 100644 --- a/src/main/java/com/simibubi/create/block/SchematicTableContainer.java +++ b/src/main/java/com/simibubi/create/block/SchematicTableContainer.java @@ -45,14 +45,14 @@ public class SchematicTableContainer extends Container { this.player = inv.player; this.te = te; - inputSlot = new Slot(tableInventory, 0, -9, 15) { + inputSlot = new Slot(tableInventory, 0, -9, 40) { @Override public boolean isItemValid(ItemStack stack) { return AllItems.EMPTY_BLUEPRINT.typeOf(stack); } }; - outputSlot = new Slot(tableInventory, 1, 75, 15) { + outputSlot = new Slot(tableInventory, 1, 75, 40) { @Override public boolean isItemValid(ItemStack stack) { return false; @@ -72,12 +72,12 @@ public class SchematicTableContainer extends Container { tableInventory.openInventory(inv.player); for (int l = 0; l < 3; ++l) { for (int j1 = 0; j1 < 9; ++j1) { - this.addSlot(new Slot(inv, j1 + l * 9 + 9, -8 + j1 * 18, 77 + l * 18)); + this.addSlot(new Slot(inv, j1 + l * 9 + 9, -8 + j1 * 18, 102 + l * 18)); } } for (int i1 = 0; i1 < 9; ++i1) { - this.addSlot(new Slot(inv, i1, -8 + i1 * 18, 135)); + this.addSlot(new Slot(inv, i1, -8 + i1 * 18, 160)); } } diff --git a/src/main/java/com/simibubi/create/block/SchematicannonTileEntity.java b/src/main/java/com/simibubi/create/block/SchematicannonTileEntity.java index d556ad35b..3192cc005 100644 --- a/src/main/java/com/simibubi/create/block/SchematicannonTileEntity.java +++ b/src/main/java/com/simibubi/create/block/SchematicannonTileEntity.java @@ -32,6 +32,8 @@ import net.minecraft.tileentity.ITickableTileEntity; import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntityType; import net.minecraft.util.Direction; +import net.minecraft.util.SoundCategory; +import net.minecraft.util.SoundEvents; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; @@ -262,19 +264,27 @@ public class SchematicannonTileEntity extends TileEntitySynced implements ITicka anchor = null; reader = null; missingBlock = false; + target = getPos().add(1, 0, 0); + world.playSound(null, pos.getX(), pos.getY(), pos.getZ(), SoundEvents.BLOCK_NOTE_BLOCK_BELL, + SoundCategory.BLOCKS, 1, .7f); + world.notifyBlockUpdate(getPos(), getBlockState(), getBlockState(), 2); return; } state = reader.getBlockState(anchor.add(currentPos)); } while (state.getBlock() == Blocks.AIR); target = anchor.add(currentPos); + missingBlock = false; // Update orientation - world.notifyBlockUpdate(getPos(), getBlockState(), getBlockState(), 3); + world.notifyBlockUpdate(getPos(), getBlockState(), getBlockState(), 2); + + if (target.withinDistance(getPos(), 2f)) { + return; + } if (creative) { launchBlock(currentPos.add(anchor), state); - missingBlock = false; return; } @@ -285,7 +295,6 @@ public class SchematicannonTileEntity extends TileEntitySynced implements ITicka // Overwrite in case its rotated launchBlock(target, state); - missingBlock = false; } // Search for required item diff --git a/src/main/java/com/simibubi/create/gui/AbstractSimiScreen.java b/src/main/java/com/simibubi/create/gui/AbstractSimiScreen.java index 5f01b4b92..31ea5eb2b 100644 --- a/src/main/java/com/simibubi/create/gui/AbstractSimiScreen.java +++ b/src/main/java/com/simibubi/create/gui/AbstractSimiScreen.java @@ -8,7 +8,10 @@ import com.simibubi.create.gui.widgets.AbstractSimiWidget; import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.widget.Widget; import net.minecraft.util.text.StringTextComponent; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +@OnlyIn(Dist.CLIENT) public abstract class AbstractSimiScreen extends Screen { protected int sWidth, sHeight; diff --git a/src/main/java/com/simibubi/create/gui/BlueprintHotbarOverlay.java b/src/main/java/com/simibubi/create/gui/BlueprintHotbarOverlay.java new file mode 100644 index 000000000..a5712f38e --- /dev/null +++ b/src/main/java/com/simibubi/create/gui/BlueprintHotbarOverlay.java @@ -0,0 +1,20 @@ +package com.simibubi.create.gui; + +import com.mojang.blaze3d.platform.GlStateManager; + +import net.minecraft.client.MainWindow; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.AbstractGui; + +public class BlueprintHotbarOverlay extends AbstractGui { + + public void renderOn(int slot) { + MainWindow mainWindow = Minecraft.getInstance().mainWindow; + int x = mainWindow.getScaledWidth() / 2 - 92; + int y = mainWindow.getScaledHeight() - 23; + GlStateManager.enableBlend(); + GlStateManager.enableAlphaTest(); + GuiResources.BLUEPRINT_SLOT.draw(this, x + 20 * slot, y); + } + +} diff --git a/src/main/java/com/simibubi/create/gui/GuiHandler.java b/src/main/java/com/simibubi/create/gui/GuiHandler.java deleted file mode 100644 index f7fa187ab..000000000 --- a/src/main/java/com/simibubi/create/gui/GuiHandler.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.simibubi.create.gui; - -public class GuiHandler { - -} diff --git a/src/main/java/com/simibubi/create/gui/GuiOpener.java b/src/main/java/com/simibubi/create/gui/GuiOpener.java index 74112956f..d24a45826 100644 --- a/src/main/java/com/simibubi/create/gui/GuiOpener.java +++ b/src/main/java/com/simibubi/create/gui/GuiOpener.java @@ -2,11 +2,14 @@ package com.simibubi.create.gui; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.screen.Screen; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.common.Mod.EventBusSubscriber; import net.minecraftforge.fml.common.gameevent.TickEvent.ClientTickEvent; -@EventBusSubscriber +@OnlyIn(Dist.CLIENT) +@EventBusSubscriber(value = Dist.CLIENT) public class GuiOpener { private static Screen openedGuiNextTick; diff --git a/src/main/java/com/simibubi/create/gui/GuiResources.java b/src/main/java/com/simibubi/create/gui/GuiResources.java index 599dbfa38..4025376a1 100644 --- a/src/main/java/com/simibubi/create/gui/GuiResources.java +++ b/src/main/java/com/simibubi/create/gui/GuiResources.java @@ -27,6 +27,8 @@ public enum GuiResources { INDICATOR_RED("widgets.png", 36, 23, 18, 5), GRAY("background.png", 0, 0, 16, 16), + BLUEPRINT_SLOT("widgets.png", 90, 0, 24, 24), + // Icons ICON_NONE("icons.png", 16, 16, 16, 16), ICON_ADD("icons.png", 16, 16), diff --git a/src/main/java/com/simibubi/create/utility/Keyboard.java b/src/main/java/com/simibubi/create/gui/Keyboard.java similarity index 78% rename from src/main/java/com/simibubi/create/utility/Keyboard.java rename to src/main/java/com/simibubi/create/gui/Keyboard.java index 088e26633..ada30d0a7 100644 --- a/src/main/java/com/simibubi/create/utility/Keyboard.java +++ b/src/main/java/com/simibubi/create/gui/Keyboard.java @@ -1,7 +1,8 @@ -package com.simibubi.create.utility; +package com.simibubi.create.gui; + +import org.lwjgl.glfw.GLFW; import net.minecraft.client.Minecraft; -import net.minecraft.client.util.InputMappings; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; @@ -24,7 +25,7 @@ public class Keyboard { public static final int G = 71; public static boolean isKeyDown(int key) { - return InputMappings.isKeyDown(Minecraft.getInstance().mainWindow.getHandle(), key); + return GLFW.glfwGetKey(Minecraft.getInstance().mainWindow.getHandle(), key) != 0; } } diff --git a/src/main/java/com/simibubi/create/gui/SchematicTableScreen.java b/src/main/java/com/simibubi/create/gui/SchematicTableScreen.java index 4fb5b7406..8e8a0d5ab 100644 --- a/src/main/java/com/simibubi/create/gui/SchematicTableScreen.java +++ b/src/main/java/com/simibubi/create/gui/SchematicTableScreen.java @@ -2,8 +2,6 @@ package com.simibubi.create.gui; import java.util.List; -import org.lwjgl.opengl.GL11; - import com.mojang.blaze3d.platform.GlStateManager; import com.simibubi.create.AllBlocks; import com.simibubi.create.Create; @@ -18,15 +16,11 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.gui.IHasContainer; import net.minecraft.client.gui.screen.inventory.ContainerScreen; import net.minecraft.client.gui.widget.Widget; -import net.minecraft.client.renderer.BufferBuilder; -import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.RenderHelper; import net.minecraft.client.renderer.texture.AtlasTexture; -import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.entity.player.PlayerInventory; -import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; import net.minecraft.util.text.ITextComponent; -import net.minecraftforge.client.model.data.EmptyModelData; public class SchematicTableScreen extends ContainerScreen implements IHasContainer { @@ -53,7 +47,7 @@ public class SchematicTableScreen extends ContainerScreen tools; + protected Consumer callback; + public boolean focused; + private float yOffset; + protected int selection; + + protected int w; + protected int h; + + public ToolSelectionScreen(List tools, Consumer callback) { + super(new StringTextComponent("Tool Selection")); + this.minecraft = Minecraft.getInstance(); + this.tools = tools; + this.callback = callback; + focused = false; + yOffset = 0; + selection = 0; + + callback.accept(tools.get(selection)); + + w = tools.size() * 50 + 30; + h = 30; + } + + public void setSelectedElement(Tools tool) { + if (!tools.contains(tool)) + return; + selection = tools.indexOf(tool); + } + + public void cycle(int direction) { + selection += (direction < 0)? 1 : -1; + selection = (selection + tools.size()) % tools.size(); + } + + private void draw(float partialTicks) { + MainWindow mainWindow = Minecraft.getInstance().mainWindow; + + int x = (mainWindow.getScaledWidth() - w) / 2 + 15; + int y = mainWindow.getScaledHeight() - h - 75; + + GlStateManager.pushMatrix(); + GlStateManager.translatef(0, -yOffset, 0); + + GuiResources gray = GuiResources.GRAY; + GlStateManager.enableBlend(); + GlStateManager.enableAlphaTest(); + GlStateManager.color4f(1, 1, 1, focused? 7 / 8f : 1 / 2f); + + Minecraft.getInstance().getTextureManager().bindTexture(gray.location); + blit(x - 15, y, gray.startX, gray.startY, w, h, gray.width, gray.height); + GlStateManager.color4f(1, 1, 1, 1); + + for (int i = 0; i < tools.size(); i++) { + GlStateManager.pushMatrix(); + + float alpha = focused? 1 : .2f; + if (i == selection) { + GlStateManager.translatef(0, -10, 0); + drawCenteredString(minecraft.fontRenderer, tools.get(i).getDisplayName(), x + i * 50 + 24, y + 28, 0xCCDDFF); + alpha = 1; + } + GlStateManager.color4f(0, 0, 0, alpha); + tools.get(i).getIcon().draw(this, x + i * 50 + 16, y + 12); + GlStateManager.color4f(1, 1, 1, alpha); + tools.get(i).getIcon().draw(this, x + i * 50 + 16, y + 11); + + GlStateManager.popMatrix(); + } + + GlStateManager.popMatrix(); + } + + public void update() { + if (focused) yOffset += (10 - yOffset) * .1f; + else yOffset *= .9f; + } + + public void renderPassive(float partialTicks) { + draw(partialTicks); + } + + @Override + public void onClose() { + callback.accept(tools.get(selection)); + } + +} diff --git a/src/main/java/com/simibubi/create/gui/widgets/ScrollArea.java b/src/main/java/com/simibubi/create/gui/widgets/ScrollArea.java index fed9acd9c..fbf0f6ed9 100644 --- a/src/main/java/com/simibubi/create/gui/widgets/ScrollArea.java +++ b/src/main/java/com/simibubi/create/gui/widgets/ScrollArea.java @@ -2,7 +2,7 @@ package com.simibubi.create.gui.widgets; import java.util.function.Consumer; -import com.simibubi.create.utility.Keyboard; +import com.simibubi.create.gui.Keyboard; import net.minecraft.util.text.TextFormatting; diff --git a/src/main/java/com/simibubi/create/item/ItemBlueprint.java b/src/main/java/com/simibubi/create/item/ItemBlueprint.java index 947104667..7698a1d86 100644 --- a/src/main/java/com/simibubi/create/item/ItemBlueprint.java +++ b/src/main/java/com/simibubi/create/item/ItemBlueprint.java @@ -9,6 +9,7 @@ import java.nio.file.StandardOpenOption; import org.apache.commons.io.IOUtils; import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllItems; import com.simibubi.create.block.SchematicannonTileEntity; import com.simibubi.create.schematic.SchematicHologram; @@ -24,10 +25,15 @@ import net.minecraft.nbt.NBTUtil; import net.minecraft.util.ActionResult; import net.minecraft.util.ActionResultType; import net.minecraft.util.Hand; +import net.minecraft.util.Mirror; +import net.minecraft.util.Rotation; import net.minecraft.util.math.BlockPos; import net.minecraft.util.text.StringTextComponent; +import net.minecraft.util.text.TextFormatting; import net.minecraft.world.World; +import net.minecraft.world.gen.feature.template.PlacementSettings; import net.minecraft.world.gen.feature.template.Template; +import net.minecraftforge.fml.common.thread.SidedThreadGroups; public class ItemBlueprint extends Item { @@ -35,6 +41,70 @@ public class ItemBlueprint extends Item { super(properties.maxStackSize(1)); } + public static ItemStack create(String schematic, String owner) { + ItemStack blueprint = new ItemStack(AllItems.BLUEPRINT.item); + + CompoundNBT tag = new CompoundNBT(); + tag.putBoolean("Deployed", false); + tag.putString("Owner", owner); + tag.putString("File", schematic); + tag.put("Anchor", NBTUtil.writeBlockPos(BlockPos.ZERO)); + tag.putString("Rotation", Rotation.NONE.name()); + tag.putString("Mirror", Mirror.NONE.name()); + blueprint.setTag(tag); + + writeSize(blueprint); + blueprint.setDisplayName(new StringTextComponent(TextFormatting.RESET + "" + TextFormatting.WHITE + + "Blueprint (" + TextFormatting.GOLD + schematic + TextFormatting.WHITE + ")")); + + return blueprint; + } + + public static void writeSize(ItemStack blueprint) { + CompoundNBT tag = blueprint.getTag(); + Template t = getSchematic(blueprint); + tag.put("Bounds", NBTUtil.writeBlockPos(t.getSize())); + blueprint.setTag(tag); + } + + public static PlacementSettings getSettings(ItemStack blueprint) { + CompoundNBT tag = blueprint.getTag(); + + PlacementSettings settings = new PlacementSettings(); + settings.setRotation(Rotation.valueOf(tag.getString("Rotation"))); + settings.setMirror(Mirror.valueOf(tag.getString("Mirror"))); + + return settings; + } + + public static Template getSchematic(ItemStack blueprint) { + Template t = new Template(); + String owner = blueprint.getTag().getString("Owner"); + String schematic = blueprint.getTag().getString("File"); + + String filepath = ""; + + if (Thread.currentThread().getThreadGroup() == SidedThreadGroups.SERVER) + filepath = "schematics/uploaded/" + owner + "/" + schematic; + else + filepath = "schematics/" + schematic; + + InputStream stream = null; + try { + stream = Files.newInputStream(Paths.get(filepath), StandardOpenOption.READ); + CompoundNBT nbt = CompressedStreamTools.readCompressed(stream); + t.read(nbt); + + } catch (IOException e) { + e.printStackTrace(); + } finally { + if (stream != null) + IOUtils.closeQuietly(stream); + } + + return t; + } + @Override public ActionResultType onItemUse(ItemUseContext context) { @@ -66,28 +136,6 @@ public class ItemBlueprint extends Item { return ActionResultType.SUCCESS; } - if (!(context.getPlayer().getName().getFormattedText().equals(tag.getString("Owner")))) { - context.getPlayer() - .sendStatusMessage(new StringTextComponent("You are not the Owner of this Schematic."), true); - } - - String filepath = "schematics/" + tag.getString("File"); - Template t = new Template(); - - InputStream stream = null; - try { - stream = Files.newInputStream(Paths.get(filepath), StandardOpenOption.READ); - CompoundNBT nbt = CompressedStreamTools.readCompressed(stream); - t.read(nbt); - new SchematicHologram().startHologram(t, pos.offset(context.getFace())); - - } catch (IOException e) { - e.printStackTrace(); - } finally { - if (stream != null) - IOUtils.closeQuietly(stream); - } - } context.getPlayer().getCooldownTracker().setCooldown(this, 10); diff --git a/src/main/java/com/simibubi/create/item/ItemWandSymmetry.java b/src/main/java/com/simibubi/create/item/ItemWandSymmetry.java index 70332bc05..0c2608c62 100644 --- a/src/main/java/com/simibubi/create/item/ItemWandSymmetry.java +++ b/src/main/java/com/simibubi/create/item/ItemWandSymmetry.java @@ -31,6 +31,9 @@ import net.minecraft.util.math.shapes.ISelectionContext; import net.minecraft.util.text.StringTextComponent; import net.minecraft.util.text.TextFormatting; import net.minecraft.world.World; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.fml.DistExecutor; import net.minecraftforge.fml.network.PacketDistributor; public class ItemWandSymmetry extends Item { @@ -41,16 +44,16 @@ public class ItemWandSymmetry extends Item { public ItemWandSymmetry(Properties properties) { super(properties.maxStackSize(1)); } - + @Override public ActionResultType onItemUse(ItemUseContext context) { PlayerEntity player = context.getPlayer(); BlockPos pos = context.getPos(); player.getCooldownTracker().setCooldown(this, 5); - - if (context.getWorld().isRemote || context.getHand() != Hand.MAIN_HAND) + + if (context.getWorld().isRemote || context.getHand() != Hand.MAIN_HAND) return ActionResultType.SUCCESS; - + ItemStack wand = player.getHeldItem(context.getHand()); checkNBT(wand); CompoundNBT compound = wand.getTag().getCompound($SYMMETRY); @@ -68,8 +71,9 @@ public class ItemWandSymmetry extends Item { SymmetryElement newElement = new SymmetryPlane(pos3d); if (previousElement instanceof SymmetryEmptySlot) { - newElement.setOrientation((player.getHorizontalFacing() == Direction.NORTH - || player.getHorizontalFacing() == Direction.SOUTH) ? SymmetryPlane.Align.XY.ordinal() + newElement.setOrientation( + (player.getHorizontalFacing() == Direction.NORTH || player.getHorizontalFacing() == Direction.SOUTH) + ? SymmetryPlane.Align.XY.ordinal() : SymmetryPlane.Align.YZ.ordinal()); newElement.enable = true; player.sendStatusMessage(new StringTextComponent(TextFormatting.GREEN + "New Plane created"), true); @@ -105,12 +109,19 @@ public class ItemWandSymmetry extends Item { @Override public ActionResult onItemRightClick(World worldIn, PlayerEntity playerIn, Hand handIn) { if (worldIn.isRemote) { - GuiOpener.open(new GuiWandSymmetry(playerIn.getHeldItem(handIn))); - playerIn.getCooldownTracker().setCooldown(this, 5); + DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> { + openWandGUI(playerIn.getHeldItem(handIn)); + }); + playerIn.getCooldownTracker().setCooldown(this, 5); } return super.onItemRightClick(worldIn, playerIn, handIn); } + @OnlyIn(Dist.CLIENT) + private void openWandGUI(ItemStack wand) { + GuiOpener.open(new GuiWandSymmetry(wand)); + } + private static void checkNBT(ItemStack wand) { if (!wand.hasTag() || !wand.getTag().contains($SYMMETRY)) { wand.setTag(new CompoundNBT()); @@ -136,15 +147,14 @@ public class ItemWandSymmetry extends Item { Map blockSet = new HashMap<>(); blockSet.put(pos, block); - SymmetryElement symmetry = SymmetryElement - .fromNBT((CompoundNBT) wand.getTag().getCompound($SYMMETRY)); + SymmetryElement symmetry = SymmetryElement.fromNBT((CompoundNBT) wand.getTag().getCompound($SYMMETRY)); Vec3d mirrorPos = symmetry.getPosition(); if (mirrorPos.distanceTo(new Vec3d(pos)) > 50) return; symmetry.process(blockSet); - + BlockPos to = new BlockPos(mirrorPos); List targets = new ArrayList<>(); @@ -152,11 +162,12 @@ public class ItemWandSymmetry extends Item { for (BlockPos position : blockSet.keySet()) { if (world.func_217350_a(block, position, ISelectionContext.forEntity(player))) { world.setBlockState(position, blockSet.get(position)); - targets.add(position); + targets.add(position); } } - - Packets.channel.send(PacketDistributor.TRACKING_ENTITY_AND_SELF.with(() -> player), new PacketSymmetryEffect(to, targets)); + + Packets.channel.send(PacketDistributor.TRACKING_ENTITY_AND_SELF.with(() -> player), + new PacketSymmetryEffect(to, targets)); } public static void remove(World world, ItemStack wand, PlayerEntity player, BlockPos pos) { @@ -167,8 +178,7 @@ public class ItemWandSymmetry extends Item { Map blockSet = new HashMap<>(); blockSet.put(pos, air); - SymmetryElement symmetry = SymmetryElement - .fromNBT((CompoundNBT) wand.getTag().getCompound($SYMMETRY)); + SymmetryElement symmetry = SymmetryElement.fromNBT((CompoundNBT) wand.getTag().getCompound($SYMMETRY)); Vec3d mirrorPos = symmetry.getPosition(); if (mirrorPos.distanceTo(new Vec3d(pos)) > 50) @@ -178,14 +188,15 @@ public class ItemWandSymmetry extends Item { BlockPos to = new BlockPos(mirrorPos); List targets = new ArrayList<>(); - + targets.add(pos); for (BlockPos position : blockSet.keySet()) { targets.add(position); world.setBlockState(position, air); } - - Packets.channel.send(PacketDistributor.TRACKING_ENTITY_AND_SELF.with(() -> player), new PacketSymmetryEffect(to, targets)); + + Packets.channel.send(PacketDistributor.TRACKING_ENTITY_AND_SELF.with(() -> player), + new PacketSymmetryEffect(to, targets)); } - + } diff --git a/src/main/java/com/simibubi/create/networking/PacketNbt.java b/src/main/java/com/simibubi/create/networking/PacketNbt.java index 1b90cc077..acd64d186 100644 --- a/src/main/java/com/simibubi/create/networking/PacketNbt.java +++ b/src/main/java/com/simibubi/create/networking/PacketNbt.java @@ -10,26 +10,44 @@ import net.minecraftforge.fml.network.NetworkEvent.Context; public class PacketNbt { public ItemStack stack; + public int slot; public PacketNbt(ItemStack stack) { + this(stack, -1); + } + + public PacketNbt(ItemStack stack, int slot) { this.stack = stack; + this.slot = slot; } public PacketNbt(PacketBuffer buffer) { stack = buffer.readItemStack(); + slot = buffer.readInt(); } public void toBytes(PacketBuffer buffer) { buffer.writeItemStack(stack); + buffer.writeInt(slot); } public void handle(Supplier context) { context.get().enqueueWork(() -> { ServerPlayerEntity player = context.get().getSender(); - ItemStack heldItem = player.getHeldItemMainhand(); - if (heldItem.getItem() == stack.getItem()) { - heldItem.setTag(stack.getTag()); + + if (slot == -1) { + ItemStack heldItem = player.getHeldItemMainhand(); + if (heldItem.getItem() == stack.getItem()) { + heldItem.setTag(stack.getTag()); + } + return; } + + ItemStack heldInSlot = player.inventory.getStackInSlot(slot); + if (heldInSlot.getItem() == stack.getItem()) { + heldInSlot.setTag(stack.getTag()); + } + }); } diff --git a/src/main/java/com/simibubi/create/networking/PacketSchematicTableContainer.java b/src/main/java/com/simibubi/create/networking/PacketSchematicTableContainer.java index bee33fe95..5a5605be4 100644 --- a/src/main/java/com/simibubi/create/networking/PacketSchematicTableContainer.java +++ b/src/main/java/com/simibubi/create/networking/PacketSchematicTableContainer.java @@ -7,8 +7,6 @@ import com.simibubi.create.block.SchematicTableContainer; import net.minecraft.client.Minecraft; import net.minecraft.inventory.container.Container; import net.minecraft.network.PacketBuffer; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.fml.network.NetworkEvent.Context; public class PacketSchematicTableContainer { @@ -33,14 +31,12 @@ public class PacketSchematicTableContainer { buffer.writeFloat(progress); } - @OnlyIn(Dist.CLIENT) public void handle(Supplier context) { context.get().enqueueWork(() -> { Container c = Minecraft.getInstance().player.openContainer; if (c != null && c instanceof SchematicTableContainer) { ((SchematicTableContainer) c).receiveSchematicInfo(schematic, progress); } - }); } diff --git a/src/main/java/com/simibubi/create/networking/PacketSchematicUpload.java b/src/main/java/com/simibubi/create/networking/PacketSchematicUpload.java index 60c9bc7ce..71c8a1f10 100644 --- a/src/main/java/com/simibubi/create/networking/PacketSchematicUpload.java +++ b/src/main/java/com/simibubi/create/networking/PacketSchematicUpload.java @@ -43,7 +43,7 @@ public class PacketSchematicUpload { public PacketSchematicUpload(PacketBuffer buffer) { code = buffer.readInt(); - schematic = buffer.readString(); + schematic = buffer.readString(256); if (code == WRITE) data = buffer.readByteArray(); diff --git a/src/main/java/com/simibubi/create/networking/Packets.java b/src/main/java/com/simibubi/create/networking/Packets.java index 1993307c3..0bae86f3a 100644 --- a/src/main/java/com/simibubi/create/networking/Packets.java +++ b/src/main/java/com/simibubi/create/networking/Packets.java @@ -10,13 +10,14 @@ public class Packets { private static final String PROTOCOL_VERSION = "1"; - public static final SimpleChannel channel = NetworkRegistry.newSimpleChannel( - new ResourceLocation(Create.ID, "main"), () -> PROTOCOL_VERSION, PROTOCOL_VERSION::equals, - PROTOCOL_VERSION::equals); + public static SimpleChannel channel; public static void registerPackets() { int i = 0; + channel = NetworkRegistry.newSimpleChannel(new ResourceLocation(Create.ID, "main"), () -> PROTOCOL_VERSION, + PROTOCOL_VERSION::equals, PROTOCOL_VERSION::equals); + channel.registerMessage(i++, PacketNbt.class, PacketNbt::toBytes, PacketNbt::new, PacketNbt::handle); channel.registerMessage(i++, PacketSchematicTableContainer.class, PacketSchematicTableContainer::toBytes, PacketSchematicTableContainer::new, PacketSchematicTableContainer::handle); diff --git a/src/main/java/com/simibubi/create/schematic/BlueprintHandler.java b/src/main/java/com/simibubi/create/schematic/BlueprintHandler.java new file mode 100644 index 000000000..d591bf545 --- /dev/null +++ b/src/main/java/com/simibubi/create/schematic/BlueprintHandler.java @@ -0,0 +1,355 @@ +package com.simibubi.create.schematic; + +import java.util.HashMap; + +import org.lwjgl.glfw.GLFW; + +import com.google.common.collect.ImmutableList; +import com.simibubi.create.AllItems; +import com.simibubi.create.Create; +import com.simibubi.create.gui.BlueprintHotbarOverlay; +import com.simibubi.create.gui.Keyboard; +import com.simibubi.create.gui.ToolSelectionScreen; +import com.simibubi.create.item.ItemBlueprint; +import com.simibubi.create.networking.PacketNbt; +import com.simibubi.create.networking.Packets; +import com.simibubi.create.utility.TessellatorHelper; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.player.ClientPlayerEntity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.CompoundNBT; +import net.minecraft.nbt.NBTUtil; +import net.minecraft.util.Direction.Axis; +import net.minecraft.util.Mirror; +import net.minecraft.util.Rotation; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.text.StringTextComponent; +import net.minecraft.world.gen.feature.template.PlacementSettings; +import net.minecraft.world.gen.feature.template.Template; +import net.minecraftforge.client.event.InputEvent.KeyInputEvent; +import net.minecraftforge.client.event.InputEvent.MouseInputEvent; +import net.minecraftforge.client.event.RenderGameOverlayEvent; +import net.minecraftforge.client.event.RenderWorldLastEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod.EventBusSubscriber; +import net.minecraftforge.fml.common.Mod.EventBusSubscriber.Bus; +import net.minecraftforge.fml.common.gameevent.TickEvent.ClientTickEvent; + +@EventBusSubscriber(bus = Bus.FORGE) +public class BlueprintHandler { + + public static BlueprintHandler instance; + + public Template cachedSchematic; + public String cachedSchematicName; + public PlacementSettings cachedSettings; + + public BlockPos anchor; + public BlockPos size; + public boolean active; + public boolean deployed; + public int slot; + public ItemStack item; + + public Tools currentTool; + public ToolSelectionScreen selectionScreen; + + public static final int SYNC_DELAY = 20; + public int syncCooldown; + + private BlueprintHotbarOverlay overlay; + + public BlueprintHandler() { + instance = this; + currentTool = Tools.Deploy; + overlay = new BlueprintHotbarOverlay(); + selectionScreen = new ToolSelectionScreen(ImmutableList.of(Tools.Deploy), this::equip); + } + + @SubscribeEvent + public static void onClientTick(ClientTickEvent event) { + ClientPlayerEntity player = Minecraft.getInstance().player; + + if (player == null) + return; + + ItemStack stack = findBlueprintInHand(player); + if (stack == null) { + instance.active = false; + instance.syncCooldown = 0; + instance.slot = 0; + if (instance.item != null && itemLost(player)) { + instance.item = null; + SchematicHologram.reset(); + } + return; + } + + // Newly equipped + if (!instance.active || !stack.getTag().getString("File").equals(instance.cachedSchematicName)) { + instance.loadSettings(stack); + instance.cachedSchematicName = stack.getTag().getString("File"); + instance.active = true; + if (instance.deployed) { + Tools toolBefore = instance.currentTool; + instance.selectionScreen = new ToolSelectionScreen(Tools.getTools(), instance::equip); + if (toolBefore != null) { + instance.selectionScreen.setSelectedElement(toolBefore); + instance.equip(toolBefore); + } + } + else + instance.selectionScreen = new ToolSelectionScreen(ImmutableList.of(Tools.Deploy), instance::equip); + instance.sync(); + } + + if (!instance.active) + return; + + if (instance.syncCooldown > 0) + instance.syncCooldown--; + if (instance.syncCooldown == 1) + instance.sync(); + + instance.selectionScreen.update(); + instance.currentTool.getTool().updateSelection(); + } + + @SubscribeEvent + public static void onRenderWorld(RenderWorldLastEvent event) { + if (!instance.active) + return; + + TessellatorHelper.prepareForDrawing(); + instance.currentTool.getTool().renderTool(); + TessellatorHelper.cleanUpAfterDrawing(); + } + + @SubscribeEvent + public static void onRenderOverlay(RenderGameOverlayEvent event) { + if (!instance.active) + return; + + instance.overlay.renderOn(instance.slot); + instance.currentTool.getTool().renderOverlay(); + instance.selectionScreen.renderPassive(event.getPartialTicks()); + } + + @SubscribeEvent + public static void onClick(MouseInputEvent event) { + if (Minecraft.getInstance().currentScreen != null) + return; + if (event.getAction() != Keyboard.PRESS) + return; + if (event.getButton() != 1) + return; + if (!instance.active) + return; + + instance.currentTool.getTool().handleRightClick(); + } + + @SubscribeEvent + public static void onKeyTyped(KeyInputEvent event) { + if (Minecraft.getInstance().currentScreen != null) + return; + if (event.getKey() != Create.TOOL_MENU.getKey().getKeyCode()) + return; + if (!instance.active) + return; + + boolean released = event.getAction() == Keyboard.RELEASE; + + ToolSelectionScreen toolSelection = instance.selectionScreen; + if (released && toolSelection.focused) { + toolSelection.focused = false; + toolSelection.onClose(); + } + + if (!released && !toolSelection.focused) + toolSelection.focused = true; + } + + public boolean onScroll(double delta) { + if (!active) + return false; + if (selectionScreen.focused) { + selectionScreen.cycle((int) delta); + return true; + } + if (Keyboard.isKeyDown(GLFW.GLFW_KEY_LEFT_CONTROL)) { + return currentTool.getTool().handleMouseWheel(delta); + } + + return false; + } + + private static ItemStack findBlueprintInHand(PlayerEntity player) { + ItemStack stack = player.getHeldItemMainhand(); + if (!AllItems.BLUEPRINT.typeOf(stack)) + return null; + if (!stack.hasTag()) + return null; + + instance.item = stack; + instance.slot = player.inventory.currentItem; + return stack; + } + + private static boolean itemLost(PlayerEntity player) { + for (int i = 0; i < PlayerInventory.getHotbarSize(); i++) { + if (!player.inventory.getStackInSlot(i).isItemEqual(instance.item)) + continue; + if (!ItemStack.areItemStackTagsEqual(player.inventory.getStackInSlot(i), instance.item)) + continue; + return false; + } + return true; + } + + public void markDirty() { + syncCooldown = SYNC_DELAY; + SchematicHologram.reset(); + } + + public void sync() { + Minecraft.getInstance().player.sendStatusMessage(new StringTextComponent("Syncing..."), true); + Packets.channel.sendToServer(new PacketNbt(item, slot)); + + SchematicWorld w = new SchematicWorld(new HashMap<>(), new Cuboid(), anchor); + PlacementSettings settings = cachedSettings.copy(); + settings.setBoundingBox(null); + ItemBlueprint.getSchematic(item).addBlocksToWorld(w, anchor, settings); + + new SchematicHologram().startHologram(w); + } + + public void equip(Tools tool) { + this.currentTool = tool; + currentTool.getTool().init(); + } + + public void loadSettings(ItemStack blueprint) { + CompoundNBT tag = blueprint.getTag(); + cachedSettings = new PlacementSettings(); + cachedSettings.setRotation(Rotation.valueOf(tag.getString("Rotation"))); + cachedSettings.setMirror(Mirror.valueOf(tag.getString("Mirror"))); + + deployed = tag.getBoolean("Deployed"); + if (deployed) + anchor = NBTUtil.readBlockPos(tag.getCompound("Anchor")); + + size = NBTUtil.readBlockPos(tag.getCompound("Bounds")); + } + + public void flip(Axis axis) { + + Rotation r = cachedSettings.getRotation(); + boolean rotationAt90s = r == Rotation.CLOCKWISE_90 || r == Rotation.COUNTERCLOCKWISE_90; + Mirror mirror = axis == Axis.Z ^ rotationAt90s ? Mirror.FRONT_BACK : Mirror.LEFT_RIGHT; + + BlockPos coordModifier = new BlockPos((r == Rotation.NONE || r == Rotation.COUNTERCLOCKWISE_90) ? 1 : -1, 0, + (r == Rotation.NONE || r == Rotation.CLOCKWISE_90) ? 1 : -1); + BlockPos anchorOffset = axis == Axis.Z + ? new BlockPos(((rotationAt90s ? size.getZ() : size.getX()) - 1) * coordModifier.getX(), 0, 0) + : new BlockPos(0, 0, ((!rotationAt90s ? size.getZ() : size.getX()) - 1) * coordModifier.getZ()); + + Mirror m = cachedSettings.getMirror(); + + if (m == Mirror.NONE) { + cachedSettings.setMirror(mirror); + anchor = anchor.add(anchorOffset); + Minecraft.getInstance().player.sendStatusMessage( + new StringTextComponent("Mirror: " + cachedSettings.getMirror().toString()), true); + + } else if (m == mirror) { + cachedSettings.setMirror(Mirror.NONE); + anchor = anchor.subtract(anchorOffset); + Minecraft.getInstance().player.sendStatusMessage( + new StringTextComponent("Mirror: " + cachedSettings.getMirror().toString()), true); + + } else if (m != mirror) { + cachedSettings.setMirror(Mirror.NONE); + anchor = anchor.add(anchorOffset); + cachedSettings.setRotation(r.add(Rotation.CLOCKWISE_180)); + Minecraft.getInstance().player.sendStatusMessage( + new StringTextComponent("Mirror: None, Rotation: " + cachedSettings.getRotation().toString()), + true); + } + + item.getTag().put("Anchor", NBTUtil.writeBlockPos(anchor)); + item.getTag().putString("Mirror", cachedSettings.getMirror().name()); + item.getTag().putString("Rotation", r.name()); + + markDirty(); + } + + public void rotate(Rotation rotation) { + Rotation r = cachedSettings.getRotation(); + BlockPos center = centerOfSchematic(); + cachedSettings.setRotation(r.add(rotation)); + BlockPos diff = center.subtract(anchor); + BlockPos move = diff.subtract(diff.rotate(rotation)); + anchor = anchor.add(move); + + item.getTag().put("Anchor", NBTUtil.writeBlockPos(anchor)); + item.getTag().putString("Rotation", cachedSettings.getRotation().name()); + + Minecraft.getInstance().player.sendStatusMessage( + new StringTextComponent("Rotation: " + cachedSettings.getRotation().toString()), true); + + markDirty(); + } + + public void moveTo(BlockPos anchor) { + if (!deployed) + instance.selectionScreen = new ToolSelectionScreen(Tools.getTools(), instance::equip); + + deployed = true; + this.anchor = anchor; + item.getTag().putBoolean("Deployed", true); + item.getTag().put("Anchor", NBTUtil.writeBlockPos(anchor)); + markDirty(); + } + + public BlockPos getTransformedSize() { + BlockPos flipped = size; + if (cachedSettings.getMirror() == Mirror.FRONT_BACK) + flipped = new BlockPos(-flipped.getX(), flipped.getY(), flipped.getZ()); + if (cachedSettings.getMirror() == Mirror.LEFT_RIGHT) + flipped = new BlockPos(flipped.getX(), flipped.getY(), -flipped.getZ()); + + BlockPos rotate = flipped.rotate(cachedSettings.getRotation()); + return rotate; + } + + public BlockPos getTransformedAnchor() { + BlockPos anchor = this.anchor; + Rotation r = cachedSettings.getRotation(); + + BlockPos flipOffset = BlockPos.ZERO; + if (cachedSettings.getMirror() == Mirror.FRONT_BACK) + flipOffset = new BlockPos(1, 0, 0); + if (cachedSettings.getMirror() == Mirror.LEFT_RIGHT) + flipOffset = new BlockPos(0, 0, 1); + + flipOffset = flipOffset.rotate(r); + anchor = anchor.add(flipOffset); + + if (r == Rotation.CLOCKWISE_90 || r == Rotation.CLOCKWISE_180) + anchor = anchor.add(1, 0, 0); + if (r == Rotation.COUNTERCLOCKWISE_90 || r == Rotation.CLOCKWISE_180) + anchor = anchor.add(0, 0, 1); + return anchor; + } + + public BlockPos centerOfSchematic() { + BlockPos size = getTransformedSize(); + BlockPos center = new BlockPos(size.getX() / 2, 0, size.getZ() / 2); + return anchor.add(center); + } + +} diff --git a/src/main/java/com/simibubi/create/schematic/Cuboid.java b/src/main/java/com/simibubi/create/schematic/Cuboid.java index 7530aa0f5..de28c2d52 100644 --- a/src/main/java/com/simibubi/create/schematic/Cuboid.java +++ b/src/main/java/com/simibubi/create/schematic/Cuboid.java @@ -11,6 +11,10 @@ public class Cuboid { public int height; public int length; + public Cuboid() { + this(BlockPos.ZERO, 0, 0, 0); + } + public Cuboid(BlockPos origin, BlockPos size) { this(origin, size.getX(), size.getY(), size.getZ()); } diff --git a/src/main/java/com/simibubi/create/schematic/ISchematicTool.java b/src/main/java/com/simibubi/create/schematic/ISchematicTool.java new file mode 100644 index 000000000..b3b1ed19e --- /dev/null +++ b/src/main/java/com/simibubi/create/schematic/ISchematicTool.java @@ -0,0 +1,15 @@ +package com.simibubi.create.schematic; + +public interface ISchematicTool { + + public void init(); + public void updateSelection(); + + public boolean handleRightClick(); + public boolean handleMouseWheel(double delta); + + public void renderTool(); + public void renderOverlay(); + + +} diff --git a/src/main/java/com/simibubi/create/schematic/SchematicDeployTool.java b/src/main/java/com/simibubi/create/schematic/SchematicDeployTool.java new file mode 100644 index 000000000..cbc6d524c --- /dev/null +++ b/src/main/java/com/simibubi/create/schematic/SchematicDeployTool.java @@ -0,0 +1,84 @@ +package com.simibubi.create.schematic; + +import org.lwjgl.glfw.GLFW; + +import com.mojang.blaze3d.platform.GlStateManager; +import com.simibubi.create.gui.Keyboard; + +import net.minecraft.client.renderer.WorldRenderer; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.MutableBoundingBox; + +public class SchematicDeployTool extends SchematicPlacementToolBase { + + @Override + public void init() { + super.init(); + selectionRange = -1; + } + + @Override + public void updateSelection() { + if (blueprint.active && selectionRange == -1) { + selectionRange = (int) blueprint.size.manhattanDistance(BlockPos.ZERO) / 2; + selectionRange = MathHelper.clamp(selectionRange, 1, 100); + } + selectIgnoreBlocks = Keyboard.isKeyDown(GLFW.GLFW_KEY_LEFT_CONTROL); + + super.updateSelection(); + } + + @Override + public void renderTool() { + super.renderTool(); + + if (selectedPos == null) + return; + + BlockPos size = blueprint.getTransformedSize(); + BlockPos min = selectedPos.add(Math.round(size.getX() * -.5f), 0, Math.round(size.getZ() * -.5f)); + BlockPos max = min.add(size.getX(), size.getY(), size.getZ()); + + if (blueprint.deployed) { + MutableBoundingBox bb = new MutableBoundingBox(min, min.add(blueprint.getTransformedSize())); + min = new BlockPos(bb.minX, bb.minY, bb.minZ); + max = new BlockPos(bb.maxX, bb.maxY, bb.maxZ); + } + + GlStateManager.lineWidth(3); + GlStateManager.color4f(.5f, .8f, 1, 1); + GlStateManager.disableTexture(); + + WorldRenderer.drawBoundingBox(min.getX() - 1 / 8d, min.getY() + 1 / 16d, min.getZ() - 1 / 8d, + max.getX() + 1 / 8d, max.getY() + 1 / 8d, max.getZ() + 1 / 8d, 1, 1, 1, 1); + + GlStateManager.lineWidth(1); + GlStateManager.enableTexture(); + + } + + @Override + public boolean handleMouseWheel(double delta) { + + if (selectIgnoreBlocks) { + selectionRange += delta; + selectionRange = MathHelper.clamp(selectionRange, 1, 100); + return true; + } + + return super.handleMouseWheel(delta); + } + + @Override + public boolean handleRightClick() { + if (selectedPos == null) + return super.handleRightClick(); + + BlockPos size = blueprint.getTransformedSize(); + blueprint.moveTo(selectedPos.add(Math.round(size.getX() * -.5f), 0, Math.round(size.getZ() * -.5f))); + + return true; + } + +} diff --git a/src/main/java/com/simibubi/create/schematic/SchematicFlipTool.java b/src/main/java/com/simibubi/create/schematic/SchematicFlipTool.java new file mode 100644 index 000000000..9efda8a8d --- /dev/null +++ b/src/main/java/com/simibubi/create/schematic/SchematicFlipTool.java @@ -0,0 +1,39 @@ +package com.simibubi.create.schematic; + +public class SchematicFlipTool extends SchematicPlacementToolBase { + + @Override + public void init() { + super.init(); + renderSelectedFace = true; + } + + @Override + public boolean handleRightClick() { + mirror(); + return true; + } + + @Override + public boolean handleMouseWheel(double delta) { + mirror(); + return true; + } + + @Override + public void updateSelection() { + super.updateSelection(); + + if (!schematicSelected) + return; + + renderSelectedFace = selectedFace.getAxis().isHorizontal(); + } + + private void mirror() { + if (schematicSelected && selectedFace.getAxis().isHorizontal()) { + blueprint.flip(selectedFace.getAxis()); + } + } + +} diff --git a/src/main/java/com/simibubi/create/schematic/SchematicHologram.java b/src/main/java/com/simibubi/create/schematic/SchematicHologram.java index 8a5d7fb3d..1d69826e5 100644 --- a/src/main/java/com/simibubi/create/schematic/SchematicHologram.java +++ b/src/main/java/com/simibubi/create/schematic/SchematicHologram.java @@ -28,6 +28,7 @@ import net.minecraft.util.math.Vec3d; import net.minecraft.world.gen.feature.template.PlacementSettings; import net.minecraft.world.gen.feature.template.Template; import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.client.ForgeHooksClient; import net.minecraftforge.client.event.RenderWorldLastEvent; import net.minecraftforge.client.model.data.EmptyModelData; @@ -36,6 +37,7 @@ import net.minecraftforge.fml.common.Mod.EventBusSubscriber; import net.minecraftforge.fml.common.gameevent.TickEvent; import net.minecraftforge.fml.common.gameevent.TickEvent.ClientTickEvent; +@OnlyIn(Dist.CLIENT) @EventBusSubscriber(Dist.CLIENT) public class SchematicHologram { @@ -63,6 +65,13 @@ public class SchematicHologram { active = true; changed = true; } + + public void startHologram(SchematicWorld world) { + this.anchor = world.anchor; + this.schematic = world; + this.active = true; + this.changed = true; + } public static SchematicHologram getInstance() { return instance; diff --git a/src/main/java/com/simibubi/create/schematic/SchematicMoveTool.java b/src/main/java/com/simibubi/create/schematic/SchematicMoveTool.java new file mode 100644 index 000000000..916f8fedb --- /dev/null +++ b/src/main/java/com/simibubi/create/schematic/SchematicMoveTool.java @@ -0,0 +1,23 @@ +package com.simibubi.create.schematic; + +public class SchematicMoveTool extends SchematicPlacementToolBase { + + @Override + public void init() { + super.init(); + renderSelectedFace = true; + } + + @Override + public boolean handleMouseWheel(double delta) { + + if (schematicSelected && selectedFace.getAxis().isHorizontal()) { + blueprint.moveTo(delta < 0 ? blueprint.anchor.add(selectedFace.getDirectionVec()) + : blueprint.anchor.subtract(selectedFace.getDirectionVec())); + return true; + } + + return super.handleMouseWheel(delta); + } + +} diff --git a/src/main/java/com/simibubi/create/schematic/SchematicMoveVerticalTool.java b/src/main/java/com/simibubi/create/schematic/SchematicMoveVerticalTool.java new file mode 100644 index 000000000..2d130df42 --- /dev/null +++ b/src/main/java/com/simibubi/create/schematic/SchematicMoveVerticalTool.java @@ -0,0 +1,16 @@ +package com.simibubi.create.schematic; + +public class SchematicMoveVerticalTool extends SchematicPlacementToolBase { + + @Override + public boolean handleMouseWheel(double delta) { + + if (blueprint.deployed) { + blueprint.moveTo(blueprint.anchor.add(0, delta, 0)); + return true; + } + + return super.handleMouseWheel(delta); + } + +} diff --git a/src/main/java/com/simibubi/create/schematic/SchematicPlacementToolBase.java b/src/main/java/com/simibubi/create/schematic/SchematicPlacementToolBase.java new file mode 100644 index 000000000..0d94227de --- /dev/null +++ b/src/main/java/com/simibubi/create/schematic/SchematicPlacementToolBase.java @@ -0,0 +1,35 @@ +package com.simibubi.create.schematic; + +public abstract class SchematicPlacementToolBase extends SchematicToolBase { + + @Override + public void init() { + super.init(); + } + + @Override + public void updateSelection() { + super.updateSelection(); + } + + @Override + public void renderTool() { + super.renderTool(); + } + + @Override + public void renderOverlay() { + super.renderOverlay(); + } + + @Override + public boolean handleMouseWheel(double delta) { + return false; + } + + @Override + public boolean handleRightClick() { + return false; + } + +} diff --git a/src/main/java/com/simibubi/create/schematic/SchematicRotateTool.java b/src/main/java/com/simibubi/create/schematic/SchematicRotateTool.java new file mode 100644 index 000000000..6f0f53cf3 --- /dev/null +++ b/src/main/java/com/simibubi/create/schematic/SchematicRotateTool.java @@ -0,0 +1,13 @@ +package com.simibubi.create.schematic; + +import net.minecraft.util.Rotation; + +public class SchematicRotateTool extends SchematicPlacementToolBase { + + @Override + public boolean handleMouseWheel(double delta) { + blueprint.rotate(delta > 0 ? Rotation.CLOCKWISE_90 : Rotation.COUNTERCLOCKWISE_90); + return true; + } + +} diff --git a/src/main/java/com/simibubi/create/schematic/SchematicToolBase.java b/src/main/java/com/simibubi/create/schematic/SchematicToolBase.java new file mode 100644 index 000000000..74cbc5648 --- /dev/null +++ b/src/main/java/com/simibubi/create/schematic/SchematicToolBase.java @@ -0,0 +1,122 @@ +package com.simibubi.create.schematic; + +import com.mojang.blaze3d.platform.GlStateManager; +import com.simibubi.create.utility.RaycastHelper; +import com.simibubi.create.utility.RaycastHelper.PredicateTraceResult; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.player.ClientPlayerEntity; +import net.minecraft.client.renderer.WorldRenderer; +import net.minecraft.item.BlockItemUseContext; +import net.minecraft.item.ItemUseContext; +import net.minecraft.util.Direction; +import net.minecraft.util.Hand; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.BlockRayTraceResult; +import net.minecraft.util.math.MutableBoundingBox; +import net.minecraft.util.math.RayTraceResult.Type; +import net.minecraft.util.math.Vec3d; + +public abstract class SchematicToolBase implements ISchematicTool { + + protected BlueprintHandler blueprint; + + public BlockPos selectedPos; + public boolean selectIgnoreBlocks; + public int selectionRange; + + public boolean schematicSelected; + public boolean renderSelectedFace; + public Direction selectedFace; + + public SchematicToolBase() { + blueprint = BlueprintHandler.instance; + } + + @Override + public void init() { + selectedPos = null; + selectedFace = null; + schematicSelected = false; + } + + @Override + public void updateSelection() { + ClientPlayerEntity player = Minecraft.getInstance().player; + + // Select Blueprint + if (blueprint.deployed) { + PredicateTraceResult result = RaycastHelper.rayTraceUntil(player, 70, + pos -> new MutableBoundingBox(BlockPos.ZERO, blueprint.getTransformedSize()) + .isVecInside(pos.subtract(blueprint.anchor))); + schematicSelected = !result.missed(); + selectedFace = schematicSelected ? result.getFacing() : null; + } + + // Select location at distance + if (selectIgnoreBlocks) { + selectedPos = new BlockPos(player.getEyePosition(Minecraft.getInstance().getRenderPartialTicks()) + .add(player.getLookVec().scale(selectionRange))); + return; + } + + // Select targeted Block + BlockRayTraceResult trace = RaycastHelper.rayTraceRange(player.world, player, 75); + if (trace != null && trace.getType() == Type.BLOCK) { + + BlockPos hit = new BlockPos(trace.getHitVec()); + boolean replaceable = player.world.getBlockState(hit) + .isReplaceable(new BlockItemUseContext(new ItemUseContext(player, Hand.MAIN_HAND, trace))); + if (trace.getFace().getAxis().isVertical() && !replaceable) + hit = hit.offset(trace.getFace()); + + selectedPos = hit; + } else { + selectedPos = null; + } + } + + @Override + public void renderTool() { + + if (blueprint.deployed) { + GlStateManager.lineWidth(5); + GlStateManager.color4f(1, 1, 1, 1); + GlStateManager.disableTexture(); + + BlockPos min = blueprint.getTransformedAnchor(); + MutableBoundingBox bb = new MutableBoundingBox(min, min.add(blueprint.getTransformedSize())); + min = new BlockPos(bb.minX, bb.minY, bb.minZ); + BlockPos max = new BlockPos(bb.maxX, bb.maxY, bb.maxZ); + + WorldRenderer.drawBoundingBox(min.getX() - 1 / 8d, min.getY() + 1 / 16d, min.getZ() - 1 / 8d, + max.getX() + 1 / 8d, max.getY() + 1 / 8d, max.getZ() + 1 / 8d, .3f, .4f, 1, 1); + + if (schematicSelected && renderSelectedFace) { + Vec3d vec = new Vec3d(selectedFace.getDirectionVec()); + Vec3d center = new Vec3d(min.add(max)).scale(1 / 2f); + Vec3d radii = new Vec3d(max.subtract(min)).scale(1 / 2f); + + Vec3d onFaceOffset = new Vec3d(1 - Math.abs(vec.x), 1 - Math.abs(vec.y), 1 - Math.abs(vec.z)) + .mul(radii); + Vec3d faceMin = center.add(vec.mul(radii).add(onFaceOffset)); + Vec3d faceMax = center.add(vec.mul(radii).subtract(onFaceOffset)); + + GlStateManager.lineWidth(4); + WorldRenderer.drawBoundingBox(faceMin.getX(), faceMin.getY() + 1 / 16d, faceMin.getZ(), faceMax.getX(), + faceMax.getY() + 1 / 8d, faceMax.getZ(), 1, 1, 1, 1); + } + + GlStateManager.lineWidth(1); + GlStateManager.enableTexture(); + + } + + } + + @Override + public void renderOverlay() { + + } + +} diff --git a/src/main/java/com/simibubi/create/schematic/SchematicWorld.java b/src/main/java/com/simibubi/create/schematic/SchematicWorld.java index 2f08fdef4..be0b71e01 100644 --- a/src/main/java/com/simibubi/create/schematic/SchematicWorld.java +++ b/src/main/java/com/simibubi/create/schematic/SchematicWorld.java @@ -45,7 +45,7 @@ public class SchematicWorld implements IWorld { private Map blocks; private Cuboid bounds; - private BlockPos anchor; + public BlockPos anchor; public SchematicWorld(Map blocks, Cuboid bounds, BlockPos anchor) { this.blocks = blocks; diff --git a/src/main/java/com/simibubi/create/schematic/Tools.java b/src/main/java/com/simibubi/create/schematic/Tools.java new file mode 100644 index 000000000..a8c59530f --- /dev/null +++ b/src/main/java/com/simibubi/create/schematic/Tools.java @@ -0,0 +1,46 @@ +package com.simibubi.create.schematic; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import com.simibubi.create.gui.GuiResources; + +public enum Tools { + + Deploy(new SchematicDeployTool(), "Deploy", GuiResources.ICON_3x3), + + Move(new SchematicMoveTool(), "Move XZ", GuiResources.ICON_3x3), + MoveY(new SchematicMoveVerticalTool(), "Move Y", GuiResources.ICON_3x3), + Rotate(new SchematicRotateTool(), "Rotate", GuiResources.ICON_3x3), + Flip(new SchematicFlipTool(), "Flip", GuiResources.ICON_3x3); + + private ISchematicTool tool; + private String displayName; + private GuiResources icon; + + private Tools(ISchematicTool tool, String name, GuiResources icon) { + this.tool = tool; + this.displayName = name; + this.icon = icon; + } + + public ISchematicTool getTool() { + return tool; + } + + public String getDisplayName() { + return displayName; + } + + public GuiResources getIcon() { + return icon; + } + + public static List getTools() { + List tools = new ArrayList<>(); + Collections.addAll(tools, Move, MoveY, Deploy, Rotate, Flip); + return tools; + } + +} diff --git a/src/main/java/com/simibubi/create/utility/RaycastHelper.java b/src/main/java/com/simibubi/create/utility/RaycastHelper.java new file mode 100644 index 000000000..a58b0591d --- /dev/null +++ b/src/main/java/com/simibubi/create/utility/RaycastHelper.java @@ -0,0 +1,195 @@ +package com.simibubi.create.utility; + +import java.util.function.Predicate; + +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.util.Direction; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.BlockRayTraceResult; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.RayTraceContext; +import net.minecraft.util.math.RayTraceContext.BlockMode; +import net.minecraft.util.math.RayTraceContext.FluidMode; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; + +public class RaycastHelper { + + public static BlockRayTraceResult rayTraceRange(World worldIn, PlayerEntity playerIn, double range) { + Vec3d origin = getTraceOrigin(playerIn); + Vec3d target = getTraceTarget(playerIn, range, origin); + RayTraceContext context = new RayTraceContext(origin, target, BlockMode.COLLIDER, FluidMode.NONE, playerIn); + return worldIn.rayTraceBlocks(context); + } + + public static PredicateTraceResult rayTraceUntil(PlayerEntity playerIn, double range, Predicate predicate) { + Vec3d origin = getTraceOrigin(playerIn); + Vec3d target = getTraceTarget(playerIn, range, origin); + return rayTraceUntil(origin, target, predicate); + } + + private static Vec3d getTraceTarget(PlayerEntity playerIn, double range, Vec3d origin) { + float f = playerIn.rotationPitch; + float f1 = playerIn.rotationYaw; + float f2 = MathHelper.cos(-f1 * 0.017453292F - (float) Math.PI); + float f3 = MathHelper.sin(-f1 * 0.017453292F - (float) Math.PI); + float f4 = -MathHelper.cos(-f * 0.017453292F); + float f5 = MathHelper.sin(-f * 0.017453292F); + float f6 = f3 * f4; + float f7 = f2 * f4; + double d3 = range; + Vec3d vec3d1 = origin.add((double) f6 * d3, (double) f5 * d3, (double) f7 * d3); + return vec3d1; + } + + private static Vec3d getTraceOrigin(PlayerEntity playerIn) { + double d0 = playerIn.posX; + double d1 = playerIn.posY + (double) playerIn.getEyeHeight(); + double d2 = playerIn.posZ; + Vec3d vec3d = new Vec3d(d0, d1, d2); + return vec3d; + } + + private static PredicateTraceResult rayTraceUntil(Vec3d start, Vec3d end, Predicate predicate) { + if (Double.isNaN(start.x) || Double.isNaN(start.y) || Double.isNaN(start.z)) + return null; + if (Double.isNaN(end.x) || Double.isNaN(end.y) || Double.isNaN(end.z)) + return null; + + int dx = MathHelper.floor(end.x); + int dy = MathHelper.floor(end.y); + int dz = MathHelper.floor(end.z); + int x = MathHelper.floor(start.x); + int y = MathHelper.floor(start.y); + int z = MathHelper.floor(start.z); + + BlockPos currentPos = new BlockPos(x, y, z); + + if (predicate.test(currentPos)) + return new PredicateTraceResult(currentPos, Direction.getFacingFromVector(dx - x, dy - y, dz - z)); + + int remainingDistance = 200; + + while (remainingDistance-- >= 0) { + if (Double.isNaN(start.x) || Double.isNaN(start.y) || Double.isNaN(start.z)) { + return null; + } + + if (x == dx && y == dy && z == dz) { + return new PredicateTraceResult(); + } + + boolean flag2 = true; + boolean flag = true; + boolean flag1 = true; + double d0 = 999.0D; + double d1 = 999.0D; + double d2 = 999.0D; + + if (dx > x) { + d0 = (double) x + 1.0D; + } else if (dx < x) { + d0 = (double) x + 0.0D; + } else { + flag2 = false; + } + + if (dy > y) { + d1 = (double) y + 1.0D; + } else if (dy < y) { + d1 = (double) y + 0.0D; + } else { + flag = false; + } + + if (dz > z) { + d2 = (double) z + 1.0D; + } else if (dz < z) { + d2 = (double) z + 0.0D; + } else { + flag1 = false; + } + + double d3 = 999.0D; + double d4 = 999.0D; + double d5 = 999.0D; + double d6 = end.x - start.x; + double d7 = end.y - start.y; + double d8 = end.z - start.z; + + if (flag2) { + d3 = (d0 - start.x) / d6; + } + + if (flag) { + d4 = (d1 - start.y) / d7; + } + + if (flag1) { + d5 = (d2 - start.z) / d8; + } + + if (d3 == -0.0D) { + d3 = -1.0E-4D; + } + + if (d4 == -0.0D) { + d4 = -1.0E-4D; + } + + if (d5 == -0.0D) { + d5 = -1.0E-4D; + } + + Direction enumfacing; + + if (d3 < d4 && d3 < d5) { + enumfacing = dx > x ? Direction.WEST : Direction.EAST; + start = new Vec3d(d0, start.y + d7 * d3, start.z + d8 * d3); + } else if (d4 < d5) { + enumfacing = dy > y ? Direction.DOWN : Direction.UP; + start = new Vec3d(start.x + d6 * d4, d1, start.z + d8 * d4); + } else { + enumfacing = dz > z ? Direction.NORTH : Direction.SOUTH; + start = new Vec3d(start.x + d6 * d5, start.y + d7 * d5, d2); + } + + x = MathHelper.floor(start.x) - (enumfacing == Direction.EAST ? 1 : 0); + y = MathHelper.floor(start.y) - (enumfacing == Direction.UP ? 1 : 0); + z = MathHelper.floor(start.z) - (enumfacing == Direction.SOUTH ? 1 : 0); + currentPos = new BlockPos(x, y, z); + + if (predicate.test(currentPos)) + return new PredicateTraceResult(currentPos, enumfacing); + } + + return new PredicateTraceResult(); + } + + public static class PredicateTraceResult { + private BlockPos pos; + private Direction facing; + + public PredicateTraceResult(BlockPos pos, Direction facing) { + this.pos = pos; + this.facing = facing; + } + + public PredicateTraceResult() { + // missed, no result + } + + public Direction getFacing() { + return facing; + } + + public BlockPos getPos() { + return pos; + } + + public boolean missed() { + return this.pos == null; + } + } + +} diff --git a/src/main/java/com/simibubi/create/utility/TessellatorTextures.java b/src/main/java/com/simibubi/create/utility/TessellatorTextures.java new file mode 100644 index 000000000..e7a431a91 --- /dev/null +++ b/src/main/java/com/simibubi/create/utility/TessellatorTextures.java @@ -0,0 +1,29 @@ +package com.simibubi.create.utility; + +import com.simibubi.create.Create; + +import net.minecraft.client.Minecraft; +import net.minecraft.util.ResourceLocation; + +public enum TessellatorTextures { + + Room("inner.png"), + RoomTransparent("inner_transparent.png"), + SelectedRoom("inner_selected.png"), + SuperSelectedRoom("inner_super_selected.png"), + Selection("select.png"), + Exporter("exporter.png"), + Trim("trim.png"); + + private ResourceLocation location; + + private TessellatorTextures(String filename) { + location = new ResourceLocation(Create.ID, + "textures/block/marker/" + filename); + } + + public void bind() { + Minecraft.getInstance().getTextureManager().bindTexture(location); + } + +} \ No newline at end of file diff --git a/src/main/resources/assets/create/lang/en_us.json b/src/main/resources/assets/create/lang/en_us.json index 92c0fbb5e..eeb8ac86b 100644 --- a/src/main/resources/assets/create/lang/en_us.json +++ b/src/main/resources/assets/create/lang/en_us.json @@ -1,8 +1,9 @@ { "item.create.symmetry_wand": "Staff of Symmetry", - "item.create.empty_blueprint": "Empty Blueprint", - "item.create.blueprint": "Blueprint", + "item.create.empty_blueprint": "Empty Schematic", + "item.create.blueprint": "Schematic", "block.create.schematicannon": "SchematiCannon 9000", - "block.create.schematic_table": "Schematic Planner", + "block.create.schematic_table": "Schematic Table", + "block.create.creative_crate": "SchematiCannon Creatifier", "itemGroup.create": "Create" } diff --git a/src/main/resources/assets/create/textures/gui/widgets.png b/src/main/resources/assets/create/textures/gui/widgets.png index 0c7695db7..1c4f897f6 100644 Binary files a/src/main/resources/assets/create/textures/gui/widgets.png and b/src/main/resources/assets/create/textures/gui/widgets.png differ