package com.matt.forgehax.mods; import com.matt.forgehax.events.RenderEvent; import com.matt.forgehax.util.color.Colors; import com.matt.forgehax.util.command.Setting; import com.matt.forgehax.util.mod.Category; import com.matt.forgehax.util.mod.ToggleMod; import com.matt.forgehax.util.mod.loader.RegisterMod; import com.matt.forgehax.util.schematica.Schematic; import com.matt.forgehax.util.schematica.SchematicaHelper; import com.matt.forgehax.util.tesselation.GeometryMasks; import com.matt.forgehax.util.tesselation.GeometryTessellator; import java.util.Optional; import java.util.OptionalInt; import net.minecraft.block.Block; import net.minecraft.block.state.IBlockState; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.item.ItemBlock; import net.minecraft.item.ItemStack; import net.minecraft.util.Tuple; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.RayTraceResult; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import org.lwjgl.opengl.GL11; @RegisterMod public class SchematicHelper extends ToggleMod { private final Setting<Float> line_width = getCommandStub() .builders() .<Float>newSettingBuilder() .name("width") .description("Line width") .defaultTo(5f) .min(1f) .build(); public SchematicHelper() { super(Category.RENDER, "SchematicHelper", false, "Render box where a block would be placed"); } @SubscribeEvent public void onRender(RenderEvent event) { if (!SchematicaHelper.isSchematicaPresent()) return; final ItemStack heldStack = MC.player.getHeldItemMainhand(); if (heldStack.isEmpty()) { return; } if (!(heldStack.getItem() instanceof ItemBlock)) { return; } final Block block = ((ItemBlock) heldStack.getItem()).getBlock(); final int metaData = heldStack.getMetadata(); // using metadata is gay and not 1.13 compatible but dont know a better way to get blockstate from itemstack final IBlockState heldBlockState = block.getStateFromMeta(metaData); getBlockPlacePos().ifPresent(pos -> getColor(pos, heldBlockState).ifPresent(color -> { event.getBuffer().begin(GL11.GL_LINES, DefaultVertexFormats.POSITION_COLOR); GlStateManager.glLineWidth(line_width.get()); GeometryTessellator.drawCuboid(event.getBuffer(), pos, GeometryMasks.Line.ALL, color); event.getTessellator().draw(); }) ); } private static OptionalInt getColor(BlockPos pos, IBlockState heldBlock) { final Optional<Tuple<Schematic, BlockPos>> optSchematic = SchematicaHelper.getOpenSchematic(); if (optSchematic.isPresent()) { final Schematic schematic = optSchematic.get().getFirst(); final BlockPos schematicOffset = optSchematic.get().getSecond(); final BlockPos schematicPos = pos.subtract(schematicOffset); if (schematic.inSchematic(schematicPos)) { final IBlockState schematicBlock = schematic.desiredState(schematicPos); return OptionalInt .of(schematicBlock.equals(heldBlock) ? Colors.GREEN.toBuffer() : Colors.RED.toBuffer()); } else { return OptionalInt.empty(); } } else { return OptionalInt.empty(); } } private static Optional<BlockPos> getBlockPlacePos() { return Optional.ofNullable(MC.objectMouseOver) .filter(result -> result.typeOfHit == RayTraceResult.Type.BLOCK) .map(ray -> ray.getBlockPos().offset(ray.sideHit)); } }