173 lines
5.1 KiB
Python
173 lines
5.1 KiB
Python
#
|
|
# This script uses RaspberryJamMod's ability to capture all hits, not just sword hits, to provide symmetric
|
|
# drawing. Stand at the center of symmetry. By default, you get north-south and east-west mirroring, but you
|
|
# can include other transformations on the commandline:
|
|
#
|
|
# n : northsouth flip
|
|
# e : east west flip
|
|
# u : up down flip
|
|
# nw : nw - se flip
|
|
# ne : ne - sw flip
|
|
#
|
|
# 90 : 90, 180 and 270 degrees in the plane
|
|
# 180 : 180 degrees in the plane
|
|
#
|
|
# You can do translational symmetry with:
|
|
# t N x y z : translate N-1 times by vector (x,y,z)
|
|
#
|
|
# The transformations are combined in a complicated fashion to generate the list of all applied transformations.
|
|
# Effectively this works like this:
|
|
# 1. The group generated by all the rotations and flips is put into the list.
|
|
# 2. For each translational symmetry "t N x y z", the list is updated as follows: For each transformation F on the list
|
|
# so far, the N-1 transformations lambda (x1,y1,z1) : F(x1,y1,z1) + (kx,ky,kz) are added to the list, for k from 1 to N-1.
|
|
# 3. The identity transformation is removed.
|
|
#
|
|
# Then whenever you draw or erase a block, all the transforms of that block location are are also drawn or erased.
|
|
#
|
|
# For instance, specifying n e t 10 0 1 0 will do north-south and east-west mirroring, plus raising up pillars 10 high on
|
|
# top of whatever you draw. On the other hand, doing t 10 1 0 0 t 10 0 1 0 t 10 0 0 1 will draw 10x10x10 cubes wherever you
|
|
# draw.
|
|
#
|
|
|
|
|
|
#
|
|
# Code by Alexander Pruss under MIT license.
|
|
#
|
|
|
|
from mcpi.minecraft import Minecraft
|
|
import mcpi.block as block
|
|
from functools import partial
|
|
import sys
|
|
import time
|
|
|
|
xn = ( (1,0,0),
|
|
(0,1,0),
|
|
(0,0,-1) )
|
|
xe = ( (-1,0,0),
|
|
(0,1,0),
|
|
(0,0,1) )
|
|
xu = ( (1,0,0),
|
|
(0,-1,0),
|
|
(0,0,-1) )
|
|
xnw = ( (0,0,-1),
|
|
(0,1,0),
|
|
(-1,0,0) )
|
|
xne = ( (0,0,1),
|
|
(0,1,0),
|
|
(1,0,0 ) )
|
|
x90 = ( (0,0,1),
|
|
(0,1,0),
|
|
(-1,0,0) )
|
|
xid = ( (1,0,0),
|
|
(0,1,0),
|
|
(0,0,1) )
|
|
|
|
faces = ( (0,-1,0), (0,1,0), (0,0,-1), (0,0,1), (-1,0,0), (1,0,0), (0,0,0) )
|
|
|
|
def mulMat(a,b):
|
|
return tuple(tuple(a[i][0]*b[0][j]+a[i][1]*b[1][j]+a[i][2]*b[2][j] for j in range(3)) for i in range(3))
|
|
|
|
def mulMatVec(a,b):
|
|
return tuple(a[i][0]*b[0]+a[i][1]*b[1]+a[i][2]*b[2] for i in range(3))
|
|
|
|
def subVec(a,b):
|
|
return tuple(a[i]-b[i] for i in range(3))
|
|
|
|
def addVec(a,b):
|
|
return tuple(a[i]+b[i] for i in range(3))
|
|
|
|
x180 = mulMat(x90,x90)
|
|
|
|
if __name__ == "__main__":
|
|
def copy(v,airOnly=False):
|
|
b = mc.getBlockWithNBT(v)
|
|
if airOnly and b.id != block.AIR.id:
|
|
return
|
|
v1 = addVec(v,(0.5,0.5,0.5))
|
|
for t in transforms:
|
|
mc.setBlockWithNBT(t(v1),b)
|
|
|
|
def err():
|
|
mc.postToChat("Invalid symmetry specification. See symmetry.py comments.")
|
|
exit()
|
|
|
|
mc = Minecraft()
|
|
|
|
playerPos = mc.player.getPos()
|
|
|
|
matrices = set()
|
|
translations = []
|
|
|
|
if len(sys.argv) <= 1:
|
|
matrices.add(xn)
|
|
matrices.add(xe)
|
|
|
|
i = 1
|
|
while i < len(sys.argv):
|
|
opt = sys.argv[i]
|
|
i += 1
|
|
if opt == 't':
|
|
if len(sys.argv) <= i + 3:
|
|
err()
|
|
translations.append((int(sys.argv[i]), float(sys.argv[i+1]), float(sys.argv[i+2]), float(sys.argv[i+3])))
|
|
i += 4
|
|
elif opt == 'n':
|
|
matrices.add(xn)
|
|
elif opt == 'e':
|
|
matrices.add(xe)
|
|
elif opt == 'u':
|
|
matrices.add(xu)
|
|
elif opt == 'nw':
|
|
matrices.add(xnw)
|
|
elif opt == 'ne':
|
|
matrices.add(xne)
|
|
elif opt == '90':
|
|
matrices.add(x90)
|
|
elif opt == '180':
|
|
matrices.add(x180)
|
|
|
|
matrices.add(xid)
|
|
old = set()
|
|
while len(old) < len(matrices):
|
|
old = matrices
|
|
matrices = set()
|
|
for a in old:
|
|
for b in old:
|
|
matrices.add(mulMat(a,b))
|
|
matrices.remove(xid)
|
|
|
|
transforms = []
|
|
matrixApply = lambda v,mat : addVec(mulMatVec(mat,subVec(v,center)),center)
|
|
for m in matrices:
|
|
transforms.append(partial(matrixApply, mat=m))
|
|
|
|
for t in translations:
|
|
add = []
|
|
for k in range(1,t[0]):
|
|
delta = (t[1]*k,t[2]*k,t[3]*k)
|
|
f = partial(addVec,b=delta)
|
|
add.append(f)
|
|
for g in transforms:
|
|
add.append(lambda v,f=f,g=g : f(g(v)))
|
|
transforms += add
|
|
|
|
center = tuple(0.5 * round(2 * x) for x in playerPos)
|
|
|
|
# if (len(matrices) > 0):
|
|
# mc.conn.send("world.spawnParticle", "footstep", center, 0.0,0.0,0.0, 0, 1)
|
|
|
|
mc.conn.send("events.setting","restrict_to_sword",0)
|
|
mc.conn.send("events.setting","detect_left_click",1)
|
|
|
|
mc.postToChat("Will be drawing {} copies".format(1+len(transforms)))
|
|
|
|
mc.events.clearAll()
|
|
|
|
while True:
|
|
hits = mc.events.pollBlockHits()
|
|
time.sleep(0.25)
|
|
for h in hits:
|
|
v = tuple(x for x in h.pos)
|
|
copy(v,airOnly=True)
|
|
copy(addVec(v,faces[h.face]))
|