diff --git a/src/main/scala/mrtjp/mcframes/api/IFrame.java b/src/main/scala/mrtjp/mcframes/api/IFrame.java index 210a40a..6124114 100644 --- a/src/main/scala/mrtjp/mcframes/api/IFrame.java +++ b/src/main/scala/mrtjp/mcframes/api/IFrame.java @@ -1,47 +1,42 @@ /* - * Copyright (c) 2014. - * Created by MrTJP. - * All rights reserved. + * Copyright (c) 2014. Created by MrTJP. All rights reserved. */ package mrtjp.mcframes.api; import mrtjp.relocation.api.Relocator; + import net.minecraft.world.World; /** - * Interface that can be implemented on Tile Entities or Blocks that wish to - * act as frames, which are the blocks that stick together and form a - * moving structure when moved through the {@link Relocator}. No other action besides + * Interface that can be implemented on Tile Entities or Blocks that wish to act as frames, which are the blocks that + * stick together and form a moving structure when moved through the {@link Relocator}. No other action besides * implementation of this interface is needed for the block to function. */ public interface IFrame { + /** - * Used to check if this frame block is allowed to grab - * a block on the given side. + * Used to check if this frame block is allowed to grab a block on the given side. * - * Convention requires that this method yields the same result - * on both client and server. + * Convention requires that this method yields the same result on both client and server. * - * @param w The world. - * @param x The x coordinate. - * @param y The y coordinate. - * @param z The z coordinate. + * @param w The world. + * @param x The x coordinate. + * @param y The y coordinate. + * @param z The z coordinate. * @param side The side of this block, as a ForgeDirection * @return True if the side can grab another block. */ boolean stickOut(World w, int x, int y, int z, int side); /** - * Used to check if this frame block can be grabbed on the - * given side by another frame. + * Used to check if this frame block can be grabbed on the given side by another frame. * - * Convention requires that this method yields the same result - * on both client and server. + * Convention requires that this method yields the same result on both client and server. * - * @param w The world. - * @param x The x coordinate. - * @param y The y coordinate. - * @param z The z coordinate. + * @param w The world. + * @param x The x coordinate. + * @param y The y coordinate. + * @param z The z coordinate. * @param side The side of this block, as a ForgeDirection * @return True if the side can be grabbed by a frame block. */ diff --git a/src/main/scala/mrtjp/mcframes/api/IFrameInteraction.java b/src/main/scala/mrtjp/mcframes/api/IFrameInteraction.java index 79254d1..bbed901 100644 --- a/src/main/scala/mrtjp/mcframes/api/IFrameInteraction.java +++ b/src/main/scala/mrtjp/mcframes/api/IFrameInteraction.java @@ -1,30 +1,26 @@ /* - * Copyright (c) 2014. - * Created by MrTJP. - * All rights reserved. + * Copyright (c) 2014. Created by MrTJP. All rights reserved. */ package mrtjp.mcframes.api; import mrtjp.relocation.api.RelocationAPI; + import net.minecraft.world.World; /** - * Class used instead of {@link IFrame} to add frame capabilities - * to a block without having the block or tile in that location - * implement the IFrame interface. This class must be registered in - * the {@link RelocationAPI}. + * Class used instead of {@link IFrame} to add frame capabilities to a block without having the block or tile in that + * location implement the IFrame interface. This class must be registered in the {@link RelocationAPI}. */ public interface IFrameInteraction extends IFrame { + /** - * Check to see if this interaction can be executed at the given - * coordinates. + * Check to see if this interaction can be executed at the given coordinates. * * @param w The world. * @param x The x coordinate. * @param y The y coordinate. * @param z The z coordinate. - * @return True if this interaction is valid for the given - * location. + * @return True if this interaction is valid for the given location. */ boolean canInteract(World w, int x, int y, int z); } diff --git a/src/main/scala/mrtjp/mcframes/api/IFramePlacement.java b/src/main/scala/mrtjp/mcframes/api/IFramePlacement.java index 63ea59e..771648e 100644 --- a/src/main/scala/mrtjp/mcframes/api/IFramePlacement.java +++ b/src/main/scala/mrtjp/mcframes/api/IFramePlacement.java @@ -1,36 +1,36 @@ /* - * Copyright (c) 2014. - * Created by MrTJP. - * All rights reserved. + * Copyright (c) 2014. Created by MrTJP. All rights reserved. */ package mrtjp.mcframes.api; -import codechicken.lib.vec.Vector3; import mrtjp.relocation.api.RelocationAPI; + import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; import net.minecraft.world.World; +import codechicken.lib.vec.Vector3; + /** - * A utility interface used by the frame ItemBlock when placing. - * It can be used to add interactions to the default frame block - * placement. This class can be registered through the - * {@link RelocationAPI}. + * A utility interface used by the frame ItemBlock when placing. It can be used to add interactions to the default frame + * block placement. This class can be registered through the {@link RelocationAPI}. */ public interface IFramePlacement { + /** - * Called sequentially on all registered IFrameBlockPlacements on - * the frame item block's onItemUse function, until one returns true. - * @param item The itemstack of the frame block. + * Called sequentially on all registered IFrameBlockPlacements on the frame item block's onItemUse function, until + * one returns true. + * + * @param item The itemstack of the frame block. * @param player The player who is placing the block. - * @param world The world the block is being placed in. - * @param x The x coordinate that the block is being placed in. - * @param y The y coordinate that the block is being placed in. - * @param z The z coordinate that the block is being placed in. - * @param side The side the player clicked on - * @param hit The exact hit position of the click. + * @param world The world the block is being placed in. + * @param x The x coordinate that the block is being placed in. + * @param y The y coordinate that the block is being placed in. + * @param z The z coordinate that the block is being placed in. + * @param side The side the player clicked on + * @param hit The exact hit position of the click. * @return True if something happened. This will subsequently block the actual placement of the block. */ - public boolean onItemUse( - ItemStack item, EntityPlayer player, World world, int x, int y, int z, int side, Vector3 hit); + public boolean onItemUse(ItemStack item, EntityPlayer player, World world, int x, int y, int z, int side, + Vector3 hit); } diff --git a/src/main/scala/mrtjp/mcframes/api/MCFramesAPI.java b/src/main/scala/mrtjp/mcframes/api/MCFramesAPI.java index 6ebcc18..d56ef41 100644 --- a/src/main/scala/mrtjp/mcframes/api/MCFramesAPI.java +++ b/src/main/scala/mrtjp/mcframes/api/MCFramesAPI.java @@ -1,7 +1,5 @@ /* - * Copyright (c) 2015. - * Created by MrTJP. - * All rights reserved. + * Copyright (c) 2015. Created by MrTJP. All rights reserved. */ package mrtjp.mcframes.api; @@ -10,20 +8,20 @@ import net.minecraft.util.MovingObjectPosition; import net.minecraft.util.Vec3; /** - * API class for MCFrames. - *

+ * API class for MCFrames.
+ *
* It is recommended that mods access this class within a soft dependency class. */ public abstract class MCFramesAPI { + /** * This field will contain an implementor of this API if Relocation is installed. */ public static MCFramesAPI instance; /** - * Used to register a custom placment that can define how a frame is placed. - * This is useful for cases such as if the frame is placed on a Multipart from - * the Forge Multipart API, this placement property can perform special actions + * Used to register a custom placment that can define how a frame is placed. This is useful for cases such as if the + * frame is placed on a Multipart from the Forge Multipart API, this placement property can perform special actions * that would add the frame to the multipart tile. * * @param placement The custom frame placement to register. @@ -31,51 +29,49 @@ public abstract class MCFramesAPI { public abstract void registerFramePlacement(IFramePlacement placement); /** - * Used to register a {@link IFrameInteraction}, which is a class that - * can be used to add frame-like properties to any block. + * Used to register a {@link IFrameInteraction}, which is a class that can be used to add frame-like properties to + * any block. * * @param interaction The interaction to register. */ public abstract void registerFrameInteraction(IFrameInteraction interaction); /** - * Getter for the optional StickResolver object which can be used to quicky - * resolve a structure based on default Relocation frame blocks and stick - * rules. + * Getter for the optional StickResolver object which can be used to quicky resolve a structure based on default + * Relocation frame blocks and stick rules. * * @return The StickResolver object */ public abstract StickResolver getStickResolver(); /** - * Getter for the instance variable of the Frame block. Used if external - * implementations need the block. (i.e. registration purposes) + * Getter for the instance variable of the Frame block. Used if external implementations need the block. (i.e. + * registration purposes) * * @return The frame block. */ public abstract Block getFrameBlock(); /** - * Tessellates the frame model at the given coordinates. Useful for making - * your block look like the default frame block. + * Tessellates the frame model at the given coordinates. Useful for making your block look like the default frame + * block. * - * @param x The x coordinate. - * @param y The y coordinate. - * @param z The z coordinate. + * @param x The x coordinate. + * @param y The y coordinate. + * @param z The z coordinate. * @param mask The mask of sides not to render. */ public abstract void renderFrame(double x, double y, double z, int mask); /** - * Raytrace a frame block at the given world coords with start and end - * points of a ray. + * Raytrace a frame block at the given world coords with start and end points of a ray. * - * @param x The x coordinate. - * @param y The y coordinate. - * @param z The z coordinate. - * @param mask The side mask for the model. + * @param x The x coordinate. + * @param y The y coordinate. + * @param z The z coordinate. + * @param mask The side mask for the model. * @param start The start point of the ray. - * @param end The end point of the ray. + * @param end The end point of the ray. * @return The object position if anything from the frame model was hit. */ public abstract MovingObjectPosition raytraceFrame(double x, double y, double z, int mask, Vec3 start, Vec3 end); diff --git a/src/main/scala/mrtjp/mcframes/api/StickResolver.java b/src/main/scala/mrtjp/mcframes/api/StickResolver.java index 7bff070..e65e261 100644 --- a/src/main/scala/mrtjp/mcframes/api/StickResolver.java +++ b/src/main/scala/mrtjp/mcframes/api/StickResolver.java @@ -1,28 +1,29 @@ /* - * Copyright (c) 2015. - * Created by MrTJP. - * All rights reserved. + * Copyright (c) 2015. Created by MrTJP. All rights reserved. */ package mrtjp.mcframes.api; import java.util.Set; + import mrtjp.relocation.api.BlockPos; + import net.minecraft.world.World; /** * Helper class used to resolve frame structures. */ public abstract class StickResolver { + /** - * Method used to obtain the block coordinates of every block that is part of the same - * framed structure as the one that was given as an argument. + * Method used to obtain the block coordinates of every block that is part of the same framed structure as the one + * that was given as an argument. * - * @param world The world - * @param x The x coordinate of any block in the structure. - * @param y The y coordinate of any block in the structure. - * @param z The z coordinate of any block in the structure. - * @param exclusions All coordinates to not include in the structure. - * generally, one of these is the motor block that moved the structure. + * @param world The world + * @param x The x coordinate of any block in the structure. + * @param y The y coordinate of any block in the structure. + * @param z The z coordinate of any block in the structure. + * @param exclusions All coordinates to not include in the structure. generally, one of these is the motor block + * that moved the structure. * @return A set of all block coordinates that are part of the structure that the input block was in. */ public abstract Set getStructure(World world, int x, int y, int z, BlockPos... exclusions); diff --git a/src/main/scala/mrtjp/mcframes/api/package-info.java b/src/main/scala/mrtjp/mcframes/api/package-info.java index 159f355..dc4588f 100644 --- a/src/main/scala/mrtjp/mcframes/api/package-info.java +++ b/src/main/scala/mrtjp/mcframes/api/package-info.java @@ -1,7 +1,5 @@ /* - * Copyright (c) 2015. - * Created by MrTJP. - * All rights reserved. + * Copyright (c) 2015. Created by MrTJP. All rights reserved. */ // @API(owner = "MCFrames", provides = "MCFrames|API", apiVersion = "GRADLETOKEN_VERSION") diff --git a/src/main/scala/mrtjp/mcframes/frame.scala b/src/main/scala/mrtjp/mcframes/frame.scala index 032fffd..11f6bac 100644 --- a/src/main/scala/mrtjp/mcframes/frame.scala +++ b/src/main/scala/mrtjp/mcframes/frame.scala @@ -29,210 +29,275 @@ import net.minecraftforge.common.util.ForgeDirection import scala.collection.JavaConversions._ -class BlockFrame extends BlockCore("mcframes.frame", Material.wood) with IFrame -{ - setResistance(5.0F) - setHardness(2.0F) - setStepSound(Block.soundTypeWood) - setCreativeTab(CreativeTabs.tabTransport) +class BlockFrame + extends BlockCore("mcframes.frame", Material.wood) + with IFrame { + setResistance(5.0f) + setHardness(2.0f) + setStepSound(Block.soundTypeWood) + setCreativeTab(CreativeTabs.tabTransport) - override def getItemBlockClass = classOf[ItemBlockFrame] + override def getItemBlockClass = classOf[ItemBlockFrame] - override def stickOut(w:World, x:Int, y:Int, z:Int, side:Int) = true - override def stickIn(w:World, x:Int, y:Int, z:Int, side:Int) = true + override def stickOut(w: World, x: Int, y: Int, z: Int, side: Int) = true + override def stickIn(w: World, x: Int, y: Int, z: Int, side: Int) = true - override def isSideSolid(w:IBlockAccess, x:Int, y:Int, z:Int, side:ForgeDirection) = false + override def isSideSolid( + w: IBlockAccess, + x: Int, + y: Int, + z: Int, + side: ForgeDirection + ) = false - override def isOpaqueCube = false + override def isOpaqueCube = false - override def renderAsNormalBlock = false + override def renderAsNormalBlock = false - override def collisionRayTrace(world:World, x:Int, y:Int, z:Int, start:Vec3, end:Vec3) = - MCFramesAPI.instance.raytraceFrame(x, y, z, 0, start, end) + override def collisionRayTrace( + world: World, + x: Int, + y: Int, + z: Int, + start: Vec3, + end: Vec3 + ) = + MCFramesAPI.instance.raytraceFrame(x, y, z, 0, start, end) - @SideOnly(Side.CLIENT) - override def getSelectedBoundingBoxFromPool(w:World, x:Int, y:Int, z:Int) = - Cuboid6.full.copy.add(new Vector3(x, y, z)).toAABB + @SideOnly(Side.CLIENT) + override def getSelectedBoundingBoxFromPool( + w: World, + x: Int, + y: Int, + z: Int + ) = + Cuboid6.full.copy.add(new Vector3(x, y, z)).toAABB - override def getRenderType = RenderFrame.renderID + override def getRenderType = RenderFrame.renderID - override def getIcon(side:Int, meta:Int) = RenderFrame.icon + override def getIcon(side: Int, meta: Int) = RenderFrame.icon - @SideOnly(Side.CLIENT) - override def registerBlockIcons(reg:IIconRegister) - { - RenderFrame.registerIcons(reg) - } + @SideOnly(Side.CLIENT) + override def registerBlockIcons(reg: IIconRegister) { + RenderFrame.registerIcons(reg) + } } -object ItemBlockFrame -{ - var placements = Seq[IFramePlacement]() +object ItemBlockFrame { + var placements = Seq[IFramePlacement]() } -class ItemBlockFrame(b:Block) extends ItemBlock(b) -{ - override def getMetadata(meta:Int) = meta +class ItemBlockFrame(b: Block) extends ItemBlock(b) { + override def getMetadata(meta: Int) = meta - override def onItemUse(item:ItemStack, player:EntityPlayer, world:World, x:Int, y:Int, z:Int, side:Int, hitX:Float, hitY:Float, hitZ:Float):Boolean = - { - if (ItemBlockFrame.placements.exists(_.onItemUse(item, player, world, x, y, z, - side, new Vector3(hitX, hitY, hitZ)))) - { - SoundLib.playBlockPlacement(world, x, y, z, field_150939_a) - true - } - else super.onItemUse(item, player, world, x, y, z, side, hitX, hitY, hitZ) - } + override def onItemUse( + item: ItemStack, + player: EntityPlayer, + world: World, + x: Int, + y: Int, + z: Int, + side: Int, + hitX: Float, + hitY: Float, + hitZ: Float + ): Boolean = { + if ( + ItemBlockFrame.placements.exists( + _.onItemUse( + item, + player, + world, + x, + y, + z, + side, + new Vector3(hitX, hitY, hitZ) + ) + ) + ) { + SoundLib.playBlockPlacement(world, x, y, z, field_150939_a) + true + } else super.onItemUse(item, player, world, x, y, z, side, hitX, hitY, hitZ) + } - override def func_150936_a(world:World, x:Int, y:Int, z:Int, side:Int, player:EntityPlayer, stack:ItemStack) = true + override def func_150936_a( + world: World, + x: Int, + y: Int, + z: Int, + side: Int, + player: EntityPlayer, + stack: ItemStack + ) = true } -object RenderFrame extends ISimpleBlockRenderingHandler -{ - var renderID = -1 - var icon:IIcon = _ +object RenderFrame extends ISimpleBlockRenderingHandler { + var renderID = -1 + var icon: IIcon = _ - private val model = parseModel("frame") - private val models = new Array[CCModel](64) + private val model = parseModel("frame") + private val models = new Array[CCModel](64) - private def parseModel(name:String) = - { - val m = combine(parseObjModels(this.getClass.getResource( - "/assets/mcframes/obj/"+name+".obj").openStream(), - 7, InvertX).values()) + private def parseModel(name: String) = { + val m = combine( + parseObjModels( + this.getClass + .getResource("/assets/mcframes/obj/" + name + ".obj") + .openStream(), + 7, + InvertX + ).values() + ) - m.apply(new Scale(1.00075, 1.00075, 1.00075)) - m.apply(new Translation(Vector3.center)) - m - } - - override def getRenderId = renderID - - override def shouldRender3DInInventory(modelId:Int) = true - - override def renderInventoryBlock(b:Block, meta:Int, id:Int, rb:RenderBlocks) - { - renderInvBlock(rb, meta) - } - - override def renderWorldBlock(world:IBlockAccess, x:Int, y:Int, z:Int, b:Block, id:Int, rb:RenderBlocks) = - { - renderWorldBlock(rb, world, x, y, z, world.getBlockMetadata(x, y, z)) - true - } - - def renderWorldBlock(r:RenderBlocks, w:IBlockAccess, x:Int, y:Int, z:Int, meta:Int) - { - TextureUtils.bindAtlas(0) - CCRenderState.reset() - CCRenderState.lightMatrix.locate(w, x, y, z) - CCRenderState.setBrightness(w, x, y, z) - - if (r.hasOverrideBlockTexture) - { - getOrGenerateModel(0).render(new Translation(x, y, z), new IconTransformation(r.overrideBlockTexture)) - } - else RenderFrame.render(new Vector3(x, y, z), 0) - } - - def renderInvBlock(r:RenderBlocks, meta:Int) - { - TextureUtils.bindAtlas(0) - CCRenderState.reset() - CCRenderState.setDynamic() - CCRenderState.pullLightmap() - - CCRenderState.startDrawing() - RenderFrame.render(new Vector3(-0.5, -0.5, -0.5), 0) - - CCRenderState.render() - CCRenderState.draw() - } - - def registerIcons(reg:IIconRegister) - { - icon = reg.registerIcon("mcframes:frame") - } - - def render(pos:Vector3, mask:Int) - { - getOrGenerateModel(mask).render(pos.translation, new IconTransformation(icon)) - } - - def getOrGenerateModel(mask:Int) = - { - var m = models(mask&0x3F) - if (m == null) - { - m = FrameModelGen.generate(model, mask) - models(mask&0x3F) = m - } - m + m.apply(new Scale(1.00075, 1.00075, 1.00075)) + m.apply(new Translation(Vector3.center)) + m + } + + override def getRenderId = renderID + + override def shouldRender3DInInventory(modelId: Int) = true + + override def renderInventoryBlock( + b: Block, + meta: Int, + id: Int, + rb: RenderBlocks + ) { + renderInvBlock(rb, meta) + } + + override def renderWorldBlock( + world: IBlockAccess, + x: Int, + y: Int, + z: Int, + b: Block, + id: Int, + rb: RenderBlocks + ) = { + renderWorldBlock(rb, world, x, y, z, world.getBlockMetadata(x, y, z)) + true + } + + def renderWorldBlock( + r: RenderBlocks, + w: IBlockAccess, + x: Int, + y: Int, + z: Int, + meta: Int + ) { + TextureUtils.bindAtlas(0) + CCRenderState.reset() + CCRenderState.lightMatrix.locate(w, x, y, z) + CCRenderState.setBrightness(w, x, y, z) + + if (r.hasOverrideBlockTexture) { + getOrGenerateModel(0).render( + new Translation(x, y, z), + new IconTransformation(r.overrideBlockTexture) + ) + } else RenderFrame.render(new Vector3(x, y, z), 0) + } + + def renderInvBlock(r: RenderBlocks, meta: Int) { + TextureUtils.bindAtlas(0) + CCRenderState.reset() + CCRenderState.setDynamic() + CCRenderState.pullLightmap() + + CCRenderState.startDrawing() + RenderFrame.render(new Vector3(-0.5, -0.5, -0.5), 0) + + CCRenderState.render() + CCRenderState.draw() + } + + def registerIcons(reg: IIconRegister) { + icon = reg.registerIcon("mcframes:frame") + } + + def render(pos: Vector3, mask: Int) { + getOrGenerateModel(mask).render( + pos.translation, + new IconTransformation(icon) + ) + } + + def getOrGenerateModel(mask: Int) = { + var m = models(mask & 0x3f) + if (m == null) { + m = FrameModelGen.generate(model, mask) + models(mask & 0x3f) = m } + m + } } -object FrameModelGen -{ - val w = 2.0/16.0 - val l = 16.0/16.0 - val i = 1.0/16.0 - val u = 0.5 - val v = 0.5 +object FrameModelGen { + val w = 2.0 / 16.0 + val l = 16.0 / 16.0 + val i = 1.0 / 16.0 + val u = 0.5 + val v = 0.5 - def generate(box:CCModel, mask:Int) = - { - var m = generateSinglePeg - m = generateQuartRotated(m) - m = generateEightRotated(m) - m = generateBackface(m) + def generate(box: CCModel, mask: Int) = { + var m = generateSinglePeg + m = generateQuartRotated(m) + m = generateEightRotated(m) + m = generateBackface(m) - var b = Seq.newBuilder[CCModel] - b += box - for (s <- 0 until 6) if ((mask&1< JSet} import codechicken.lib.vec.{BlockCoord, Vector3} import mrtjp.core.vec.ModelRayTracer import mrtjp.core.world.WorldLib -import mrtjp.mcframes.api.{IFrameInteraction, IFramePlacement, MCFramesAPI, StickResolver} +import mrtjp.mcframes.api.{ + IFrameInteraction, + IFramePlacement, + MCFramesAPI, + StickResolver +} import mrtjp.mcframes.{ItemBlockFrame, RenderFrame, StickRegistry} import mrtjp.relocation.api.{BlockPos, RelocationAPI} import net.minecraft.block.Block @@ -21,70 +26,87 @@ import scala.annotation.tailrec import scala.collection.JavaConversions._ import scala.collection.immutable.Queue -object MCFramesAPI_Impl extends MCFramesAPI -{ - override def registerFramePlacement(placement:IFramePlacement) - { - ItemBlockFrame.placements :+= placement - } +object MCFramesAPI_Impl extends MCFramesAPI { + override def registerFramePlacement(placement: IFramePlacement) { + ItemBlockFrame.placements :+= placement + } - override def getFrameBlock = MCFramesMod.blockFrame + override def getFrameBlock = MCFramesMod.blockFrame - override def registerFrameInteraction(interaction:IFrameInteraction) - { - StickRegistry.interactionList :+= interaction - } + override def registerFrameInteraction(interaction: IFrameInteraction) { + StickRegistry.interactionList :+= interaction + } - override def getStickResolver = StickResolver_Impl + override def getStickResolver = StickResolver_Impl - override def renderFrame(x:Double, y:Double, z:Double, mask:Int) - { - RenderFrame.render(new Vector3(x, y, z), mask) - } + override def renderFrame(x: Double, y: Double, z: Double, mask: Int) { + RenderFrame.render(new Vector3(x, y, z), mask) + } - override def raytraceFrame(x:Double, y:Double, z:Double, mask:Int, start:Vec3, end:Vec3) = - ModelRayTracer.raytraceModel(x, y, z, start, end, RenderFrame.getOrGenerateModel(mask)) + override def raytraceFrame( + x: Double, + y: Double, + z: Double, + mask: Int, + start: Vec3, + end: Vec3 + ) = + ModelRayTracer.raytraceModel( + x, + y, + z, + start, + end, + RenderFrame.getOrGenerateModel(mask) + ) } -object StickResolver_Impl extends StickResolver -{ - private var world:World = null - private var start:BlockCoord = null - private var excl:Set[BlockCoord] = null +object StickResolver_Impl extends StickResolver { + private var world: World = null + private var start: BlockCoord = null + private var excl: Set[BlockCoord] = null - override def getStructure(w:World, x:Int, y:Int, z:Int, ex:BlockPos*):JSet[BlockPos] = - { - world = w - start = new BlockCoord(x, y, z) - excl = ex.map(b => new BlockCoord(b.x, b.y, b.z)).toSet - val result = iterate(Queue(start)) - world = null - start = null - excl = null - result.map(b => new BlockPos(b.x, b.y, b.z)) - } + override def getStructure( + w: World, + x: Int, + y: Int, + z: Int, + ex: BlockPos* + ): JSet[BlockPos] = { + world = w + start = new BlockCoord(x, y, z) + excl = ex.map(b => new BlockCoord(b.x, b.y, b.z)).toSet + val result = iterate(Queue(start)) + world = null + start = null + excl = null + result.map(b => new BlockPos(b.x, b.y, b.z)) + } - @tailrec - private def iterate(open:Seq[BlockCoord], closed:Set[BlockCoord] = Set.empty):Set[BlockCoord] = open match - { - case Seq() => closed - case Seq(next, rest@_*) => WorldLib.getBlock(world, next) match - { - case block:Block => - val toCheck = Vector.newBuilder[BlockCoord] - for (s <- 0 until 6) - { - if (StickRegistry.resolveStick(world, next, s)) - { - val to = next.copy.offset(s) - if (!excl(to) && !closed(to) && !open.contains(to)) - if (!world.isAirBlock(to.x, to.y, to.z) && !RelocationAPI.instance.isMoving(world, to.x, to.y, to.z) - /**&& MovingTileRegistry.canMove(world, to.x, to.y, to.z)**/)//Dont ignore non-movables, have them halt movement. - toCheck += to - } - } - iterate(rest++toCheck.result(), closed+next) - case _ => iterate(rest, closed+next) - } - } -} \ No newline at end of file + @tailrec + private def iterate( + open: Seq[BlockCoord], + closed: Set[BlockCoord] = Set.empty + ): Set[BlockCoord] = open match { + case Seq() => closed + case Seq(next, rest @ _*) => + WorldLib.getBlock(world, next) match { + case block: Block => + val toCheck = Vector.newBuilder[BlockCoord] + for (s <- 0 until 6) { + if (StickRegistry.resolveStick(world, next, s)) { + val to = next.copy.offset(s) + if (!excl(to) && !closed(to) && !open.contains(to)) + if ( + !world.isAirBlock(to.x, to.y, to.z) && !RelocationAPI.instance + .isMoving(world, to.x, to.y, to.z) + /** && MovingTileRegistry.canMove(world, to.x, to.y, to.z)* */ + ) // Dont ignore non-movables, have them halt movement. + toCheck += to + } + } + iterate(rest ++ toCheck.result(), closed + next) + case _ => iterate(rest, closed + next) + } + } +} diff --git a/src/main/scala/mrtjp/mcframes/handler/mod.scala b/src/main/scala/mrtjp/mcframes/handler/mod.scala index c3e4b32..c49f9f9 100644 --- a/src/main/scala/mrtjp/mcframes/handler/mod.scala +++ b/src/main/scala/mrtjp/mcframes/handler/mod.scala @@ -6,75 +6,85 @@ package mrtjp.mcframes.handler import cpw.mods.fml.common.Mod -import cpw.mods.fml.common.event.{FMLInitializationEvent, FMLPostInitializationEvent, FMLPreInitializationEvent} +import cpw.mods.fml.common.event.{ + FMLInitializationEvent, + FMLPostInitializationEvent, + FMLPreInitializationEvent +} import mrtjp.core.data.{ModConfig, SpecialConfigGui, TModGuiFactory} import mrtjp.mcframes.api.MCFramesAPI import mrtjp.mcframes.{BlockFrame, BlockMotor, StickRegistry} import net.minecraft.client.gui.GuiScreen -@Mod(modid = MCFramesMod.modID, useMetadata = true, modLanguage = "scala", guiFactory = "mrtjp.mcframes.handler.GuiConfigFactory", acceptedMinecraftVersions = "[1.7.10]", dependencies = "required-after:MrTJPCoreMod", name = MCFramesMod.modName, version = MCFramesMod.version) -object MCFramesMod -{ - MCFramesAPI.instance = MCFramesAPI_Impl +@Mod( + modid = MCFramesMod.modID, + useMetadata = true, + modLanguage = "scala", + guiFactory = "mrtjp.mcframes.handler.GuiConfigFactory", + acceptedMinecraftVersions = "[1.7.10]", + dependencies = "required-after:MrTJPCoreMod", + name = MCFramesMod.modName, + version = MCFramesMod.version +) +object MCFramesMod { + MCFramesAPI.instance = MCFramesAPI_Impl - final val modID = "MCFrames" - final val modName = "MCFrames" - final val version = "GRADLETOKEN_VERSION" + final val modID = "MCFrames" + final val modName = "MCFrames" + final val version = "GRADLETOKEN_VERSION" - var blockFrame:BlockFrame = _ - var blockMotor:BlockMotor = _ + var blockFrame: BlockFrame = _ + var blockMotor: BlockMotor = _ - @Mod.EventHandler - def preInit(event:FMLPreInitializationEvent) - { - MCFramesProxy.preinit() - } + @Mod.EventHandler + def preInit(event: FMLPreInitializationEvent) { + MCFramesProxy.preinit() + } - @Mod.EventHandler - def init(event:FMLInitializationEvent) - { - MCFramesConfig.loadConfig() - MCFramesProxy.init() - } + @Mod.EventHandler + def init(event: FMLInitializationEvent) { + MCFramesConfig.loadConfig() + MCFramesProxy.init() + } - @Mod.EventHandler - def postInit(event:FMLPostInitializationEvent) - { - MCFramesProxy.postinit() - } + @Mod.EventHandler + def postInit(event: FMLPostInitializationEvent) { + MCFramesProxy.postinit() + } } -class MCFramesConfigGui(parent:GuiScreen) extends SpecialConfigGui(parent, "MCFrames", MCFramesConfig.config) -class GuiConfigFactory extends TModGuiFactory -{ - override def mainConfigGuiClass() = classOf[MCFramesConfigGui] +class MCFramesConfigGui(parent: GuiScreen) + extends SpecialConfigGui(parent, "MCFrames", MCFramesConfig.config) +class GuiConfigFactory extends TModGuiFactory { + override def mainConfigGuiClass() = classOf[MCFramesConfigGui] } -object MCFramesConfig extends ModConfig("MCFrames") -{ - var setMap = Array( - "minecraft:bed -> minecraft:bed", - "minecraft:wooden_door -> minecraft:wooden_door", - "minecraft:iron_door -> minecraft:iron_door" +object MCFramesConfig extends ModConfig("MCFrames") { + var setMap = Array( + "minecraft:bed -> minecraft:bed", + "minecraft:wooden_door -> minecraft:wooden_door", + "minecraft:iron_door -> minecraft:iron_door" + ) + + override protected def initValues() { + val sets = new BaseCategory("Latched Sets", buildLatchSetsDesc) + setMap = sets.put("latch registry", setMap) + setMap = sets.put( + "latch registry", + StickRegistry.parseAndAddLatchSets(setMap), + true ) + } - override protected def initValues() - { - val sets = new BaseCategory("Latched Sets", buildLatchSetsDesc) - setMap = sets.put("latch registry", setMap) - setMap = sets.put("latch registry", StickRegistry.parseAndAddLatchSets(setMap), true) - } - - def buildLatchSetsDesc:String = - { - var s = "Used to define which pairs of blocks will be stuck together. \n" - s += "Latched sets will always move in pairs, even if only one of them are actually connected to a block. \n" - s += "'block1 -> block2' means that if block1 is moved, any block2 connected to it will also move. \n" - s += "However, moving block2 does not move block1. To do that, you must also register block2 -> block1. \n" - s += "Sets are defined using the syntax of key -> value. \n" - s += "Possible keys and values:\n" - s += " ':' - to assign block from a mod for every meta. \n" - s += " ':m' - to assign block from mod for specific meta. \n" - s - } + def buildLatchSetsDesc: String = { + var s = "Used to define which pairs of blocks will be stuck together. \n" + s += "Latched sets will always move in pairs, even if only one of them are actually connected to a block. \n" + s += "'block1 -> block2' means that if block1 is moved, any block2 connected to it will also move. \n" + s += "However, moving block2 does not move block1. To do that, you must also register block2 -> block1. \n" + s += "Sets are defined using the syntax of key -> value. \n" + s += "Possible keys and values:\n" + s += " ':' - to assign block from a mod for every meta. \n" + s += " ':m' - to assign block from mod for specific meta. \n" + s + } } diff --git a/src/main/scala/mrtjp/mcframes/handler/proxies.scala b/src/main/scala/mrtjp/mcframes/handler/proxies.scala index 45d4e1b..81977ad 100644 --- a/src/main/scala/mrtjp/mcframes/handler/proxies.scala +++ b/src/main/scala/mrtjp/mcframes/handler/proxies.scala @@ -17,47 +17,47 @@ import net.minecraft.init.Items import net.minecraft.item.ItemStack import net.minecraftforge.oredict.ShapedOreRecipe -class MCFramesProxy_server -{ - def preinit() - { - blockMotor = new BlockMotor - blockFrame = new BlockFrame - } +class MCFramesProxy_server { + def preinit() { + blockMotor = new BlockMotor + blockFrame = new BlockFrame + } - def init() - { - MCFramesRecipes.initRecipes() - } + def init() { + MCFramesRecipes.initRecipes() + } - def postinit(){} + def postinit() {} } -class MCFramesProxy_client extends MCFramesProxy_server -{ - @SideOnly(Side.CLIENT) - override def preinit() - { - super.preinit() +class MCFramesProxy_client extends MCFramesProxy_server { + @SideOnly(Side.CLIENT) + override def preinit() { + super.preinit() - TileRenderRegistry.setRenderer(MCFramesMod.blockMotor, 0, RenderMotor) + TileRenderRegistry.setRenderer(MCFramesMod.blockMotor, 0, RenderMotor) - RenderFrame.renderID = RenderingRegistry.getNextAvailableRenderId - RenderingRegistry.registerBlockHandler(RenderFrame) - } + RenderFrame.renderID = RenderingRegistry.getNextAvailableRenderId + RenderingRegistry.registerBlockHandler(RenderFrame) + } } object MCFramesProxy extends MCFramesProxy_client -object MCFramesRecipes -{ - def initRecipes() - { - //Frame - GameRegistry.addRecipe(new ShapedOreRecipe(new ItemStack(blockFrame, 8), - "sls","lsl","sls", - 's':JC, Items.stick, - 'l':JC, "logWood" - )) - } -} \ No newline at end of file +object MCFramesRecipes { + def initRecipes() { + // Frame + GameRegistry.addRecipe( + new ShapedOreRecipe( + new ItemStack(blockFrame, 8), + "sls", + "lsl", + "sls", + 's': JC, + Items.stick, + 'l': JC, + "logWood" + ) + ) + } +} diff --git a/src/main/scala/mrtjp/mcframes/motor.scala b/src/main/scala/mrtjp/mcframes/motor.scala index 7f3b5ae..9240dac 100644 --- a/src/main/scala/mrtjp/mcframes/motor.scala +++ b/src/main/scala/mrtjp/mcframes/motor.scala @@ -25,155 +25,152 @@ import net.minecraft.util.IIcon import net.minecraft.world.{IBlockAccess, World} import net.minecraftforge.common.util.ForgeDirection -class BlockMotor extends InstancedBlock("mcframes.motor", Material.iron) -{ - setHardness(5f) - setResistance(10f) - setStepSound(Block.soundTypeMetal) - setCreativeTab(CreativeTabs.tabTransport) - addSingleTile(classOf[TileMotor]) +class BlockMotor extends InstancedBlock("mcframes.motor", Material.iron) { + setHardness(5f) + setResistance(10f) + setStepSound(Block.soundTypeMetal) + setCreativeTab(CreativeTabs.tabTransport) + addSingleTile(classOf[TileMotor]) - override def isSideSolid(world:IBlockAccess, x:Int, y:Int, z:Int, side:ForgeDirection) = true + override def isSideSolid( + world: IBlockAccess, + x: Int, + y: Int, + z: Int, + side: ForgeDirection + ) = true - override def renderAsNormalBlock = true + override def renderAsNormalBlock = true } -class TileMotor extends InstancedBlockTile with TTileOrient with IFrame -{ - override def save(tag:NBTTagCompound) - { - super.save(tag) - tag.setByte("orient", orientation) - } - - override def load(tag:NBTTagCompound) - { - super.load(tag) - orientation = tag.getByte("orient") - } - - override def readDesc(in:MCDataInput) - { - super.readDesc(in) - orientation = in.readByte() - } - - override def writeDesc(out:MCDataOutput) - { - super.writeDesc(out) - out.writeByte(orientation) - } - - override def read(in:MCDataInput, key:Int) = key match - { - case 2 => - orientation = in.readByte() - markRender() - case _ => super.read(in, key) - } - - def sendOrientUpdate() - { - if (!world.isRemote) - writeStream(2).writeByte(orientation).sendToChunk() - } - - override def onBlockPlaced(side:Int, meta:Int, player:EntityPlayer, stack:ItemStack, hit:Vector3) - { - super.onBlockPlaced(side, meta, player, stack, hit) - setSide(side^1) - setRotation(Rotation.getSidedRotation(player, side^1)) - } - - override def onBlockActivated(player:EntityPlayer, s:Int):Boolean = - { - if (super.onBlockActivated(player, s)) return true - - if (player.isSneaking) setRotation((rotation+1)%4) - else setSide((side+1)%6) - - true - } - - override def onOrientChanged(oldOrient:Int) - { - super.onOrientChanged(oldOrient) - sendOrientUpdate() - } - - override def getBlock = MCFramesMod.blockMotor - - def getMoveDir = absoluteDir((rotation+2)%4) - - override def stickOut(w:World, x:Int, y:Int, z:Int, side:Int) = side == (this.side^1) - override def stickIn(w:World, x:Int, y:Int, z:Int, side:Int) = side != (this.side^1) - - override def update() - { - if (!world.isRemote && world.getBlockPowerInput(x, y, z) > 0) - { - val pos = position.offset(side^1) - if (world.isAirBlock(pos.x, pos.y, pos.z)) return - - if (!RelocationAPI.instance.isMoving(world, pos.x, pos.y, pos.z) && - !RelocationAPI.instance.isMoving(world, x, y, z)) - { - val blocks = MCFramesAPI.instance.getStickResolver - .getStructure(world, pos.x, pos.y, pos.z, new BlockPos(x, y, z)) - - val r = RelocationAPI.instance.getRelocator - r.push() - r.setWorld(world) - r.setDirection(getMoveDir) - r.setSpeed(1/16D) - r.addBlocks(blocks) - r.execute() - r.pop() - } - } +class TileMotor extends InstancedBlockTile with TTileOrient with IFrame { + override def save(tag: NBTTagCompound) { + super.save(tag) + tag.setByte("orient", orientation) + } + + override def load(tag: NBTTagCompound) { + super.load(tag) + orientation = tag.getByte("orient") + } + + override def readDesc(in: MCDataInput) { + super.readDesc(in) + orientation = in.readByte() + } + + override def writeDesc(out: MCDataOutput) { + super.writeDesc(out) + out.writeByte(orientation) + } + + override def read(in: MCDataInput, key: Int) = key match { + case 2 => + orientation = in.readByte() + markRender() + case _ => super.read(in, key) + } + + def sendOrientUpdate() { + if (!world.isRemote) + writeStream(2).writeByte(orientation).sendToChunk() + } + + override def onBlockPlaced( + side: Int, + meta: Int, + player: EntityPlayer, + stack: ItemStack, + hit: Vector3 + ) { + super.onBlockPlaced(side, meta, player, stack, hit) + setSide(side ^ 1) + setRotation(Rotation.getSidedRotation(player, side ^ 1)) + } + + override def onBlockActivated(player: EntityPlayer, s: Int): Boolean = { + if (super.onBlockActivated(player, s)) return true + + if (player.isSneaking) setRotation((rotation + 1) % 4) + else setSide((side + 1) % 6) + + true + } + + override def onOrientChanged(oldOrient: Int) { + super.onOrientChanged(oldOrient) + sendOrientUpdate() + } + + override def getBlock = MCFramesMod.blockMotor + + def getMoveDir = absoluteDir((rotation + 2) % 4) + + override def stickOut(w: World, x: Int, y: Int, z: Int, side: Int) = + side == (this.side ^ 1) + override def stickIn(w: World, x: Int, y: Int, z: Int, side: Int) = + side != (this.side ^ 1) + + override def update() { + if (!world.isRemote && world.getBlockPowerInput(x, y, z) > 0) { + val pos = position.offset(side ^ 1) + if (world.isAirBlock(pos.x, pos.y, pos.z)) return + + if ( + !RelocationAPI.instance.isMoving(world, pos.x, pos.y, pos.z) && + !RelocationAPI.instance.isMoving(world, x, y, z) + ) { + val blocks = MCFramesAPI.instance.getStickResolver + .getStructure(world, pos.x, pos.y, pos.z, new BlockPos(x, y, z)) + + val r = RelocationAPI.instance.getRelocator + r.push() + r.setWorld(world) + r.setDirection(getMoveDir) + r.setSpeed(1 / 16d) + r.addBlocks(blocks) + r.execute() + r.pop() + } } + } } -object RenderMotor extends TCubeMapRender -{ - var bottom:IIcon = _ - var side:IIcon = _ - var sidew:IIcon = _ - var sidee:IIcon = _ - var top:IIcon = _ +object RenderMotor extends TCubeMapRender { + var bottom: IIcon = _ + var side: IIcon = _ + var sidew: IIcon = _ + var sidee: IIcon = _ + var top: IIcon = _ - override def getData(w:IBlockAccess, x:Int, y:Int, z:Int) = - { - val te = WorldLib.getTileEntity(w, x, y, z, classOf[TileMotor]) - var s = 0 - var r = 0 - if (te != null) - { - s = te.side - r = te.rotation - } - (s, r, new MultiIconTransformation(bottom, top, side, side, sidew, sidee)) + override def getData(w: IBlockAccess, x: Int, y: Int, z: Int) = { + val te = WorldLib.getTileEntity(w, x, y, z, classOf[TileMotor]) + var s = 0 + var r = 0 + if (te != null) { + s = te.side + r = te.rotation } + (s, r, new MultiIconTransformation(bottom, top, side, side, sidew, sidee)) + } - override def getInvData = - (0, 0, new MultiIconTransformation(bottom, top, side, side, sidew, sidee)) + override def getInvData = + (0, 0, new MultiIconTransformation(bottom, top, side, side, sidew, sidee)) - override def getIcon(s:Int, meta:Int) = s match - { - case 0 => bottom - case 1 => top - case 2 => side - case 3 => side - case 4 => sidew - case 5 => sidee - } + override def getIcon(s: Int, meta: Int) = s match { + case 0 => bottom + case 1 => top + case 2 => side + case 3 => side + case 4 => sidew + case 5 => sidee + } - override def registerIcons(reg:IIconRegister) - { - bottom = reg.registerIcon("mcframes:motor/bottom") - top = reg.registerIcon("mcframes:motor/top") - side = reg.registerIcon("mcframes:motor/side") - sidew = reg.registerIcon("mcframes:motor/sidew") - sidee = reg.registerIcon("mcframes:motor/sidee") - } -} \ No newline at end of file + override def registerIcons(reg: IIconRegister) { + bottom = reg.registerIcon("mcframes:motor/bottom") + top = reg.registerIcon("mcframes:motor/top") + side = reg.registerIcon("mcframes:motor/side") + sidew = reg.registerIcon("mcframes:motor/sidew") + sidee = reg.registerIcon("mcframes:motor/sidee") + } +} diff --git a/src/main/scala/mrtjp/mcframes/registry.scala b/src/main/scala/mrtjp/mcframes/registry.scala index 60d762e..1d71e0d 100644 --- a/src/main/scala/mrtjp/mcframes/registry.scala +++ b/src/main/scala/mrtjp/mcframes/registry.scala @@ -11,79 +11,82 @@ import mrtjp.mcframes.api.{IFrame, IFrameInteraction} import net.minecraft.block.Block import net.minecraft.world.World -object StickRegistry -{ - val rKeyVal = raw"([\w:]+)\s*->\s*(.+)".r - val rName = raw"(.+)".r - val rNameMetaM = raw"(.+)m(\d+)".r - val rMod = raw"mod:(\w+)".r +object StickRegistry { + val rKeyVal = raw"([\w:]+)\s*->\s*(.+)".r + val rName = raw"(.+)".r + val rNameMetaM = raw"(.+)m(\d+)".r + val rMod = raw"mod:(\w+)".r - var latchMap = Map[(Block, Int), Set[(Block, Int)]]().withDefaultValue(Set()) - var interactionList = Seq[IFrameInteraction]() + var latchMap = Map[(Block, Int), Set[(Block, Int)]]().withDefaultValue(Set()) + var interactionList = Seq[IFrameInteraction]() - def parseKV(kv:Seq[String]) = kv.map { case rKeyVal(k, v) => (k, v); case s => throw new MatchError(s"Illegal [k -> v] pair: $s") } - def parseBlockMeta(b:String) = b match - { - case rNameMetaM(name, meta) => Block.getBlockFromName(fixName(name)) -> meta.toInt - case rName(name) => Block.getBlockFromName(fixName(name)) -> -1 - case _ => throw new MatchError(s"Illegal set part: $b") - } - def fixName(name:String) = name.indexOf(':') match - { - case -1 => "minecraft:"+name - case i => name - } + def parseKV(kv: Seq[String]) = kv.map { + case rKeyVal(k, v) => (k, v); + case s => throw new MatchError(s"Illegal [k -> v] pair: $s") + } + def parseBlockMeta(b: String) = b match { + case rNameMetaM(name, meta) => + Block.getBlockFromName(fixName(name)) -> meta.toInt + case rName(name) => Block.getBlockFromName(fixName(name)) -> -1 + case _ => throw new MatchError(s"Illegal set part: $b") + } + def fixName(name: String) = name.indexOf(':') match { + case -1 => "minecraft:" + name + case i => name + } - def parseAndAddLatchSets(kv:Seq[String]):Array[String] = - { - parseKV(kv).foreach(b => addLatchSet(parseBlockMeta(b._1), parseBlockMeta(b._2))) - latchMap.map{kv => - val (b, i) = kv._1 - val e1 = Block.blockRegistry.getNameForObject(b)+(if (i != -1) s"m$i" else "") - kv._2.map { k => - val (b2, i2) = k - val e2 = Block.blockRegistry.getNameForObject(b2)+(if (i2 != -1) s"m$i2" else "") - e1+" -> "+e2 - } - }.flatten.toArray - } - - def addLatchSet(b1:(Block, Int), b2:(Block, Int)) - { - latchMap += b1 -> (latchMap(b1)+b2) - } - - def resolveStick(w:World, pos:BlockCoord, side:Int):Boolean = - { - def getFrame(pos:BlockCoord):IFrame = - { - val b = getBlock(w, pos) - if (b.isInstanceOf[IFrame]) return b.asInstanceOf[IFrame] - val te = getTileEntity(w, pos, classOf[IFrame]) - if (te != null) return te - interactionList.find(_.canInteract(w, pos.x, pos.y, pos.z)).orNull + def parseAndAddLatchSets(kv: Seq[String]): Array[String] = { + parseKV(kv).foreach(b => + addLatchSet(parseBlockMeta(b._1), parseBlockMeta(b._2)) + ) + latchMap + .map { kv => + val (b, i) = kv._1 + val e1 = Block.blockRegistry.getNameForObject(b) + (if (i != -1) s"m$i" + else "") + kv._2.map { k => + val (b2, i2) = k + val e2 = + Block.blockRegistry.getNameForObject(b2) + (if (i2 != -1) s"m$i2" + else "") + e1 + " -> " + e2 } + } + .flatten + .toArray + } - val f1 = getFrame(pos) - if (f1 != null && f1.stickOut(w, pos.x, pos.y, pos.z, side)) - { - val p2 = pos.copy.offset(side) - val f2 = getFrame(p2) - return f2 == null || f2.stickIn(w, p2.x, p2.y, p2.z, side^1) - } + def addLatchSet(b1: (Block, Int), b2: (Block, Int)) { + latchMap += b1 -> (latchMap(b1) + b2) + } - if (latchSet(w, pos.x, pos.y, pos.z, side)) return true - - false + def resolveStick(w: World, pos: BlockCoord, side: Int): Boolean = { + def getFrame(pos: BlockCoord): IFrame = { + val b = getBlock(w, pos) + if (b.isInstanceOf[IFrame]) return b.asInstanceOf[IFrame] + val te = getTileEntity(w, pos, classOf[IFrame]) + if (te != null) return te + interactionList.find(_.canInteract(w, pos.x, pos.y, pos.z)).orNull } - def latchSet(w:World, x:Int, y:Int, z:Int, side:Int) = - { - val pos = new BlockCoord(x, y, z).offset(side) - val b1 = getBlockMetaPair(w, x, y, z) - val b2 = getBlockMetaPair(w, pos.x, pos.y, pos.z) - - val set = latchMap.getOrElse(b1, latchMap((b1._1, -1))) - set.contains(b2) || set.contains((b2._1, -1)) + val f1 = getFrame(pos) + if (f1 != null && f1.stickOut(w, pos.x, pos.y, pos.z, side)) { + val p2 = pos.copy.offset(side) + val f2 = getFrame(p2) + return f2 == null || f2.stickIn(w, p2.x, p2.y, p2.z, side ^ 1) } -} \ No newline at end of file + + if (latchSet(w, pos.x, pos.y, pos.z, side)) return true + + false + } + + def latchSet(w: World, x: Int, y: Int, z: Int, side: Int) = { + val pos = new BlockCoord(x, y, z).offset(side) + val b1 = getBlockMetaPair(w, x, y, z) + val b2 = getBlockMetaPair(w, pos.x, pos.y, pos.z) + + val set = latchMap.getOrElse(b1, latchMap((b1._1, -1))) + set.contains(b2) || set.contains((b2._1, -1)) + } +} diff --git a/src/main/scala/mrtjp/relocation/api/BlockPos.java b/src/main/scala/mrtjp/relocation/api/BlockPos.java index 929e24c..c732ed0 100644 --- a/src/main/scala/mrtjp/relocation/api/BlockPos.java +++ b/src/main/scala/mrtjp/relocation/api/BlockPos.java @@ -1,15 +1,14 @@ /* - * Copyright (c) 2015. - * Created by MrTJP. - * All rights reserved. + * Copyright (c) 2015. Created by MrTJP. All rights reserved. */ package mrtjp.relocation.api; /** - * Lightweight block position object used to keep dependencies confined - * to the api package, used by some of the API's methods. + * Lightweight block position object used to keep dependencies confined to the api package, used by some of the API's + * methods. */ public class BlockPos { + public int x; public int y; public int z; diff --git a/src/main/scala/mrtjp/relocation/api/IMovementCallback.java b/src/main/scala/mrtjp/relocation/api/IMovementCallback.java index ed27377..1774811 100644 --- a/src/main/scala/mrtjp/relocation/api/IMovementCallback.java +++ b/src/main/scala/mrtjp/relocation/api/IMovementCallback.java @@ -1,32 +1,26 @@ /* - * Copyright (c) 2015. - * Created by MrTJP. - * All rights reserved. + * Copyright (c) 2015. Created by MrTJP. All rights reserved. */ package mrtjp.relocation.api; /** - * Interface that can be used by things that wish to receive events for - * a move that they executed. This interface is passed into the {@link Relocator} - * during movement construction. + * Interface that can be used by things that wish to receive events for a move that they executed. This interface is + * passed into the {@link Relocator} during movement construction. * - * For example, a motor may wish to know when the movement completes. In which case, - * the motor tile itself would implement this interface and pass itself into the - * Relocator. + * For example, a motor may wish to know when the movement completes. In which case, the motor tile itself would + * implement this interface and pass itself into the Relocator. * - * These methods are only called server-side. Clients will not receive any of - * these events, as this class is registered during the execution of a move, which - * can only happen server-side. + * These methods are only called server-side. Clients will not receive any of these events, as this class is registered + * during the execution of a move, which can only happen server-side. * */ public interface IMovementCallback { + /** - * Called once move starts. The descriptor contains methods that - * describe the state of the current movement that this callback - * was registered to. + * Called once move starts. The descriptor contains methods that describe the state of the current movement that + * this callback was registered to. * - * This descriptor is properly weak-referenced, keep or discard it - * at your own leasure. + * This descriptor is properly weak-referenced, keep or discard it at your own leasure. * * @param desc The movement descriptor for the current move. */ diff --git a/src/main/scala/mrtjp/relocation/api/IMovementDescriptor.java b/src/main/scala/mrtjp/relocation/api/IMovementDescriptor.java index 79a751c..2259480 100644 --- a/src/main/scala/mrtjp/relocation/api/IMovementDescriptor.java +++ b/src/main/scala/mrtjp/relocation/api/IMovementDescriptor.java @@ -1,18 +1,17 @@ /* - * Copyright (c) 2015. - * Created by MrTJP. - * All rights reserved. + * Copyright (c) 2015. Created by MrTJP. All rights reserved. */ package mrtjp.relocation.api; /** - * This is the interface of the object that is given to an {@link IMovementCallback} so - * it may access movement information whenever it needs to during the movement. + * This is the interface of the object that is given to an {@link IMovementCallback} so it may access movement + * information whenever it needs to during the movement. * - * Results of all methods is only valid during movement, undefined otherwise. Use - * isMoving() to check before using any values from this. + * Results of all methods is only valid during movement, undefined otherwise. Use isMoving() to check before using any + * values from this. */ public interface IMovementDescriptor { + /** * @return True if the structure is moving. */ diff --git a/src/main/scala/mrtjp/relocation/api/ITileMover.java b/src/main/scala/mrtjp/relocation/api/ITileMover.java index 728bb43..e650eed 100644 --- a/src/main/scala/mrtjp/relocation/api/ITileMover.java +++ b/src/main/scala/mrtjp/relocation/api/ITileMover.java @@ -1,23 +1,20 @@ /* - * Copyright (c) 2014. - * Created by MrTJP. - * All rights reserved. + * Copyright (c) 2014. Created by MrTJP. All rights reserved. */ package mrtjp.relocation.api; import net.minecraft.world.World; /** - * Interface for an object that manages the movement of blocks and tiles that are - * registered to it. This class should be registered through the {@link RelocationAPI}. + * Interface for an object that manages the movement of blocks and tiles that are registered to it. This class should be + * registered through the {@link RelocationAPI}. */ public interface ITileMover { + /** - * Used to check if the block at the given position can move. This - * method is only called if the specified block is tied to this - * handler, so there is no need to check if the block is valid - * for this handler. This is called before actually moving. If - * everything is able to move, an animation will start. + * Used to check if the block at the given position can move. This method is only called if the specified block is + * tied to this handler, so there is no need to check if the block is valid for this handler. This is called before + * actually moving. If everything is able to move, an animation will start. * * Called server-side only when determining what to move. * @@ -30,25 +27,22 @@ public interface ITileMover { boolean canMove(World w, int x, int y, int z); /** - * Method used to actually move the tile. Called after the animation - * has run. This is where you should tell the tile that it is time - * to move, and peform any extra checks or calls. This should also - * move the block and tile as well. This is called - * on every block in the moving structure sequentially. + * Method used to actually move the tile. Called after the animation has run. This is where you should tell the tile + * that it is time to move, and peform any extra checks or calls. This should also move the block and tile as well. + * This is called on every block in the moving structure sequentially. * * Called on both server and client. * - * @param w The world. - * @param x The x coordinate. - * @param y The y coordinate. - * @param z The z coordinate. + * @param w The world. + * @param x The x coordinate. + * @param y The y coordinate. + * @param z The z coordinate. * @param dir The ForgeDirection the structure is moving in. */ void move(World w, int x, int y, int z, int dir); /** - * Called after all blocks in the group have moved to their - * new locations. This is where you would reload your tile, + * Called after all blocks in the group have moved to their new locations. This is where you would reload your tile, * tell it to refresh or reacknowledge its new position. * * Callod on both server and client. diff --git a/src/main/scala/mrtjp/relocation/api/RelocationAPI.java b/src/main/scala/mrtjp/relocation/api/RelocationAPI.java index 2f2a62b..a74befa 100644 --- a/src/main/scala/mrtjp/relocation/api/RelocationAPI.java +++ b/src/main/scala/mrtjp/relocation/api/RelocationAPI.java @@ -1,90 +1,78 @@ /* - * Copyright (c) 2014. - * Created by MrTJP. - * All rights reserved. + * Copyright (c) 2014. Created by MrTJP. All rights reserved. */ package mrtjp.relocation.api; import net.minecraft.world.World; /** - * Central API class for Relocation. - * If Relocation is installed, the appropriate field will contain an - * implementor of these methods. - *

+ * Central API class for Relocation. If Relocation is installed, the appropriate field will contain an implementor of + * these methods.
+ *
* It is recommended that mods access this class within a soft dependency class. */ public abstract class RelocationAPI { + /** * This field will contain an implementor of this API if Relocation is installed. */ public static RelocationAPI instance; /** - * Used to register a {@link ITileMover} class that manages the movement of certain tiles. - * This method must be called during FML pre-initialization. + * Used to register a {@link ITileMover} class that manages the movement of certain tiles. This method must be + * called during FML pre-initialization. * - * @param name The name of the mover that will be used to assign blocks to it. - * @param desc The description of what this mover is used for or why it is included. + * @param name The name of the mover that will be used to assign blocks to it. + * @param desc The description of what this mover is used for or why it is included. * @param mover The {@link ITileMover} to register. */ public abstract void registerTileMover(String name, String desc, ITileMover mover); /** - * Used to register an in-game block to a specific {@link ITileMover} which are registered - * with the method above. This method adds the key-value pairs similar to the config, - * but their assignments can be changed from the config file if you would like. - * This method must be called during FML pre-initialization. + * Used to register an in-game block to a specific {@link ITileMover} which are registered with the method above. + * This method adds the key-value pairs similar to the config, but their assignments can be changed from the config + * file if you would like. This method must be called during FML pre-initialization. * - * @param key The mod or block key regex. This works the same way it does from the - * config file: - * Possible keys: - * default - to assign default mover - * mod: - to assign every block from a mod - * : - to assign block from a mod for every meta - * :m - to assign block from mod for specific meta + * @param key The mod or block key regex. This works the same way it does from the config file: Possible keys: + * default - to assign default mover mod: - to assign every block from a mod : + * - to assign block from a mod for every meta :m - to assign block from mod + * for specific meta * - * @param value The name of the mover to assign this block. A list of all available - * movers will show up in the configs. + * @param value The name of the mover to assign this block. A list of all available movers will show up in the + * configs. */ public abstract void registerPreferredMover(String key, String value); /** - * Used to register an in-game block to a specific {@link ITileMover} which are registered - * with the method above. This method adds the key-value pairs similar to the config. These - * assignments are manatory, and blocks that are registered will be locked to the specified - * mover, and it cannot be changed from the config. - * This method must be called during FML pre-initialization. + * Used to register an in-game block to a specific {@link ITileMover} which are registered with the method above. + * This method adds the key-value pairs similar to the config. These assignments are manatory, and blocks that are + * registered will be locked to the specified mover, and it cannot be changed from the config. This method must be + * called during FML pre-initialization. * - * @param key The mod or block key regex. This works the same way it does from the - * config file: - * Possible keys: - * default - to assign default mover - * mod: - to assign every block from a mod - * : - to assign block from a mod for every meta - * :m - to assign block from mod for specific meta + * @param key The mod or block key regex. This works the same way it does from the config file: Possible keys: + * default - to assign default mover mod: - to assign every block from a mod : + * - to assign block from a mod for every meta :m - to assign block from mod + * for specific meta * - * @param value The name of the mover to assign this block. A list of all available - * movers will show up in the configs. + * @param value The name of the mover to assign this block. A list of all available movers will show up in the + * configs. */ public abstract void registerMandatoryMover(String key, String value); /** - * Getter for the global Relocator object which is what is used - * to actually initiate movements. + * Getter for the global Relocator object which is what is used to actually initiate movements. * * @return The Relocator object */ public abstract Relocator getRelocator(); /** - * Used to check if the given block is currently moving. This method is - * client and server safe. + * Used to check if the given block is currently moving. This method is client and server safe. * * @param world The world the block is in. - * @param x The x coordinate of the block. - * @param y The y coordinate of the block. - * @param z The z coordinate of the block. + * @param x The x coordinate of the block. + * @param y The y coordinate of the block. + * @param z The z coordinate of the block. * * @return True if the block is currently moving. */ diff --git a/src/main/scala/mrtjp/relocation/api/Relocator.java b/src/main/scala/mrtjp/relocation/api/Relocator.java index 9ec2126..3e14dcb 100644 --- a/src/main/scala/mrtjp/relocation/api/Relocator.java +++ b/src/main/scala/mrtjp/relocation/api/Relocator.java @@ -1,27 +1,25 @@ /* - * Copyright (c) 2015. - * Created by MrTJP. - * All rights reserved. + * Copyright (c) 2015. Created by MrTJP. All rights reserved. */ package mrtjp.relocation.api; import java.util.Set; + import net.minecraft.world.World; /** - * Helper class used to queue and execute the movement of a set of blocks. - * See {@link mrtjp.mcframes.TileMotor} for usage. + * Helper class used to queue and execute the movement of a set of blocks. See {@link mrtjp.mcframes.TileMotor} for + * usage. */ public abstract class Relocator { + /** - * Pushes an instance of the Relocator onto the stack. - * Must be called before using any methods. + * Pushes an instance of the Relocator onto the stack. Must be called before using any methods. */ public abstract void push(); /** - * Pops the instance of the Relocator off the stack. - * Must be called after you are done using this. + * Pops the instance of the Relocator off the stack. Must be called after you are done using this. * * @throws IllegalStateException If there is no Relocator on the stack. */ @@ -36,8 +34,7 @@ public abstract class Relocator { public abstract void setWorld(World world); /** - * Sets the direction towards which all the queued blocks will move. - * This is a ForgeDirection index, from 0 to 5 + * Sets the direction towards which all the queued blocks will move. This is a ForgeDirection index, from 0 to 5 * * @param dir The direction to move the blocks. * @@ -47,8 +44,7 @@ public abstract class Relocator { public abstract void setDirection(int dir); /** - * Sets the speed of the movement. Must be greater than 0 and - * less than 1. + * Sets the speed of the movement. Must be greater than 0 and less than 1. * * @param speed The speed of the movement, in meters/tick. * @@ -58,8 +54,8 @@ public abstract class Relocator { public abstract void setSpeed(double speed); /** - * Sets a callback object that receives events during the actual move. - * This is optional and is not required to be set. + * Sets a callback object that receives events during the actual move. This is optional and is not required to be + * set. * * @param callback The callback to register for this move. * @@ -80,14 +76,12 @@ public abstract class Relocator { public abstract void addBlocks(Set blocks); /** - * Used to execute the queued movement. Before calling, the world, direction, - * and queue of blocks must be set. + * Used to execute the queued movement. Before calling, the world, direction, and queue of blocks must be set. * * @return True if the movement was successfully started. * * @throws IllegalStateException If the Relocator is not on the stack. - * @throws IllegalStateException If any of the required parameters are not set - * or are invalid. + * @throws IllegalStateException If any of the required parameters are not set or are invalid. */ public abstract boolean execute(); } diff --git a/src/main/scala/mrtjp/relocation/api/package-info.java b/src/main/scala/mrtjp/relocation/api/package-info.java index c0b3feb..8c6835d 100644 --- a/src/main/scala/mrtjp/relocation/api/package-info.java +++ b/src/main/scala/mrtjp/relocation/api/package-info.java @@ -1,7 +1,5 @@ /* - * Copyright (c) 2015. - * Created by MrTJP. - * All rights reserved. + * Copyright (c) 2015. Created by MrTJP. All rights reserved. */ @API(owner = "ForgeRelocation", provides = "ForgeRelocation|API", apiVersion = "GRADLETOKEN_VERSION") diff --git a/src/main/scala/mrtjp/relocation/asm/Transformer.scala b/src/main/scala/mrtjp/relocation/asm/Transformer.scala index 05dba89..d7ea2f6 100644 --- a/src/main/scala/mrtjp/relocation/asm/Transformer.scala +++ b/src/main/scala/mrtjp/relocation/asm/Transformer.scala @@ -7,7 +7,9 @@ package mrtjp.relocation.asm import java.util.{Map => JMap} -import cpw.mods.fml.common.asm.transformers.deobf.FMLDeobfuscatingRemapper.{INSTANCE => mapper} +import cpw.mods.fml.common.asm.transformers.deobf.FMLDeobfuscatingRemapper.{ + INSTANCE => mapper +} import cpw.mods.fml.relauncher.{IFMLCallHook, IFMLLoadingPlugin} import mrtjp.relocation.handler.RelocationMod import net.minecraft.launchwrapper.{IClassTransformer, Launch} @@ -17,92 +19,109 @@ import org.objectweb.asm.{ClassReader, ClassWriter} import scala.collection.JavaConversions._ -/** - * Add "Dfml.coreMods.load=mrtjp.relocation.asm.RelocationPlugin" to launch configs - * to enable in a development workspace. - */ +/** Add "Dfml.coreMods.load=mrtjp.relocation.asm.RelocationPlugin" to launch + * configs to enable in a development workspace. + */ @IFMLLoadingPlugin.MCVersion("1.7.10") -@IFMLLoadingPlugin.TransformerExclusions(value = Array("mrtjp.relocation.asm.*", "scala")) -class RelocationPlugin extends IFMLLoadingPlugin with IFMLCallHook -{ - override def getASMTransformerClass = Array("mrtjp.relocation.asm.Transformer") - override def getSetupClass = "mrtjp.relocation.asm.RelocationPlugin" - override def getModContainerClass = null - override def getAccessTransformerClass = null - override def injectData(data:JMap[String, AnyRef]): Unit ={} - override def call():Void = null +@IFMLLoadingPlugin.TransformerExclusions(value = + Array("mrtjp.relocation.asm.*", "scala") +) +class RelocationPlugin extends IFMLLoadingPlugin with IFMLCallHook { + override def getASMTransformerClass = Array( + "mrtjp.relocation.asm.Transformer" + ) + override def getSetupClass = "mrtjp.relocation.asm.RelocationPlugin" + override def getModContainerClass = null + override def getAccessTransformerClass = null + override def injectData(data: JMap[String, AnyRef]): Unit = {} + override def call(): Void = null } -class Transformer extends IClassTransformer -{ - type MethodChecker = (String, MethodNode) => Boolean - type InsTransformer = MethodNode => Unit +class Transformer extends IClassTransformer { + type MethodChecker = (String, MethodNode) => Boolean + type InsTransformer = MethodNode => Unit - lazy val deobfEnv = (Launch.blackboard get "fml.deobfuscatedEnvironment").asInstanceOf[Boolean] - lazy val blockClass = mapper.unmap("net/minecraft/block/Block") - lazy val teClass = mapper.unmap("net/minecraft/tileentity/TileEntity") + lazy val deobfEnv = + (Launch.blackboard get "fml.deobfuscatedEnvironment").asInstanceOf[Boolean] + lazy val blockClass = mapper.unmap("net/minecraft/block/Block") + lazy val teClass = mapper.unmap("net/minecraft/tileentity/TileEntity") - def transformBlockRender(m:MethodNode) - { - val old = m.instructions.toArray.collectFirst{ case i:MethodInsnNode => i }.get - val list = new InsnList - list.add(new VarInsnNode(ILOAD, 2)) - list.add(new VarInsnNode(ILOAD, 3)) - list.add(new VarInsnNode(ILOAD, 4)) - list.add(new MethodInsnNode(INVOKESTATIC, "mrtjp/relocation/ASMHacks", - "getRenderType", "(Lnet/minecraft/block/Block;III)I", false)) - m.instructions.insert(old, list) - m.instructions.remove(old) - } - - def transformTERender(m:MethodNode) - { - val old = m.instructions.toArray.collect{ case i:MethodInsnNode => i }.last - m.instructions.insert(old, new InsnNode(POP)) - m.instructions.insert(old, new MethodInsnNode(INVOKESTATIC, - "mrtjp/relocation/ASMHacks", "renderTileEntityAt", old.desc, false)) - m.instructions.remove(old) - } - - val classData = Map[String, (MethodChecker, MethodChecker, InsTransformer)]( - "net.minecraft.client.renderer.RenderBlocks" -> (( - (_:String, m:MethodNode) => m.name == "renderBlockByRenderType", - (n:String, m:MethodNode) => mapper.mapMethodName(n, m.name, m.desc) == "func_147805_b", - transformBlockRender _ - )), - "net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher" -> (( - (_:String, m:MethodNode) => m.name == "renderTileEntity", - (n:String, m:MethodNode) => mapper.mapMethodName(n, m.name, m.desc) == "func_147544_a", - transformTERender _ - )) + def transformBlockRender(m: MethodNode) { + val old = m.instructions.toArray.collectFirst { case i: MethodInsnNode => + i + }.get + val list = new InsnList + list.add(new VarInsnNode(ILOAD, 2)) + list.add(new VarInsnNode(ILOAD, 3)) + list.add(new VarInsnNode(ILOAD, 4)) + list.add( + new MethodInsnNode( + INVOKESTATIC, + "mrtjp/relocation/ASMHacks", + "getRenderType", + "(Lnet/minecraft/block/Block;III)I", + false + ) ) + m.instructions.insert(old, list) + m.instructions.remove(old) + } - var matched = Set[String]() + def transformTERender(m: MethodNode) { + val old = m.instructions.toArray.collect { case i: MethodInsnNode => + i + }.last + m.instructions.insert(old, new InsnNode(POP)) + m.instructions.insert( + old, + new MethodInsnNode( + INVOKESTATIC, + "mrtjp/relocation/ASMHacks", + "renderTileEntityAt", + old.desc, + false + ) + ) + m.instructions.remove(old) + } - override def transform(name:String, tName:String, data:Array[Byte]) = - { - if (classData.keys.contains(tName) && !matched.contains(tName)) - { - RelocationMod.log.info(s"transforming: $tName") - val (ch1, ch2, tr) = classData(tName) + val classData = Map[String, (MethodChecker, MethodChecker, InsTransformer)]( + "net.minecraft.client.renderer.RenderBlocks" -> (( + (_: String, m: MethodNode) => m.name == "renderBlockByRenderType", + (n: String, m: MethodNode) => + mapper.mapMethodName(n, m.name, m.desc) == "func_147805_b", + transformBlockRender _ + )), + "net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher" -> (( + (_: String, m: MethodNode) => m.name == "renderTileEntity", + (n: String, m: MethodNode) => + mapper.mapMethodName(n, m.name, m.desc) == "func_147544_a", + transformTERender _ + )) + ) - val node = new ClassNode - val reader = new ClassReader(data) - reader.accept(node, 0) + var matched = Set[String]() - for (m@(_m:MethodNode) <- node.methods) - if ((deobfEnv && ch1(name, m)) || (!deobfEnv && ch2(name, m))) - { - RelocationMod.log.info(s"$name $tName ${m.name} ${m.desc}") - tr(m) - } + override def transform(name: String, tName: String, data: Array[Byte]) = { + if (classData.keys.contains(tName) && !matched.contains(tName)) { + RelocationMod.log.info(s"transforming: $tName") + val (ch1, ch2, tr) = classData(tName) - matched += tName + val node = new ClassNode + val reader = new ClassReader(data) + reader.accept(node, 0) - val writer = new ClassWriter(ClassWriter.COMPUTE_MAXS) - node.accept(writer) - writer.toByteArray + for (m @ (_m: MethodNode) <- node.methods) + if ((deobfEnv && ch1(name, m)) || (!deobfEnv && ch2(name, m))) { + RelocationMod.log.info(s"$name $tName ${m.name} ${m.desc}") + tr(m) } - else data - } + + matched += tName + + val writer = new ClassWriter(ClassWriter.COMPUTE_MAXS) + node.accept(writer) + writer.toByteArray + } else data + } } diff --git a/src/main/scala/mrtjp/relocation/blocks.scala b/src/main/scala/mrtjp/relocation/blocks.scala index 4670b03..89877c1 100644 --- a/src/main/scala/mrtjp/relocation/blocks.scala +++ b/src/main/scala/mrtjp/relocation/blocks.scala @@ -18,75 +18,69 @@ import net.minecraft.world.World import scala.collection.JavaConversions._ -class BlockMovingRow extends InstancedBlock("relocation.blockmovingrow", Material.iron) -{ - setHardness(-1F) - setStepSound(Block.soundTypeGravel) - setCreativeTab(null) - addSingleTile(classOf[TileMovingRow]) +class BlockMovingRow + extends InstancedBlock("relocation.blockmovingrow", Material.iron) { + setHardness(-1f) + setStepSound(Block.soundTypeGravel) + setCreativeTab(null) + addSingleTile(classOf[TileMovingRow]) } -object TileMovingRow -{ - def setBlockForRow(w:World, r:BlockRow) - { - w.setBlock(r.pos.x, r.pos.y, r.pos.z, RelocationMod.blockMovingRow, 0, 3) - } - - def getBoxFor(w:World, r:BlockRow, progress:Double):Cuboid6 = - { - val p = r.pos.copy.offset(r.moveDir^1) - val bl = w.getBlock(p.x, p.y, p.z) - - if (bl == RelocationMod.blockMovingRow) return Cuboid6.full.copy() - - bl.getCollisionBoundingBoxFromPool(w, p.x, p.y, p.z) match - { - case aabb:AxisAlignedBB => new Cuboid6(aabb).sub(new Vector3(r.pos)) - .add(new Vector3(BlockCoord.sideOffsets(r.moveDir))*progress) - case _ => Cuboid6.full.copy - } +object TileMovingRow { + def setBlockForRow(w: World, r: BlockRow) { + w.setBlock(r.pos.x, r.pos.y, r.pos.z, RelocationMod.blockMovingRow, 0, 3) + } + + def getBoxFor(w: World, r: BlockRow, progress: Double): Cuboid6 = { + val p = r.pos.copy.offset(r.moveDir ^ 1) + val bl = w.getBlock(p.x, p.y, p.z) + + if (bl == RelocationMod.blockMovingRow) return Cuboid6.full.copy() + + bl.getCollisionBoundingBoxFromPool(w, p.x, p.y, p.z) match { + case aabb: AxisAlignedBB => + new Cuboid6(aabb) + .sub(new Vector3(r.pos)) + .add(new Vector3(BlockCoord.sideOffsets(r.moveDir)) * progress) + case _ => Cuboid6.full.copy } + } } -class TileMovingRow extends InstancedBlockTile -{ - var prevProg = 0.0 +class TileMovingRow extends InstancedBlockTile { + var prevProg = 0.0 - override def update() - { - if (!MovementManager2.isMoving(world, x, y, z)) world.setBlockToAir(x, y, z) + override def update() { + if (!MovementManager2.isMoving(world, x, y, z)) world.setBlockToAir(x, y, z) + } + + override def getBlock = RelocationMod.blockMovingRow + + override def getBlockBounds = { + val s = MovementManager2.getEnclosedStructure(world, x, y, z) + if (s != null) { + val r = s.rows.find(_.contains(x, y, z)).get + TileMovingRow.getBoxFor(world, r, s.progress) + } else Cuboid6.full + } + + override def getCollisionBounds = getBlockBounds + + def pushEntities(r: BlockRow, progress: Double) { + val box = Cuboid6.full.copy + .add(new Vector3(r.preMoveBlocks.head)) + .add(new Vector3(BlockCoord.sideOffsets(r.moveDir)).multiply(progress)) + .toAABB + + val dp = (if (progress >= 1.0) progress + 0.1 else progress) - prevProg + val d = new Vector3(BlockCoord.sideOffsets(r.moveDir)) * dp + world.getEntitiesWithinAABBExcludingEntity(null, box) match { + case list: JList[_] => + for (e <- list.asInstanceOf[JList[Entity]]) + e.moveEntity(d.x, d.y max 0, d.z) + case _ => } - override def getBlock = RelocationMod.blockMovingRow - - override def getBlockBounds = - { - val s = MovementManager2.getEnclosedStructure(world, x, y, z) - if (s != null) - { - val r = s.rows.find(_.contains(x, y, z)).get - TileMovingRow.getBoxFor(world, r, s.progress) - } - else Cuboid6.full - } - - override def getCollisionBounds = getBlockBounds - - def pushEntities(r:BlockRow, progress:Double) - { - val box = Cuboid6.full.copy.add(new Vector3(r.preMoveBlocks.head)) - .add(new Vector3(BlockCoord.sideOffsets(r.moveDir)).multiply(progress)).toAABB - - val dp = (if (progress >= 1.0) progress+0.1 else progress)-prevProg - val d = new Vector3(BlockCoord.sideOffsets(r.moveDir))*dp - world.getEntitiesWithinAABBExcludingEntity(null, box) match - { - case list:JList[_] => - for (e <- list.asInstanceOf[JList[Entity]]) e.moveEntity(d.x, d.y max 0, d.z) - case _ => - } - - prevProg = progress - } -} \ No newline at end of file + prevProg = progress + } +} diff --git a/src/main/scala/mrtjp/relocation/events.scala b/src/main/scala/mrtjp/relocation/events.scala index c8ad494..9db4603 100644 --- a/src/main/scala/mrtjp/relocation/events.scala +++ b/src/main/scala/mrtjp/relocation/events.scala @@ -11,58 +11,48 @@ import mrtjp.relocation.handler.RelocationSPH import net.minecraftforge.client.event.RenderWorldLastEvent import net.minecraftforge.event.world.{ChunkWatchEvent, WorldEvent} -object RelocationEventHandler -{ - @SubscribeEvent - def worldUnload(event:WorldEvent.Unload) - { - RelocationSPH.onWorldUnload(event.world) - MovementManager2.onWorldUnload(event.world) - } +object RelocationEventHandler { + @SubscribeEvent + def worldUnload(event: WorldEvent.Unload) { + RelocationSPH.onWorldUnload(event.world) + MovementManager2.onWorldUnload(event.world) + } - @SubscribeEvent - def chunkWatch(event:ChunkWatchEvent.Watch) - { - RelocationSPH.onChunkWatch(event.player, event.chunk) - } + @SubscribeEvent + def chunkWatch(event: ChunkWatchEvent.Watch) { + RelocationSPH.onChunkWatch(event.player, event.chunk) + } - @SubscribeEvent - def chunkUnwatch(event:ChunkWatchEvent.UnWatch) - { - RelocationSPH.onChunkUnWatch(event.player, event.chunk) - } + @SubscribeEvent + def chunkUnwatch(event: ChunkWatchEvent.UnWatch) { + RelocationSPH.onChunkUnWatch(event.player, event.chunk) + } - @SubscribeEvent - def serverTick(event:TickEvent.ServerTickEvent) - { - if (event.phase == TickEvent.Phase.END) - { - RelocationSPH.onTickEnd() - MovementManager2.onTick(false) - } + @SubscribeEvent + def serverTick(event: TickEvent.ServerTickEvent) { + if (event.phase == TickEvent.Phase.END) { + RelocationSPH.onTickEnd() + MovementManager2.onTick(false) } + } } -object RelocationClientEventHandler -{ - @SubscribeEvent - def onRenderTick(e:TickEvent.RenderTickEvent) - { - if (e.phase == TickEvent.Phase.START) - MovingRenderer.onPreRenderTick(e.renderTickTime) - else MovingRenderer.onPostRenderTick() - } +object RelocationClientEventHandler { + @SubscribeEvent + def onRenderTick(e: TickEvent.RenderTickEvent) { + if (e.phase == TickEvent.Phase.START) + MovingRenderer.onPreRenderTick(e.renderTickTime) + else MovingRenderer.onPostRenderTick() + } - @SubscribeEvent - def onRenderWorld(e:RenderWorldLastEvent) - { - MovingRenderer.onRenderWorldEvent() - } + @SubscribeEvent + def onRenderWorld(e: RenderWorldLastEvent) { + MovingRenderer.onRenderWorldEvent() + } - @SubscribeEvent - def clientTick(event:TickEvent.ClientTickEvent) - { - if (event.phase == TickEvent.Phase.END) - MovementManager2.onTick(true) - } -} \ No newline at end of file + @SubscribeEvent + def clientTick(event: TickEvent.ClientTickEvent) { + if (event.phase == TickEvent.Phase.END) + MovementManager2.onTick(true) + } +} diff --git a/src/main/scala/mrtjp/relocation/hacks.scala b/src/main/scala/mrtjp/relocation/hacks.scala index e997990..e1e378d 100644 --- a/src/main/scala/mrtjp/relocation/hacks.scala +++ b/src/main/scala/mrtjp/relocation/hacks.scala @@ -12,28 +12,53 @@ import net.minecraft.client.Minecraft import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher import net.minecraft.tileentity.TileEntity -object ASMHacks -{ - @SideOnly(Side.CLIENT) - def renderTileEntityAt(te:TileEntity, x:Double, y:Double, z:Double, tick:Float):Unit = - { - if (MovementManager2.isMoving(te.getWorldObj, te.xCoord, te.yCoord, te.zCoord)) - { - val s = MovementManager2.getEnclosedStructure(te.getWorldObj, te.xCoord, te.yCoord, te.zCoord) - val vec = MovingRenderer.renderPos(s, tick) +object ASMHacks { + @SideOnly(Side.CLIENT) + def renderTileEntityAt( + te: TileEntity, + x: Double, + y: Double, + z: Double, + tick: Float + ): Unit = { + if ( + MovementManager2.isMoving(te.getWorldObj, te.xCoord, te.yCoord, te.zCoord) + ) { + val s = MovementManager2.getEnclosedStructure( + te.getWorldObj, + te.xCoord, + te.yCoord, + te.zCoord + ) + val vec = MovingRenderer.renderPos(s, tick) - TileEntityRendererDispatcher.instance.renderTileEntityAt(te, - x+MathLib.clamp(-1F, 1F, vec.x.toFloat), - y+MathLib.clamp(-1F, 1F, vec.y.toFloat), - z+MathLib.clamp(-1F, 1F, vec.z.toFloat), tick) - } - else TileEntityRendererDispatcher.instance.renderTileEntityAt(te, x, y, z, tick) - } + TileEntityRendererDispatcher.instance.renderTileEntityAt( + te, + x + MathLib.clamp(-1f, 1f, vec.x.toFloat), + y + MathLib.clamp(-1f, 1f, vec.y.toFloat), + z + MathLib.clamp(-1f, 1f, vec.z.toFloat), + tick + ) + } else + TileEntityRendererDispatcher.instance.renderTileEntityAt( + te, + x, + y, + z, + tick + ) + } - @SideOnly(Side.CLIENT) - def getRenderType(block:Block, x:Int, y:Int, z:Int):Int = - { - if (MovingRenderer.renderHack && MovementManager2.isMoving(Minecraft.getMinecraft.theWorld, x, y, z)) -1 - else block.getRenderType - } -} \ No newline at end of file + @SideOnly(Side.CLIENT) + def getRenderType(block: Block, x: Int, y: Int, z: Int): Int = { + if ( + MovingRenderer.renderHack && MovementManager2.isMoving( + Minecraft.getMinecraft.theWorld, + x, + y, + z + ) + ) -1 + else block.getRenderType + } +} diff --git a/src/main/scala/mrtjp/relocation/handler/RelocationAPI_Impl.scala b/src/main/scala/mrtjp/relocation/handler/RelocationAPI_Impl.scala index 305939c..80a4918 100644 --- a/src/main/scala/mrtjp/relocation/handler/RelocationAPI_Impl.scala +++ b/src/main/scala/mrtjp/relocation/handler/RelocationAPI_Impl.scala @@ -9,30 +9,30 @@ import mrtjp.relocation.api.{ITileMover, RelocationAPI} import mrtjp.relocation.{MovementManager2, MovingTileRegistry} import net.minecraft.world.World -object RelocationAPI_Impl extends RelocationAPI -{ - var isPreInit = true +object RelocationAPI_Impl extends RelocationAPI { + var isPreInit = true - override def registerTileMover(name:String, desc:String, handler:ITileMover) = - { - assert(isPreInit) - MovingTileRegistry.registerTileMover(name, desc, handler) - } + override def registerTileMover( + name: String, + desc: String, + handler: ITileMover + ) = { + assert(isPreInit) + MovingTileRegistry.registerTileMover(name, desc, handler) + } - override def registerPreferredMover(key:String, value:String) - { - assert(isPreInit) - MovingTileRegistry.preferredMovers :+= (key, value) - } + override def registerPreferredMover(key: String, value: String) { + assert(isPreInit) + MovingTileRegistry.preferredMovers :+= (key, value) + } - override def registerMandatoryMover(key:String, value:String) - { - assert(isPreInit) - MovingTileRegistry.mandatoryMovers :+= (key, value) - } + override def registerMandatoryMover(key: String, value: String) { + assert(isPreInit) + MovingTileRegistry.mandatoryMovers :+= (key, value) + } - override def getRelocator = Relocator_Impl + override def getRelocator = Relocator_Impl - override def isMoving(world:World, x:Int, y:Int, z:Int) = - MovementManager2.isMoving(world, x, y, z) -} \ No newline at end of file + override def isMoving(world: World, x: Int, y: Int, z: Int) = + MovementManager2.isMoving(world, x, y, z) +} diff --git a/src/main/scala/mrtjp/relocation/handler/Relocator_Impl.scala b/src/main/scala/mrtjp/relocation/handler/Relocator_Impl.scala index 33aa4d4..6da38f8 100644 --- a/src/main/scala/mrtjp/relocation/handler/Relocator_Impl.scala +++ b/src/main/scala/mrtjp/relocation/handler/Relocator_Impl.scala @@ -15,107 +15,108 @@ import net.minecraft.world.World import scala.collection.JavaConversions._ import scala.collection.mutable.{Set => MSet, Stack => MStack} -class RelocationRun -{ - var world:World = null - var dir = -1 - var speed = 0.0 - var callback:IMovementCallback = null - val blocks = MSet[BlockCoord]() +class RelocationRun { + var world: World = null + var dir = -1 + var speed = 0.0 + var callback: IMovementCallback = null + val blocks = MSet[BlockCoord]() - def clear() - { - world = null - dir = -1 - speed = 0 - callback = null - blocks.clear() - } + def clear() { + world = null + dir = -1 + speed = 0 + callback = null + blocks.clear() + } } -object Relocator_Impl extends Relocator -{ - var mainStack = new MStack[RelocationRun]() - var tempStack = new MStack[RelocationRun]() +object Relocator_Impl extends Relocator { + var mainStack = new MStack[RelocationRun]() + var tempStack = new MStack[RelocationRun]() - private def assertState() - { - if (mainStack.isEmpty) throw new IllegalStateException("Relocator stack is empty.") - } + private def assertState() { + if (mainStack.isEmpty) + throw new IllegalStateException("Relocator stack is empty.") + } - override def push() - { - val r = if (tempStack.isEmpty) new RelocationRun else tempStack.pop() - mainStack.push(r) - } + override def push() { + val r = if (tempStack.isEmpty) new RelocationRun else tempStack.pop() + mainStack.push(r) + } - override def pop() - { - assertState() - val r = mainStack.pop() - r.clear() - tempStack.push(r) - } + override def pop() { + assertState() + val r = mainStack.pop() + r.clear() + tempStack.push(r) + } - override def setWorld(world:World) - { - assertState() - val top = mainStack.top - if (top.world != null) throw new IllegalStateException("World already set.") - top.world = world - } + override def setWorld(world: World) { + assertState() + val top = mainStack.top + if (top.world != null) throw new IllegalStateException("World already set.") + top.world = world + } - override def setDirection(dir:Int) - { - assertState() - val top = mainStack.top - if (top.dir != -1) throw new IllegalStateException("Direction already set.") - top.dir = dir - } + override def setDirection(dir: Int) { + assertState() + val top = mainStack.top + if (top.dir != -1) throw new IllegalStateException("Direction already set.") + top.dir = dir + } - override def setSpeed(speed:Double) - { - assertState() - val top = mainStack.top - if (top.speed > 0) throw new IllegalStateException("Speed already set.") - top.speed = speed - } + override def setSpeed(speed: Double) { + assertState() + val top = mainStack.top + if (top.speed > 0) throw new IllegalStateException("Speed already set.") + top.speed = speed + } + override def setCallback(callback: IMovementCallback) { + assertState() + val top = mainStack.top + if (top.callback != null) + throw new IllegalStateException("Callback already set.") + top.callback = callback + } - override def setCallback(callback:IMovementCallback) - { - assertState() - val top = mainStack.top - if (top.callback != null) throw new IllegalStateException("Callback already set.") - top.callback = callback - } + override def addBlock(x: Int, y: Int, z: Int) { + assertState() + mainStack.top.blocks += new BlockCoord(x, y, z) + } - override def addBlock(x:Int, y:Int, z:Int) - { - assertState() - mainStack.top.blocks += new BlockCoord(x, y, z) - } + override def addBlock(bc: BlockPos) { + addBlock(bc.x, bc.y, bc.z) + } - override def addBlock(bc:BlockPos) - { - addBlock(bc.x, bc.y, bc.z) - } + override def addBlocks(blocks: JSet[BlockPos]) { + for (b <- blocks) addBlock(b) + } - override def addBlocks(blocks:JSet[BlockPos]) - { - for (b <- blocks) addBlock(b) - } - - override def execute() = - { - assertState() - val top = mainStack.top - if (top.world == null) throw new IllegalStateException("World must be set before move.") - if (top.world.isRemote) throw new IllegalStateException("Movements cannot be executed client-side.") - if (top.dir == -1) throw new IllegalStateException("Direction must be set before move.") - if (top.speed <= 0) throw new IllegalStateException("Speed must be greater than 0.") - if (top.speed >= 1) throw new IllegalStateException("Speed must be less than 1.") - if (top.blocks.isEmpty) throw new IllegalStateException("No blocks queued for move.") - MovementManager2.tryStartMove(top.world, top.blocks.toSet, top.dir, top.speed, top.callback) - } -} \ No newline at end of file + override def execute() = { + assertState() + val top = mainStack.top + if (top.world == null) + throw new IllegalStateException("World must be set before move.") + if (top.world.isRemote) + throw new IllegalStateException( + "Movements cannot be executed client-side." + ) + if (top.dir == -1) + throw new IllegalStateException("Direction must be set before move.") + if (top.speed <= 0) + throw new IllegalStateException("Speed must be greater than 0.") + if (top.speed >= 1) + throw new IllegalStateException("Speed must be less than 1.") + if (top.blocks.isEmpty) + throw new IllegalStateException("No blocks queued for move.") + MovementManager2.tryStartMove( + top.world, + top.blocks.toSet, + top.dir, + top.speed, + top.callback + ) + } +} diff --git a/src/main/scala/mrtjp/relocation/handler/mod.scala b/src/main/scala/mrtjp/relocation/handler/mod.scala index 6e62647..54a5d61 100644 --- a/src/main/scala/mrtjp/relocation/handler/mod.scala +++ b/src/main/scala/mrtjp/relocation/handler/mod.scala @@ -6,94 +6,108 @@ package mrtjp.relocation.handler import cpw.mods.fml.common.Mod -import cpw.mods.fml.common.event.{FMLInitializationEvent, FMLPostInitializationEvent, FMLPreInitializationEvent} +import cpw.mods.fml.common.event.{ + FMLInitializationEvent, + FMLPostInitializationEvent, + FMLPreInitializationEvent +} import mrtjp.core.data.{ModConfig, SpecialConfigGui, TModGuiFactory} import mrtjp.relocation.api._ import mrtjp.relocation.{BlockMovingRow, MovingTileRegistry} import net.minecraft.client.gui.GuiScreen import org.apache.logging.log4j.LogManager -@Mod(modid = RelocationMod.modID, useMetadata = true, modLanguage = "scala", guiFactory = "mrtjp.relocation.handler.GuiConfigFactory", acceptedMinecraftVersions = "[1.7.10]", dependencies = "required-after:MrTJPCoreMod", name = RelocationMod.modName, version = RelocationMod.version) -object RelocationMod -{ - RelocationAPI.instance = RelocationAPI_Impl +@Mod( + modid = RelocationMod.modID, + useMetadata = true, + modLanguage = "scala", + guiFactory = "mrtjp.relocation.handler.GuiConfigFactory", + acceptedMinecraftVersions = "[1.7.10]", + dependencies = "required-after:MrTJPCoreMod", + name = RelocationMod.modName, + version = RelocationMod.version +) +object RelocationMod { + RelocationAPI.instance = RelocationAPI_Impl - final val modID = "ForgeRelocation" - final val modName = "ForgeRelocation" - final val version = "GRADLETOKEN_VERSION" + final val modID = "ForgeRelocation" + final val modName = "ForgeRelocation" + final val version = "GRADLETOKEN_VERSION" - val log = LogManager.getFormatterLogger(modID) + val log = LogManager.getFormatterLogger(modID) - var blockMovingRow:BlockMovingRow = _ + var blockMovingRow: BlockMovingRow = _ - @Mod.EventHandler - def preInit(event:FMLPreInitializationEvent) - { - RelocationProxy.preinit() - } + @Mod.EventHandler + def preInit(event: FMLPreInitializationEvent) { + RelocationProxy.preinit() + } - @Mod.EventHandler - def init(event:FMLInitializationEvent) - { - RelocationAPI_Impl.isPreInit = false - RelocationConfig.loadConfig() - RelocationProxy.init() - } + @Mod.EventHandler + def init(event: FMLInitializationEvent) { + RelocationAPI_Impl.isPreInit = false + RelocationConfig.loadConfig() + RelocationProxy.init() + } - @Mod.EventHandler - def postInit(event:FMLPostInitializationEvent) - { - RelocationProxy.postinit() - } + @Mod.EventHandler + def postInit(event: FMLPostInitializationEvent) { + RelocationProxy.postinit() + } } -class RelocationConfigGui(parent:GuiScreen) extends SpecialConfigGui(parent, "ForgeRelocation", RelocationConfig.config) -class GuiConfigFactory extends TModGuiFactory -{ - override def mainConfigGuiClass() = classOf[RelocationConfigGui] +class RelocationConfigGui(parent: GuiScreen) + extends SpecialConfigGui(parent, "ForgeRelocation", RelocationConfig.config) +class GuiConfigFactory extends TModGuiFactory { + override def mainConfigGuiClass() = classOf[RelocationConfigGui] } -object RelocationConfig extends ModConfig("ForgeRelocation") -{ - var moveLimit = 2048 +object RelocationConfig extends ModConfig("ForgeRelocation") { + var moveLimit = 2048 - var moverMap = Array( - "default -> saveload" + var moverMap = Array( + "default -> saveload" + ) + + override protected def initValues() { + val general = new BaseCategory("General", "Basic settings") + moveLimit = general.put( + "moveLimit", + moveLimit, + "Maximum amount of blocks that can be moved at once." ) - override protected def initValues() - { - val general = new BaseCategory("General", "Basic settings") - moveLimit = general.put("moveLimit", moveLimit, "Maximum amount of blocks that can be moved at once.") + val movers = new BaseCategory("Tile Movers", buildMoverDesc) + moverMap = movers.put("mover registry", moverMap) + moverMap = movers.put( + "mover registry", + MovingTileRegistry.parseAndSetMovers(moverMap), + true + ) + } - val movers = new BaseCategory("Tile Movers", buildMoverDesc) - moverMap = movers.put("mover registry", moverMap) - moverMap = movers.put("mover registry", MovingTileRegistry.parseAndSetMovers(moverMap), true) + def buildMoverDesc: String = { + var s = + "Used to configure which registered Tile Mover is used for a block. Key-Value pairs are defined using \n" + + "the syntax key -> value. \n" + s += "Most blocks are configurable, but some mods may have opted to lock which handlers can be used for its \n" + + "blocks.\n" + s += "Possible keys: \n" + s += " 'default' - to assign default handler. \n" + s += " 'mod:' - to assign every block from a mod. \n" + s += " ':' - to assign block from a mod for every meta. \n" + s += " ':m' - to assign block from mod for specific meta. \n" + + s += "\nAvailable tile movers:\n" + for ((k, v) <- MovingTileRegistry.moverDescMap) + s += " '" + k + "' - " + v + "\n" + + if (MovingTileRegistry.mandatoryMovers.nonEmpty) { + s += "\nMovers locked via API:\n" + for ((k, v) <- MovingTileRegistry.mandatoryMovers) + s += " " + k + " -> " + v + "\n" } - def buildMoverDesc:String = - { - var s = "Used to configure which registered Tile Mover is used for a block. Key-Value pairs are defined using \n" + - "the syntax key -> value. \n" - s += "Most blocks are configurable, but some mods may have opted to lock which handlers can be used for its \n" + - "blocks.\n" - s += "Possible keys: \n" - s += " 'default' - to assign default handler. \n" - s += " 'mod:' - to assign every block from a mod. \n" - s += " ':' - to assign block from a mod for every meta. \n" - s += " ':m' - to assign block from mod for specific meta. \n" - - s += "\nAvailable tile movers:\n" - for ((k, v) <- MovingTileRegistry.moverDescMap) - s += " '"+k+"' - "+v+"\n" - - if (MovingTileRegistry.mandatoryMovers.nonEmpty) - { - s += "\nMovers locked via API:\n" - for ((k, v) <- MovingTileRegistry.mandatoryMovers) - s += " "+k+" -> "+v+"\n" - } - - s - } + s + } } diff --git a/src/main/scala/mrtjp/relocation/handler/network.scala b/src/main/scala/mrtjp/relocation/handler/network.scala index 94a8561..1e4c83a 100644 --- a/src/main/scala/mrtjp/relocation/handler/network.scala +++ b/src/main/scala/mrtjp/relocation/handler/network.scala @@ -10,7 +10,10 @@ import java.util.{LinkedList => JLinkedList, List => JList} import codechicken.lib.data.MCDataOutputWrapper import codechicken.lib.packet.PacketCustom -import codechicken.lib.packet.PacketCustom.{IClientPacketHandler, IServerPacketHandler} +import codechicken.lib.packet.PacketCustom.{ + IClientPacketHandler, + IServerPacketHandler +} import mrtjp.relocation.MovementManager2 import net.minecraft.client.Minecraft import net.minecraft.entity.player.{EntityPlayer, EntityPlayerMP} @@ -21,163 +24,168 @@ import net.minecraft.util.ChatComponentText import net.minecraft.world.{ChunkCoordIntPair, World} import scala.collection.JavaConversions._ -import scala.collection.mutable.{HashMap => MHashMap, Map => MMap, MultiMap => MMultiMap, Set => MSet} - -/** - * Tweaked version of Chickenbones' compressed end-of-tick tile data stream. - */ -class RelocationPH -{ - val channel = RelocationMod +import scala.collection.mutable.{ + HashMap => MHashMap, + Map => MMap, + MultiMap => MMultiMap, + Set => MSet } -object RelocationCPH extends RelocationPH with IClientPacketHandler -{ - def handlePacket(packet: PacketCustom, mc: Minecraft, netHandler:INetHandlerPlayClient) { - try { - packet.getType match { - case 1 => handleChunkDesc(packet, mc.theWorld) - case 2 => handleChunkData(packet, mc.theWorld) - } - } - catch { - case e:RuntimeException if e.getMessage.startsWith("DC: ") => - netHandler.handleDisconnect(new S40PacketDisconnect(new ChatComponentText(e.getMessage.substring(4)))) - } - } - - def handleChunkData(packet:PacketCustom, world:World) - { - var i = packet.readUByte() - while (i != 255) { - MovementManager2.read(world, packet, i) - i = packet.readUByte() - } - } - - def handleChunkDesc(packet:PacketCustom, world:World) - { - MovementManager2.readDesc(world, packet) - } +/** Tweaked version of Chickenbones' compressed end-of-tick tile data stream. + */ +class RelocationPH { + val channel = RelocationMod } -object RelocationSPH extends RelocationPH with IServerPacketHandler -{ - class MCByteStream(bout:ByteArrayOutputStream) extends MCDataOutputWrapper(new DataOutputStream(bout)) - { - def getBytes = bout.toByteArray +object RelocationCPH extends RelocationPH with IClientPacketHandler { + def handlePacket( + packet: PacketCustom, + mc: Minecraft, + netHandler: INetHandlerPlayClient + ) { + try { + packet.getType match { + case 1 => handleChunkDesc(packet, mc.theWorld) + case 2 => handleChunkData(packet, mc.theWorld) + } + } catch { + case e: RuntimeException if e.getMessage.startsWith("DC: ") => + netHandler.handleDisconnect( + new S40PacketDisconnect( + new ChatComponentText(e.getMessage.substring(4)) + ) + ) } + } - override def handlePacket(packetCustom:PacketCustom, entityPlayerMP:EntityPlayerMP, iNetHandlerPlayServer:INetHandlerPlayServer){} + def handleChunkData(packet: PacketCustom, world: World) { + var i = packet.readUByte() + while (i != 255) { + MovementManager2.read(world, packet, i) + i = packet.readUByte() + } + } - private val updateMap = MMap[World, MMap[Set[ChunkCoordIntPair], MCByteStream]]() - private val chunkWatchers = new MHashMap[Int, MSet[ChunkCoordIntPair]] with MMultiMap[Int, ChunkCoordIntPair] - private val newWatchers = MMap[Int, JLinkedList[ChunkCoordIntPair]]() + def handleChunkDesc(packet: PacketCustom, world: World) { + MovementManager2.readDesc(world, packet) + } +} - def onTickEnd() - { +object RelocationSPH extends RelocationPH with IServerPacketHandler { + class MCByteStream(bout: ByteArrayOutputStream) + extends MCDataOutputWrapper(new DataOutputStream(bout)) { + def getBytes = bout.toByteArray + } + + override def handlePacket( + packetCustom: PacketCustom, + entityPlayerMP: EntityPlayerMP, + iNetHandlerPlayServer: INetHandlerPlayServer + ) {} + + private val updateMap = + MMap[World, MMap[Set[ChunkCoordIntPair], MCByteStream]]() + private val chunkWatchers = new MHashMap[Int, MSet[ChunkCoordIntPair]] + with MMultiMap[Int, ChunkCoordIntPair] + private val newWatchers = MMap[Int, JLinkedList[ChunkCoordIntPair]]() + + def onTickEnd() { + val players = getServerPlayers + sendData(players) + sendDesc(players) + } + + def onWorldUnload(world: World) { + if (!world.isRemote) { + updateMap.remove(world) + if (chunkWatchers.nonEmpty) { val players = getServerPlayers - sendData(players) - sendDesc(players) + for (p <- players) + if (p.worldObj.provider.dimensionId == world.provider.dimensionId) + chunkWatchers.remove(p.getEntityId) + } } + } - def onWorldUnload(world:World) - { - if(!world.isRemote) - { - updateMap.remove(world) - if (chunkWatchers.nonEmpty) - { - val players = getServerPlayers - for (p <- players) if (p.worldObj.provider.dimensionId == world.provider.dimensionId) - chunkWatchers.remove(p.getEntityId) - } + def onChunkWatch(p: EntityPlayer, c: ChunkCoordIntPair) { + newWatchers.getOrElseUpdate(p.getEntityId, new JLinkedList).add(c) + } + + def onChunkUnWatch(p: EntityPlayer, c: ChunkCoordIntPair) { + newWatchers.get(p.getEntityId) match { + case Some(chunks) => chunks.remove(c) + case _ => + } + chunkWatchers.removeBinding(p.getEntityId, c) + } + + private def getServerPlayers: Seq[EntityPlayerMP] = + MinecraftServer.getServer.getConfigurationManager.playerEntityList + .asInstanceOf[JList[EntityPlayerMP]] + + private def sendData(players: Seq[EntityPlayerMP]) { + for (p <- players if chunkWatchers.containsKey(p.getEntityId)) { + updateMap.get(p.worldObj) match { + case Some(m) if m.nonEmpty => + val chunks = chunkWatchers(p.getEntityId) + val packet = new PacketCustom(channel, 2).compress() + var send = false + for ((uchunks, stream) <- m if uchunks.exists(chunks.contains)) { + send = true + packet.writeByteArray(stream.getBytes) + packet.writeByte(255) // terminator + } + if (send) packet.sendToPlayer(p) + case _ => + } + } + updateMap.foreach(_._2.clear()) + } + + private def sendDesc(players: Seq[EntityPlayerMP]) { + for (p <- players if newWatchers.containsKey(p.getEntityId)) { + val watched = newWatchers(p.getEntityId) + val pkt = getDescPacket(p.worldObj, watched.toSet) + if (pkt != null) pkt.sendToPlayer(p) + for (c <- watched) + chunkWatchers.addBinding(p.getEntityId, c) + } + newWatchers.clear() + } + + private def getDescPacket( + world: World, + chunks: Set[ChunkCoordIntPair] + ): PacketCustom = { + val packet = new PacketCustom(channel, 1) + if (MovementManager2.writeDesc(world, chunks, packet)) packet else null + } + + def forceSendData() { + sendData(getServerPlayers) + } + + def forceSendDesc() { + sendDesc(getServerPlayers) + } + + def getStream(world: World, chunks: Set[ChunkCoordIntPair], key: Int) = { + updateMap + .getOrElseUpdate( + world, { + if (world.isRemote) + throw new IllegalArgumentException( + "Cannot use RelocationSPH on a client world" + ) + MMap() } - } - - def onChunkWatch(p:EntityPlayer, c:ChunkCoordIntPair) - { - newWatchers.getOrElseUpdate(p.getEntityId, new JLinkedList).add(c) - } - - def onChunkUnWatch(p:EntityPlayer, c:ChunkCoordIntPair) - { - newWatchers.get(p.getEntityId) match - { - case Some(chunks) => chunks.remove(c) - case _ => + ) + .getOrElseUpdate( + chunks, { + val s = new MCByteStream(new ByteArrayOutputStream) + s.writeByte(key) + s } - chunkWatchers.removeBinding(p.getEntityId, c) - } - - private def getServerPlayers:Seq[EntityPlayerMP] = - MinecraftServer.getServer.getConfigurationManager.playerEntityList - .asInstanceOf[JList[EntityPlayerMP]] - - private def sendData(players:Seq[EntityPlayerMP]) - { - for(p <- players if chunkWatchers.containsKey(p.getEntityId)) - { - updateMap.get(p.worldObj) match - { - case Some(m) if m.nonEmpty => - val chunks = chunkWatchers(p.getEntityId) - val packet = new PacketCustom(channel, 2).compress() - var send = false - for((uchunks, stream) <- m if uchunks.exists(chunks.contains)) - { - send = true - packet.writeByteArray(stream.getBytes) - packet.writeByte(255) //terminator - } - if(send) packet.sendToPlayer(p) - case _ => - } - } - updateMap.foreach(_._2.clear()) - } - - private def sendDesc(players:Seq[EntityPlayerMP]) - { - for(p <- players if newWatchers.containsKey(p.getEntityId)) - { - val watched = newWatchers(p.getEntityId) - val pkt = getDescPacket(p.worldObj, watched.toSet) - if(pkt != null) pkt.sendToPlayer(p) - for(c <- watched) - chunkWatchers.addBinding(p.getEntityId, c) - } - newWatchers.clear() - } - - private def getDescPacket(world:World, chunks:Set[ChunkCoordIntPair]):PacketCustom = - { - val packet = new PacketCustom(channel, 1) - if(MovementManager2.writeDesc(world, chunks, packet)) packet else null - } - - def forceSendData() - { - sendData(getServerPlayers) - } - - def forceSendDesc() - { - sendDesc(getServerPlayers) - } - - def getStream(world:World, chunks:Set[ChunkCoordIntPair], key:Int) = - { - updateMap.getOrElseUpdate(world, - { - if(world.isRemote) - throw new IllegalArgumentException("Cannot use RelocationSPH on a client world") - MMap() - }).getOrElseUpdate(chunks, - { - val s = new MCByteStream(new ByteArrayOutputStream) - s.writeByte(key) - s - }) - } -} \ No newline at end of file + ) + } +} diff --git a/src/main/scala/mrtjp/relocation/handler/proxies.scala b/src/main/scala/mrtjp/relocation/handler/proxies.scala index aab33d6..46a76ea 100644 --- a/src/main/scala/mrtjp/relocation/handler/proxies.scala +++ b/src/main/scala/mrtjp/relocation/handler/proxies.scala @@ -12,66 +12,66 @@ import mrtjp.relocation._ import mrtjp.relocation.api.RelocationAPI.{instance => API} import net.minecraftforge.common.MinecraftForge -class RelocationProxy_server -{ - def preinit() - { - RelocationMod.blockMovingRow = new BlockMovingRow +class RelocationProxy_server { + def preinit() { + RelocationMod.blockMovingRow = new BlockMovingRow - API.registerTileMover("saveload", - "Saves the tile and then reloads it in the next position. Reliable but CPU intensive.", - new SaveLoadTileMover) + API.registerTileMover( + "saveload", + "Saves the tile and then reloads it in the next position. Reliable but CPU intensive.", + new SaveLoadTileMover + ) - API.registerTileMover("coordpush", - "Physically changes the location of tiles. Works if tiles do not cache their position.", - new CoordPushTileMover) + API.registerTileMover( + "coordpush", + "Physically changes the location of tiles. Works if tiles do not cache their position.", + new CoordPushTileMover + ) - API.registerTileMover("static", "Setting this disables movement for the specified block.", - new StaticTileMover) + API.registerTileMover( + "static", + "Setting this disables movement for the specified block.", + new StaticTileMover + ) - API.registerPreferredMover("default", "saveload") - API.registerPreferredMover("mod:minecraft", "coordpush") - API.registerPreferredMover("mod:Relocation", "coordpush") - API.registerPreferredMover("mod:ComputerCraft", "coordpush") - API.registerPreferredMover("mod:EnderStorage", "coordpush") - API.registerPreferredMover("mod:ChickenChunks", "coordpush") - API.registerPreferredMover("mod:Translocator", "coordpush") - API.registerPreferredMover("mod:ProjRed|Compatibility", "coordpush") - API.registerPreferredMover("mod:ProjRed|Core", "coordpush") - API.registerPreferredMover("mod:ProjRed|Expansion", "coordpush") - API.registerPreferredMover("mod:ProjRed|Exploration", "coordpush") - API.registerPreferredMover("mod:ProjRed|Fabrication", "coordpush") - API.registerPreferredMover("mod:ProjRed|Illumination", "coordpush") - API.registerPreferredMover("mod:ProjRed|Integration", "coordpush") - API.registerPreferredMover("mod:ProjRed|Transmission", "coordpush") - API.registerPreferredMover("mod:ProjRed|Transportation", "coordpush") - } + API.registerPreferredMover("default", "saveload") + API.registerPreferredMover("mod:minecraft", "coordpush") + API.registerPreferredMover("mod:Relocation", "coordpush") + API.registerPreferredMover("mod:ComputerCraft", "coordpush") + API.registerPreferredMover("mod:EnderStorage", "coordpush") + API.registerPreferredMover("mod:ChickenChunks", "coordpush") + API.registerPreferredMover("mod:Translocator", "coordpush") + API.registerPreferredMover("mod:ProjRed|Compatibility", "coordpush") + API.registerPreferredMover("mod:ProjRed|Core", "coordpush") + API.registerPreferredMover("mod:ProjRed|Expansion", "coordpush") + API.registerPreferredMover("mod:ProjRed|Exploration", "coordpush") + API.registerPreferredMover("mod:ProjRed|Fabrication", "coordpush") + API.registerPreferredMover("mod:ProjRed|Illumination", "coordpush") + API.registerPreferredMover("mod:ProjRed|Integration", "coordpush") + API.registerPreferredMover("mod:ProjRed|Transmission", "coordpush") + API.registerPreferredMover("mod:ProjRed|Transportation", "coordpush") + } - def init() - { - } + def init() {} - def postinit() - { - PacketCustom.assignHandler(RelocationSPH.channel, RelocationSPH) + def postinit() { + PacketCustom.assignHandler(RelocationSPH.channel, RelocationSPH) - FMLCommonHandler.instance.bus.register(RelocationEventHandler) - MinecraftForge.EVENT_BUS.register(RelocationEventHandler) - } + FMLCommonHandler.instance.bus.register(RelocationEventHandler) + MinecraftForge.EVENT_BUS.register(RelocationEventHandler) + } } -class RelocationProxy_client extends RelocationProxy_server -{ - @SideOnly(Side.CLIENT) - override def postinit() - { - super.postinit() - PacketCustom.assignHandler(RelocationCPH.channel, RelocationCPH) +class RelocationProxy_client extends RelocationProxy_server { + @SideOnly(Side.CLIENT) + override def postinit() { + super.postinit() + PacketCustom.assignHandler(RelocationCPH.channel, RelocationCPH) - FMLCommonHandler.instance.bus.register(RelocationClientEventHandler) - MinecraftForge.EVENT_BUS.register(RelocationClientEventHandler) + FMLCommonHandler.instance.bus.register(RelocationClientEventHandler) + MinecraftForge.EVENT_BUS.register(RelocationClientEventHandler) - } + } } -object RelocationProxy extends RelocationProxy_client \ No newline at end of file +object RelocationProxy extends RelocationProxy_client diff --git a/src/main/scala/mrtjp/relocation/movement.scala b/src/main/scala/mrtjp/relocation/movement.scala index 0fc66c8..e1f1adf 100644 --- a/src/main/scala/mrtjp/relocation/movement.scala +++ b/src/main/scala/mrtjp/relocation/movement.scala @@ -18,402 +18,401 @@ import net.minecraft.init.Blocks import net.minecraft.world.{ChunkCoordIntPair, World} import net.minecraftforge.common.DimensionManager -import scala.collection.mutable.{HashMap => MHashMap, MultiMap => MMultiMap, Set => MSet} +import scala.collection.mutable.{ + HashMap => MHashMap, + MultiMap => MMultiMap, + Set => MSet +} import scala.ref.WeakReference -object MovementManager2 -{ - val serverRelocations = MHashMap[Int, WorldStructs]() - val clientRelocations = MHashMap[Int, WorldStructs]() +object MovementManager2 { + val serverRelocations = MHashMap[Int, WorldStructs]() + val clientRelocations = MHashMap[Int, WorldStructs]() - def relocationMap(isClient:Boolean) = if (isClient) clientRelocations else serverRelocations + def relocationMap(isClient: Boolean) = + if (isClient) clientRelocations else serverRelocations - def getWorldStructs(w:World) = - relocationMap(w.isRemote).getOrElseUpdate(w.provider.dimensionId, new WorldStructs) + def getWorldStructs(w: World) = + relocationMap(w.isRemote) + .getOrElseUpdate(w.provider.dimensionId, new WorldStructs) - def getWorld(dim:Int, isClient:Boolean) = - if (!isClient) DimensionManager.getWorld(dim) - else getClientWorld(dim) + def getWorld(dim: Int, isClient: Boolean) = + if (!isClient) DimensionManager.getWorld(dim) + else getClientWorld(dim) - @SideOnly(Side.CLIENT) - private def getClientWorld(dim:Int):World = - { - val w = Minecraft.getMinecraft.theWorld - if (w.provider.dimensionId == dim) w else null + @SideOnly(Side.CLIENT) + private def getClientWorld(dim: Int): World = { + val w = Minecraft.getMinecraft.theWorld + if (w.provider.dimensionId == dim) w else null + } + + def writeDesc(w: World, chunks: Set[ChunkCoordIntPair], out: MCDataOutput) = { + var send = false + for ( + s <- getWorldStructs(w).structs if s.getChunks.exists(chunks.contains) + ) { + send = true + out.writeShort(s.id) + s.writeDesc(out) + } + if (send) out.writeShort(Short.MaxValue) + send + } + + def readDesc(w: World, in: MCDataInput) { + var id = in.readUShort() + while (id != Short.MaxValue) { + val struct = new BlockStruct + struct.id = id + struct.readDesc(in) + addStructToWorld(w, struct) + id = in.readUShort() + } + } + + def read(w: World, in: MCDataInput, key: Int) = key match { + case 1 => + val struct = new BlockStruct + struct.id = in.readUShort() + struct.readDesc(in) + addStructToWorld(w, struct) + for (b <- struct.allBlocks) // rerender all moving blocks + w.func_147479_m(b.x, b.y, b.z) + case 2 => + val id = in.readUShort() + getWorldStructs(w).structs.find(_.id == id) match { + case Some(struct) => clientCycleMove(w, struct) + case None => + throw new RuntimeException( + s"DC: Moving structure with id $id was not found client-side." + ) + } + case _ => + throw new RuntimeException( + s"DC: Packet with ID $key was not handled. " + + s"Skipped ${in.asInstanceOf[PacketCustom].getByteBuf.array().length} bytes." + ) + } + + def sendStruct(w: World, struct: BlockStruct) { + val out = RelocationSPH.getStream(w, struct.getChunks, 1) + out.writeShort(struct.id) + struct.writeDesc(out) + RelocationSPH.forceSendData() + } + + def sendCycle(w: World, struct: BlockStruct) { + RelocationSPH.getStream(w, struct.getChunks, 2).writeShort(struct.id) + RelocationSPH.forceSendData() + } + + def isMoving(w: World, x: Int, y: Int, z: Int) = + getWorldStructs(w).contains(x, y, z) + + def addStructToWorld(w: World, b: BlockStruct) { + getWorldStructs(w).addStruct(b) + b.onAdded(w) + } + + def getEnclosedStructure(w: World, x: Int, y: Int, z: Int) = + getWorldStructs(w).structs.find(_.contains(x, y, z)).orNull + + def tryStartMove( + w: World, + blocks: Set[BlockCoord], + moveDir: Int, + speed: Double, + c: IMovementCallback + ): Boolean = { + if (blocks.size > RelocationConfig.moveLimit) return false + + val map = new MHashMap[(Int, Int), MSet[Int]] + with MMultiMap[(Int, Int), Int] + for (b <- blocks) + map.addBinding(MathLib.normal(b, moveDir), MathLib.basis(b, moveDir)) + + val shift = if ((moveDir & 1) == 1) 1 else -1 + val rowB = Set.newBuilder[BlockRow] + for (normal <- map.keys) { + val line = map(normal).toArray + val sline = + if (shift == 1) line.sorted else line.sorted(Ordering[Int].reverse) + for ((basis, size) <- MathLib.splitLine(sline, shift)) { + val c = MathLib.rhrAxis(moveDir, normal, basis + shift) + rowB += new BlockRow(c, moveDir, size) + } } - def writeDesc(w:World, chunks:Set[ChunkCoordIntPair], out:MCDataOutput) = - { - var send = false - for (s <- getWorldStructs(w).structs if s.getChunks.exists(chunks.contains)) - { - send = true - out.writeShort(s.id) - s.writeDesc(out) + val rows = rowB.result() + if ( + rows.exists(row => + !MovingTileRegistry.canRunOverBlock(w, row.pos.x, row.pos.y, row.pos.z) + ) + ) return false + for (r <- rows) TileMovingRow.setBlockForRow(w, r) + + val struct = new BlockStruct + struct.id = BlockStruct.claimID() + struct.speed = speed + struct.rows = rows + struct.callback = WeakReference(c) + addStructToWorld(w, struct) + sendStruct(w, struct) + + true + } + + def onTick(isClient: Boolean) { + val map = relocationMap(isClient) + for ((dim, ws) <- map) if (ws.nonEmpty) { + ws.pushAll() + val world = getWorld(dim, isClient) + if (world != null) + for (bs <- ws.structs) + for (br <- bs.rows) + br.pushEntities(world, bs.progress) + } + + if (!isClient) { + val fin = map + .map(pair => (pair._1, pair._2.removeFinished())) + .filter(_._2.nonEmpty) + for ((dim, b) <- fin) { + val w = getWorld(dim, false) + if (w != null) for (s <- b) { + cycleMove(w, s) + sendCycle(w, s) } - if (send) out.writeShort(Short.MaxValue) - send + } } + } - def readDesc(w:World, in:MCDataInput) - { - var id = in.readUShort() - while (id != Short.MaxValue) - { - val struct = new BlockStruct - struct.id = id - struct.readDesc(in) - addStructToWorld(w, struct) - id = in.readUShort() - } - } + def onWorldUnload(w: World) { + getWorldStructs(w).clear() + } - def read(w:World, in:MCDataInput, key:Int) = key match - { - case 1 => - val struct = new BlockStruct - struct.id = in.readUShort() - struct.readDesc(in) - addStructToWorld(w, struct) - for (b <- struct.allBlocks) //rerender all moving blocks - w.func_147479_m(b.x, b.y, b.z) - case 2 => - val id = in.readUShort() - getWorldStructs(w).structs.find(_.id == id) match - { - case Some(struct) => clientCycleMove(w, struct) - case None => throw new RuntimeException(s"DC: Moving structure with id $id was not found client-side.") - } - case _ => throw new RuntimeException(s"DC: Packet with ID $key was not handled. " + - s"Skipped ${in.asInstanceOf[PacketCustom].getByteBuf.array().length} bytes.") - } + def clientCycleMove(w: World, struct: BlockStruct) { + getWorldStructs(w).removeStruct(struct) + struct.rows.foreach(_.pushEntities(w, 1.0)) + cycleMove(w, struct) + } - def sendStruct(w:World, struct:BlockStruct) - { - val out = RelocationSPH.getStream(w, struct.getChunks, 1) - out.writeShort(struct.id) - struct.writeDesc(out) - RelocationSPH.forceSendData() - } + def cycleMove(w: World, struct: BlockStruct) { + struct.doMove(w) + struct.postMove(w) + struct.endMove(w) - def sendCycle(w:World, struct:BlockStruct) - { - RelocationSPH.getStream(w, struct.getChunks, 2).writeShort(struct.id) - RelocationSPH.forceSendData() - } + Utils.rescheduleTicks( + w, + struct.preMoveBlocks, + struct.allBlocks, + struct.moveDir + ) - def isMoving(w:World, x:Int, y:Int, z:Int) = getWorldStructs(w).contains(x, y, z) + val changes = MSet[BlockCoord]() + for (r <- struct.rows) r.cacheChanges(w, changes) + for (bc <- changes) + w.notifyBlockOfNeighborChange(bc.x, bc.y, bc.z, Blocks.air) - def addStructToWorld(w:World, b:BlockStruct) - { - getWorldStructs(w).addStruct(b) - b.onAdded(w) - } - - def getEnclosedStructure(w:World, x:Int, y:Int, z:Int) = - getWorldStructs(w).structs.find(_.contains(x, y, z)).orNull - - def tryStartMove(w:World, blocks:Set[BlockCoord], moveDir:Int, speed:Double, c:IMovementCallback):Boolean = - { - if (blocks.size > RelocationConfig.moveLimit) return false - - val map = new MHashMap[(Int, Int), MSet[Int]] with MMultiMap[(Int, Int), Int] - for (b <- blocks) map.addBinding(MathLib.normal(b, moveDir), MathLib.basis(b, moveDir)) - - val shift = if ((moveDir&1) == 1) 1 else -1 - val rowB = Set.newBuilder[BlockRow] - for (normal <- map.keys) - { - val line = map(normal).toArray - val sline = if (shift == 1) line.sorted else line.sorted(Ordering[Int].reverse) - for ((basis, size) <- MathLib.splitLine(sline, shift)) - { - val c = MathLib.rhrAxis(moveDir, normal, basis+shift) - rowB += new BlockRow(c, moveDir, size) - } - } - - val rows = rowB.result() - if (rows.exists(row => !MovingTileRegistry.canRunOverBlock(w, row.pos.x, row.pos.y, row.pos.z))) return false - for (r <- rows) TileMovingRow.setBlockForRow(w, r) - - val struct = new BlockStruct - struct.id = BlockStruct.claimID() - struct.speed = speed - struct.rows = rows - struct.callback = WeakReference(c) - addStructToWorld(w, struct) - sendStruct(w, struct) - - true - } - - def onTick(isClient:Boolean) - { - val map = relocationMap(isClient) - for ((dim, ws) <- map) if (ws.nonEmpty) - { - ws.pushAll() - val world = getWorld(dim, isClient) - if (world != null) for (bs <- ws.structs) for (br <- bs.rows) - br.pushEntities(world, bs.progress) - } - - if (!isClient) - { - val fin = map.map(pair => (pair._1, pair._2.removeFinished())).filter(_._2.nonEmpty) - for ((dim, b) <- fin) - { - val w = getWorld(dim, false) - if (w != null) for (s <- b) - { - cycleMove(w, s) - sendCycle(w, s) - } - } - } - } - - def onWorldUnload(w:World) - { - getWorldStructs(w).clear() - } - - def clientCycleMove(w:World, struct:BlockStruct) - { - getWorldStructs(w).removeStruct(struct) - struct.rows.foreach(_.pushEntities(w, 1.0)) - cycleMove(w, struct) - } - - def cycleMove(w:World, struct:BlockStruct) - { - struct.doMove(w) - struct.postMove(w) - struct.endMove(w) - - Utils.rescheduleTicks(w, struct.preMoveBlocks, struct.allBlocks, struct.moveDir) - - val changes = MSet[BlockCoord]() - for (r <- struct.rows) r.cacheChanges(w, changes) - for (bc <- changes) w.notifyBlockOfNeighborChange(bc.x, bc.y, bc.z, Blocks.air) - - Utils.rerenderBlocks(w, struct.preMoveBlocks) - } + Utils.rerenderBlocks(w, struct.preMoveBlocks) + } } -class WorldStructs -{ - var structs:Set[BlockStruct] = Set.empty +class WorldStructs { + var structs: Set[BlockStruct] = Set.empty - def isEmpty = structs.isEmpty + def isEmpty = structs.isEmpty - def nonEmpty = !isEmpty + def nonEmpty = !isEmpty - def contains(x:Int, y:Int, z:Int) = structs.exists(_.contains(x, y, z)) + def contains(x: Int, y: Int, z: Int) = structs.exists(_.contains(x, y, z)) - def addStruct(b:BlockStruct){ structs += b } + def addStruct(b: BlockStruct) { structs += b } - def pushAll(){ structs.foreach(_.push()) } + def pushAll() { structs.foreach(_.push()) } - def removeFinished() = - { - val finished = structs.filter(_.isFinished) - structs = structs.filterNot(_.isFinished) - finished - } + def removeFinished() = { + val finished = structs.filter(_.isFinished) + structs = structs.filterNot(_.isFinished) + finished + } - def removeStruct(s:BlockStruct) - { - structs = structs.filterNot(_ == s) - } + def removeStruct(s: BlockStruct) { + structs = structs.filterNot(_ == s) + } - def clear(){structs = Set.empty} + def clear() { structs = Set.empty } - def getChunks:Set[ChunkCoordIntPair] = - { - structs.flatMap(_.getChunks) - } + def getChunks: Set[ChunkCoordIntPair] = { + structs.flatMap(_.getChunks) + } } -object BlockStruct -{ - private var maxID = 0 - def claimID() = - { - if (maxID < 32765) maxID += 1//little less than Short.MaxValue (reserved for terminator) - else maxID = 0 - maxID - } +object BlockStruct { + private var maxID = 0 + def claimID() = { + if (maxID < 32765) + maxID += 1 // little less than Short.MaxValue (reserved for terminator) + else maxID = 0 + maxID + } } -class MoveDesc(b:WeakReference[BlockStruct]) extends IMovementDescriptor -{ - def this(b:BlockStruct) = this(new WeakReference(b)) +class MoveDesc(b: WeakReference[BlockStruct]) extends IMovementDescriptor { + def this(b: BlockStruct) = this(new WeakReference(b)) - override def isMoving = b match { - case WeakReference(b:BlockStruct) => !b.isFinished - case _ => false - } + override def isMoving = b match { + case WeakReference(b: BlockStruct) => !b.isFinished + case _ => false + } - override def getProgress = b match { - case WeakReference(b:BlockStruct) => b.progress - case _ => -1 - } + override def getProgress = b match { + case WeakReference(b: BlockStruct) => b.progress + case _ => -1 + } - override def getSize = b match { - case WeakReference(b:BlockStruct) => b.allBlocks.size - case _ => 0 - } + override def getSize = b match { + case WeakReference(b: BlockStruct) => b.allBlocks.size + case _ => 0 + } } -class BlockStruct -{ - var id = -1 - var speed = 1/16D - var rows:Set[BlockRow] = Set.empty - var callback = WeakReference[IMovementCallback](null) +class BlockStruct { + var id = -1 + var speed = 1 / 16d + var rows: Set[BlockRow] = Set.empty + var callback = WeakReference[IMovementCallback](null) - var progress = 0.0D + var progress = 0.0d - lazy val allBlocks = rows.flatMap(_.allBlocks) - lazy val preMoveBlocks = rows.flatMap(_.preMoveBlocks) - lazy val postMoveBlocks = rows.flatMap(_.postMoveBlocks) + lazy val allBlocks = rows.flatMap(_.allBlocks) + lazy val preMoveBlocks = rows.flatMap(_.preMoveBlocks) + lazy val postMoveBlocks = rows.flatMap(_.postMoveBlocks) - def moveDir = rows.head.moveDir + def moveDir = rows.head.moveDir - def contains(x:Int, y:Int, z:Int) = rows.exists(_.contains(x, y, z)) + def contains(x: Int, y: Int, z: Int) = rows.exists(_.contains(x, y, z)) - def push(){ progress = math.min(1.0, progress+speed) } + def push() { progress = math.min(1.0, progress + speed) } - def isFinished = progress >= 1.0D + def isFinished = progress >= 1.0d - def getChunks:Set[ChunkCoordIntPair] = - { - val c = Set.newBuilder[ChunkCoordIntPair] - for (b <- allBlocks) - c += new ChunkCoordIntPair(b.x>>4, b.z>>4) - c.result() + def getChunks: Set[ChunkCoordIntPair] = { + val c = Set.newBuilder[ChunkCoordIntPair] + for (b <- allBlocks) + c += new ChunkCoordIntPair(b.x >> 4, b.z >> 4) + c.result() + } + + def onAdded(w: World) { + if (!w.isRemote) callback match { + case WeakReference(c) => + c.setDescriptor(new MoveDesc(this)) + c.onMovementStarted() + case _ => } + } - def onAdded(w:World) - { - if (!w.isRemote) callback match - { - case WeakReference(c) => - c.setDescriptor(new MoveDesc(this)) - c.onMovementStarted() - case _ => - } - } + def doMove(w: World) { + for (r <- rows) r.doMove(w) + } - def doMove(w:World) - { - for (r <- rows) r.doMove(w) - } + def postMove(w: World) { + for (r <- rows) r.postMove(w) + } - def postMove(w:World) - { - for (r <- rows) r.postMove(w) + def endMove(w: World) { + for (r <- rows) r.endMove(w) + if (!w.isRemote) callback match { + case WeakReference(c) => c.onMovementFinished() + case _ => } + } - def endMove(w:World) - { - for (r <- rows) r.endMove(w) - if (!w.isRemote) callback match - { - case WeakReference(c) => c.onMovementFinished() - case _ => - } - } + override def equals(obj: scala.Any) = obj match { + case that: BlockStruct => id == that.id + case _ => false + } - override def equals(obj:scala.Any) = obj match - { - case that:BlockStruct => id == that.id - case _ => false + def writeDesc(out: MCDataOutput) { + out.writeFloat(progress.toFloat) + out.writeFloat(speed.toFloat) + out.writeByte(rows.size) + for (r <- rows) { + out.writeLong(WorldLib.packCoords(r.pos)) + out.writeByte(r.moveDir) + out.writeShort(r.size) } + } - def writeDesc(out:MCDataOutput) - { - out.writeFloat(progress.toFloat) - out.writeFloat(speed.toFloat) - out.writeByte(rows.size) - for (r <- rows) - { - out.writeLong(WorldLib.packCoords(r.pos)) - out.writeByte(r.moveDir) - out.writeShort(r.size) - } - } - - def readDesc(in:MCDataInput) - { - progress = in.readFloat() - speed = in.readFloat() - val rb = Set.newBuilder[BlockRow] - for (i <- 0 until in.readUByte()) - rb += new BlockRow(WorldLib.unpackCoords(in.readLong()), in.readUByte(), in.readUShort()) - rows = rb.result() - } + def readDesc(in: MCDataInput) { + progress = in.readFloat() + speed = in.readFloat() + val rb = Set.newBuilder[BlockRow] + for (i <- 0 until in.readUByte()) + rb += new BlockRow( + WorldLib.unpackCoords(in.readLong()), + in.readUByte(), + in.readUShort() + ) + rows = rb.result() + } } -class BlockRow(val pos:BlockCoord, val moveDir:Int, val size:Int) -{ - val allBlocks = 0 to size map {i => pos.copy.offset(moveDir^1, i)} - val preMoveBlocks = allBlocks drop 1 - val postMoveBlocks = allBlocks dropRight 1 +class BlockRow(val pos: BlockCoord, val moveDir: Int, val size: Int) { + val allBlocks = 0 to size map { i => pos.copy.offset(moveDir ^ 1, i) } + val preMoveBlocks = allBlocks drop 1 + val postMoveBlocks = allBlocks dropRight 1 - def contains(x:Int, y:Int, z:Int) = - { - import MathLib.{basis, normal, shift} + def contains(x: Int, y: Int, z: Int) = { + import MathLib.{basis, normal, shift} - import math.{max, min} + import math.{max, min} - if (normal(x, y, z, moveDir) == normal(pos, moveDir)) - { - val b1 = basis(pos, moveDir) - val b2 = b1+size*shift(moveDir^1) - min(b1, b2) to max(b1, b2) contains basis(x, y, z, moveDir) - } - else false + if (normal(x, y, z, moveDir) == normal(pos, moveDir)) { + val b1 = basis(pos, moveDir) + val b2 = b1 + size * shift(moveDir ^ 1) + min(b1, b2) to max(b1, b2) contains basis(x, y, z, moveDir) + } else false + } + + def pushEntities(w: World, progress: Double) { + WorldLib.uncheckedGetTileEntity(w, pos.x, pos.y, pos.z) match { + case te: TileMovingRow => te.pushEntities(this, progress) + case _ => } + } - def pushEntities(w:World, progress:Double) - { - WorldLib.uncheckedGetTileEntity(w, pos.x, pos.y, pos.z) match - { - case te:TileMovingRow => te.pushEntities(this, progress) - case _ => - } + def doMove(w: World) { + if (pos.y < 0 || pos.y >= 256) return + + w.removeTileEntity(pos.x, pos.y, pos.z) + WorldLib.uncheckedSetBlock( + w, + pos.x, + pos.y, + pos.z, + Blocks.air, + 0 + ) // Remove movement block + + for (b <- preMoveBlocks) + MovingTileRegistry.move(w, b.x, b.y, b.z, moveDir) + } + + def postMove(w: World) { + for (b <- postMoveBlocks) + MovingTileRegistry.postMove(w, b.x, b.y, b.z) + } + + def endMove(w: World) {} + + def cacheChanges(w: World, changes: MSet[BlockCoord]) { + for (i <- 0 to size) { + val c = pos.copy.offset(moveDir ^ 1, i) + changes += c + for (s <- 0 until 6; s1 <- 0 until 6 if s1 != (s ^ 1)) + changes += c.copy.offset(s).offset(s1) } - - def doMove(w:World) - { - if (pos.y < 0 || pos.y >= 256) return - - w.removeTileEntity(pos.x, pos.y, pos.z) - WorldLib.uncheckedSetBlock(w, pos.x, pos.y, pos.z, Blocks.air, 0) //Remove movement block - - for (b <- preMoveBlocks) - MovingTileRegistry.move(w, b.x, b.y, b.z, moveDir) - } - - def postMove(w:World) - { - for (b <- postMoveBlocks) - MovingTileRegistry.postMove(w, b.x, b.y, b.z) - } - - def endMove(w:World){} - - def cacheChanges(w:World, changes:MSet[BlockCoord]) - { - for (i <- 0 to size) - { - val c = pos.copy.offset(moveDir^1, i) - changes += c - for (s <- 0 until 6; s1 <- 0 until 6 if s1 != (s^1)) - changes += c.copy.offset(s).offset(s1) - } - } -} \ No newline at end of file + } +} diff --git a/src/main/scala/mrtjp/relocation/registry.scala b/src/main/scala/mrtjp/relocation/registry.scala index cb92134..e847b31 100644 --- a/src/main/scala/mrtjp/relocation/registry.scala +++ b/src/main/scala/mrtjp/relocation/registry.scala @@ -20,176 +20,166 @@ import net.minecraft.world.World import scala.collection.immutable.ListMap -object MovingTileRegistry extends ITileMover -{ - val rKeyVal = raw"([^\s]+.+[^\s]+)\s*->\s*([^\s]+.+[^\s]+)".r - val rName = raw"([^\s]+.+[^\s]+)".r - val rNameMetaM = raw"([^\s]+.+[^\s]+)m(\d+)".r - val rMod = raw"mod:([^\s]+.+[^\s]+)".r +object MovingTileRegistry extends ITileMover { + val rKeyVal = raw"([^\s]+.+[^\s]+)\s*->\s*([^\s]+.+[^\s]+)".r + val rName = raw"([^\s]+.+[^\s]+)".r + val rNameMetaM = raw"([^\s]+.+[^\s]+)m(\d+)".r + val rMod = raw"mod:([^\s]+.+[^\s]+)".r - var blockMetaMap = Map[(Block, Int), ITileMover]() - var modMap = Map[String, ITileMover]() + var blockMetaMap = Map[(Block, Int), ITileMover]() + var modMap = Map[String, ITileMover]() - var moverDescMap = Map[String, String]() - var moverNameMap = Map[String, ITileMover]() + var moverDescMap = Map[String, String]() + var moverNameMap = Map[String, ITileMover]() - var defaultMover:ITileMover = _ - var preferredMovers = Seq[(String, String)]() - var mandatoryMovers = Seq[(String, String)]() + var defaultMover: ITileMover = _ + var preferredMovers = Seq[(String, String)]() + var mandatoryMovers = Seq[(String, String)]() - def parseKV(kv:Seq[String]) = kv.map { case rKeyVal(k, v) => (k, v); case s => throw new MatchError(s"Illegal [k -> v] pair: $s") } - def parseBlockMeta(b:String) = b match - { - case rNameMetaM(name, meta) => Block.getBlockFromName(fixName(name)) -> meta.toInt - case rName(name) => Block.getBlockFromName(fixName(name)) -> -1 - case _ => throw new MatchError(s"Illegal set part: $b") - } - def fixName(name:String) = name.indexOf(':') match - { - case -1 => "minecraft:"+name - case i => name + def parseKV(kv: Seq[String]) = kv.map { + case rKeyVal(k, v) => (k, v); + case s => throw new MatchError(s"Illegal [k -> v] pair: $s") + } + def parseBlockMeta(b: String) = b match { + case rNameMetaM(name, meta) => + Block.getBlockFromName(fixName(name)) -> meta.toInt + case rName(name) => Block.getBlockFromName(fixName(name)) -> -1 + case _ => throw new MatchError(s"Illegal set part: $b") + } + def fixName(name: String) = name.indexOf(':') match { + case -1 => "minecraft:" + name + case i => name + } + + def parseAndSetMovers(kv: Seq[String]) = { + var moverMap = ListMap(parseKV(kv): _*) + for ((k, v) <- preferredMovers) + if (!moverMap.contains(k)) moverMap += k -> v + for (pair <- mandatoryMovers) moverMap += pair + moverMap.foreach(h => setMover(h._1, h._2)) + moverMap.map(p => p._1 + " -> " + p._2).toArray + } + + def setMover(that: String, m: String) { + if (!moverNameMap.contains(m)) return + val h = moverNameMap(m) + that match { + case "default" => defaultMover = h + case rMod(mod) if Loader.isModLoaded(mod) => modMap += mod -> h + case _ => blockMetaMap += parseBlockMeta(that) -> h } + } - def parseAndSetMovers(kv:Seq[String]) = - { - var moverMap = ListMap(parseKV(kv):_*) - for ((k, v) <- preferredMovers) if (!moverMap.contains(k)) moverMap += k -> v - for (pair <- mandatoryMovers) moverMap += pair - moverMap.foreach(h => setMover(h._1, h._2)) - moverMap.map(p => p._1+" -> "+p._2).toArray - } + def registerTileMover(name: String, desc: String, m: ITileMover) { + moverDescMap += name -> desc + moverNameMap += name -> m + } - def setMover(that:String, m:String) - { - if (!moverNameMap.contains(m)) return - val h = moverNameMap(m) - that match - { - case "default" => defaultMover = h - case rMod(mod) if Loader.isModLoaded(mod) => modMap += mod -> h - case _ => blockMetaMap += parseBlockMeta(that) -> h - } - } + private def getHandler(b: Block, m: Int) = { + blockMetaMap.getOrElse( + (b, m), + blockMetaMap.getOrElse( + (b, -1), + modMap.getOrElse(BlockLib.getModId(b), defaultMover) + ) + ) + } - def registerTileMover(name:String, desc:String, m:ITileMover) - { - moverDescMap += name -> desc - moverNameMap += name -> m + override def canMove(w: World, x: Int, y: Int, z: Int) = { + val meta = w.getBlockMetadata(x, y, z) + w.getBlock(x, y, z) match { + case block: Block => getHandler(block, meta).canMove(w, x, y, z) + case _ => false } + } - private def getHandler(b:Block, m:Int) = - { - blockMetaMap.getOrElse((b, m), blockMetaMap.getOrElse((b, -1), - modMap.getOrElse(BlockLib.getModId(b), defaultMover))) + override def move(w: World, x: Int, y: Int, z: Int, side: Int) { + val meta = w.getBlockMetadata(x, y, z) + w.getBlock(x, y, z) match { + case block: Block => getHandler(block, meta).move(w, x, y, z, side) + case _ => } + } - override def canMove(w:World, x:Int, y:Int, z:Int) = - { - val meta = w.getBlockMetadata(x, y, z) - w.getBlock(x, y, z) match - { - case block:Block => getHandler(block, meta).canMove(w, x, y, z) - case _ => false - } + override def postMove(w: World, x: Int, y: Int, z: Int) { + val meta = w.getBlockMetadata(x, y, z) + w.getBlock(x, y, z) match { + case block: Block => getHandler(block, meta).postMove(w, x, y, z) + case _ => } + } - override def move(w:World, x:Int, y:Int, z:Int, side:Int) - { - val meta = w.getBlockMetadata(x, y, z) - w.getBlock(x, y, z) match - { - case block:Block => getHandler(block, meta).move(w, x, y, z, side) - case _ => - } - } - - override def postMove(w:World, x:Int, y:Int, z:Int) - { - val meta = w.getBlockMetadata(x, y, z) - w.getBlock(x, y, z) match - { - case block:Block => getHandler(block, meta).postMove(w, x, y, z) - case _ => - } - } - - def canRunOverBlock(w:World, x:Int, y:Int, z:Int) = - { - if (w.blockExists(x, y, z)) - w.isAirBlock(x, y, z) || WorldLib.isBlockSoft(w, x, y, z, w.getBlock(x, y, z)) - else false - } + def canRunOverBlock(w: World, x: Int, y: Int, z: Int) = { + if (w.blockExists(x, y, z)) + w.isAirBlock(x, y, z) || WorldLib.isBlockSoft( + w, + x, + y, + z, + w.getBlock(x, y, z) + ) + else false + } } -class CoordPushTileMover extends ITileMover -{ - override def canMove(w:World, x:Int, y:Int, z:Int) = true +class CoordPushTileMover extends ITileMover { + override def canMove(w: World, x: Int, y: Int, z: Int) = true - override def move(w:World, x:Int, y:Int, z:Int, side:Int) - { - val (b, meta, te) = getBlockInfo(w, x, y, z) - val pos = new BlockCoord(x, y, z).offset(side) - if (te != null) - { - te.invalidate() - uncheckedRemoveTileEntity(w, x, y, z) - } - uncheckedSetBlock(w, x, y, z, Blocks.air, 0) - uncheckedSetBlock(w, pos.x, pos.y, pos.z, b, meta) - if (te != null) - { - te.xCoord = pos.x - te.yCoord = pos.y - te.zCoord = pos.z - te.validate() - uncheckedSetTileEntity(w, pos.x, pos.y, pos.z, te) - } + override def move(w: World, x: Int, y: Int, z: Int, side: Int) { + val (b, meta, te) = getBlockInfo(w, x, y, z) + val pos = new BlockCoord(x, y, z).offset(side) + if (te != null) { + te.invalidate() + uncheckedRemoveTileEntity(w, x, y, z) } + uncheckedSetBlock(w, x, y, z, Blocks.air, 0) + uncheckedSetBlock(w, pos.x, pos.y, pos.z, b, meta) + if (te != null) { + te.xCoord = pos.x + te.yCoord = pos.y + te.zCoord = pos.z + te.validate() + uncheckedSetTileEntity(w, pos.x, pos.y, pos.z, te) + } + } - override def postMove(w:World, x:Int, y:Int, z:Int){} + override def postMove(w: World, x: Int, y: Int, z: Int) {} } -class SaveLoadTileMover extends ITileMover -{ - override def canMove(w:World, x:Int, y:Int, z:Int) = true +class SaveLoadTileMover extends ITileMover { + override def canMove(w: World, x: Int, y: Int, z: Int) = true - override def move(w:World, x:Int, y:Int, z:Int, side:Int) - { - val (b, meta, te) = getBlockInfo(w, x, y, z) - val pos = new BlockCoord(x, y, z).offset(side) - val tag = if (te != null) - { - val tag = new NBTTagCompound - te.writeToNBT(tag) - tag.setInteger("x", pos.x) - tag.setInteger("y", pos.y) - tag.setInteger("z", pos.z) - te.onChunkUnload() - w.removeTileEntity(x, y, z) - tag - } - else null - uncheckedSetBlock(w, x, y, z, Blocks.air, 0) - uncheckedSetBlock(w, pos.x, pos.y, pos.z, b, meta) - if (tag != null) - { - TileEntity.createAndLoadEntity(tag) match - { - case te:TileEntity => - w.getChunkFromBlockCoords(pos.x, pos.z).addTileEntity(te) - case _ => - } - } + override def move(w: World, x: Int, y: Int, z: Int, side: Int) { + val (b, meta, te) = getBlockInfo(w, x, y, z) + val pos = new BlockCoord(x, y, z).offset(side) + val tag = if (te != null) { + val tag = new NBTTagCompound + te.writeToNBT(tag) + tag.setInteger("x", pos.x) + tag.setInteger("y", pos.y) + tag.setInteger("z", pos.z) + te.onChunkUnload() + w.removeTileEntity(x, y, z) + tag + } else null + uncheckedSetBlock(w, x, y, z, Blocks.air, 0) + uncheckedSetBlock(w, pos.x, pos.y, pos.z, b, meta) + if (tag != null) { + TileEntity.createAndLoadEntity(tag) match { + case te: TileEntity => + w.getChunkFromBlockCoords(pos.x, pos.z).addTileEntity(te) + case _ => + } } + } - override def postMove(w:World, x:Int, y:Int, z:Int){} + override def postMove(w: World, x: Int, y: Int, z: Int) {} } -class StaticTileMover extends ITileMover -{ - override def canMove(w:World, x:Int, y:Int, z:Int) = false +class StaticTileMover extends ITileMover { + override def canMove(w: World, x: Int, y: Int, z: Int) = false - override def move(w:World, x:Int, y:Int, z:Int, side:Int){} + override def move(w: World, x: Int, y: Int, z: Int, side: Int) {} - override def postMove(w:World, x:Int, y:Int, z:Int){} -} \ No newline at end of file + override def postMove(w: World, x: Int, y: Int, z: Int) {} +} diff --git a/src/main/scala/mrtjp/relocation/renders.scala b/src/main/scala/mrtjp/relocation/renders.scala index 2ff6b50..02d5ffb 100644 --- a/src/main/scala/mrtjp/relocation/renders.scala +++ b/src/main/scala/mrtjp/relocation/renders.scala @@ -12,164 +12,183 @@ import net.minecraft.block.Block import net.minecraft.client.Minecraft import net.minecraft.client.renderer.texture.TextureMap import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher -import net.minecraft.client.renderer.{OpenGlHelper, RenderBlocks, RenderHelper, Tessellator} +import net.minecraft.client.renderer.{ + OpenGlHelper, + RenderBlocks, + RenderHelper, + Tessellator +} import net.minecraft.world.{EnumSkyBlock, IBlockAccess, World} import net.minecraftforge.common.util.ForgeDirection import org.lwjgl.opengl.GL11._ -object MovingRenderer -{ - var isRendering = false - var renderHack = true +object MovingRenderer { + var isRendering = false + var renderHack = true - private var oldWorld:World = null - private var frame = 0.0f - private var renderBlocks:RenderBlocks = null + private var oldWorld: World = null + private var frame = 0.0f + private var renderBlocks: RenderBlocks = null - private def mc = Minecraft.getMinecraft - private def world = mc.theWorld - private def tes = Tessellator.instance + private def mc = Minecraft.getMinecraft + private def world = mc.theWorld + private def tes = Tessellator.instance - private def render(x:Int, y:Int, z:Int, rpos:Vector3) - { - val oldOcclusion = mc.gameSettings.ambientOcclusion - mc.gameSettings.ambientOcclusion = 0 + private def render(x: Int, y: Int, z: Int, rpos: Vector3) { + val oldOcclusion = mc.gameSettings.ambientOcclusion + mc.gameSettings.ambientOcclusion = 0 - val block = world.getBlock(x, y, z) - if (block == null) return + val block = world.getBlock(x, y, z) + if (block == null) return - val engine = TileEntityRendererDispatcher.instance.field_147553_e - if (engine != null) engine.bindTexture(TextureMap.locationBlocksTexture) - mc.entityRenderer.enableLightmap(frame) + val engine = TileEntityRendererDispatcher.instance.field_147553_e + if (engine != null) engine.bindTexture(TextureMap.locationBlocksTexture) + mc.entityRenderer.enableLightmap(frame) - val light = world.getLightBrightnessForSkyBlocks(x, y, z, block.getLightValue(world, x, y, z)) - val l1 = light%65536 - val l2 = light/65536 + val light = world.getLightBrightnessForSkyBlocks( + x, + y, + z, + block.getLightValue(world, x, y, z) + ) + val l1 = light % 65536 + val l2 = light / 65536 - OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, l1, l2) - glColor4f(0, 0, 0, 0) - RenderHelper.disableStandardItemLighting() - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) - glEnable(GL_BLEND) - glDisable(GL_CULL_FACE) - glShadeModel(if (Minecraft.isAmbientOcclusionEnabled) GL_SMOOTH else GL_FLAT) + OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, l1, l2) + glColor4f(0, 0, 0, 0) + RenderHelper.disableStandardItemLighting() + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) + glEnable(GL_BLEND) + glDisable(GL_CULL_FACE) + glShadeModel( + if (Minecraft.isAmbientOcclusionEnabled) GL_SMOOTH else GL_FLAT + ) - for (pass <- 0 to 1) - { - tes.startDrawingQuads() - tes.setTranslation( - -TileEntityRendererDispatcher.staticPlayerX+MathLib.clamp(-1F, 1F, rpos.x.toFloat), - -TileEntityRendererDispatcher.staticPlayerY+MathLib.clamp(-1F, 1F, rpos.y.toFloat), - -TileEntityRendererDispatcher.staticPlayerZ+MathLib.clamp(-1F, 1F, rpos.z.toFloat)) - tes.setColorOpaque(1, 1, 1) + for (pass <- 0 to 1) { + tes.startDrawingQuads() + tes.setTranslation( + -TileEntityRendererDispatcher.staticPlayerX + MathLib + .clamp(-1f, 1f, rpos.x.toFloat), + -TileEntityRendererDispatcher.staticPlayerY + MathLib + .clamp(-1f, 1f, rpos.y.toFloat), + -TileEntityRendererDispatcher.staticPlayerZ + MathLib.clamp( + -1f, + 1f, + rpos.z.toFloat + ) + ) + tes.setColorOpaque(1, 1, 1) - block.getRenderBlockPass - if (block.canRenderInPass(pass)) - { - renderHack = false - renderBlocks.renderBlockByRenderType(block, x, y, z) - renderHack = true - } + block.getRenderBlockPass + if (block.canRenderInPass(pass)) { + renderHack = false + renderBlocks.renderBlockByRenderType(block, x, y, z) + renderHack = true + } - tes.setTranslation(0, 0, 0) - tes.draw() - } - RenderHelper.enableStandardItemLighting() - mc.entityRenderer.disableLightmap(frame) - mc.gameSettings.ambientOcclusion = oldOcclusion + tes.setTranslation(0, 0, 0) + tes.draw() + } + RenderHelper.enableStandardItemLighting() + mc.entityRenderer.disableLightmap(frame) + mc.gameSettings.ambientOcclusion = oldOcclusion + } + + def onRenderWorldEvent() { + if (oldWorld != world) { + oldWorld = world + renderBlocks = new MovingRenderBlocks(new MovingWorld(world)) + renderBlocks.renderAllFaces = true } - def onRenderWorldEvent() - { - if (oldWorld != world) - { - oldWorld = world - renderBlocks = new MovingRenderBlocks(new MovingWorld(world)) - renderBlocks.renderAllFaces = true - } + for (s <- MovementManager2.getWorldStructs(world).structs) + for (b <- s.preMoveBlocks) + render(b.x, b.y, b.z, renderPos(s, frame)) + } - for (s <- MovementManager2.getWorldStructs(world).structs) for (b <- s.preMoveBlocks) - render(b.x, b.y, b.z, renderPos(s, frame)) - } + def onPreRenderTick(time: Float) { + isRendering = true + frame = time + } - def onPreRenderTick(time:Float) - { - isRendering = true - frame = time - } + def onPostRenderTick() { + isRendering = false + } - def onPostRenderTick() - { - isRendering = false - } - - def renderPos(s:BlockStruct, partial:Float) = - { - new Vector3(BlockCoord.sideOffsets(s.moveDir)) - .multiply(s.progress+s.speed*partial) - } + def renderPos(s: BlockStruct, partial: Float) = { + new Vector3(BlockCoord.sideOffsets(s.moveDir)) + .multiply(s.progress + s.speed * partial) + } } @SideOnly(Side.CLIENT) -class MovingRenderBlocks(w:IBlockAccess) extends RenderBlocks(w) -{ - val eps = 1.0/0x10000 +class MovingRenderBlocks(w: IBlockAccess) extends RenderBlocks(w) { + val eps = 1.0 / 0x10000 - override def renderStandardBlock(block:Block, x:Int, y:Int, z:Int) = - { - if (MovementManager2.isMoving(Minecraft.getMinecraft.theWorld, x, y, z)) - { - if (renderMinX == 0.0D) renderMinX += eps - if (renderMinY == 0.0D) renderMinY += eps - if (renderMinZ == 0.0D) renderMinZ += eps - if (renderMaxX == 1.0D) renderMaxX -= eps - if (renderMaxY == 1.0D) renderMaxY -= eps - if (renderMaxZ == 1.0D) renderMaxZ -= eps - } - super.renderStandardBlock(block, x, y, z) + override def renderStandardBlock(block: Block, x: Int, y: Int, z: Int) = { + if (MovementManager2.isMoving(Minecraft.getMinecraft.theWorld, x, y, z)) { + if (renderMinX == 0.0d) renderMinX += eps + if (renderMinY == 0.0d) renderMinY += eps + if (renderMinZ == 0.0d) renderMinZ += eps + if (renderMaxX == 1.0d) renderMaxX -= eps + if (renderMaxY == 1.0d) renderMaxY -= eps + if (renderMaxZ == 1.0d) renderMaxZ -= eps } + super.renderStandardBlock(block, x, y, z) + } } -class MovingWorld(val world:World) extends IBlockAccess -{ - override def getBlock(x:Int, y:Int, z:Int) = world.getBlock(x, y, z) +class MovingWorld(val world: World) extends IBlockAccess { + override def getBlock(x: Int, y: Int, z: Int) = world.getBlock(x, y, z) - override def getTileEntity(x:Int, y:Int, z:Int) = world.getTileEntity(x, y, z) + override def getTileEntity(x: Int, y: Int, z: Int) = + world.getTileEntity(x, y, z) - def computeLightValue(x:Int, y:Int, z:Int, tpe:EnumSkyBlock) = - { - (for (s <- 0 until 6; c = new BlockCoord(x, y, z).offset(s)) - yield world.getSavedLightValue(tpe, c.x, c.y, c.z)).max + def computeLightValue(x: Int, y: Int, z: Int, tpe: EnumSkyBlock) = { + (for (s <- 0 until 6; c = new BlockCoord(x, y, z).offset(s)) + yield world.getSavedLightValue(tpe, c.x, c.y, c.z)).max + } + + @SideOnly(Side.CLIENT) + override def getLightBrightnessForSkyBlocks( + x: Int, + y: Int, + z: Int, + light: Int + ) = + MovementManager2.isMoving(Minecraft.getMinecraft.theWorld, x, y, z) match { + case true => + val l1 = computeLightValue(x, y, z, EnumSkyBlock.Sky) + val l2 = computeLightValue(x, y, z, EnumSkyBlock.Block) + l1 << 20 | Seq(l2, light).max << 4 + case false => world.getLightBrightnessForSkyBlocks(x, y, z, light) } - @SideOnly(Side.CLIENT) - override def getLightBrightnessForSkyBlocks(x:Int, y:Int, z:Int, light:Int) = - MovementManager2.isMoving(Minecraft.getMinecraft.theWorld, x, y, z) match - { - case true => - val l1 = computeLightValue(x, y, z, EnumSkyBlock.Sky) - val l2 = computeLightValue(x, y, z, EnumSkyBlock.Block) - l1<<20|Seq(l2, light).max<<4 - case false => world.getLightBrightnessForSkyBlocks(x, y, z, light) - } + override def getBlockMetadata(x: Int, y: Int, z: Int) = + world.getBlockMetadata(x, y, z) - override def getBlockMetadata(x:Int, y:Int, z:Int) = world.getBlockMetadata(x, y, z) + @SideOnly(Side.CLIENT) + override def isAirBlock(x: Int, y: Int, z: Int) = world.isAirBlock(x, y, z) - @SideOnly(Side.CLIENT) - override def isAirBlock(x:Int, y:Int, z:Int) = world.isAirBlock(x, y, z) + @SideOnly(Side.CLIENT) + override def getBiomeGenForCoords(x: Int, z: Int) = + world.getBiomeGenForCoords(x, z) - @SideOnly(Side.CLIENT) - override def getBiomeGenForCoords(x:Int, z:Int) = world.getBiomeGenForCoords(x, z) + @SideOnly(Side.CLIENT) + override def getHeight = world.getHeight - @SideOnly(Side.CLIENT) - override def getHeight = world.getHeight + @SideOnly(Side.CLIENT) + override def extendedLevelsInChunkCache() = world.extendedLevelsInChunkCache() - @SideOnly(Side.CLIENT) - override def extendedLevelsInChunkCache() = world.extendedLevelsInChunkCache() + override def isBlockProvidingPowerTo(x: Int, y: Int, z: Int, side: Int) = + world.isBlockProvidingPowerTo(x, y, z, side) - override def isBlockProvidingPowerTo(x:Int, y:Int, z:Int, side:Int) = - world.isBlockProvidingPowerTo(x, y, z, side) - - override def isSideSolid(x:Int, y:Int, z:Int, side:ForgeDirection, _default:Boolean) = - world.isSideSolid(x, y, z, side, _default) -} \ No newline at end of file + override def isSideSolid( + x: Int, + y: Int, + z: Int, + side: ForgeDirection, + _default: Boolean + ) = + world.isSideSolid(x, y, z, side, _default) +} diff --git a/src/main/scala/mrtjp/relocation/util.scala b/src/main/scala/mrtjp/relocation/util.scala index 80fd815..37046d3 100644 --- a/src/main/scala/mrtjp/relocation/util.scala +++ b/src/main/scala/mrtjp/relocation/util.scala @@ -5,7 +5,12 @@ */ package mrtjp.relocation -import java.util.{ArrayList => JAList, List => JList, Set => JSet, TreeSet => JTreeSet} +import java.util.{ + ArrayList => JAList, + List => JList, + Set => JSet, + TreeSet => JTreeSet +} import codechicken.lib.vec.BlockCoord import cpw.mods.fml.common.ObfuscationReflectionHelper @@ -19,78 +24,94 @@ import net.minecraft.world._ import scala.collection.JavaConversions._ import scala.collection.immutable.HashSet -object Utils -{ - def rescheduleTicks(world:World, blocks:Set[BlockCoord], allBlocks:Set[BlockCoord], dir:Int) = world match - { - case world:WorldServer => - val hash = ObfuscationReflectionHelper.getPrivateValue(classOf[WorldServer], world, "field_73064_N", - "pendingTickListEntriesHashSet").asInstanceOf[JSet[NextTickListEntry]] +object Utils { + def rescheduleTicks( + world: World, + blocks: Set[BlockCoord], + allBlocks: Set[BlockCoord], + dir: Int + ) = world match { + case world: WorldServer => + val hash = ObfuscationReflectionHelper + .getPrivateValue( + classOf[WorldServer], + world, + "field_73064_N", + "pendingTickListEntriesHashSet" + ) + .asInstanceOf[JSet[NextTickListEntry]] - val tree = ObfuscationReflectionHelper.getPrivateValue(classOf[WorldServer], world, "field_73065_O", - "pendingTickListEntriesTreeSet").asInstanceOf[JTreeSet[NextTickListEntry]] + val tree = ObfuscationReflectionHelper + .getPrivateValue( + classOf[WorldServer], + world, + "field_73065_O", + "pendingTickListEntriesTreeSet" + ) + .asInstanceOf[JTreeSet[NextTickListEntry]] - val list = ObfuscationReflectionHelper.getPrivateValue(classOf[WorldServer], world, "field_94579_S", - "pendingTickListEntriesThisTick").asInstanceOf[JAList[NextTickListEntry]] + val list = ObfuscationReflectionHelper + .getPrivateValue( + classOf[WorldServer], + world, + "field_94579_S", + "pendingTickListEntriesThisTick" + ) + .asInstanceOf[JAList[NextTickListEntry]] - val isOptifine = world.getClass.getName == "WorldServerOF" + val isOptifine = world.getClass.getName == "WorldServerOF" - val chunks = allBlocks.map(b => world.getChunkFromBlockCoords(b.x, b.z)).filter(_ != null) + val chunks = allBlocks + .map(b => world.getChunkFromBlockCoords(b.x, b.z)) + .filter(_ != null) - val scheduledTicks = chunks.flatMap(ch => world.getPendingBlockUpdates(ch, !isOptifine) - .asInstanceOf[JAList[NextTickListEntry]] match - { - case null => HashSet[NextTickListEntry]() - case tList => tList.toSet - }) - - if (isOptifine) for (tick <- scheduledTicks) - { - tree.remove(tick) - hash.remove(tick) - list.remove(tick) - } - - for (tick <- scheduledTicks) - { - val bc = new BlockCoord(tick.xCoord, tick.yCoord, tick.zCoord) - if (blocks(bc)) - { - bc.offset(dir) - tick.xCoord = bc.x - tick.yCoord = bc.y - tick.zCoord = bc.z - } - } - - for (tick <- scheduledTicks) if (!hash.contains(tick)) - { - hash.add(tick) - tree.add(tick) - } - case _ => - } - - def rerenderBlocks(world:World, blocks:Set[BlockCoord]) - { - if (world.isRemote) - { - val mc = Minecraft.getMinecraft - val teList = mc.renderGlobal.tileEntities.asInstanceOf[JList[TileEntity]] - - for (pass <- 0 to 1) - { - for(c <- blocks; te = world.getTileEntity(c.x, c.y, c.z)) - { - if (te != null) pass match - { - case 0 => teList.remove(te) - case 1 => teList.add(te) - } - mc.renderGlobal.markBlockForRenderUpdate(c.x, c.y, c.z) - } - mc.renderGlobal.updateRenderers(mc.renderViewEntity, false) - } + val scheduledTicks = chunks.flatMap(ch => + world + .getPendingBlockUpdates(ch, !isOptifine) + .asInstanceOf[JAList[NextTickListEntry]] match { + case null => HashSet[NextTickListEntry]() + case tList => tList.toSet } + ) + + if (isOptifine) for (tick <- scheduledTicks) { + tree.remove(tick) + hash.remove(tick) + list.remove(tick) + } + + for (tick <- scheduledTicks) { + val bc = new BlockCoord(tick.xCoord, tick.yCoord, tick.zCoord) + if (blocks(bc)) { + bc.offset(dir) + tick.xCoord = bc.x + tick.yCoord = bc.y + tick.zCoord = bc.z + } + } + + for (tick <- scheduledTicks) if (!hash.contains(tick)) { + hash.add(tick) + tree.add(tick) + } + case _ => + } + + def rerenderBlocks(world: World, blocks: Set[BlockCoord]) { + if (world.isRemote) { + val mc = Minecraft.getMinecraft + val teList = mc.renderGlobal.tileEntities.asInstanceOf[JList[TileEntity]] + + for (pass <- 0 to 1) { + for (c <- blocks; te = world.getTileEntity(c.x, c.y, c.z)) { + if (te != null) pass match { + case 0 => teList.remove(te) + case 1 => teList.add(te) + } + mc.renderGlobal.markBlockForRenderUpdate(c.x, c.y, c.z) + } + mc.renderGlobal.updateRenderers(mc.renderViewEntity, false) + } } -} \ No newline at end of file + } +}