613 lines
16 KiB
Python
613 lines
16 KiB
Python
import materials
|
|
from materials import alphaMaterials
|
|
from numpy import arange, zeros
|
|
|
|
|
|
def genericVerticalFlip(cls):
|
|
rotation = arange(16, dtype='uint8')
|
|
if hasattr(cls, "Up") and hasattr(cls, "Down"):
|
|
rotation[cls.Up] = cls.Down
|
|
rotation[cls.Down] = cls.Up
|
|
|
|
if hasattr(cls, "TopNorth") and hasattr(cls, "TopWest") and hasattr(cls, "TopSouth") and hasattr(cls, "TopEast"):
|
|
rotation[cls.North] = cls.TopNorth
|
|
rotation[cls.West] = cls.TopWest
|
|
rotation[cls.South] = cls.TopSouth
|
|
rotation[cls.East] = cls.TopEast
|
|
rotation[cls.TopNorth] = cls.North
|
|
rotation[cls.TopWest] = cls.West
|
|
rotation[cls.TopSouth] = cls.South
|
|
rotation[cls.TopEast] = cls.East
|
|
|
|
return rotation
|
|
|
|
|
|
def genericRotation(cls):
|
|
rotation = arange(16, dtype='uint8')
|
|
rotation[cls.North] = cls.West
|
|
rotation[cls.West] = cls.South
|
|
rotation[cls.South] = cls.East
|
|
rotation[cls.East] = cls.North
|
|
if hasattr(cls, "TopNorth") and hasattr(cls, "TopWest") and hasattr(cls, "TopSouth") and hasattr(cls, "TopEast"):
|
|
rotation[cls.TopNorth] = cls.TopWest
|
|
rotation[cls.TopWest] = cls.TopSouth
|
|
rotation[cls.TopSouth] = cls.TopEast
|
|
rotation[cls.TopEast] = cls.TopNorth
|
|
|
|
return rotation
|
|
|
|
|
|
def genericEastWestFlip(cls):
|
|
rotation = arange(16, dtype='uint8')
|
|
rotation[cls.West] = cls.East
|
|
rotation[cls.East] = cls.West
|
|
if hasattr(cls, "TopWest") and hasattr(cls, "TopEast"):
|
|
rotation[cls.TopWest] = cls.TopEast
|
|
rotation[cls.TopEast] = cls.TopWest
|
|
|
|
return rotation
|
|
|
|
|
|
def genericNorthSouthFlip(cls):
|
|
rotation = arange(16, dtype='uint8')
|
|
rotation[cls.South] = cls.North
|
|
rotation[cls.North] = cls.South
|
|
if hasattr(cls, "TopNorth") and hasattr(cls, "TopSouth"):
|
|
rotation[cls.TopSouth] = cls.TopNorth
|
|
rotation[cls.TopNorth] = cls.TopSouth
|
|
|
|
return rotation
|
|
|
|
rotationClasses = []
|
|
|
|
def genericFlipRotation(cls):
|
|
cls.rotateLeft = genericRotation(cls)
|
|
|
|
cls.flipVertical = genericVerticalFlip(cls)
|
|
cls.flipEastWest = genericEastWestFlip(cls)
|
|
cls.flipNorthSouth = genericNorthSouthFlip(cls)
|
|
rotationClasses.append(cls)
|
|
return cls
|
|
|
|
|
|
class Torch:
|
|
blocktypes = [
|
|
alphaMaterials.Torch.ID,
|
|
alphaMaterials.RedstoneTorchOn.ID,
|
|
alphaMaterials.RedstoneTorchOff.ID,
|
|
]
|
|
|
|
South = 1
|
|
North = 2
|
|
West = 3
|
|
East = 4
|
|
|
|
genericFlipRotation(Torch)
|
|
|
|
|
|
class Ladder:
|
|
blocktypes = [alphaMaterials.Ladder.ID]
|
|
|
|
East = 2
|
|
West = 3
|
|
North = 4
|
|
South = 5
|
|
genericFlipRotation(Ladder)
|
|
|
|
|
|
class Stair:
|
|
blocktypes = [b.ID for b in alphaMaterials.AllStairs]
|
|
|
|
South = 0
|
|
North = 1
|
|
West = 2
|
|
East = 3
|
|
TopSouth = 4
|
|
TopNorth = 5
|
|
TopWest = 6
|
|
TopEast = 7
|
|
genericFlipRotation(Stair)
|
|
|
|
|
|
class HalfSlab:
|
|
blocktypes = [alphaMaterials.StoneSlab.ID]
|
|
|
|
StoneSlab = 0
|
|
SandstoneSlab = 1
|
|
WoodenSlab = 2
|
|
CobblestoneSlab = 3
|
|
BrickSlab = 4
|
|
StoneBrickSlab = 5
|
|
TopStoneSlab = 8
|
|
TopSandstoneSlab = 9
|
|
TopWoodenSlab = 10
|
|
TopCobblestoneSlab = 11
|
|
TopBrickSlab = 12
|
|
TopStoneBrickSlab = 13
|
|
|
|
HalfSlab.flipVertical = arange(16, dtype='uint8')
|
|
HalfSlab.flipVertical[HalfSlab.StoneSlab] = HalfSlab.TopStoneSlab
|
|
HalfSlab.flipVertical[HalfSlab.SandstoneSlab] = HalfSlab.TopSandstoneSlab
|
|
HalfSlab.flipVertical[HalfSlab.WoodenSlab] = HalfSlab.TopWoodenSlab
|
|
HalfSlab.flipVertical[HalfSlab.CobblestoneSlab] = HalfSlab.TopCobblestoneSlab
|
|
HalfSlab.flipVertical[HalfSlab.BrickSlab] = HalfSlab.TopBrickSlab
|
|
HalfSlab.flipVertical[HalfSlab.StoneBrickSlab] = HalfSlab.TopStoneBrickSlab
|
|
HalfSlab.flipVertical[HalfSlab.TopStoneSlab] = HalfSlab.StoneSlab
|
|
HalfSlab.flipVertical[HalfSlab.TopSandstoneSlab] = HalfSlab.SandstoneSlab
|
|
HalfSlab.flipVertical[HalfSlab.TopWoodenSlab] = HalfSlab.WoodenSlab
|
|
HalfSlab.flipVertical[HalfSlab.TopCobblestoneSlab] = HalfSlab.CobblestoneSlab
|
|
HalfSlab.flipVertical[HalfSlab.TopBrickSlab] = HalfSlab.BrickSlab
|
|
HalfSlab.flipVertical[HalfSlab.TopStoneBrickSlab] = HalfSlab.StoneBrickSlab
|
|
rotationClasses.append(HalfSlab)
|
|
|
|
|
|
class WallSign:
|
|
blocktypes = [alphaMaterials.WallSign.ID]
|
|
|
|
East = 2
|
|
West = 3
|
|
North = 4
|
|
South = 5
|
|
genericFlipRotation(WallSign)
|
|
|
|
|
|
class FurnaceDispenserChest:
|
|
blocktypes = [
|
|
alphaMaterials.Furnace.ID,
|
|
alphaMaterials.LitFurnace.ID,
|
|
alphaMaterials.Dispenser.ID,
|
|
alphaMaterials.Chest.ID,
|
|
]
|
|
East = 2
|
|
West = 3
|
|
North = 4
|
|
South = 5
|
|
genericFlipRotation(FurnaceDispenserChest)
|
|
|
|
|
|
class Pumpkin:
|
|
blocktypes = [
|
|
alphaMaterials.Pumpkin.ID,
|
|
alphaMaterials.JackOLantern.ID,
|
|
]
|
|
|
|
East = 0
|
|
South = 1
|
|
West = 2
|
|
North = 3
|
|
genericFlipRotation(Pumpkin)
|
|
|
|
|
|
class Rail:
|
|
blocktypes = [alphaMaterials.Rail.ID]
|
|
|
|
EastWest = 0
|
|
NorthSouth = 1
|
|
South = 2
|
|
North = 3
|
|
East = 4
|
|
West = 5
|
|
|
|
Northeast = 6
|
|
Southeast = 7
|
|
Southwest = 8
|
|
Northwest = 9
|
|
|
|
|
|
def generic8wayRotation(cls):
|
|
|
|
cls.rotateLeft = genericRotation(cls)
|
|
cls.rotateLeft[cls.Northeast] = cls.Northwest
|
|
cls.rotateLeft[cls.Southeast] = cls.Northeast
|
|
cls.rotateLeft[cls.Southwest] = cls.Southeast
|
|
cls.rotateLeft[cls.Northwest] = cls.Southwest
|
|
|
|
cls.flipEastWest = genericEastWestFlip(cls)
|
|
cls.flipEastWest[cls.Northeast] = cls.Northwest
|
|
cls.flipEastWest[cls.Northwest] = cls.Northeast
|
|
cls.flipEastWest[cls.Southwest] = cls.Southeast
|
|
cls.flipEastWest[cls.Southeast] = cls.Southwest
|
|
|
|
cls.flipNorthSouth = genericNorthSouthFlip(cls)
|
|
cls.flipNorthSouth[cls.Northeast] = cls.Southeast
|
|
cls.flipNorthSouth[cls.Southeast] = cls.Northeast
|
|
cls.flipNorthSouth[cls.Southwest] = cls.Northwest
|
|
cls.flipNorthSouth[cls.Northwest] = cls.Southwest
|
|
rotationClasses.append(cls)
|
|
|
|
generic8wayRotation(Rail)
|
|
Rail.rotateLeft[Rail.NorthSouth] = Rail.EastWest
|
|
Rail.rotateLeft[Rail.EastWest] = Rail.NorthSouth
|
|
|
|
|
|
def applyBit(apply):
|
|
def _applyBit(class_or_array):
|
|
if hasattr(class_or_array, "rotateLeft"):
|
|
for a in (class_or_array.flipEastWest,
|
|
class_or_array.flipNorthSouth,
|
|
class_or_array.rotateLeft):
|
|
apply(a)
|
|
else:
|
|
array = class_or_array
|
|
apply(array)
|
|
|
|
return _applyBit
|
|
|
|
|
|
@applyBit
|
|
def applyBit8(array):
|
|
array[8:16] = array[0:8] | 0x8
|
|
|
|
|
|
@applyBit
|
|
def applyBit4(array):
|
|
array[4:8] = array[0:4] | 0x4
|
|
array[12:16] = array[8:12] | 0x4
|
|
|
|
|
|
@applyBit
|
|
def applyBits48(array):
|
|
array[4:8] = array[0:4] | 0x4
|
|
array[8:16] = array[0:8] | 0x8
|
|
|
|
applyThrownBit = applyBit8
|
|
|
|
|
|
class PoweredDetectorRail(Rail):
|
|
blocktypes = [alphaMaterials.PoweredRail.ID, alphaMaterials.DetectorRail.ID]
|
|
PoweredDetectorRail.rotateLeft = genericRotation(PoweredDetectorRail)
|
|
|
|
PoweredDetectorRail.rotateLeft[PoweredDetectorRail.NorthSouth] = PoweredDetectorRail.EastWest
|
|
PoweredDetectorRail.rotateLeft[PoweredDetectorRail.EastWest] = PoweredDetectorRail.NorthSouth
|
|
|
|
PoweredDetectorRail.flipEastWest = genericEastWestFlip(PoweredDetectorRail)
|
|
PoweredDetectorRail.flipNorthSouth = genericNorthSouthFlip(PoweredDetectorRail)
|
|
applyThrownBit(PoweredDetectorRail)
|
|
rotationClasses.append(PoweredDetectorRail)
|
|
|
|
|
|
class Lever:
|
|
blocktypes = [alphaMaterials.Lever.ID]
|
|
ThrownBit = 0x8
|
|
South = 1
|
|
North = 2
|
|
West = 3
|
|
East = 4
|
|
EastWest = 5
|
|
NorthSouth = 6
|
|
Lever.rotateLeft = genericRotation(Lever)
|
|
Lever.rotateLeft[Lever.NorthSouth] = Lever.EastWest
|
|
Lever.rotateLeft[Lever.EastWest] = Lever.NorthSouth
|
|
Lever.flipEastWest = genericEastWestFlip(Lever)
|
|
Lever.flipNorthSouth = genericNorthSouthFlip(Lever)
|
|
applyThrownBit(Lever)
|
|
rotationClasses.append(Lever)
|
|
|
|
|
|
class Button:
|
|
blocktypes = [alphaMaterials.Button.ID, alphaMaterials.WoodenButton.ID]
|
|
PressedBit = 0x8
|
|
South = 1
|
|
North = 2
|
|
West = 3
|
|
East = 4
|
|
Button.rotateLeft = genericRotation(Button)
|
|
Button.flipEastWest = genericEastWestFlip(Button)
|
|
Button.flipNorthSouth = genericNorthSouthFlip(Button)
|
|
applyThrownBit(Button)
|
|
rotationClasses.append(Button)
|
|
|
|
|
|
class SignPost:
|
|
blocktypes = [alphaMaterials.Sign.ID]
|
|
#west is 0, increasing clockwise
|
|
|
|
rotateLeft = arange(16, dtype='uint8')
|
|
rotateLeft -= 4
|
|
rotateLeft &= 0xf
|
|
|
|
flipEastWest = arange(16, dtype='uint8')
|
|
flipNorthSouth = arange(16, dtype='uint8')
|
|
pass
|
|
|
|
rotationClasses.append(SignPost)
|
|
|
|
|
|
class Bed:
|
|
blocktypes = [alphaMaterials.Bed.ID]
|
|
West = 0
|
|
North = 1
|
|
East = 2
|
|
South = 3
|
|
|
|
genericFlipRotation(Bed)
|
|
applyBit8(Bed)
|
|
applyBit4(Bed)
|
|
|
|
|
|
class Door:
|
|
blocktypes = [
|
|
alphaMaterials.IronDoor.ID,
|
|
alphaMaterials.WoodenDoor.ID,
|
|
]
|
|
TopHalfBit = 0x8
|
|
SwungCCWBit = 0x4
|
|
|
|
Northeast = 0
|
|
Southeast = 1
|
|
Southwest = 2
|
|
Northwest = 3
|
|
|
|
rotateLeft = arange(16, dtype='uint8')
|
|
|
|
Door.rotateLeft[Door.Northeast] = Door.Northwest
|
|
Door.rotateLeft[Door.Southeast] = Door.Northeast
|
|
Door.rotateLeft[Door.Southwest] = Door.Southeast
|
|
Door.rotateLeft[Door.Northwest] = Door.Southwest
|
|
|
|
applyBit4(Door.rotateLeft)
|
|
|
|
#when flipping horizontally, swing the doors so they at least look the same
|
|
|
|
Door.flipEastWest = arange(16, dtype='uint8')
|
|
Door.flipEastWest[Door.Northeast] = Door.Northwest
|
|
Door.flipEastWest[Door.Northwest] = Door.Northeast
|
|
Door.flipEastWest[Door.Southwest] = Door.Southeast
|
|
Door.flipEastWest[Door.Southeast] = Door.Southwest
|
|
Door.flipEastWest[4:8] = Door.flipEastWest[0:4]
|
|
Door.flipEastWest[0:4] = Door.flipEastWest[4:8] | 0x4
|
|
Door.flipEastWest[8:16] = Door.flipEastWest[0:8] | 0x8
|
|
|
|
Door.flipNorthSouth = arange(16, dtype='uint8')
|
|
Door.flipNorthSouth[Door.Northeast] = Door.Southeast
|
|
Door.flipNorthSouth[Door.Northwest] = Door.Southwest
|
|
Door.flipNorthSouth[Door.Southwest] = Door.Northwest
|
|
Door.flipNorthSouth[Door.Southeast] = Door.Northeast
|
|
Door.flipNorthSouth[4:8] = Door.flipNorthSouth[0:4]
|
|
Door.flipNorthSouth[0:4] = Door.flipNorthSouth[4:8] | 0x4
|
|
Door.flipNorthSouth[8:16] = Door.flipNorthSouth[0:8] | 0x8
|
|
|
|
rotationClasses.append(Door)
|
|
|
|
|
|
class RedstoneRepeater:
|
|
blocktypes = [
|
|
alphaMaterials.RedstoneRepeaterOff.ID,
|
|
alphaMaterials.RedstoneRepeaterOn.ID,
|
|
|
|
]
|
|
|
|
East = 0
|
|
South = 1
|
|
West = 2
|
|
North = 3
|
|
|
|
genericFlipRotation(RedstoneRepeater)
|
|
|
|
#high bits of the repeater indicate repeater delay, and should be preserved
|
|
applyBits48(RedstoneRepeater)
|
|
|
|
|
|
class Trapdoor:
|
|
blocktypes = [alphaMaterials.Trapdoor.ID]
|
|
|
|
West = 0
|
|
East = 1
|
|
South = 2
|
|
North = 3
|
|
|
|
genericFlipRotation(Trapdoor)
|
|
applyOpenedBit = applyBit4
|
|
applyOpenedBit(Trapdoor)
|
|
|
|
|
|
class PistonBody:
|
|
blocktypes = [alphaMaterials.StickyPiston.ID, alphaMaterials.Piston.ID]
|
|
|
|
Down = 0
|
|
Up = 1
|
|
East = 2
|
|
West = 3
|
|
North = 4
|
|
South = 5
|
|
|
|
genericFlipRotation(PistonBody)
|
|
applyPistonBit = applyBit8
|
|
applyPistonBit(PistonBody)
|
|
|
|
|
|
class PistonHead(PistonBody):
|
|
blocktypes = [alphaMaterials.PistonHead.ID]
|
|
|
|
rotationClasses.append(PistonHead)
|
|
|
|
|
|
#Mushroom types:
|
|
#Value Description Textures
|
|
#0 Fleshy piece Pores on all sides
|
|
#1 Corner piece Cap texture on top, directions 1 (cloud direction) and 2 (sunrise)
|
|
#2 Side piece Cap texture on top and direction 2 (sunrise)
|
|
#3 Corner piece Cap texture on top, directions 2 (sunrise) and 3 (cloud origin)
|
|
#4 Side piece Cap texture on top and direction 1 (cloud direction)
|
|
#5 Top piece Cap texture on top
|
|
#6 Side piece Cap texture on top and direction 3 (cloud origin)
|
|
#7 Corner piece Cap texture on top, directions 0 (sunset) and 1 (cloud direction)
|
|
#8 Side piece Cap texture on top and direction 0 (sunset)
|
|
#9 Corner piece Cap texture on top, directions 3 (cloud origin) and 0 (sunset)
|
|
#10 Stem piece Stem texture on all four sides, pores on top and bottom
|
|
|
|
|
|
class HugeMushroom:
|
|
blocktypes = [alphaMaterials.HugeRedMushroom.ID, alphaMaterials.HugeBrownMushroom.ID]
|
|
Northeast = 1
|
|
East = 2
|
|
Southeast = 3
|
|
South = 6
|
|
Southwest = 9
|
|
West = 8
|
|
Northwest = 7
|
|
North = 4
|
|
|
|
generic8wayRotation(HugeMushroom)
|
|
|
|
|
|
class Vines:
|
|
blocktypes = [alphaMaterials.Vines.ID]
|
|
|
|
WestBit = 1
|
|
NorthBit = 2
|
|
EastBit = 4
|
|
SouthBit = 8
|
|
|
|
rotateLeft = arange(16, dtype='uint8')
|
|
flipEastWest = arange(16, dtype='uint8')
|
|
flipNorthSouth = arange(16, dtype='uint8')
|
|
|
|
#Hmm... Since each bit is a direction, we can rotate by shifting!
|
|
Vines.rotateLeft = 0xf & ((Vines.rotateLeft >> 1) | (Vines.rotateLeft << 3))
|
|
# Wherever each bit is set, clear it and set the opposite bit
|
|
EastWestBits = (Vines.EastBit | Vines.WestBit)
|
|
Vines.flipEastWest[(Vines.flipEastWest & EastWestBits) > 0] ^= EastWestBits
|
|
|
|
NorthSouthBits = (Vines.NorthBit | Vines.SouthBit)
|
|
Vines.flipNorthSouth[(Vines.flipNorthSouth & NorthSouthBits) > 0] ^= NorthSouthBits
|
|
|
|
rotationClasses.append(Vines)
|
|
|
|
|
|
|
|
class Anvil:
|
|
blocktypes = [alphaMaterials.Anvil.ID]
|
|
|
|
NorthSouth = 0
|
|
WestEast = 1
|
|
|
|
rotateLeft = arange(16, dtype='uint8')
|
|
flipEastWest = arange(16, dtype='uint8')
|
|
flipNorthSouth = arange(16, dtype='uint8')
|
|
|
|
rotateLeft[NorthSouth] = WestEast
|
|
rotateLeft[WestEast] = NorthSouth
|
|
|
|
rotationClasses.append(Anvil)
|
|
|
|
@genericFlipRotation
|
|
class FenceGate:
|
|
blocktypes = [alphaMaterials.FenceGate.ID]
|
|
|
|
South = 0
|
|
West = 1
|
|
North = 2
|
|
East = 3
|
|
|
|
@genericFlipRotation
|
|
class EnderPortal:
|
|
blocktypes = [alphaMaterials.EnderPortal.ID]
|
|
|
|
South = 0
|
|
West = 1
|
|
North = 2
|
|
East = 3
|
|
|
|
@genericFlipRotation
|
|
class CocoaPlant:
|
|
blocktypes = [alphaMaterials.CocoaPlant.ID]
|
|
|
|
North = 0
|
|
East = 1
|
|
South = 2
|
|
West = 3
|
|
|
|
applyBits48(CocoaPlant) # growth state
|
|
|
|
@genericFlipRotation
|
|
class TripwireHook:
|
|
blocktypes = [alphaMaterials.TripwireHook.ID]
|
|
|
|
South = 0
|
|
West = 1
|
|
North = 2
|
|
East = 3
|
|
|
|
applyBits48(TripwireHook) # activation/ready state
|
|
|
|
@genericFlipRotation
|
|
class MobHead:
|
|
blocktypes = [alphaMaterials.MobHead.ID]
|
|
|
|
North = 2
|
|
South = 3
|
|
East = 4
|
|
West = 5
|
|
|
|
@genericFlipRotation
|
|
class Hopper:
|
|
blocktypes = [alphaMaterials.Hopper.ID]
|
|
|
|
South = 2
|
|
North = 3
|
|
East = 4
|
|
West = 5
|
|
|
|
@genericFlipRotation
|
|
class RedstoneComparator:
|
|
blocktypes = [alphaMaterials.RedstoneComparatorInactive.ID, alphaMaterials.RedstoneComparatorActive.ID]
|
|
|
|
South = 0
|
|
West = 1
|
|
North = 2
|
|
East = 3
|
|
|
|
applyBits48(RedstoneComparator)
|
|
|
|
def masterRotationTable(attrname):
|
|
# compute a materials.id_limitx16 table mapping each possible blocktype/data combination to
|
|
# the resulting data when the block is rotated
|
|
table = zeros((materials.id_limit, 16), dtype='uint8')
|
|
table[:] = arange(16, dtype='uint8')
|
|
for cls in rotationClasses:
|
|
if hasattr(cls, attrname):
|
|
blocktable = getattr(cls, attrname)
|
|
for blocktype in cls.blocktypes:
|
|
table[blocktype] = blocktable
|
|
|
|
return table
|
|
|
|
|
|
def rotationTypeTable():
|
|
table = {}
|
|
for cls in rotationClasses:
|
|
for b in cls.blocktypes:
|
|
table[b] = cls
|
|
|
|
return table
|
|
|
|
|
|
class BlockRotation:
|
|
rotateLeft = masterRotationTable("rotateLeft")
|
|
flipEastWest = masterRotationTable("flipEastWest")
|
|
flipNorthSouth = masterRotationTable("flipNorthSouth")
|
|
flipVertical = masterRotationTable("flipVertical")
|
|
typeTable = rotationTypeTable()
|
|
|
|
|
|
def SameRotationType(blocktype1, blocktype2):
|
|
#use different default values for typeTable.get() to make it return false when neither blocktype is present
|
|
return BlockRotation.typeTable.get(blocktype1.ID) == BlockRotation.typeTable.get(blocktype2.ID, BlockRotation)
|
|
|
|
|
|
def FlipVertical(blocks, data):
|
|
data[:] = BlockRotation.flipVertical[blocks, data]
|
|
|
|
|
|
def FlipNorthSouth(blocks, data):
|
|
data[:] = BlockRotation.flipNorthSouth[blocks, data]
|
|
|
|
|
|
def FlipEastWest(blocks, data):
|
|
data[:] = BlockRotation.flipEastWest[blocks, data]
|
|
|
|
|
|
def RotateLeft(blocks, data):
|
|
data[:] = BlockRotation.rotateLeft[blocks, data]
|