Some work for #115
This commit is contained in:
parent
d4c663ae72
commit
2e00382632
7 changed files with 446 additions and 0 deletions
28
src/main/java/techreborn/client/multiblock/IMultiblockRenderHook.java
Executable file
28
src/main/java/techreborn/client/multiblock/IMultiblockRenderHook.java
Executable file
|
@ -0,0 +1,28 @@
|
|||
/**
|
||||
* This class was created by <Vazkii>. It's distributed as
|
||||
* part of the Botania Mod. Get the Source Code in github:
|
||||
* https://github.com/Vazkii/Botania
|
||||
*
|
||||
* Botania is Open Source and distributed under the
|
||||
* Botania License: http://botaniamod.net/license.php
|
||||
*
|
||||
*/
|
||||
package techreborn.client.multiblock;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.client.renderer.RenderBlocks;
|
||||
import net.minecraft.world.IBlockAccess;
|
||||
|
||||
/**
|
||||
* A hook for rendering blocks in the multiblock display.
|
||||
*/
|
||||
public interface IMultiblockRenderHook {
|
||||
|
||||
public static Map<Block, IMultiblockRenderHook> renderHooks = new HashMap();
|
||||
|
||||
public void renderBlockForMultiblock(IBlockAccess world, Multiblock mb, Block block, int meta, RenderBlocks renderBlocks);
|
||||
|
||||
}
|
152
src/main/java/techreborn/client/multiblock/Multiblock.java
Executable file
152
src/main/java/techreborn/client/multiblock/Multiblock.java
Executable file
|
@ -0,0 +1,152 @@
|
|||
/**
|
||||
* This class was created by <Vazkii>. It's distributed as
|
||||
* part of the Botania Mod. Get the Source Code in github:
|
||||
* https://github.com/Vazkii/Botania
|
||||
*
|
||||
* Botania is Open Source and distributed under the
|
||||
* Botania License: http://botaniamod.net/license.php
|
||||
*
|
||||
*/
|
||||
package techreborn.client.multiblock;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.ChunkCoordinates;
|
||||
import techreborn.client.multiblock.component.MultiblockComponent;
|
||||
|
||||
/**
|
||||
* This class describes a Mutiblock object. It's used to display a
|
||||
* multiblock in the pda and to show the player in a ghost-like
|
||||
* look in the world.
|
||||
*/
|
||||
public class Multiblock {
|
||||
|
||||
public List<MultiblockComponent> components = new ArrayList();
|
||||
public List<ItemStack> materials = new ArrayList();
|
||||
|
||||
public int minX, minY, minZ, maxX, maxY, maxZ, offX, offY, offZ;
|
||||
|
||||
/**
|
||||
* Adds a multiblock component to this multiblock. The component's x y z
|
||||
* coords should be pivoted to the center of the structure.
|
||||
*/
|
||||
public void addComponent(MultiblockComponent component) {
|
||||
components.add(component);
|
||||
changeAxisForNewComponent(component.relPos.posX, component.relPos.posY, component.relPos.posZ);
|
||||
calculateCostForNewComponent(component);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs and adds a multiblock component to this multiblock. The x y z
|
||||
* coords should be pivoted to the center of the structure.
|
||||
*/
|
||||
public void addComponent(int x, int y, int z, Block block, int meta) {
|
||||
addComponent(new MultiblockComponent(new ChunkCoordinates(x, y, z), block, meta));
|
||||
}
|
||||
|
||||
private void changeAxisForNewComponent(int x, int y, int z) {
|
||||
if(x < minX)
|
||||
minX = x;
|
||||
else if(x > maxX)
|
||||
maxX = x;
|
||||
|
||||
if(y < minY)
|
||||
minY = y;
|
||||
else if(y > maxY)
|
||||
maxY = y;
|
||||
|
||||
if(z < minZ)
|
||||
minZ = z;
|
||||
else if(z > maxZ)
|
||||
maxZ = z;
|
||||
}
|
||||
|
||||
private void calculateCostForNewComponent(MultiblockComponent comp) {
|
||||
ItemStack[] materials = comp.getMaterials();
|
||||
if(materials != null)
|
||||
for(ItemStack stack : materials)
|
||||
addStack(stack);
|
||||
}
|
||||
|
||||
private void addStack(ItemStack stack) {
|
||||
if(stack == null)
|
||||
return;
|
||||
|
||||
for(ItemStack oStack : materials)
|
||||
if(oStack.isItemEqual(stack) && ItemStack.areItemStackTagsEqual(oStack, stack)) {
|
||||
oStack.stackSize += stack.stackSize;
|
||||
return;
|
||||
}
|
||||
|
||||
materials.add(stack);
|
||||
}
|
||||
|
||||
public void setRenderOffset(int x, int y, int z) {
|
||||
offX = x;
|
||||
offY = y;
|
||||
offZ = z;
|
||||
}
|
||||
|
||||
public List<MultiblockComponent> getComponents() {
|
||||
return components;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rotates this multiblock by the angle passed in. For the best results, use
|
||||
* only multiples of pi/2.
|
||||
*/
|
||||
public void rotate(double angle) {
|
||||
for(MultiblockComponent comp : getComponents())
|
||||
comp.rotate(angle);
|
||||
}
|
||||
|
||||
public Multiblock copy() {
|
||||
Multiblock mb = new Multiblock();
|
||||
for(MultiblockComponent comp : getComponents())
|
||||
mb.addComponent(comp.copy());
|
||||
|
||||
return mb;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a length 4 array of all the rotations multiple of pi/2 required
|
||||
* to render this multiblock in the world relevant to the 4 cardinal
|
||||
* orientations.
|
||||
*/
|
||||
public Multiblock[] createRotations() {
|
||||
Multiblock[] blocks = new Multiblock[4];
|
||||
blocks[0] = this;
|
||||
blocks[1] = blocks[0].copy();
|
||||
blocks[1].rotate(Math.PI / 2);
|
||||
blocks[2] = blocks[1].copy();
|
||||
blocks[2].rotate(Math.PI / 2);
|
||||
blocks[3] = blocks[2].copy();
|
||||
blocks[3].rotate(Math.PI / 2);
|
||||
|
||||
return blocks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes a MultiblockSet from this Multiblock and its rotations using
|
||||
* createRotations().
|
||||
*/
|
||||
public MultiblockSet makeSet() {
|
||||
return new MultiblockSet(this);
|
||||
}
|
||||
|
||||
public int getXSize() {
|
||||
return Math.abs(minX) + Math.abs(maxX) + 1;
|
||||
}
|
||||
|
||||
public int getYSize() {
|
||||
return Math.abs(minY) + Math.abs(maxY) + 1;
|
||||
}
|
||||
|
||||
public int getZSize() {
|
||||
return Math.abs(minZ) + Math.abs(maxZ) + 1;
|
||||
}
|
||||
|
||||
}
|
42
src/main/java/techreborn/client/multiblock/MultiblockSet.java
Executable file
42
src/main/java/techreborn/client/multiblock/MultiblockSet.java
Executable file
|
@ -0,0 +1,42 @@
|
|||
/**
|
||||
* This class was created by <Vazkii>. It's distributed as
|
||||
* part of the Botania Mod. Get the Source Code in github:
|
||||
* https://github.com/Vazkii/Botania
|
||||
*
|
||||
* Botania is Open Source and distributed under the
|
||||
* Botania License: http://botaniamod.net/license.php
|
||||
*
|
||||
*/
|
||||
package techreborn.client.multiblock;
|
||||
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.util.MathHelper;
|
||||
|
||||
/**
|
||||
* A set of Multiblock objects for various rotations.
|
||||
*/
|
||||
public class MultiblockSet {
|
||||
|
||||
private final Multiblock[] mbs;
|
||||
|
||||
public MultiblockSet(Multiblock[] mbs) {
|
||||
this.mbs = mbs;
|
||||
}
|
||||
|
||||
public MultiblockSet(Multiblock mb) {
|
||||
this(mb.createRotations());
|
||||
}
|
||||
|
||||
public Multiblock getForEntity(Entity e) {
|
||||
return getForRotation(e.rotationYaw);
|
||||
}
|
||||
|
||||
public Multiblock getForRotation(double rotation) {
|
||||
int facing = MathHelper.floor_double(rotation * 4.0 / 360.0 + 0.5) & 3;
|
||||
return getForIndex(facing);
|
||||
}
|
||||
|
||||
public Multiblock getForIndex(int index) {
|
||||
return mbs[index];
|
||||
}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
/**
|
||||
* This class was created by <Vazkii>. It's distributed as
|
||||
* part of the Botania Mod. Get the Source Code in github:
|
||||
* https://github.com/Vazkii/Botania
|
||||
*
|
||||
* Botania is Open Source and distributed under the
|
||||
* Botania License: http://botaniamod.net/license.php
|
||||
*
|
||||
*/
|
||||
package techreborn.client.multiblock.component;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.ChunkCoordinates;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
/**
|
||||
* A component of a multiblock, the normal one
|
||||
* is just a block.
|
||||
*/
|
||||
public class MultiblockComponent {
|
||||
|
||||
public ChunkCoordinates relPos;
|
||||
public final Block block;
|
||||
public final int meta;
|
||||
|
||||
public MultiblockComponent(ChunkCoordinates relPos, Block block, int meta) {
|
||||
this.relPos = relPos;
|
||||
this.block = block;
|
||||
this.meta = meta;
|
||||
}
|
||||
|
||||
public ChunkCoordinates getRelativePosition() {
|
||||
return relPos;
|
||||
}
|
||||
|
||||
public Block getBlock() {
|
||||
return block;
|
||||
}
|
||||
|
||||
public int getMeta() {
|
||||
return meta;
|
||||
}
|
||||
|
||||
public boolean matches(World world, int x, int y, int z) {
|
||||
return world.getBlock(x, y, z) == getBlock() && (meta == -1 || world.getBlockMetadata(x, y, z) == meta);
|
||||
}
|
||||
|
||||
public ItemStack[] getMaterials() {
|
||||
return new ItemStack[] { new ItemStack(block, 1, meta) };
|
||||
}
|
||||
|
||||
public void rotate(double angle) {
|
||||
double x = relPos.posX;
|
||||
double z = relPos.posZ;
|
||||
double sin = Math.sin(angle);
|
||||
double cos = Math.cos(angle);
|
||||
|
||||
double xn = x * cos - z * sin;
|
||||
double zn = x * sin + z * cos;
|
||||
relPos = new ChunkCoordinates((int) Math.round(xn), relPos.posY, (int) Math.round(zn));
|
||||
}
|
||||
|
||||
public MultiblockComponent copy() {
|
||||
return new MultiblockComponent(relPos, block, meta);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,113 @@
|
|||
/**
|
||||
* This class was created by <Vazkii>. It's distributed as
|
||||
* part of the Botania Mod. Get the Source Code in github:
|
||||
* https://github.com/Vazkii/Botania
|
||||
*
|
||||
* Botania is Open Source and distributed under the
|
||||
* Botania License: http://botaniamod.net/license.php
|
||||
*
|
||||
*/
|
||||
package techreborn.client.render;
|
||||
|
||||
|
||||
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.RenderBlocks;
|
||||
import net.minecraft.client.renderer.entity.RenderManager;
|
||||
import net.minecraft.client.renderer.texture.TextureMap;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.util.ChatComponentText;
|
||||
import net.minecraft.util.ChatStyle;
|
||||
import net.minecraft.util.ChunkCoordinates;
|
||||
import net.minecraft.util.EnumChatFormatting;
|
||||
import net.minecraft.util.MathHelper;
|
||||
import net.minecraft.util.MovingObjectPosition;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.client.event.RenderWorldLastEvent;
|
||||
import net.minecraftforge.event.entity.player.PlayerInteractEvent;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import techreborn.client.multiblock.IMultiblockRenderHook;
|
||||
import techreborn.client.multiblock.Multiblock;
|
||||
import techreborn.client.multiblock.MultiblockSet;
|
||||
import techreborn.client.multiblock.component.MultiblockComponent;
|
||||
|
||||
public class MultiblockRenderEvent {
|
||||
public static boolean rendering = false;
|
||||
|
||||
private static RenderBlocks blockRender = RenderBlocks.getInstance();
|
||||
public MultiblockSet currentMultiblock;
|
||||
public ChunkCoordinates anchor;
|
||||
public int angle;
|
||||
|
||||
public void setMultiblock(MultiblockSet set) {
|
||||
currentMultiblock = set;
|
||||
anchor = null;
|
||||
angle = 0;
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void onWorldRenderLast(RenderWorldLastEvent event) {
|
||||
Minecraft mc = Minecraft.getMinecraft();
|
||||
if(mc.thePlayer != null && mc.objectMouseOver != null && (!mc.thePlayer.isSneaking() || anchor != null)) {
|
||||
mc.thePlayer.getCurrentEquippedItem();
|
||||
renderPlayerLook(mc.thePlayer, mc.objectMouseOver);
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void onPlayerInteract(PlayerInteractEvent event) {
|
||||
if(currentMultiblock != null && anchor == null && event.action == PlayerInteractEvent.Action.RIGHT_CLICK_AIR && event.entityPlayer == Minecraft.getMinecraft().thePlayer) {
|
||||
anchor = new ChunkCoordinates(event.x, event.y, event.z);
|
||||
angle = MathHelper.floor_double(event.entityPlayer.rotationYaw * 4.0 / 360.0 + 0.5) & 3;
|
||||
event.setCanceled(true);
|
||||
}
|
||||
}
|
||||
|
||||
private void renderPlayerLook(EntityPlayer player, MovingObjectPosition src) {
|
||||
if(currentMultiblock != null) {
|
||||
int anchorX = anchor != null ? anchor.posX : src.blockX;
|
||||
int anchorY = anchor != null ? anchor.posY : src.blockY;
|
||||
int anchorZ = anchor != null ? anchor.posZ : src.blockZ;
|
||||
|
||||
rendering = true;
|
||||
Multiblock mb = anchor != null ? currentMultiblock.getForIndex(angle) : currentMultiblock.getForEntity(player);
|
||||
boolean didAny = false;
|
||||
for(MultiblockComponent comp : mb.getComponents())
|
||||
if(renderComponent(player.worldObj, mb, comp, anchorX, anchorY, anchorZ))
|
||||
didAny = true;
|
||||
rendering = false;
|
||||
|
||||
if(!didAny) {
|
||||
setMultiblock(null);
|
||||
player.addChatComponentMessage(new ChatComponentText("Structure Complete!").setChatStyle(new ChatStyle().setColor(EnumChatFormatting.GREEN)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean renderComponent(World world, Multiblock mb, MultiblockComponent comp, int anchorX, int anchorY, int anchorZ) {
|
||||
ChunkCoordinates pos = comp.getRelativePosition();
|
||||
int x = pos.posX + anchorX;
|
||||
int y = pos.posY + anchorY;
|
||||
int z = pos.posZ + anchorZ;
|
||||
if(anchor != null && comp.matches(world, x, y, z))
|
||||
return false;
|
||||
|
||||
GL11.glPushMatrix();
|
||||
GL11.glEnable(GL11.GL_BLEND);
|
||||
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
|
||||
GL11.glDisable(GL11.GL_DEPTH_TEST);
|
||||
GL11.glColor4f(1F, 1F, 1F, 0.4F);
|
||||
GL11.glTranslated(x + 0.5 - RenderManager.renderPosX, y + 0.5 - RenderManager.renderPosY, z + 0.5 - RenderManager.renderPosZ);
|
||||
Minecraft.getMinecraft().renderEngine.bindTexture(TextureMap.locationBlocksTexture);
|
||||
|
||||
blockRender.useInventoryTint = false;
|
||||
Block block = comp.getBlock();
|
||||
if(IMultiblockRenderHook.renderHooks.containsKey(block))
|
||||
IMultiblockRenderHook.renderHooks.get(block).renderBlockForMultiblock(world, mb, block, comp.getMeta(), blockRender);
|
||||
else blockRender.renderBlockAsItem(comp.getBlock(), comp.getMeta(), 1F);
|
||||
GL11.glEnable(GL11.GL_DEPTH_TEST);
|
||||
GL11.glPopMatrix();
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -1,13 +1,18 @@
|
|||
package techreborn.pda.pages;
|
||||
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.init.Blocks;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.entity.RenderItem;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import techreborn.client.multiblock.Multiblock;
|
||||
import techreborn.client.multiblock.MultiblockSet;
|
||||
import techreborn.init.ModBlocks;
|
||||
import techreborn.pda.PageCollection;
|
||||
import techreborn.proxies.ClientProxy;
|
||||
|
||||
public class MultiBlockPage extends TitledPage{
|
||||
|
||||
|
@ -20,6 +25,11 @@ public class MultiBlockPage extends TitledPage{
|
|||
@Override
|
||||
public void initGui() {
|
||||
super.initGui();
|
||||
GuiButton button = new GuiButton(212, 10, 10, "Show multiblock in world");
|
||||
buttonList.add(button);
|
||||
if(ClientProxy.multiblockRenderEvent.currentMultiblock != null){
|
||||
button.displayString = "Hide multiblock in world";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -32,4 +42,30 @@ public class MultiBlockPage extends TitledPage{
|
|||
super.renderOverlayComponents(minecraft, offsetX, offsetY, mouseX, mouseY);
|
||||
this.drawCenteredString(fontRendererObj, "TODO", offsetX + 120, offsetY + 130, 777777);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(GuiButton button) {
|
||||
super.actionPerformed(button);
|
||||
if(button.id == 212){
|
||||
if(ClientProxy.multiblockRenderEvent.currentMultiblock == null){
|
||||
{//This code here makes a basic multiblock and then sets to the selected one.
|
||||
Multiblock multiblock = new Multiblock();
|
||||
multiblock.addComponent(0, 0, 0, Blocks.brick_block, 0);
|
||||
multiblock.addComponent(1, 0, 0, Blocks.cobblestone, 0);
|
||||
multiblock.addComponent(0, 0, 1, Blocks.cobblestone, 0);
|
||||
multiblock.addComponent(-1, 0, 0, Blocks.cobblestone, 0);
|
||||
multiblock.addComponent(0, 0, -1, Blocks.cobblestone, 0);
|
||||
multiblock.addComponent(-1, 0, -1, Blocks.cobblestone, 0);
|
||||
multiblock.addComponent(1, 0, 1, Blocks.cobblestone, 0);
|
||||
multiblock.addComponent(0, 1, 0, Blocks.diamond_block, 0);
|
||||
MultiblockSet set = new MultiblockSet(multiblock);
|
||||
ClientProxy.multiblockRenderEvent.setMultiblock(set);
|
||||
}
|
||||
button.displayString = "Hide multiblock in world";
|
||||
} else {
|
||||
ClientProxy.multiblockRenderEvent.setMultiblock(null);
|
||||
button.displayString = "Show multiblock in world";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,20 +1,28 @@
|
|||
package techreborn.proxies;
|
||||
|
||||
import cpw.mods.fml.client.registry.ClientRegistry;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import techreborn.client.IconSupplier;
|
||||
import techreborn.client.VersionCheckerClient;
|
||||
import techreborn.client.hud.ChargeHud;
|
||||
import techreborn.client.keybindings.KeyBindings;
|
||||
import techreborn.client.multiblock.Multiblock;
|
||||
import techreborn.client.multiblock.MultiblockSet;
|
||||
import techreborn.client.render.MultiblockRenderEvent;
|
||||
|
||||
public class ClientProxy extends CommonProxy {
|
||||
|
||||
public static MultiblockRenderEvent multiblockRenderEvent;
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
super.init();
|
||||
MinecraftForge.EVENT_BUS.register(new IconSupplier());
|
||||
MinecraftForge.EVENT_BUS.register(new ChargeHud());
|
||||
MinecraftForge.EVENT_BUS.register(new VersionCheckerClient());
|
||||
multiblockRenderEvent = new MultiblockRenderEvent();
|
||||
MinecraftForge.EVENT_BUS.register(multiblockRenderEvent);
|
||||
ClientRegistry.registerKeyBinding(KeyBindings.config);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue