Some work for #115

This commit is contained in:
modmuss50 2015-08-26 10:37:28 +01:00
parent d4c663ae72
commit 2e00382632
7 changed files with 446 additions and 0 deletions

View 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);
}

View 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;
}
}

View 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];
}
}

View file

@ -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);
}
}

View file

@ -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;
}
}

View file

@ -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";
}
}
}
}

View file

@ -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);
}
}