mirror of
https://github.com/GTNewHorizons/ForgeRelocation.git
synced 2026-11-08 12:35:07 +00:00
[ci skip] spotlessApply with the new settings
This commit is contained in:
1 parent
da006885b4
commit
79ea033e26
32 files changed
+2133
-2004
No files matched your search
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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.
|
||||
* <br><br>
|
||||
* API class for MCFrames. <br>
|
||||
* <br>
|
||||
* 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);
|
||||
|
||||
@@ -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<BlockPos> getStructure(World world, int x, int y, int z, BlockPos... exclusions);
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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<<s) == 0)
|
||||
b += generateSided(m.copy, s)
|
||||
var b = Seq.newBuilder[CCModel]
|
||||
b += box
|
||||
for (s <- 0 until 6)
|
||||
if ((mask & 1 << s) == 0)
|
||||
b += generateSided(m.copy, s)
|
||||
|
||||
finishModel(combine(b.result()))
|
||||
}
|
||||
finishModel(combine(b.result()))
|
||||
}
|
||||
|
||||
def generateSinglePeg =
|
||||
{
|
||||
val dw = w/2.0
|
||||
val dl = l/2.0
|
||||
def generateSinglePeg = {
|
||||
val dw = w / 2.0
|
||||
val dl = l / 2.0
|
||||
|
||||
val m = quadModel(4)
|
||||
m.verts(0) = new Vertex5( dw, i, -dl, u+dw, v-dl)
|
||||
m.verts(1) = new Vertex5( dw, i, dl, u+dw, v+dl)
|
||||
m.verts(2) = new Vertex5(-dw, i, dl, u-dw, v+dl)
|
||||
m.verts(3) = new Vertex5(-dw, i, -dl, u-dw, v-dl)
|
||||
m.apply(new Translation(u, 0, v))
|
||||
}
|
||||
val m = quadModel(4)
|
||||
m.verts(0) = new Vertex5(dw, i, -dl, u + dw, v - dl)
|
||||
m.verts(1) = new Vertex5(dw, i, dl, u + dw, v + dl)
|
||||
m.verts(2) = new Vertex5(-dw, i, dl, u - dw, v + dl)
|
||||
m.verts(3) = new Vertex5(-dw, i, -dl, u - dw, v - dl)
|
||||
m.apply(new Translation(u, 0, v))
|
||||
}
|
||||
|
||||
def generateQuartRotated(m:CCModel) =
|
||||
{
|
||||
combine(Seq(m, m.copy.apply(Rotation.quarterRotations(1)
|
||||
.at(Vector3.center) `with` new Translation(0, 0.01, 0))))
|
||||
}
|
||||
def generateQuartRotated(m: CCModel) = {
|
||||
combine(
|
||||
Seq(
|
||||
m,
|
||||
m.copy.apply(
|
||||
Rotation
|
||||
.quarterRotations(1)
|
||||
.at(Vector3.center) `with` new Translation(0, 0.01, 0)
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
def generateEightRotated(m:CCModel) =
|
||||
{
|
||||
m.apply(new Rotation(math.Pi/4, 0, 1, 0).at(Vector3.center))
|
||||
}
|
||||
def generateEightRotated(m: CCModel) = {
|
||||
m.apply(new Rotation(math.Pi / 4, 0, 1, 0).at(Vector3.center))
|
||||
}
|
||||
|
||||
def generateBackface(m:CCModel) =
|
||||
{
|
||||
combine(Seq(m, m.backfacedCopy()))
|
||||
}
|
||||
def generateBackface(m: CCModel) = {
|
||||
combine(Seq(m, m.backfacedCopy()))
|
||||
}
|
||||
|
||||
def generateSided(m:CCModel, side:Int) =
|
||||
{
|
||||
m.apply(Rotation.sideRotations(side).at(Vector3.center.copy))
|
||||
}
|
||||
def generateSided(m: CCModel, side: Int) = {
|
||||
m.apply(Rotation.sideRotations(side).at(Vector3.center.copy))
|
||||
}
|
||||
|
||||
def finishModel(m:CCModel) =
|
||||
{
|
||||
m.shrinkUVs(0.0005)
|
||||
m.computeNormals()
|
||||
m.computeLighting(LightModel.standardLightModel)
|
||||
}
|
||||
}
|
||||
def finishModel(m: CCModel) = {
|
||||
m.shrinkUVs(0.0005)
|
||||
m.computeNormals()
|
||||
m.computeLighting(LightModel.standardLightModel)
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,12 @@ import java.util.{Set => 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
@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)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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 += " '<modID>:<blockname>' - to assign block from a mod for every meta. \n"
|
||||
s += " '<modID>:<blockname>m<meta>' - 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 += " '<modID>:<blockname>' - to assign block from a mod for every meta. \n"
|
||||
s += " '<modID>:<blockname>m<meta>' - to assign block from mod for specific meta. \n"
|
||||
s
|
||||
}
|
||||
}
|
||||
@@ -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"
|
||||
))
|
||||
}
|
||||
}
|
||||
object MCFramesRecipes {
|
||||
def initRecipes() {
|
||||
// Frame
|
||||
GameRegistry.addRecipe(
|
||||
new ShapedOreRecipe(
|
||||
new ItemStack(blockFrame, 8),
|
||||
"sls",
|
||||
"lsl",
|
||||
"sls",
|
||||
's': JC,
|
||||
Items.stick,
|
||||
'l': JC,
|
||||
"logWood"
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -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")
|
||||
}
|
||||
}
|
||||
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")
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
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))
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
* <br><br>
|
||||
* Central API class for Relocation. If Relocation is installed, the appropriate field will contain an implementor of
|
||||
* these methods. <br>
|
||||
* <br>
|
||||
* 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:<modID> - to assign every block from a mod
|
||||
* <modID>:<blockname> - to assign block from a mod for every meta
|
||||
* <modID>:<blockname>m<meta> - 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:<modID> - to assign every block from a mod <modID>:<blockname>
|
||||
* - to assign block from a mod for every meta <modID>:<blockname>m<meta> - 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:<modID> - to assign every block from a mod
|
||||
* <modID>:<blockname> - to assign block from a mod for every meta
|
||||
* <modID>:<blockname>m<meta> - 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:<modID> - to assign every block from a mod <modID>:<blockname>
|
||||
* - to assign block from a mod for every meta <modID>:<blockname>m<meta> - 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.
|
||||
*/
|
||||
|
||||
@@ -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<BlockPos> 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();
|
||||
}
|
||||
@@ -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")
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
prevProg = progress
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@SubscribeEvent
|
||||
def clientTick(event: TickEvent.ClientTickEvent) {
|
||||
if (event.phase == TickEvent.Phase.END)
|
||||
MovementManager2.onTick(true)
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@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
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
override def isMoving(world: World, x: Int, y: Int, z: Int) =
|
||||
MovementManager2.isMoving(world, x, y, z)
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
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
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -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:<modID>' - to assign every block from a mod. \n"
|
||||
s += " '<modID>:<blockname>' - to assign block from a mod for every meta. \n"
|
||||
s += " '<modID>:<blockname>m<meta>' - 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:<modID>' - to assign every block from a mod. \n"
|
||||
s += " '<modID>:<blockname>' - to assign block from a mod for every meta. \n"
|
||||
s += " '<modID>:<blockname>m<meta>' - 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
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
})
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
object RelocationProxy extends RelocationProxy_client
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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){}
|
||||
}
|
||||
override def postMove(w: World, x: Int, y: Int, z: Int) {}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
override def isSideSolid(
|
||||
x: Int,
|
||||
y: Int,
|
||||
z: Int,
|
||||
side: ForgeDirection,
|
||||
_default: Boolean
|
||||
) =
|
||||
world.isSideSolid(x, y, z, side, _default)
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user