[ci skip] spotlessApply with the new settings

This commit is contained in:
Jason Mitchell committed 2023-01-29 11:53:43 -08:00
1 parent da006885b4
commit 79ea033e26
32 files changed
+2133 -2004

No files matched your search

+17 -22
View File
@@ -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")
+238 -173
View File
@@ -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)
}
}
}
+65 -55
View File
@@ -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"
)
)
}
}
+137 -140
View File
@@ -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")
}
}
+70 -67
View File
@@ -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
}
}
+58 -64
View File
@@ -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
}
}
+37 -47
View File
@@ -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)
}
}
+48 -23
View File
@@ -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
+338 -339
View File
@@ -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)
}
}
}
}
}
+135 -145
View File
@@ -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) {}
}
+144 -125
View File
@@ -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)
}
+90 -69
View File
@@ -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)
}
}
}
}
}