diff --git a/README.md b/README.md index 2ac223f..79a45a3 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,7 @@ If you concentrate enough, you can even conjure a block in mid air! ## Wands There are basic wands made from stone, iron and diamond and the Infinity wand. +Wand properties can be changed in the config. | Wand | Durability | Max. Blocks | Angel distance | |----------|-------------|-------------|----------------| @@ -22,22 +23,30 @@ There are basic wands made from stone, iron and diamond and the Infinity wand. ![](https://raw.githubusercontent.com/Theta-Dev/ConstructionWand/1.15/images/crafting4.png) ## Modes -There are four wand tiers: Stone, Iron, Diamond and Infinity. - **Default mode:** Extends your build on the side facing you. Maximum number of blocks depends on wand tier. SHIFT+scroll to change the placement mode (Horizontal, Vertical, North/South, East/West, No lock). **Angel mode:** Places a block on the opposite side of the block (or row of blocks) you are facing. Maximum distance depends on wand tier. Right click empty space to place a block in midair (similar to angel blocks, hence the name). To do that, you'll need to have the block you want to place in your offhand. You can't place a block in midair if you've fallen more than 10 blocks deep (no easy rescue tool from falling into the void). +You can change the wand mode using the option screen or by SHIFT+Left clicking empty space. + ## Options -**Direction lock:** To change the direction lock, hold down SHIFT and scroll. With active direction lock the wand will only place blocks in one row or column (choose between North/South, East/West on a horizontal plane and Horizontal, Vertical on a vertical plane). If the direction lock is switched off, the wand will extend the entire face of the building it's pointed at. This option has no effect in Angel mode. +SHIFT+Right clicking empty space opens the option screen of your wand. -Every wand has two additional options that can be changed using keys. (Standard: N / SHIFT+N) +![](https://raw.githubusercontent.com/Theta-Dev/ConstructionWand/1.15/images/options.png) -**Placement direction:** If set to "player" the wand places blocks in the same direction as if they were placed by yourself. Target mode places the blocks in the same direction as their supporting block. See the picture below: +**Restriction:** If restriction is enabled the wand will only place blocks in one row or column (choose between North/South, East/West on a horizontal plane and Horizontal, Vertical on a vertical plane). If the direction lock is switched off, the wand will extend the entire face of the building it's pointed at. This option has no effect in Angel mode. + +**Direction:** If set to "Player" the wand places blocks in the same direction as if they were placed by yourself. Target mode places the blocks in the same direction as their supporting block. See the picture below: ![](https://raw.githubusercontent.com/Theta-Dev/ConstructionWand/1.15/images/placedir.png) -**Fluid lock:** Enables/disables the replacement of fluid blocks (both source + flowing). +**Replacement:** Enables/disables the replacement of replaceable blocks (Fluids, snow, tallgrass). + +**Matching:** Select which blocks are extended by the wand. If set to "EXACT" it will only extend blocks that are exactly the same as the selected block. +"SIMILAR" will treat similar blocks equally (e.g. extend dirt and grass blocks). +"ANY" will extend any block on the face of the building you're looking at. + +**Random:** If random mode is enabled, the wand places random blocks from your hotbar. ~~Shamelessly stolen~~ Inspired by the Trowel from Quark. ## Additional features - If you have shulker boxes in your inventory filled with blocks, the wand can pull them out and place them @@ -50,4 +59,4 @@ Every wand has two additional options that can be changed using keys. (Standard: - Look at your statisics to see how many blocks you have placed using your wand -- **1.16 only:** The Infinity Wand won't burn in lava just like netherite gear. \ No newline at end of file +- **1.16+ only:** The Infinity Wand won't burn in lava just like netherite gear. diff --git a/build.gradle b/build.gradle index f075063..810eea7 100644 --- a/build.gradle +++ b/build.gradle @@ -97,13 +97,19 @@ dependencies { name : "forge", version: "${project.mcversion}-${project.forgeversion}" ]) - + /* compileOnly fg.deobf([ group: "vazkii.botania", name: "Botania", version: "${project.botania}", classifier: "api" - ]) + ])*/ + + runtimeOnly fg.deobf("vazkii.patchouli:Patchouli:1.14.4-1.1-25.135") + runtimeOnly fg.deobf("top.theillusivec4.curios:curios:FORGE-1.14.4-1.0.6.1") + + compileOnly fg.deobf("vazkii.botania:Botania:r1.11-379.354:api") + runtimeOnly fg.deobf("vazkii.botania:Botania:r1.11-379.354") } jar { diff --git a/gradle.properties b/gradle.properties index 54cf821..bd2eaa7 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,11 +4,11 @@ org.gradle.daemon=false author=thetadev modid=constructionwand -mcversion=1.16.2 -forgeversion=33.0.60 -mcp_mappings=20200723-1.16.1 +mcversion=1.14.4 +forgeversion=28.2.23 +mcp_mappings=20190719-1.14.3 -botania=1.16.2-405 +botania=r1.11-379.354 version_major=1 -version_minor=3 \ No newline at end of file +version_minor=4 \ No newline at end of file diff --git a/images/options.png b/images/options.png new file mode 100644 index 0000000..9adb38b Binary files /dev/null and b/images/options.png differ diff --git a/src/generated/resources/data/constructionwand/advancements/recipes/tools/stone_wand.json b/src/generated/resources/data/constructionwand/advancements/recipes/tools/stone_wand.json index c31aa4d..5b07428 100644 --- a/src/generated/resources/data/constructionwand/advancements/recipes/tools/stone_wand.json +++ b/src/generated/resources/data/constructionwand/advancements/recipes/tools/stone_wand.json @@ -11,7 +11,7 @@ "conditions": { "items": [ { - "tag": "minecraft:stone_tool_materials" + "tag": "forge:cobblestone" } ] } diff --git a/src/generated/resources/data/constructionwand/recipes/stone_wand.json b/src/generated/resources/data/constructionwand/recipes/stone_wand.json index b4448d5..114881e 100644 --- a/src/generated/resources/data/constructionwand/recipes/stone_wand.json +++ b/src/generated/resources/data/constructionwand/recipes/stone_wand.json @@ -7,7 +7,7 @@ ], "key": { "X": { - "tag": "minecraft:stone_tool_materials" + "tag": "forge:cobblestone" }, "#": { "tag": "forge:rods/wooden" diff --git a/src/main/java/thetadev/constructionwand/ConstructionWand.java b/src/main/java/thetadev/constructionwand/ConstructionWand.java index fae0393..b6b630a 100644 --- a/src/main/java/thetadev/constructionwand/ConstructionWand.java +++ b/src/main/java/thetadev/constructionwand/ConstructionWand.java @@ -19,7 +19,6 @@ import thetadev.constructionwand.basics.ReplacementRegistry; import thetadev.constructionwand.client.RenderBlockPreview; import thetadev.constructionwand.containers.ContainerManager; import thetadev.constructionwand.containers.ContainerRegistrar; -import thetadev.constructionwand.items.ModItems; import thetadev.constructionwand.job.JobHistory; import thetadev.constructionwand.network.PacketQueryUndo; import thetadev.constructionwand.network.PacketUndoBlocks; @@ -80,7 +79,6 @@ public class ConstructionWand { renderBlockPreview = new RenderBlockPreview(); MinecraftForge.EVENT_BUS.register(renderBlockPreview); - ModItems.registerModelProperties(); } public static ResourceLocation loc(String name) { diff --git a/src/main/java/thetadev/constructionwand/basics/WandUtil.java b/src/main/java/thetadev/constructionwand/basics/WandUtil.java index 1b824fe..dde168f 100644 --- a/src/main/java/thetadev/constructionwand/basics/WandUtil.java +++ b/src/main/java/thetadev/constructionwand/basics/WandUtil.java @@ -6,8 +6,7 @@ import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.util.Hand; import net.minecraft.util.ResourceLocation; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.vector.Vector3d; +import net.minecraft.util.math.Vec3d; import thetadev.constructionwand.ConstructionWand; import thetadev.constructionwand.items.ItemWand; @@ -37,16 +36,8 @@ public class WandUtil return null; } - public static BlockPos playerPos(PlayerEntity player) { - return new BlockPos(player.getPositionVec()); - } - - public static Vector3d entityPositionVec(Entity entity) { - return new Vector3d(entity.getPosX(), entity.getPosY() - entity.getYOffset() + entity.getHeight()/2, entity.getPosZ()); - } - - public static Vector3d blockPosVec(BlockPos pos) { - return new Vector3d(pos.getX(), pos.getY(), pos.getZ()); + public static Vec3d entityPositionVec(Entity entity) { + return new Vec3d(entity.posX, entity.posY - entity.getYOffset() + entity.getHeight()/2, entity.posZ); } public static List getHotbar(PlayerEntity player) { diff --git a/src/main/java/thetadev/constructionwand/basics/option/WandOptions.java b/src/main/java/thetadev/constructionwand/basics/option/WandOptions.java index 6edb29d..575d9ca 100644 --- a/src/main/java/thetadev/constructionwand/basics/option/WandOptions.java +++ b/src/main/java/thetadev/constructionwand/basics/option/WandOptions.java @@ -53,7 +53,7 @@ public class WandOptions mode = new OptionEnum<>(tag, "mode", MODE.class, MODE.DEFAULT, ConfigServer.getWandProperties(wand).getAngel() > 0); lock = new OptionEnum<>(tag, "lock", LOCK.class, LOCK.NOLOCK); - direction = new OptionEnum<>(tag, "direction", DIRECTION.class, DIRECTION.PLAYER); + direction = new OptionEnum<>(tag, "direction", DIRECTION.class, DIRECTION.TARGET); replace = new OptionBoolean(tag, "replace", true); match = new OptionEnum<>(tag, "match", MATCH.class, MATCH.SIMILAR); random = new OptionBoolean(tag, "random", false); diff --git a/src/main/java/thetadev/constructionwand/client/RenderBlockPreview.java b/src/main/java/thetadev/constructionwand/client/RenderBlockPreview.java index 7932815..f275c05 100644 --- a/src/main/java/thetadev/constructionwand/client/RenderBlockPreview.java +++ b/src/main/java/thetadev/constructionwand/client/RenderBlockPreview.java @@ -1,11 +1,9 @@ package thetadev.constructionwand.client; -import com.mojang.blaze3d.matrix.MatrixStack; -import com.mojang.blaze3d.vertex.IVertexBuilder; -import net.minecraft.client.Minecraft; import net.minecraft.client.gui.screen.Screen; -import net.minecraft.client.renderer.IRenderTypeBuffer; -import net.minecraft.client.renderer.WorldRenderer; +import net.minecraft.client.renderer.BufferBuilder; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.entity.Entity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.ItemStack; @@ -13,7 +11,7 @@ import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockRayTraceResult; import net.minecraft.util.math.RayTraceResult; -import net.minecraftforge.client.event.DrawHighlightEvent; +import net.minecraftforge.client.event.DrawBlockHighlightEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; import thetadev.constructionwand.basics.WandUtil; import thetadev.constructionwand.job.WandJob; @@ -26,7 +24,7 @@ public class RenderBlockPreview public Set undoBlocks; @SubscribeEvent - public void renderBlockHighlight(DrawHighlightEvent event) + public void renderBlockHighlight(DrawBlockHighlightEvent event) { if(event.getTarget().getType() != RayTraceResult.Type.BLOCK) return; @@ -54,24 +52,46 @@ public class RenderBlockPreview if(blocks == null || blocks.isEmpty()) return; - renderBlockList(blocks, event.getMatrix(), event.getBuffers(), colorR, colorG, colorB); + for(BlockPos block : blocks) { + double partialTicks = event.getPartialTicks(); + double d0 = player.lastTickPosX + (player.posX - player.lastTickPosX) * partialTicks; + double d1 = player.lastTickPosY + player.getEyeHeight() + (player.posY - player.lastTickPosY) * partialTicks; + double d2 = player.lastTickPosZ + (player.posZ - player.lastTickPosZ) * partialTicks; + + AxisAlignedBB aabb = new AxisAlignedBB(block).offset(-d0, -d1, -d2); + drawBoundingBox(aabb, colorR, colorG, colorB, 0.4F); + } event.setCanceled(true); } - private void renderBlockList(Set blocks, MatrixStack ms, IRenderTypeBuffer buffer, float red, float green, float blue) { - double renderPosX = Minecraft.getInstance().getRenderManager().info.getProjectedView().getX(); - double renderPosY = Minecraft.getInstance().getRenderManager().info.getProjectedView().getY(); - double renderPosZ = Minecraft.getInstance().getRenderManager().info.getProjectedView().getZ(); + private static void drawBoundingBox(AxisAlignedBB box, float red, float green, float blue, float alpha) { + Tessellator tessellator = Tessellator.getInstance(); + BufferBuilder buffer = tessellator.getBuffer(); + buffer.begin(3, DefaultVertexFormats.POSITION_COLOR); - ms.push(); - ms.translate(-renderPosX, -renderPosY, -renderPosZ); + //Base + buffer.pos(box.minX, box.minY, box.minZ).color(red, green, blue, alpha).endVertex(); + buffer.pos(box.maxX, box.minY, box.minZ).color(red, green, blue, alpha).endVertex(); + buffer.pos(box.maxX, box.minY, box.maxZ).color(red, green, blue, alpha).endVertex(); + buffer.pos(box.minX, box.minY, box.maxZ).color(red, green, blue, alpha).endVertex(); + buffer.pos(box.minX, box.minY, box.minZ).color(red, green, blue, alpha).endVertex(); + //Side1 + buffer.pos(box.minX, box.maxY, box.minZ).color(red, green, blue, alpha).endVertex(); + buffer.pos(box.minX, box.maxY, box.maxZ).color(red, green, blue, alpha).endVertex(); + buffer.pos(box.minX, box.minY, box.maxZ).color(red, green, blue, alpha).endVertex(); + //Side2 + buffer.pos(box.minX, box.maxY, box.maxZ).color(red, green, blue, alpha).endVertex(); + buffer.pos(box.maxX, box.maxY, box.maxZ).color(red, green, blue, alpha).endVertex(); + buffer.pos(box.maxX, box.minY, box.maxZ).color(red, green, blue, alpha).endVertex(); + //Side3 + buffer.pos(box.maxX, box.maxY, box.maxZ).color(red, green, blue, alpha).endVertex(); + buffer.pos(box.maxX, box.maxY, box.minZ).color(red, green, blue, alpha).endVertex(); + buffer.pos(box.maxX, box.minY, box.minZ).color(red, green, blue, alpha).endVertex(); + //Side4 + buffer.pos(box.maxX, box.maxY, box.minZ).color(red, green, blue, alpha).endVertex(); + buffer.pos(box.minX, box.maxY, box.minZ).color(red, green, blue, alpha).endVertex(); - for(BlockPos block : blocks) { - AxisAlignedBB aabb = new AxisAlignedBB(block); - IVertexBuilder lineBuilder = buffer.getBuffer(RenderTypes.TRANSLUCENT_LINES); - WorldRenderer.drawBoundingBox(ms, lineBuilder, aabb, red, green, blue, 0.4F); - } - ms.pop(); + tessellator.draw(); } } diff --git a/src/main/java/thetadev/constructionwand/client/RenderTypes.java b/src/main/java/thetadev/constructionwand/client/RenderTypes.java deleted file mode 100644 index 9f665c5..0000000 --- a/src/main/java/thetadev/constructionwand/client/RenderTypes.java +++ /dev/null @@ -1,37 +0,0 @@ -package thetadev.constructionwand.client; - -import com.mojang.blaze3d.systems.RenderSystem; -import net.minecraft.client.renderer.RenderState; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.vertex.DefaultVertexFormats; -import org.lwjgl.opengl.GL11; -import thetadev.constructionwand.ConstructionWand; - -import java.util.OptionalDouble; - -public class RenderTypes -{ - public static final RenderType TRANSLUCENT_LINES; - - protected static final RenderState.TransparencyState TRANSLUCENT_TRANSPARENCY = new RenderState.TransparencyState("translucent_transparency", () -> { - RenderSystem.enableBlend(); - RenderSystem.defaultBlendFunc(); - }, RenderSystem::disableBlend); - protected static final RenderState.DepthTestState DEPTH_ALWAYS = new RenderState.DepthTestState("always", GL11.GL_ALWAYS); - - static { - RenderType.State translucentNoDepthState = RenderType.State.getBuilder().transparency(TRANSLUCENT_TRANSPARENCY) - .line(new RenderState.LineState(OptionalDouble.of(2))) - .texture(new RenderState.TextureState()) - .depthTest(DEPTH_ALWAYS) - .build(false); - - TRANSLUCENT_LINES = RenderType.makeType( - ConstructionWand.MODID+":translucent_lines", - DefaultVertexFormats.POSITION_COLOR, - GL11.GL_LINES, - 256, - translucentNoDepthState - ); - } -} diff --git a/src/main/java/thetadev/constructionwand/client/ScreenWand.java b/src/main/java/thetadev/constructionwand/client/ScreenWand.java index bc312f1..2f3e68c 100644 --- a/src/main/java/thetadev/constructionwand/client/ScreenWand.java +++ b/src/main/java/thetadev/constructionwand/client/ScreenWand.java @@ -1,6 +1,5 @@ package thetadev.constructionwand.client; -import com.mojang.blaze3d.matrix.MatrixStack; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.widget.button.Button; @@ -13,10 +12,13 @@ import thetadev.constructionwand.basics.option.IOption; import thetadev.constructionwand.basics.option.WandOptions; import thetadev.constructionwand.network.PacketWandOption; +import java.util.HashMap; + public class ScreenWand extends Screen { private final ItemStack wand; private final WandOptions wandOptions; + private final HashMap, Button> optionButtons; private static final int BUTTON_WIDTH = 160; private static final int BUTTON_HEIGHT = 20; @@ -32,11 +34,13 @@ public class ScreenWand extends Screen super(new StringTextComponent("ScreenWand")); this.wand = wand; wandOptions = new WandOptions(wand); + optionButtons = new HashMap<>(); } @Override public void init(Minecraft minecraft, int width, int height) { super.init(minecraft, width, height); + optionButtons.clear(); createButton(0, 0, wandOptions.mode); createButton(0, 1, wandOptions.lock); @@ -47,33 +51,35 @@ public class ScreenWand extends Screen } @Override - public void render(MatrixStack matrixStack, int mouseX, int mouseY, float partialTicks) { - renderBackground(matrixStack); - super.render(matrixStack, mouseX, mouseY, partialTicks); - drawCenteredString(matrixStack, font, wand.getDisplayName(), width/2, height/2 - FIELD_HEIGHT/2 - SPACING_HEIGHT, 16777215); + public void render(int mouseX, int mouseY, float partialTicks) { + renderBackground(); + super.render(mouseX, mouseY, partialTicks); + drawCenteredString(font, wand.getDisplayName().getFormattedText(), width/2, height/2 - FIELD_HEIGHT/2 - SPACING_HEIGHT, 16777215); + optionButtons.forEach((opt, but) -> drawTooltip(mouseX, mouseY, opt, but)); } @Override public boolean charTyped(char character, int code) { - if(character == 'e') closeScreen(); + if(character == 'e') onClose(); return super.charTyped(character, code); } private void createButton(int cx, int cy, IOption option) { - Button button = new Button(getX(cx), getY(cy), BUTTON_WIDTH, BUTTON_HEIGHT, getButtonLabel(option), bt -> clickButton(bt, option), (bt, ms, x, y) -> drawTooltip(ms, x, y, option)); + Button button = new Button(getX(cx), getY(cy), BUTTON_WIDTH, BUTTON_HEIGHT, getButtonLabel(option).getFormattedText(), bt -> clickButton(bt, option)); button.active = option.isEnabled(); addButton(button); + optionButtons.put(option, button); } private void clickButton(Button button, IOption option) { option.next(); ConstructionWand.instance.HANDLER.sendToServer(new PacketWandOption(option, false)); - button.setMessage(getButtonLabel(option)); + button.setMessage(getButtonLabel(option).getFormattedText()); } - private void drawTooltip(MatrixStack matrixStack, int mouseX, int mouseY, IOption option) { - if(isMouseOver(mouseX, mouseY)) { - renderTooltip(matrixStack, new TranslationTextComponent(option.getDescTranslation()), mouseX, mouseY); + private void drawTooltip(int mouseX, int mouseY, IOption option, Button button) { + if(button.isHovered()) { + renderTooltip(new TranslationTextComponent(option.getDescTranslation()).getFormattedText(), mouseX, mouseY); } } @@ -86,6 +92,6 @@ public class ScreenWand extends Screen } private ITextComponent getButtonLabel(IOption option) { - return new TranslationTextComponent(option.getKeyTranslation()).append(new TranslationTextComponent(option.getValueTranslation())); + return new TranslationTextComponent(option.getKeyTranslation()).appendSibling(new TranslationTextComponent(option.getValueTranslation())); } } diff --git a/src/main/java/thetadev/constructionwand/data/Inp.java b/src/main/java/thetadev/constructionwand/data/Inp.java index 07e62c0..4b52641 100644 --- a/src/main/java/thetadev/constructionwand/data/Inp.java +++ b/src/main/java/thetadev/constructionwand/data/Inp.java @@ -3,7 +3,7 @@ package thetadev.constructionwand.data; import net.minecraft.advancements.criterion.ItemPredicate; import net.minecraft.item.Item; import net.minecraft.item.crafting.Ingredient; -import net.minecraft.tags.ITag; +import net.minecraft.tags.Tag; import net.minecraft.util.IItemProvider; public class Inp @@ -21,7 +21,7 @@ public class Inp public static Inp fromItem(IItemProvider in) { return new Inp(in.asItem().getRegistryName().getPath(), Ingredient.fromItems(in), ItemPredicate.Builder.create().item(in).build()); } - public static Inp fromTag(ITag.INamedTag in) { - return new Inp(in.getName().getPath(), Ingredient.fromTag(in), ItemPredicate.Builder.create().tag(in).build()); + public static Inp fromTag(Tag in) { + return new Inp(in.getId().getPath(), Ingredient.fromTag(in), ItemPredicate.Builder.create().tag(in).build()); } } \ No newline at end of file diff --git a/src/main/java/thetadev/constructionwand/data/RecipeGenerator.java b/src/main/java/thetadev/constructionwand/data/RecipeGenerator.java index 36430c8..900d683 100644 --- a/src/main/java/thetadev/constructionwand/data/RecipeGenerator.java +++ b/src/main/java/thetadev/constructionwand/data/RecipeGenerator.java @@ -4,7 +4,6 @@ import net.minecraft.data.DataGenerator; import net.minecraft.data.IFinishedRecipe; import net.minecraft.data.RecipeProvider; import net.minecraft.data.ShapedRecipeBuilder; -import net.minecraft.tags.ItemTags; import net.minecraft.util.IItemProvider; import net.minecraftforge.common.Tags; import thetadev.constructionwand.ConstructionWand; @@ -20,7 +19,7 @@ public class RecipeGenerator extends RecipeProvider @Override protected void registerRecipes(Consumer consumer) { - wandRecipe(consumer, ModItems.WAND_STONE, Inp.fromTag(ItemTags.field_232909_aa_)); //stone_tool_materials + wandRecipe(consumer, ModItems.WAND_STONE, Inp.fromTag(Tags.Items.COBBLESTONE)); wandRecipe(consumer, ModItems.WAND_IRON, Inp.fromTag(Tags.Items.INGOTS_IRON)); wandRecipe(consumer, ModItems.WAND_DIAMOND, Inp.fromTag(Tags.Items.GEMS_DIAMOND)); wandRecipe(consumer, ModItems.WAND_INFINITY, Inp.fromTag(Tags.Items.NETHER_STARS)); diff --git a/src/main/java/thetadev/constructionwand/items/ItemWand.java b/src/main/java/thetadev/constructionwand/items/ItemWand.java index 6e1001e..c48a5f1 100644 --- a/src/main/java/thetadev/constructionwand/items/ItemWand.java +++ b/src/main/java/thetadev/constructionwand/items/ItemWand.java @@ -1,7 +1,6 @@ package thetadev.constructionwand.items; import net.minecraft.block.BlockState; -import net.minecraft.client.Minecraft; import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.util.ITooltipFlag; import net.minecraft.entity.player.PlayerEntity; @@ -12,6 +11,7 @@ import net.minecraft.item.ItemUseContext; import net.minecraft.util.ActionResult; import net.minecraft.util.ActionResultType; import net.minecraft.util.Hand; +import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.BlockRayTraceResult; import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.StringTextComponent; @@ -34,6 +34,7 @@ public abstract class ItemWand extends Item public ItemWand(String name, Item.Properties properties) { super(properties.group(ItemGroup.TOOLS)); setRegistryName(ConstructionWand.loc(name)); + addPropertyOverride(new ResourceLocation(ConstructionWand.MODID, "wand_mode"), (stack, worldIn, entityIn) -> getWandMode(stack)); } @Override @@ -64,14 +65,14 @@ public abstract class ItemWand extends Item ItemStack stack = player.getHeldItem(hand); if(!player.isSneaking()) { - if(world.isRemote) return ActionResult.resultFail(stack); + if(world.isRemote) return new ActionResult<>(ActionResultType.FAIL, stack); // Right click: Place angel block //ConstructionWand.LOGGER.debug("Place angel block"); WandJob job = new AngelJob(player, world, stack); - return job.doIt() ? ActionResult.resultSuccess(stack) : ActionResult.resultFail(stack); + return new ActionResult<>(job.doIt() ? ActionResultType.SUCCESS : ActionResultType.FAIL, stack); } - return ActionResult.resultFail(stack); + return new ActionResult<>(ActionResultType.FAIL, stack); } @Override @@ -107,26 +108,26 @@ public abstract class ItemWand extends Item if(Screen.hasShiftDown()) { for(int i=1; i opt = options.allOptions[i]; - lines.add(new TranslationTextComponent(opt.getKeyTranslation()).mergeStyle(TextFormatting.AQUA) - .append(new TranslationTextComponent(opt.getValueTranslation()).mergeStyle(TextFormatting.GRAY)) + lines.add(new TranslationTextComponent(opt.getKeyTranslation()).applyTextStyle(TextFormatting.AQUA) + .appendSibling(new TranslationTextComponent(opt.getValueTranslation()).applyTextStyle(TextFormatting.GRAY)) ); } } else { IOption opt = options.allOptions[0]; - lines.add(new TranslationTextComponent(langTooltip + "blocks", getLimit()).mergeStyle(TextFormatting.GRAY)); - lines.add(new TranslationTextComponent(opt.getKeyTranslation()).mergeStyle(TextFormatting.AQUA) - .append(new TranslationTextComponent(opt.getValueTranslation()).mergeStyle(TextFormatting.WHITE))); - lines.add(new TranslationTextComponent(langTooltip + "shift").mergeStyle(TextFormatting.AQUA)); + lines.add(new TranslationTextComponent(langTooltip + "blocks", getLimit()).applyTextStyle(TextFormatting.GRAY)); + lines.add(new TranslationTextComponent(opt.getKeyTranslation()).applyTextStyle(TextFormatting.AQUA) + .appendSibling(new TranslationTextComponent(opt.getValueTranslation()).applyTextStyle(TextFormatting.WHITE))); + lines.add(new TranslationTextComponent(langTooltip + "shift").applyTextStyle(TextFormatting.AQUA)); } } public static void optionMessage(PlayerEntity player, IOption option) { player.sendStatusMessage( - new TranslationTextComponent(option.getKeyTranslation()).mergeStyle(TextFormatting.AQUA) - .append(new TranslationTextComponent(option.getValueTranslation()).mergeStyle(TextFormatting.WHITE)) - .append(new StringTextComponent(" - ").mergeStyle(TextFormatting.GRAY)) - .append(new TranslationTextComponent(option.getDescTranslation()).mergeStyle(TextFormatting.WHITE)) + new TranslationTextComponent(option.getKeyTranslation()).applyTextStyle(TextFormatting.AQUA) + .appendSibling(new TranslationTextComponent(option.getValueTranslation()).applyTextStyle(TextFormatting.WHITE)) + .appendSibling(new StringTextComponent(" - ").applyTextStyle(TextFormatting.GRAY)) + .appendSibling(new TranslationTextComponent(option.getDescTranslation()).applyTextStyle(TextFormatting.WHITE)) , true); } } diff --git a/src/main/java/thetadev/constructionwand/items/ItemWandBasic.java b/src/main/java/thetadev/constructionwand/items/ItemWandBasic.java index 3186834..ff5d3dd 100644 --- a/src/main/java/thetadev/constructionwand/items/ItemWandBasic.java +++ b/src/main/java/thetadev/constructionwand/items/ItemWandBasic.java @@ -2,12 +2,7 @@ package thetadev.constructionwand.items; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.IItemTier; -import net.minecraft.item.Item; -import net.minecraft.item.Item.Properties; import net.minecraft.item.ItemStack; -import net.minecraft.item.crafting.Ingredient; -import net.minecraft.tags.ItemTags; -import net.minecraft.util.ResourceLocation; import thetadev.constructionwand.basics.ConfigServer; public class ItemWandBasic extends ItemWand diff --git a/src/main/java/thetadev/constructionwand/items/ItemWandInfinity.java b/src/main/java/thetadev/constructionwand/items/ItemWandInfinity.java index ae9e2aa..a089160 100644 --- a/src/main/java/thetadev/constructionwand/items/ItemWandInfinity.java +++ b/src/main/java/thetadev/constructionwand/items/ItemWandInfinity.java @@ -9,7 +9,7 @@ public class ItemWandInfinity extends ItemWand { public ItemWandInfinity(String name) { - super(name, new Properties().maxStackSize(1).isBurnable()); + super(name, new Properties().maxStackSize(1)); } @Override diff --git a/src/main/java/thetadev/constructionwand/items/ModItems.java b/src/main/java/thetadev/constructionwand/items/ModItems.java index f043b7a..97574fe 100644 --- a/src/main/java/thetadev/constructionwand/items/ModItems.java +++ b/src/main/java/thetadev/constructionwand/items/ModItems.java @@ -1,7 +1,6 @@ package thetadev.constructionwand.items; import net.minecraft.item.Item; -import net.minecraft.item.ItemModelsProperties; import net.minecraft.item.ItemTier; import net.minecraft.util.ResourceLocation; import net.minecraftforge.event.RegistryEvent; @@ -26,13 +25,4 @@ public class ModItems { event.getRegistry().registerAll(WANDS); } - - public static void registerModelProperties() { - for(Item item : WANDS) { - ItemModelsProperties.func_239418_a_( - item, new ResourceLocation(ConstructionWand.MODID, "wand_mode"), - (stack, world, entity) -> entity == null || !(stack.getItem() instanceof ItemWand) ? 0 : ItemWand.getWandMode(stack) - ); - } - } } diff --git a/src/main/java/thetadev/constructionwand/job/AngelJob.java b/src/main/java/thetadev/constructionwand/job/AngelJob.java index 59d11f3..0a69954 100644 --- a/src/main/java/thetadev/constructionwand/job/AngelJob.java +++ b/src/main/java/thetadev/constructionwand/job/AngelJob.java @@ -6,7 +6,7 @@ import net.minecraft.item.ItemStack; import net.minecraft.util.Direction; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockRayTraceResult; -import net.minecraft.util.math.vector.Vector3d; +import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; import thetadev.constructionwand.basics.ConfigServer; import thetadev.constructionwand.basics.WandUtil; @@ -15,10 +15,10 @@ import thetadev.constructionwand.basics.option.WandOptions; public class AngelJob extends WandJob { public AngelJob(PlayerEntity player, World world, ItemStack wand) { - super(player, world, new BlockRayTraceResult(player.getLookVec(), fromVector(player.getLookVec()), WandUtil.playerPos(player), false), wand); + super(player, world, new BlockRayTraceResult(player.getLookVec(), fromVector(player.getLookVec()), player.getPosition(), false), wand); } - private static Direction fromVector(Vector3d vector) { + private static Direction fromVector(Vec3d vector) { return Direction.getFacingFromVector(vector.x, vector.y, vector.z); } @@ -28,9 +28,9 @@ public class AngelJob extends WandJob if(!player.isCreative() && !ConfigServer.ANGEL_FALLING.get() && player.fallDistance > 10) return; - Vector3d playerVec = WandUtil.entityPositionVec(player); - Vector3d lookVec = player.getLookVec().mul(2, 2, 2); - Vector3d placeVec = playerVec.add(lookVec); + Vec3d playerVec = WandUtil.entityPositionVec(player); + Vec3d lookVec = player.getLookVec().mul(2, 2, 2); + Vec3d placeVec = playerVec.add(lookVec); BlockPos currentPos = new BlockPos(placeVec); diff --git a/src/main/java/thetadev/constructionwand/job/PlaceSnapshot.java b/src/main/java/thetadev/constructionwand/job/PlaceSnapshot.java index de64757..e04b6ef 100644 --- a/src/main/java/thetadev/constructionwand/job/PlaceSnapshot.java +++ b/src/main/java/thetadev/constructionwand/job/PlaceSnapshot.java @@ -6,14 +6,15 @@ import net.minecraft.util.math.BlockPos; public class PlaceSnapshot { - public final BlockState block; + public BlockState block; + public final BlockState supportingBlock; public final BlockPos pos; public final BlockItem item; - public PlaceSnapshot(BlockPos pos, BlockState block, BlockItem item) + public PlaceSnapshot(BlockPos pos, BlockState supportingBlock, BlockItem item) { this.pos = pos; - this.block = block; + this.supportingBlock = supportingBlock; this.item = item; } } diff --git a/src/main/java/thetadev/constructionwand/job/WandItemUseContext.java b/src/main/java/thetadev/constructionwand/job/WandItemUseContext.java index ca32780..dbdc7e7 100644 --- a/src/main/java/thetadev/constructionwand/job/WandItemUseContext.java +++ b/src/main/java/thetadev/constructionwand/job/WandItemUseContext.java @@ -6,8 +6,7 @@ import net.minecraft.item.ItemStack; import net.minecraft.util.Hand; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockRayTraceResult; -import net.minecraft.util.math.vector.Vector3d; -import thetadev.constructionwand.basics.WandUtil; +import net.minecraft.util.math.Vec3d; public class WandItemUseContext extends BlockItemUseContext { @@ -15,10 +14,9 @@ public class WandItemUseContext extends BlockItemUseContext super(job.world, job.player, Hand.MAIN_HAND, new ItemStack(item), new BlockRayTraceResult(getBlockHitVec(job, pos), job.rayTraceResult.getFace(), pos, false)); } - private static Vector3d getBlockHitVec(WandJob job, BlockPos pos) { - Vector3d hitVec = job.rayTraceResult.getHitVec(); // Absolute coords of hit target - - Vector3d blockDelta = WandUtil.blockPosVec(job.rayTraceResult.getPos()).subtract(WandUtil.blockPosVec(pos)); // Vector between start and current block + private static Vec3d getBlockHitVec(WandJob job, BlockPos pos) { + Vec3d hitVec = job.rayTraceResult.getHitVec(); // Absolute coords of hit target + Vec3d blockDelta = new Vec3d(job.rayTraceResult.getPos()).subtract(new Vec3d(pos)); // Vector between start and current block return blockDelta.add(hitVec); // Absolute coords of current block hit target } diff --git a/src/main/java/thetadev/constructionwand/job/WandJob.java b/src/main/java/thetadev/constructionwand/job/WandJob.java index df8cf05..a1826ea 100644 --- a/src/main/java/thetadev/constructionwand/job/WandJob.java +++ b/src/main/java/thetadev/constructionwand/job/WandJob.java @@ -4,7 +4,7 @@ import net.minecraft.block.*; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.*; -import net.minecraft.state.Property; +import net.minecraft.state.IProperty; import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.state.properties.SlabType; import net.minecraft.stats.Stats; @@ -220,54 +220,15 @@ public abstract class WandJob protected abstract void getBlockPositionList(); + // Get PlaceSnapshot, or null if no block can be placed @Nullable - private BlockState getPlaceBlockstate(BlockPos pos, BlockItem item, BlockState supportingBlock) { + protected PlaceSnapshot getPlaceSnapshot(BlockPos pos, BlockState supportingBlock) { // Is position out of world? if(!world.isBlockPresent(pos)) return null; - // Is block at pos replaceable? - BlockItemUseContext ctx = new WandItemUseContext(this, pos, item); - if(!ctx.canPlace()) return null; - // If replace mode is off, target has to be air if(!options.replace.get() && !world.isAirBlock(pos)) return null; - // Can block be placed? - BlockState placeBlock = Block.getBlockFromItem(item).getStateForPlacement(ctx); - if(placeBlock == null) return null; - placeBlock = Block.getValidBlockForPosition(placeBlock, world, pos); - if(placeBlock.getBlock() == Blocks.AIR || !placeBlock.isValidPosition(world, pos)) return null; - - // No entities colliding? - VoxelShape shape = placeBlock.getCollisionShape(world, pos); - if(!shape.isEmpty()) { - AxisAlignedBB blockBB = shape.getBoundingBox().offset(pos); - if(!world.getEntitiesWithinAABB(LivingEntity.class, blockBB, EntityPredicates.NOT_SPECTATING).isEmpty()) return null; - } - - // Copy certain properties of supporting block (save the effort when running preview on client) - if(options.direction.get() == WandOptions.DIRECTION.TARGET && !world.isRemote) { - // Block properties to be copied (alignment/rotation properties) - for(Property property : new Property[] { - BlockStateProperties.HORIZONTAL_FACING, BlockStateProperties.FACING, BlockStateProperties.FACING_EXCEPT_UP, - BlockStateProperties.ROTATION_0_15, BlockStateProperties.AXIS, BlockStateProperties.HALF, BlockStateProperties.STAIRS_SHAPE}) - { - if(supportingBlock.hasProperty(property) && placeBlock.hasProperty(property)) { - placeBlock = placeBlock.with(property, supportingBlock.get(property)); - } - } - - // Dont dupe double slabs - if(supportingBlock.hasProperty(BlockStateProperties.SLAB_TYPE) && placeBlock.hasProperty(BlockStateProperties.SLAB_TYPE)) { - SlabType slabType = supportingBlock.get(BlockStateProperties.SLAB_TYPE); - if(slabType != SlabType.DOUBLE) placeBlock = placeBlock.with(BlockStateProperties.SLAB_TYPE, slabType); - } - } - return placeBlock; - } - - @Nullable - protected PlaceSnapshot getPlaceSnapshot(BlockPos pos, BlockState supportingBlock) { ArrayList items = new ArrayList<>(itemCounts.keySet()); if(doRandomize) { for(BlockItem item : itemWeights.keySet()) { @@ -282,18 +243,63 @@ public abstract class WandJob int count = itemCounts.get(item); if(count == 0) continue; - BlockState placeBlock = getPlaceBlockstate(pos, item, supportingBlock); - if(placeBlock == null) continue; + // Is block at pos replaceable? + BlockItemUseContext ctx = new WandItemUseContext(this, pos, item); + if(!ctx.canPlace()) continue; + // Can block be placed? + BlockState blockState = item.getBlock().getStateForPlacement(ctx); + if(blockState == null) continue; + blockState = Block.getValidBlockForPosition(blockState, world, pos); + if(blockState.getBlock() == Blocks.AIR || !blockState.isValidPosition(world, pos)) continue; + + // No entities colliding? + VoxelShape shape = blockState.getCollisionShape(world, pos); + if(!shape.isEmpty()) { + AxisAlignedBB blockBB = shape.getBoundingBox().offset(pos); + if(!world.getEntitiesWithinAABB(LivingEntity.class, blockBB, EntityPredicates.NOT_SPECTATING).isEmpty()) continue; + } + + // Reduce item count if(count < Integer.MAX_VALUE) itemCounts.merge(item, -1, Integer::sum); - return new PlaceSnapshot(pos, placeBlock, item); + return new PlaceSnapshot(pos, supportingBlock, item); } return null; } private boolean placeBlock(PlaceSnapshot placeSnapshot) { BlockPos blockPos = placeSnapshot.pos; - BlockState placeBlock = placeSnapshot.block; + + BlockItemUseContext ctx = new WandItemUseContext(this, blockPos, placeSnapshot.item); + if(!ctx.canPlace()) return false; + + BlockState placeBlock = Block.getBlockFromItem(placeSnapshot.item).getStateForPlacement(ctx); + if(placeBlock == null) return false; + + BlockState supportingBlock = placeSnapshot.supportingBlock; + + if(options.direction.get() == WandOptions.DIRECTION.TARGET) { + // Block properties to be copied (alignment/rotation properties) + for(IProperty property : new IProperty[] { + BlockStateProperties.HORIZONTAL_FACING, BlockStateProperties.FACING, BlockStateProperties.FACING_EXCEPT_UP, + BlockStateProperties.ROTATION_0_15, BlockStateProperties.AXIS, BlockStateProperties.HALF, BlockStateProperties.STAIRS_SHAPE}) + { + if(supportingBlock.has(property) && placeBlock.has(property)) { + placeBlock = placeBlock.with(property, supportingBlock.get(property)); + } + } + + // Dont dupe double slabs + if(supportingBlock.has(BlockStateProperties.SLAB_TYPE) && placeBlock.has(BlockStateProperties.SLAB_TYPE)) { + SlabType slabType = supportingBlock.get(BlockStateProperties.SLAB_TYPE); + if(slabType != SlabType.DOUBLE) placeBlock = placeBlock.with(BlockStateProperties.SLAB_TYPE, slabType); + } + } + // Abort if placeEvent is canceled + BlockSnapshot snapshot = new BlockSnapshot(world, blockPos, placeBlock); + BlockEvent.EntityPlaceEvent placeEvent = new BlockEvent.EntityPlaceEvent(snapshot, placeBlock, player); + MinecraftForge.EVENT_BUS.post(placeEvent); + if(placeEvent.isCanceled()) return false; // Place the block if(!world.setBlockState(blockPos, placeBlock)) { @@ -301,22 +307,11 @@ public abstract class WandJob return false; } - // Remove block if placeEvent is canceled - BlockSnapshot snapshot = BlockSnapshot.create(world.func_234923_W_(), world, blockPos); - BlockEvent.EntityPlaceEvent placeEvent = new BlockEvent.EntityPlaceEvent(snapshot, placeBlock, player); - MinecraftForge.EVENT_BUS.post(placeEvent); - if(placeEvent.isCanceled()) { - world.removeBlock(blockPos, false); - return false; - } - - // Update neighbor block states - world.notifyNeighborsOfStateChange(blockPos, placeBlock.getBlock()); - // Update stats player.addStat(Stats.ITEM_USED.get(placeSnapshot.item)); player.addStat(ModStats.USE_WAND); + placeSnapshot.block = placeBlock; return true; } @@ -351,10 +346,9 @@ public abstract class WandJob } placeSnapshots = placed; - // Play place sound if(!placeSnapshots.isEmpty()) { SoundType sound = placeSnapshots.getFirst().block.getSoundType(); - world.playSound(null, WandUtil.playerPos(player), sound.getPlaceSound(), SoundCategory.BLOCKS, sound.volume, sound.pitch); + world.playSound(null, player.getPosition(), sound.getPlaceSound(), SoundCategory.BLOCKS, sound.volume, sound.pitch); } // Add to job history for undo @@ -390,7 +384,7 @@ public abstract class WandJob // Play teleport sound SoundEvent sound = SoundEvents.ITEM_CHORUS_FRUIT_TELEPORT; - world.playSound(null, WandUtil.playerPos(player), sound, SoundCategory.PLAYERS, 1.0F, 1.0F); + world.playSound(null, player.getPosition(), sound, SoundCategory.PLAYERS, 1.0F, 1.0F); return true; } diff --git a/src/main/resources/META-INF/mods.toml b/src/main/resources/META-INF/mods.toml index cfdd15e..ff7c8d2 100644 --- a/src/main/resources/META-INF/mods.toml +++ b/src/main/resources/META-INF/mods.toml @@ -1,13 +1,13 @@ modLoader="javafml" -loaderVersion="[33,)" license="MIT License" +loaderVersion="[28,)" [[mods]] modId="constructionwand" version="${file.jarVersion}" displayName="Construction Wand" displayURL="https://github.com/Theta-Dev/ConstructionWand" #optional -logoFile="logo.png" #optional -authors="ThetaDev" #optional +logoFile="logo.png" +authors="ThetaDev" description=''' Construction Wands make building easier! @@ -20,12 +20,12 @@ This is my first minecraft mod. May the odds be ever in your favor. [[dependencies.constructionwand]] modId="forge" mandatory=true - versionRange="[33,)" + versionRange="[28,)" ordering="NONE" side="BOTH" [[dependencies.constructionwand]] modId="minecraft" mandatory=true - versionRange="[1.16.2, 1.16.3]" + versionRange="[1.14.4]" ordering="NONE" side="BOTH"