diff --git a/.gitignore b/.gitignore index ea1974b..7d26eff 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,4 @@ *.out unittest/htmlcov/* *.coverage -parsetab.py \ No newline at end of file +parsetab.py diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..981e692 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,33 @@ +ci: + autofix_commit_msg: "[pre-commit.ci] auto fixes from pre-commit.com hooks" + autofix_prs: true + autoupdate_commit_msg: "[pre-commit.ci] pre-commit autoupdate" + autoupdate_schedule: quarterly + submodules: false + skip: [badgie] + +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.6.0 + hooks: + - id: trailing-whitespace + - id: end-of-file-fixer + - id: check-ast + - id: check-yaml + - id: check-toml + - id: check-merge-conflict + - id: mixed-line-ending + - id: check-case-conflict + - id: sort-simple-yaml + files: .pre-commit-config.yaml + - repo: https://github.com/hadialqattan/pycln + rev: v2.4.0 + hooks: + - id: pycln + args: [--config=pyproject.toml, src] + types: [file] + types_or: [python, pyi] + - repo: https://github.com/psf/black-pre-commit-mirror + rev: 24.3.0 + hooks: + - id: black diff --git a/CompileError.py b/CompileError.py index 0f34308..172125b 100644 --- a/CompileError.py +++ b/CompileError.py @@ -1,3 +1,3 @@ class CompileError(Exception): - def __init__(self, text): - super(Exception, self).__init__(text) \ No newline at end of file + def __init__(self, text): + super(Exception, self).__init__(text) diff --git a/Scripts/archived 1.15 scripts/Atari.cbscript b/Scripts/archived 1.15 scripts/Atari.cbscript index 2fc1889..267c49c 100644 --- a/Scripts/archived 1.15 scripts/Atari.cbscript +++ b/Scripts/archived 1.15 scripts/Atari.cbscript @@ -383,12 +383,12 @@ $BaseCycles = { 0xD8: 2, 0xB8: 2, 0x38: 2, - 0x78: 2, - 0xF8: 2, - 0xEA: 2, - 0xCA: 2, - 0x88: 2, - 0xE8: 2, + 0x78: 2, + 0xF8: 2, + 0xEA: 2, + 0xCA: 2, + 0x88: 2, + 0xE8: 2, 0xC8: 2 } @@ -517,10 +517,10 @@ function global_reset() /kill @Beam /kill @Buffer - + create @Beam 0 0 0 create @Buffer 0 0 0 - + for $addr in $MemoryAddresses /scoreboard objectives add Memory$addr dummy /scoreboard players set Global Memory$addr 0 @@ -530,20 +530,20 @@ function global_reset() /scoreboard objectives add GRP$playerBit$bit dummy end end - + # Fill in the pallete from 0, 0, -8 to 3, 15, -1 for $color_data in $atari_colors $color = $color_data[0] $minlum = $color_data[1] $maxlum = $color_data[2] $material = $color_data[3] - + $y = $color $zmin = $minlum - 8 $zmax = $maxlum - 8 /fill 0 $y $zmin 3 $y $zmax $material end - + # Clear the existing screen /fill 0 0 0 159 100 0 air /fill 0 101 0 159 200 0 air @@ -553,7 +553,7 @@ function global_reset() # Color mode, reset and select buttons released # SWCHB Memory642 = 0b00001011 - + Addr = 0 PC = 0 A = 0 @@ -566,12 +566,12 @@ function global_reset() Negative = False Interrupt = False Decimal = False - + HMOVE = False HMCLR = False RESP0 = False RESP1 = False - + for $player in $range(2) NUSIZ[$player] = 0 GRP[$player] = 0 @@ -579,11 +579,11 @@ function global_reset() PV[$player] = 0 ReflectP[$player] = False end - + VBLANK = True INPT45Control = False Scan = -68 - + # Initialize Palettes from Color 0 Lum 0 COLUPF = 0 /clone 0 0 -8 3 0 -8 0 254 -2 @@ -593,7 +593,7 @@ function global_reset() /clone 0 0 -8 3 0 -8 0 252 -1 COLUP1 = 0 /clone 0 0 -8 3 0 -8 0 253 -1 - + ReflectPF = 0 Clock = 0 ClockRate = 3 @@ -601,36 +601,36 @@ function global_reset() RunProcessor = True GameTicks = 0 Delay = 0 - + Halt = False Step = 0 Frame = 0 FrameSkip = 1 Skipped = 0 MCTick = 0 - + Up = False Down = False Left = False Right = False Button = False LatchedButton = False - + Difficulty0 = 0 Difficulty1 = 0 ColorMode = True SelectSwitch = True ResetSwitch = True - + /tp @Beam 10 250 0 - + StepsPerTick = 500 - + read_whole_rom() get_vectors() PC = Reset # Atari - + as @a draw_controller() end @@ -688,14 +688,14 @@ function check_right_click() @s.right_click = False as create @Marker /tp @s ~ ~ ~ ~ ~ - + # Raycast to find the block on the crosshair for i = 1 to 200 move @s ^ ^ ^2 at @s /particle barrier ~ ~ ~ end - + # Find the lowest x,y,z coordinate in the block at @s unless block ~ ~ ~ air for j = 1 to 256 @@ -717,7 +717,7 @@ function check_right_click() tell @a "Loading ROM at (ROMX), (ROMY), (ROMZ)..." global_reset() end - + /kill @s end end @@ -768,7 +768,7 @@ end function button() WasPressed = Button if WasPressed then Button = False - unless WasPressed + unless WasPressed Button = True LatchedButton = True end @@ -809,15 +809,15 @@ function read_whole_rom() for z = 0 to 0x0F @s.z = ROMZ + z - at @s + at @s # Read Byte val = 0 for $bit in $range(8) $exp = 2 ** $bit if block ~ ~$bit ~ stone do val += $exp - end + end end - + ROM[(z+0xF0)*0x100 + x] = val end end @@ -837,7 +837,7 @@ function read_3bytes_rom(addr) # 6507 only has 13 address pins addr %= 0x2000 addr += 0xE000 - + switch addr case $addr in $range(0xF000, 0xFFFD) $addr2 = $addr+1 @@ -860,7 +860,7 @@ function read_addr(addr) raw_addr = addr # 6507 only has 13 address pins addr %= 0x2000 - + # Atari Stack Mirroring if addr >= 0x100 and addr < 0x200 addr -= 0x100 @@ -868,9 +868,9 @@ function read_addr(addr) if addr == $INSTAT update_clock() end - + $read_mirrors = $"lambda a: [a % 0x10 + i for i in range(0x00, 0x80, 0x10)]" - + switch addr case $addr in $MemoryAddresses /scoreboard players operation Global ReturnValue = Global Memory$addr @@ -916,7 +916,7 @@ function read_addr(addr) unless Down do val += 0x20 unless Left do val += 0x40 unless Right do val += 0x80 - + return val end case $SWCHB @@ -947,7 +947,7 @@ function read_addr(addr) return CXP0P1 * 0x80 + CXM0M1 * 0x40 end end - + if addr == $INTIM update_clock() return Ticks @@ -961,7 +961,7 @@ end clock main /gamerule sendCommandFeedback true /effect give @a night_vision 1000000 0 true - + check_right_click() if GRStep @@ -973,7 +973,7 @@ clock main MCTick++ for step = 0 to StepsPerTick skip = Frame % FrameSkip - + if RunProcessor > 0 read_instruction() get_base_cycles() @@ -1001,7 +1001,7 @@ function read_instruction() Addr = PC read_3bytes_rom(Addr) Instruction = rom1 - + # Get the opcode's function AddrMode = Instruction % 0x20 OpFamily = Instruction / 0x20 @@ -1016,14 +1016,14 @@ function read_instruction() Function = $func end end - + switch Instruction case $op in $OpCodes $func = $OpCodes[$op] Function = $func end end - + switch Function case $LENGTH1LOW to $LENGTH1HIGH OpLength = 1 @@ -1035,7 +1035,7 @@ function read_instruction() OpLength = 3 end end - + Push = 0 Pull = 0 Write = False # Write Byte to instructed memory address @@ -1067,7 +1067,7 @@ function get_addressing_mode() YIndexPost = False Constant = False Accumulator = False - + # Get Non-Standard Addressing Modes switch Instruction case $op in $AddrModes @@ -1086,10 +1086,10 @@ function get_addressing_mode() MemoryOp = False if Function >= $LENGTHVARLOW and Function <= $LENGTHVARHIGH then MemoryOp = True - + # JMP (addr) if Instruction == 0x6C then AddrAbs = True - + if MemoryOp switch AddrMode case 0x01 @@ -1125,7 +1125,7 @@ function get_addressing_mode() AddrZP = True XIndexPre = True Cycles = 4 - + if Instruction == 0x96 XIndexPre = False YIndexPre = True @@ -1146,7 +1146,7 @@ function get_addressing_mode() XIndexPre = True Cycles = 4 if Write then Cycles++ - + if Instruction == 0xBE XIndexPre = False YIndexPre = True @@ -1159,7 +1159,7 @@ function get_addressing_mode() if AddrZP then OpLength = 2 if AddrAbs then OpLength = 3 end - + # Read+write functions take an extra 2 cycles switch Function case $readwrite in [$ASL, $LSR, $ROL, $ROR, $INC, $DEC] @@ -1175,26 +1175,26 @@ function get_pc_data() # Read Operand 1 Addr++ Op1 = rom2 - + if OpLength >= 3 # Read Operand 2 Addr++ Op2 = rom3 - + Op12 = Op2 * 0x100 + Op1 end end - + if Debug display_instruction() end - + if PC == BreakOnExecute tell @a "Executed break point at (Addr). {G[\[Continue\]](/scoreboard players set Global Halt 0) {R[\[Remove Breakpoint\]](/scoreboard players set Global BreakOnExecute -1)" display_instruction() Halt = True end - + PC += OpLength if PC >= 0x10000 then PC -= 0x10000 end @@ -1207,10 +1207,10 @@ function display_instruction() hex_number(X, 12, 2) hex_number(Y, 14, 2) hex_number(Stack, 16, 2) - + # Get the mnemonic for the current instruction mnemonic() - + switch OpLength case 1 tell @a "$(@digit0)(@digit1)(@digit2)(@digit3): (@mnemonic)" @@ -1245,7 +1245,7 @@ function display_instruction() case 3 hex_number(Op1, 4, 2) hex_number(Op2, 6, 2) - + Handled = False if XIndexPre tell @a "$(@digit0)(@digit1)(@digit2)(@digit3): (@mnemonic) $(@digit6)(@digit7)(@digit4)(@digit5),X" @@ -1254,7 +1254,7 @@ function display_instruction() if YIndexPre tell @a "$(@digit0)(@digit1)(@digit2)(@digit3): (@mnemonic) $(@digit6)(@digit7)(@digit4)(@digit5),Y" Handled = True - end + end if not Handled tell @a "$(@digit0)(@digit1)(@digit2)(@digit3): (@mnemonic) $(@digit6)(@digit7)(@digit4)(@digit5)" end @@ -1273,47 +1273,47 @@ function run_branch_instruction() switch Function case $BCC get_pc_data() - + if not Carry then branch() end case $BCS get_pc_data() - + if Carry then branch() end case $BEQ get_pc_data() - + if Zero then branch() end case $BNE get_pc_data() - + if not Zero then branch() end case $BMI get_pc_data() - + if Negative then branch() end case $BPL get_pc_data() - + if not Negative then branch() end case $BVS get_pc_data() - + if Overflow then branch() end case $BVC get_pc_data() - + if not Overflow then branch() end end end - + if Debug and DisplayCycles tell @a "\ (Cycles) cycles" end @@ -1322,19 +1322,19 @@ end function branch() # 1 cycle penalty for branching Cycles++ - + BranchAmount = Op1 if BranchAmount >= 0x80 then BranchAmount -= 0x100 - + OldPage = PC / 0x100 - + PC += BranchAmount - + NewPage = PC / 0x100 - + # Additional 1 cycle penalty for crossing a page boundary unless OldPage == NewPage do Cycles++ - + if PC >= 0x10000 then PC -= 0x10000 if PC < 0 then PC += 0x10000 end @@ -1350,8 +1350,8 @@ function operate_memory_bus() end if Accumulator then Byte = A - if Constant then Byte = Op1 -end + if Constant then Byte = Op1 +end # Move the memory pointer to the direct-addressed memory function move_to_direct_addr() @@ -1374,7 +1374,7 @@ end # Read the direct-addressed memory function read_direct() SavedAddr = Addr - + if Pull Addr++ if Addr >= 0x100 then Addr -= 0x100 @@ -1383,28 +1383,28 @@ function read_direct() if Addr >= 0 Byte2 = -1 Byte = read_addr(Addr) - + if Pull >= 2 Addr++ if Addr >= 0x100 then Addr -= 0x100 Byte2 = read_addr(Addr) - + if Pull == 3 Addr++ if Addr >= 0x100 then Addr -= 0x100 - + Byte3 = read_addr(Addr) end end - + Stack += Pull if Stack >= 0x100 then Stack -= 0x100 - + if Indirect Addr++ Byte2 = read_addr(Addr) end - + if Instruction == 0x6C Addr++ Byte2 = read_addr(Addr) @@ -1412,7 +1412,7 @@ function read_direct() end Addr = SavedAddr - + if Debug and Addr >= 0 hex_number(Addr, 0, 4) hex_number(Byte, 4, 2) @@ -1432,7 +1432,7 @@ function move_to_indirect_addr() if Indirect Addr = Byte2 * 0x100 + Byte if YIndexPost - Addr += Y + Addr += Y if Addr >= 0x10000 then Addr -= 0x10000 end @@ -1443,7 +1443,7 @@ function move_to_indirect_addr() tell @a "\ Memory Indirect Read at Addr $(@digit0)(@digit1)(@digit2)(@digit3) -- Byte: $(@digit4)(@digit5)" clear_digits() end - end + end end # Run processor instructions @@ -1452,14 +1452,14 @@ function run_instruction() DecodeP = False # Decode the processor status bits Compare = -1 # Compare to this value to set N and Z bits TestZN = -1 # Test this value for N and Z bits - + if Function == $BRK GetP = True tell @a "BRK at address (PC) A=(A) X=(X) Y=(Y) S=(Stack) Scan=(@Beam.Scan)" Halt = True end if Function == $PHP then GetP = True - + if GetP P = 0 if Negative then P += 0x80 @@ -1469,28 +1469,28 @@ function run_instruction() if Zero then P += 0x02 if Carry then P += 0x01 end - + switch Function case $ADC operate_memory_bus() - + if Decimal la = A % 0x10 ha = A / 0x10 lb = Byte % 0x10 hb = Byte / 0x10 - + la += lb + Carry Carry = la / 10 la %= 10 - + ha += hb ha += Carry Carry = ha / 10 ha %= 10 A = ha * 0x10 + la end - + unless Decimal SignedA = A if SignedA >= 0x80 then SignedA -= 0x100 @@ -1498,10 +1498,10 @@ function run_instruction() if SignedByte >= 0x80 then SignedByte -= 0x100 SignedA += SignedByte SignedA += Carry - + Overflow = True if SignedA >= -0x80 and SignedA <= 0x7F then Overflow = False - + A += Byte A += Carry Carry = False @@ -1510,42 +1510,42 @@ function run_instruction() A -= 0x100 end end - + TestZN = A end case $AND operate_memory_bus() - + Byte2 = 0 for $exp in [128, 64, 32, 16, 8, 4, 2, 1] if A >= $exp and Byte >= $exp then Byte2 += $exp - + if Byte >= $exp then Byte -= $exp if A >= $exp then A -= $exp end A = Byte2 - + TestZN = A end case $ASL operate_memory_bus() - + Byte *= 2 Carry = False if Byte >= 0x100 Carry = True Byte -= 0x100 end - + TestZN = Byte end case $BIT operate_memory_bus() - + Byte2 = A Zero = True Negative = False - + if Byte2 >= 0x80 # If there are any bits in common, Zero is cleared if Byte >= 0x80 then Zero = False @@ -1561,60 +1561,60 @@ function run_instruction() for $exp in [64, 32, 16, 8, 4, 2, 1] # If there are any bits in common, Zero is cleared if Byte2 >= $exp and Byte >= $exp then Zero = False - + if Byte >= $exp then Byte -= $exp if Byte2 >= $exp then Byte2 -= $exp end end case $BRK operate_memory_bus() - + P += 16 # Set the break flag for the processor status - + Byte = PC / 0x100 Byte2 = PC % 0x100 Byte3 = P - PC = NMI + PC = NMI end case $CLC get_pc_data() - + Carry = False end case $CLD get_pc_data() - + Decimal = False end case $CLI get_pc_data() - + Interrupt = False end case $CLV get_pc_data() - + Overflow = False end case $CMP operate_memory_bus() - + Compare = A end case $CPX operate_memory_bus() - + Compare = X end case $CPY operate_memory_bus() - + Compare = Y end case $DEC operate_memory_bus() - + Byte-- if Byte < 0 then Byte += 0x100 @@ -1622,7 +1622,7 @@ function run_instruction() end case $DEX get_pc_data() - + X-- if X < 0 then X += 0x100 @@ -1630,7 +1630,7 @@ function run_instruction() end case $DEY get_pc_data() - + Y-- if Y < 0 then Y += 0x100 @@ -1638,22 +1638,22 @@ function run_instruction() end case $EOR operate_memory_bus() - + Byte2 = 0 for $exp in [128, 64, 32, 16, 8, 4, 2, 1] if A >= $exp and Byte < $exp then Byte2 += $exp if A < $exp and Byte >= $exp then Byte2 += $exp - + if Byte >= $exp then Byte -= $exp if A >= $exp then A -= $exp end A = Byte2 - + TestZN = A end case $INC operate_memory_bus() - + Byte++ if Byte >= 0x100 then Byte -= 0x100 @@ -1661,33 +1661,33 @@ function run_instruction() end case $INX get_pc_data() - + X++ if X >= 0x100 then X -= 0x100 TestZN = X end case $INY get_pc_data() - + Y++ if Y >= 0x100 then Y -= 0x100 TestZN = Y end - case $JMP + case $JMP if Instruction == 0x6C operate_memory_bus() - + PC = Byte2 * 0x100 + Byte end if Instruction == 0x4C get_pc_data() - + PC = Op12 end end case $JSR operate_memory_bus() - + PC-- Byte = PC / 0x100 Byte2 = PC % 0x100 @@ -1695,25 +1695,25 @@ function run_instruction() end case $LDA operate_memory_bus() - + A = Byte TestZN = A end case $LDX operate_memory_bus() - + X = Byte TestZN = X end case $LDY operate_memory_bus() - + Y = Byte TestZN = Y end case $LSR operate_memory_bus() - + Carry = Byte % 2 Byte /= 2 @@ -1724,44 +1724,44 @@ function run_instruction() end case $ORA operate_memory_bus() - + Byte2 = 0 for $exp in [128, 64, 32, 16, 8, 4, 2, 1] if A >= $exp then Byte2 += $exp if A < $exp and Byte >= $exp then Byte2 += $exp - + if Byte >= $exp then Byte -= $exp if A >= $exp then A -= $exp end A = Byte2 - + TestZN = A end case $PHA operate_memory_bus() - + Byte = A end case $PHP operate_memory_bus() - + Byte = P end case $PLA operate_memory_bus() - + A = Byte TestZN = A end case $PLP operate_memory_bus() - + P = Byte DecodeP = True end case $ROL operate_memory_bus() - + LowBit = Carry Byte *= 2 Carry = False @@ -1773,7 +1773,7 @@ function run_instruction() end case $ROR operate_memory_bus() - + LowBit = Byte % 2 Byte /= 2 if Carry then Byte += 0x80 @@ -1783,42 +1783,42 @@ function run_instruction() end case $RTI operate_memory_bus() - + PC = Byte3 * 0x100 + Byte2 P = Byte DecodeP = True end case $RTS operate_memory_bus() - + PC = Byte2 * 0x100 + Byte + 1 end case $SBC operate_memory_bus() - + if Decimal la = A % 0x10 ha = A / 0x10 lb = Byte % 0x10 hb = Byte / 0x10 - + la -= lb + 1 - Carry Carry = 1 if la < 0 Carry = 0 la += 10 end - + ha -= hb + 1 - Carry Carry = 1 if ha < 0 Carry = 0 ha += 10 end - + A = ha * 0x10 + la end - + unless Decimal SignedA = A if SignedA >= 0x80 then SignedA -= 0x100 @@ -1826,86 +1826,86 @@ function run_instruction() if SignedByte >= 0x80 then SignedByte -= 0x100 SignedA -= SignedByte if not Carry then SignedA-- - + Overflow = True if SignedA >= -0x80 and SignedA <= 0x7F then Overflow = False - + A -= Byte if not Carry then A-- Carry = True if A < 0 then Carry = False if A < 0 then A += 0x100 end - + TestZN = A end case $SEC get_pc_data() - + Carry = True end case $SED get_pc_data() - + Decimal = True end case $SEI get_pc_data() - + Interrupt = True end case $STA operate_memory_bus() - + Byte = A end case $STX operate_memory_bus() - + Byte = X end case $STY operate_memory_bus() - + Byte = Y end case $TAX get_pc_data() - + X = A TestZN = X end case $TAY get_pc_data() - + Y = A TestZN = Y end case $TSX get_pc_data() - + X = Stack TestZN = X end case $TXA get_pc_data() - + A = X TestZN = A end case $TXS get_pc_data() - + Stack = X end case $TYA get_pc_data() - + A = Y TestZN = A end end - + # Set new values for the processor status flags, from byte P if DecodeP Negative = False @@ -1914,7 +1914,7 @@ function run_instruction() Interrupt = False Zero = False Carry = False - + if P >= 0x80 Negative = True P -= 0x80 @@ -1922,7 +1922,7 @@ function run_instruction() if P >= 0x40 Overflow = True end - + P %= 0x10 if P >= 0x08 Decimal = True @@ -1940,20 +1940,20 @@ function run_instruction() Carry = True end end - + if Compare >= 0 Result = Compare - Byte Carry = False if Result >= 0 then Carry = True if Result < 0 then Result += 0x100 - + TestZN = Result end if TestZN >= 0 Zero = False if TestZN == 0 then Zero = True - + Negative = False if TestZN >= 0x80 then Negative = True end @@ -1964,15 +1964,15 @@ function get_pixel_count() Pixels = Cycles * 3 # Account for previously delayed register write Pixels -= Delay - + # Find the delay for the current register write get_delay() Pixels += Delay - + if Write and Addr == $WSYNC Pixels = $ScreenWidth - Scan - end - + end + Clock += Pixels end @@ -1984,7 +1984,7 @@ function update_clock() if Ticks < 0 # INSTAT Register Underflow Memory645 = 0b11000000 - + Ticks *= ClockRate Ticks /= 3 Ticks -= Clock / 3 @@ -2046,7 +2046,7 @@ function draw_beam() /tp @s ~ 250 ~ ScanLine = 0 end - + # Mark beam start point for color filling if Scan >= 0 start_point = Scan @@ -2054,16 +2054,16 @@ function draw_beam() if Scan < 0 start_point = 0 end - + end_point = Scan + Pixels - 1 if end_point >= $ScreenWidth $ScreenEnd = $ScreenWidth - 1 end_point = $ScreenEnd end - + # Draw all the pixels draw_range(start_point, end_point) - + Scan += Pixels if Scan >= $ScreenWidth @@ -2100,13 +2100,13 @@ function draw_pixels{$x, $reflect}() /execute unless blocks 0 254 -3 0 254 -3 $x ~ 0 all run clone 0 254 -3 0 254 -3 $x ~ ~ PFPixel = False end - + draw_sprites_missiles_ball() - + x++ - + $sub_pixel = ($x+1) % 4 - + if $sub_pixel != 0 and $x+1 < $ScreenWidth draw_pixels{$x+1, $reflect}() end @@ -2128,15 +2128,15 @@ function draw_four_pixels{$x, $reflect}() /execute unless blocks 0 254 -3 3 254 -3 $x ~ 0 all run clone 0 254 -3 3 254 -3 $x ~ 0 PFPixel = False end - + for $step in $range(4) if x <= x2 draw_sprites_missiles_ball() - + x++ end end - + if $x+4 < $ScreenWidth draw_four_pixels{$x+4, $reflect}() end @@ -2145,7 +2145,7 @@ end # Draw pixel at x for ball, sprites and missiles function draw_sprites_missiles_ball() - draw_ball_pixel() + draw_ball_pixel() draw_sprite_pixel{0}() draw_sprite_pixel{1}() draw_missile_pixel{0}() @@ -2159,10 +2159,10 @@ function draw_ball_pixel() if x >= BLX and x < BallEnd @Self.x = x at @Self - /clone 0 254 -2 0 254 -2 ~ ~ ~ + /clone 0 254 -2 0 254 -2 ~ ~ ~ end BallPixel = True - + if PFPixel then CXBLPF = True end end @@ -2172,10 +2172,10 @@ end function draw_sprite_pixel{$player}() if GRP[$player] PlayerPixel[$player] = False - + dx = (x - PX[$player]) / Stretch[$player] copy = dx / Spread[$player] - + if copy >= 0 and copy < Copies[$player] if ReflectP[$player] do bit = dx % Spread[$player] unless ReflectP[$player] then bit = 7 - (dx % Spread[$player]) @@ -2190,7 +2190,7 @@ function draw_sprite_pixel{$player}() $y = 252 + $player /clone 0 $y -1 0 $y -1 ~ ~ ~ end - + PlayerPixel[$player] = True if $player == 1 if PlayerPixel[0] then CXP0P1 = True @@ -2210,7 +2210,7 @@ function draw_sprite_pixel{$player}() if $player == 1 CXP1BL = True end - end + end end end end @@ -2223,10 +2223,10 @@ end function draw_missile_pixel{$player}() if ENAM[$player] MissilePixel[$player] = False - + dx = x - MX[$player] copy = dx / Spread[$player] - + if copy >= 0 and copy < Copies[$player] bit = dx % Spread[$player] if bit >= 0 and bit < MissileSize[$player] @@ -2235,9 +2235,9 @@ function draw_missile_pixel{$player}() $y = 252 + $player /clone 0 $y -1 0 $y -1 ~ ~ ~ end - + MissilePixel[$player] = True - + if $player == 1 if MissilePixel[0] then CXM0M1 = True end @@ -2289,23 +2289,23 @@ function write_to_memory() clear_digits() Halt = True end - + if not Accumulator write_addr(Addr, Byte) end - + if Accumulator then A = Byte end - + if Push >= 1 Addr = Stack # + 256 # Atari stack mirroring write_addr(Addr, Byte) - + if Push >= 2 Addr-- if Addr < 0 then Addr += 0x100 write_addr(Addr, Byte2) - + if Push >= 3 Addr-- if Addr < 0 then Addr += 0x100 @@ -2313,7 +2313,7 @@ function write_to_memory() write_addr(Addr, Byte3) end end - + Stack -= Push if Stack < 0 then Stack += 0x100 end @@ -2326,18 +2326,18 @@ function write_addr(addr, val) tell @a "\ Memory Write at Addr $(@digit0)(@digit1)(@digit2)(@digit3) -- Byte: $(@digit4)(@digit5)" clear_digits() end - + # Atari Stack Mirroring if addr >= 0x100 and addr < 0x200 addr -= 0x100 end - + if addr == BreakOnWrite tell @a "Wrote (val) to break point (Addr). {G[\[Continue\]](/scoreboard players set Global Halt 0) {R[\[Remove Breakpoint\]](/scoreboard players set Global BreakOnWrite -1)" display_instruction() Halt = True end - + $write_mirrors = $"lambda a: [a % 0x40 + i for i in range(0, 0x80, 0x40)]" switch addr case $addr in $MemoryAddresses @@ -2381,14 +2381,14 @@ function write_addr(addr, val) case $i in $write_mirrors($COLUBK) unless Byte == COLUBK COLUBK = Byte - + Lum = (COLUBK % 0x10) / 2 Color = (COLUBK / 0x10) - + as @Buffer @s.y = Color @s.z = Lum - 8 - + at @s /clone 0 ~ ~ 3 ~ ~ 0 254 -3 end @@ -2398,14 +2398,14 @@ function write_addr(addr, val) case $i in $write_mirrors($COLUPF) unless Byte == COLUPF COLUPF = Byte - + Lum = (COLUPF % 0x10) / 2 Color = (COLUPF / 0x10) - + as @Buffer @s.y = Color @s.z = Lum - 8 - + at @s /clone 0 ~ ~ 3 ~ ~ 0 254 -2 end @@ -2413,16 +2413,16 @@ function write_addr(addr, val) end end case $i in $write_mirrors($COLUP0) - unless Byte == COLUP0 + unless Byte == COLUP0 COLUP0 = Byte - + Lum = (COLUP0 % 0x10) / 2 Color = (COLUP0 / 0x10) - + as @Buffer @s.y = Color @s.z = Lum - 8 - + at @s /clone 0 ~ ~ 0 ~ ~ 0 252 -1 end @@ -2430,16 +2430,16 @@ function write_addr(addr, val) end end case $i in $write_mirrors($COLUP1) - unless Byte == COLUP1 + unless Byte == COLUP1 COLUP1 = Byte - + Lum = (COLUP1 % 0x10) / 2 Color = (COLUP1 / 0x10) - + as @Buffer @s.y = Color @s.z = Lum - 8 - + at @s /clone 0 ~ ~ 0 ~ ~ 0 253 -1 end @@ -2452,14 +2452,14 @@ function write_addr(addr, val) if not VBLANK and was_vblank Frame++ end - + INPT45Control = (Byte / 0x40) % 2 LatchedButton = Button end case $i in $write_mirrors($PF0) unless Byte == PF0 PF0 = Byte - + PFByte = PF0 / 0x10 for $bit in $range(4) PFBit[$bit] = PFByte % 2 @@ -2470,7 +2470,7 @@ function write_addr(addr, val) case $i in $write_mirrors($PF1) unless Byte == PF1 PF1 = Byte - + PFByte = PF1 for $bit in $range(8) PFBit[$bit+4] = PFByte / 0x80 @@ -2482,7 +2482,7 @@ function write_addr(addr, val) case $i in $write_mirrors($PF2) unless Byte == PF2 PF2 = Byte - + PFByte = PF2 for $bit in $range(8) PFBit[$bit+12] = PFByte % 2 @@ -2507,13 +2507,13 @@ function write_addr(addr, val) if VDELP1 GRP1A = Byte end - if VDELP0 + if VDELP0 GRP[0] = GRP0A $UpdateGRPBits(0) end if VDELBL ENABL = ENABLA - + # Make sure ball-object collisions aren't triggered while disabled BallPixel = False end @@ -2547,15 +2547,15 @@ function write_addr(addr, val) VDELBL = Byte % 2 end case $i in $write_mirrors($VDELP1) - VDELP1 = Byte % 2 + VDELP1 = Byte % 2 end case $TIM1T to $TIM1024T Ticks = Byte - 1 Clock = 0 - + # Clear INSTAT Read Flag Memory645 %= 0x80 - + if Addr == $TIM1T then ClockRate = 3 if Addr == $TIM8T then ClockRate = 24 if Addr == $TIM64T then ClockRate = 192 @@ -2563,7 +2563,7 @@ function write_addr(addr, val) end case $i in $write_mirrors($CTRLPF) ReflectPF = Byte % 2 - + switch (Byte / 0x10) % 0x04 case $bits in $range(4) $size = 2 ** $bits @@ -2574,14 +2574,14 @@ function write_addr(addr, val) end case $i in $write_mirrors($ENAM0) ENAM[0] = (Byte / 2) % 2 - + # Make sure missile-object collisions aren't triggered while disabled MissilePixel[0] = False end case $i in $write_mirrors($ENAM1) ENAM[1] = (Byte / 2) % 2 # Make sure missile-object collisions aren't triggered while disabled - MissilePixel[1] = False + MissilePixel[1] = False end case $i in $write_mirrors($ENABL) if VDELBL @@ -2596,7 +2596,7 @@ function write_addr(addr, val) case $i in $write_mirrors($RESP0) PX[0] = Scan + 5 if PX[0] < 0 then PX[0] = 3 - end + end case $i in $write_mirrors($RESP1) PX[1] = Scan + 5 if PX[1] < 0 then PX[1] = 3 @@ -2635,7 +2635,7 @@ function write_addr(addr, val) CXM1BL = False CXBLPF = False CXP0P1 = False - CXM0M1 = False + CXM0M1 = False end end end @@ -2643,7 +2643,7 @@ end macro $UpdateGRPBits($player) # Make sure player-object collisions aren't triggered while disabled PlayerPixel[$player] = False - + GRP = GRP[$player] for $bit in $range(8) bit = GRP % 2 @@ -2696,7 +2696,7 @@ macro $UpdateNumSize($player) Copies[$player] = 1 end end - + MissileSizeBits = (NUSIZ[$player] / 0x10) % 0x04 switch MissileSizeBits case $bits in $range(4) @@ -2744,4 +2744,4 @@ function mnemonic() end end end -end \ No newline at end of file +end diff --git a/Scripts/archived 1.15 scripts/UHC.cbscript b/Scripts/archived 1.15 scripts/UHC.cbscript index 5120676..6d59cb6 100644 --- a/Scripts/archived 1.15 scripts/UHC.cbscript +++ b/Scripts/archived 1.15 scripts/UHC.cbscript @@ -15,7 +15,7 @@ reset /team add $team /team modify $team color $team end - + running = False end @@ -102,7 +102,7 @@ clock main tell @a '{R{DTEST MARKER:{- End of episode (episode)!' end timer++ - + /gamemode spectator @a[deaths > 0] /scoreboard players set @a[gamemode=spectator] deaths 0 end diff --git a/Scripts/archived 1.15 scripts/bee_gun.cbscript b/Scripts/archived 1.15 scripts/bee_gun.cbscript index 74c99c9..fd3f0a1 100644 --- a/Scripts/archived 1.15 scripts/bee_gun.cbscript +++ b/Scripts/archived 1.15 scripts/bee_gun.cbscript @@ -47,7 +47,7 @@ define @Bullet : @Entity[type=bee, tag=Bullet] Tags: ["Bullet"], NoAI:1 } - + function tick() at @s @s.age = -20000 @@ -56,7 +56,7 @@ define @Bullet : @Entity[type=bee, tag=Bullet] if @Target /tp @Position2 @Target move @Position2 ~ ~1 ~ - + at @Position2 if @s[distance=..0.5] as @Target hp = @s.hp @@ -70,7 +70,7 @@ define @Bullet : @Entity[type=bee, tag=Bullet] target_ry = @Position.ry target_rx = @Position.rx end - + dry = (@s.my_ry + 180000 - target_ry) % 360000 - 180000 if dry > 5000 @s.my_ry -= 5000 @@ -79,7 +79,7 @@ define @Bullet : @Entity[type=bee, tag=Bullet] else @s.my_ry -= dry end - + drx = @s.my_rx - target_rx if drx > 5000 @s.my_rx -= 5000 @@ -93,10 +93,10 @@ define @Bullet : @Entity[type=bee, tag=Bullet] @s.rx = @s.my_rx @s.ry = @s.my_ry - + @s.rx += randint(-1000, 1000) @s.ry += randint(-1000, 1000) - + at @s ^ ^ ^0.3 if block ~ ~ ~ no_collision /tp @s ~ ~ ~ ~ ~ else at @s @@ -108,7 +108,7 @@ define @Bullet : @Entity[type=bee, tag=Bullet] else bounce_z = True end - + /tp @Position ^ ^ ^0.3 @Position.x = @s.x @Position.z = @s.z @@ -117,7 +117,7 @@ define @Bullet : @Entity[type=bee, tag=Bullet] else bounce_y = True end - + /tp @Position ^ ^ ^0.3 @Position.y = @s.y @Position.z = @s.z @@ -126,13 +126,13 @@ define @Bullet : @Entity[type=bee, tag=Bullet] else bounce_x = True end - + if not bounce_x and not bounce_y and not bounce_z bounce_x = True bounce_y = True bounce_z = True end - + /tp @Position ^ ^ ^0.3 = @Position. - @s. if bounce_x then dx *= -1 @@ -146,12 +146,12 @@ define @Bullet : @Entity[type=bee, tag=Bullet] @s.my_ry = @s.ry end end - + @s.ticks++ - + if @s.ticks >= 100 /kill @s - end + end end end end @@ -214,17 +214,17 @@ clock main @s.my_ry = ry + randint(-10000, 10000) @s.my_rx = rx + randint(-10000, 10000) end - + unless @s.bee_meter >= 0 @s.bee_meter = 30 end @s.bee_meter-- assign_bossbar() set_bossbar_value() - + @s.recent_shot = 20 end - + if @s.recent_shot > 0 @s.recent_shot-- else @@ -245,9 +245,9 @@ clock main end end end - + @s.shot_gun = False end - + @Bullet.tick() end diff --git a/Scripts/archived 1.15 scripts/better_flight.cbscript b/Scripts/archived 1.15 scripts/better_flight.cbscript index 7b7107f..eaa0890 100644 --- a/Scripts/archived 1.15 scripts/better_flight.cbscript +++ b/Scripts/archived 1.15 scripts/better_flight.cbscript @@ -32,16 +32,16 @@ clock main as @s.prev_pos(@Marker) = (@s. - @player.) speedsq = vx^2 + vy^2 + vz^2 - + at @s if speedsq < 90000 /say stop end - + /kill @s end - + at @s @s.prev_pos = create @Marker end end -end \ No newline at end of file +end diff --git a/Scripts/archived 1.15 scripts/bifurcation.cbscript b/Scripts/archived 1.15 scripts/bifurcation.cbscript index 967e241..3657d16 100644 --- a/Scripts/archived 1.15 scripts/bifurcation.cbscript +++ b/Scripts/archived 1.15 scripts/bifurcation.cbscript @@ -13,7 +13,7 @@ end reset /kill @Branch - + tell @a "{G[\[Create Tree\]](call create_tree)" end @@ -32,11 +32,11 @@ clock main growth_clock++ if growth_clock >= 20 growth_clock = 0 - + as @Branch @s.radius += 200 end - + as @Branch[leaf] @s.leaf = False = (@s. + <0, 100, 0>) * 9 / 10 @@ -52,7 +52,7 @@ clock main end end end - + as @Branch at @s unless @Position do create @Position for dx = -@s.radius to @s.radius by 200 @@ -75,6 +75,6 @@ clock main end end end - + end -end \ No newline at end of file +end diff --git a/Scripts/archived 1.15 scripts/billiards.cbscript b/Scripts/archived 1.15 scripts/billiards.cbscript index bf7a6c6..6b6ce2a 100644 --- a/Scripts/archived 1.15 scripts/billiards.cbscript +++ b/Scripts/archived 1.15 scripts/billiards.cbscript @@ -42,7 +42,7 @@ function create_balls() ] $dx = $dx * 0.36 $dz = $dz * 0.36 - + at ~$dx ~0.3 ~$dz as create @MiniBlock @s.billiard_ball = True @@ -81,7 +81,7 @@ clock trigger tell_buttons() end end - + @a.Billiards = 0 /scoreboard players enable @a Billiards end @@ -92,7 +92,7 @@ function is_moving() return False else return True - end + end end clock main @@ -105,13 +105,13 @@ clock main @s. = /playsound block.wood.hit ambient @a ~ ~ ~ 1 2 end - + as @Arrow if @s.in_ground /kill @s end end - + for @ball in @Ball @s. *= 98 @s. /= 100 @@ -123,12 +123,12 @@ clock main z++ end @s. = - + = @s. = @s. = p1 = * - + at @s while @Ball[distance=0.001..0.69, limit=1] as @Ball[distance=0.001..0.69] @@ -140,20 +140,20 @@ clock main moving1 = is_moving() if @s.y > 54590 as @Ball[distance=0.001..0.7] moving2 = is_moving() - + if not moving1 and not moving2 else if @s.y > 54590 = @s. = p2 = * = @s. - + @s. -= (-)*(-)*(-)/((-)*(-)) @ball. -= (-)*(-)*(-)/((-)*(-)) /playsound block.wood.hit ambient @a ~ ~ ~ 1 2 end end - + for $dx, $dz in [ (0, 1), (0, -1), @@ -183,7 +183,7 @@ clock main end end end - + at @s ~ ~1.2 ~ if block ~-0.3 ~-0.1 ~-0.3 air and block ~0.3 ~-0.5 ~-0.3 air and block ~-0.3 ~-0.5 ~0.3 air and block ~0.3 ~-0.5 ~0.3 air @s. -= <0, 80, 0> @@ -192,7 +192,7 @@ clock main @s. = end end - + @s. += @s. end -end \ No newline at end of file +end diff --git a/Scripts/archived 1.15 scripts/blast.cbscript b/Scripts/archived 1.15 scripts/blast.cbscript index 8b54a71..5d977d0 100644 --- a/Scripts/archived 1.15 scripts/blast.cbscript +++ b/Scripts/archived 1.15 scripts/blast.cbscript @@ -5,7 +5,7 @@ import common define @Dozer: @Entity[type=minecart,tag=Dozer] create {Tags:["Dozer"],Invulnerable:1b} - + looky: Passengers[0].Rotation[0] float lookx: Passengers[0].Rotation[1] float end @@ -29,8 +29,8 @@ clock main = @Position. move @Position ^ ^ ^1 = @Position. - - + @s. += / 5 - end + end end -end \ No newline at end of file +end diff --git a/Scripts/archived 1.15 scripts/blingedit.cbscript b/Scripts/archived 1.15 scripts/blingedit.cbscript index 788a42b..0f3cf99 100644 --- a/Scripts/archived 1.15 scripts/blingedit.cbscript +++ b/Scripts/archived 1.15 scripts/blingedit.cbscript @@ -35,7 +35,7 @@ end define @CloneDisplay = @Entity[type=armor_stand,tag=CloneDisplay] create {CustomName:"\"CloneDisplay\"", Tags:["CloneDisplay"], Glowing:1b, NoGravity:1b, NoAI: 1b, Silent:1b, AbsorptionAmount: 100f, LeftHanded:0b, Invulnerable:1, ShowArms:1b, Pose:{LeftArm:[-90f,0f,0f],RightArm:[-90f,0f,0f]}} - + function replace_items() if @s.left_handed /replaceitem entity @s weapon.offhand diamond_sword @@ -45,8 +45,8 @@ define @CloneDisplay = @Entity[type=armor_stand,tag=CloneDisplay] /replaceitem entity @s weapon.offhand shield end end - - + + function clone_flip_horizontal() if flip_x lh = @s.left_handed @@ -71,7 +71,7 @@ define @Player = @Entity[type=player] from_display: @CloneDisplay to_display: @CloneDisplay moving: @Corner - + function tell_actions() tell @s '' tell @s 'BlingEdit: {C[\[Options\]](/function blingedit:options) {B[\[Help\]](https://docs.google.com/document/d/13jC-XnCvyyaTaVWAqNc3Gyqu6JEOWAa-xGfhFC8AU50/edit?usp=sharing)' @@ -85,19 +85,19 @@ define @Player = @Entity[type=player] tell @s 'Region Particle Outline: {G[\[On\]](/function blingedit:particles_on) {R[\[Off\]](/function blingedit:particles_off)' /gamerule sendCommandFeedback false end - + function particles_on() tell @s 'Region Outline Particles {Genabled{-.' @s.particles = True /gamerule sendCommandFeedback false end - + function particles_off() tell @s 'Region Outline Particles {Rdisabled{-' @s.particles = False /gamerule sendCommandFeedback false end - + function get_cursor_position() if @s.raycast_select @Player.cursor_current = False @@ -107,7 +107,7 @@ define @Player = @Entity[type=player] unless @Position do create @Position /tp @Position @s move @Position ~ ~1.6 ~ - + step = 0 if @s.cursor_inside while step < 250 at @Position if block ~ ~ ~ cursor_continue @@ -120,18 +120,18 @@ define @Player = @Entity[type=player] step++ end end - + at @Position align xyz at ~0.5 ~ ~0.5 /tp @Position ~ ~ ~ end = @Position. end end - + if i == 5 i = 5 end - + unless @s.raycast_select if @s.cursor_range == 5 at @s ~ ~1.6 ~ at ^ ^ ^5 align xyz at ~0.5 ~ ~0.5 @@ -155,46 +155,46 @@ define @Player = @Entity[type=player] end end end - + function cursor_range_5() @s.cursor_range = 5 tell @s 'Set cursor range to {G5' /gamerule sendCommandFeedback false end - + function cursor_range_10() @s.cursor_range = 10 tell @s 'Set cursor range to {G10' /gamerule sendCommandFeedback false end - + function cursor_range_15() @s.cursor_range = 15 tell @s 'Set cursor range to {G15' /gamerule sendCommandFeedback false end - + function cursor_range_20() @s.cursor_range = 20 tell @s 'Set cursor range to {G20' /gamerule sendCommandFeedback false end - + function cursor_inside() @s.cursor_inside = True tell @s 'Set cursor raycast to stop {GInside Blocks' /gamerule sendCommandFeedback false end - + function cursor_before() @s.cursor_inside = False tell @s 'Set cursor raycast to stop just {GBefore Blocks' /gamerule sendCommandFeedback false end - + function get_minmax() has_box = -1 - + as @s.pick1 = @s. has_box++ @@ -203,7 +203,7 @@ define @Player = @Entity[type=player] = @s. has_box++ end - + if x1 < x2 xmin = x1 xmax = x2 @@ -228,21 +228,21 @@ define @Player = @Entity[type=player] zmin = z2 zmax = z1 end - + = = = - - + = / 1000 = / 1000 = ( + ) / 2 / scale = / scale + <1, 1, 1> end - + function get_dest_minmax() player = &@s has_dest_box = False - + first = True as @Corner if @s.player == player and @s.type == $Type_Dest if first @@ -255,9 +255,9 @@ define @Player = @Entity[type=player] if y < dest_ymin then dest_ymin = y if z < dest_zmin then dest_zmin = z end - + = - + first = True as @Corner if @s.player == player and @s.type == $Type_Dest if first @@ -269,24 +269,24 @@ define @Player = @Entity[type=player] if y > dest_ymax then dest_ymax = y if z > dest_zmax then dest_zmax = z end - + = end function clone_air() @s.clone_air = True tell @s 'Clone air: {GEnabled' - + /gamerule sendCommandFeedback false end - + function dont_clone_air() @s.clone_air = False tell @s 'Clone air: {RDisabled' - + /gamerule sendCommandFeedback false end - + function toggle_clone_in_place() if @s.clone_in_place @s.clone_in_place = False @@ -295,15 +295,15 @@ define @Player = @Entity[type=player] end @s.cancel() @s.clone() - + /gamerule sendCommandFeedback false end - + function clone_flip_leftright() ry = (@s.ry/scale + @s.clone_rotation) % 360 flip_x = False flip_z = False - + if ry < 45 flip_x = True end @@ -319,21 +319,21 @@ define @Player = @Entity[type=player] if ry >= 315 flip_x = True end - + @s.invert_clone_flip() - + as @s.to_display @s.clone_flip_horizontal() end /gamerule sendCommandFeedback false end - + function clone_flip_frontback() ry = (@s.ry/scale + @s.clone_rotation) % 360 - + flip_x = False flip_z = False - + if ry < 45 flip_z = True end @@ -349,15 +349,15 @@ define @Player = @Entity[type=player] if ry >= 315 flip_z = True end - + @s.invert_clone_flip() - + as @s.to_display @s.clone_flip_horizontal() end /gamerule sendCommandFeedback false end - + function invert_clone_flip_x() if flip_x if @s.clone_flip_x @@ -375,7 +375,7 @@ define @Player = @Entity[type=player] end end - + function clone_rotate_left() @s.clone_rotation -= 90 if @s.clone_rotation < 0 @@ -385,7 +385,7 @@ define @Player = @Entity[type=player] @s.ry -= 90000 end @s.rotate_dest_horizontal() - + /gamerule sendCommandFeedback false end @@ -398,42 +398,42 @@ define @Player = @Entity[type=player] @s.ry += 90000 end @s.rotate_dest_horizontal() - + /gamerule sendCommandFeedback false end - + function rotate_dest_horizontal() @s.get_dest_minmax() clone_rotation = @s.clone_rotation - + = ( + ) / 2 - + = - mod = (cx + cz) % scale - + x_offset = 0 z_offset = 0 unless mod == 0 x_offset = 500 if clone_rotation == 90 then x_offset = -500 if clone_rotation == 180 then x_offset = -500 - + z_offset = 500 if clone_rotation == 180 then z_offset = -500 if clone_rotation == 270 then z_offset = -500 end - + player = &@s as @Corner if @s.player == player and @s.type == $Type_Dest dx = cx - @s.x dz = cz - @s.z - + @s.x = cx - dz + x_offset @s.z = cz - dx + z_offset end end - + function plugin_can_run() plugin_can_run = False if @s.state == $EditSource @@ -443,23 +443,23 @@ define @Player = @Entity[type=player] end end end - + function list_plugins() @s.prime_plugins = True - + /gamerule sendCommandFeedback false end - + function randomize_menu() tell @s '' tell @s '{cRandomization Options:' tell @s '{C[\[Store Selected Region as Random Block Pool\]](/function blingedit:store_random)' tell @s '{C[\[Fill Selected Region from Random Block Pool\]](/function blingedit:fill_random)' tell @s '{C[\[Replace in Selected Region from Random Block Pool\]](/function blingedit:replace_random)' - + /gamerule sendCommandFeedback false end - + function store_random() unless @s.state == $EditSource tell @s "You can't store a region right now." @@ -470,7 +470,7 @@ define @Player = @Entity[type=player] @s. = / scale @s. = / scale @s.has_rand = True - + = @s. = @s. tell @s 'Random Block Pool region stored as \((rx1), (ry1), (rz1)\) to \((rx2), (ry2), (rz2)\)' @@ -478,10 +478,10 @@ define @Player = @Entity[type=player] tell @s "You don't currently have a region selected." end end - + /gamerule sendCommandFeedback false end - + function fill_random() if @s.state == $EditSource unless @s.has_rand @@ -489,23 +489,23 @@ define @Player = @Entity[type=player] end if @s.has_rand check_loaded() - + if loaded @s.get_minmax() if has_box replaced_blocks = 0 - + = @s. = @s. - + = @s. random_replace = @s.random_replace /bossbar set progress players @s store_tile_drops() - + unless @Position do create @Position unless @Position2 do create @Position2 - + as @Position for x = xmin to xmax by scale percent = (x - xmin) * 100 / (xmax - xmin) @@ -525,13 +525,13 @@ define @Player = @Entity[type=player] rx = randint(rx1, rx2+1) ry = randint(ry1, ry2+1) rz = randint(rz1, rz2+1) - + @Position2. = * scale = @Position2. at @Position2 /clone ~ ~ ~ ~ ~ ~ 0 1 0 end - + replaced_blocks++ /clone 0 1 0 0 1 0 ~ ~ ~ end @@ -548,35 +548,35 @@ define @Player = @Entity[type=player] else tell @s "You can't store a region right now." end - + /gamerule sendCommandFeedback false end - + function replace_random() @s.state = $ReplaceWaitRandom tell @s 'Use {w[/setblock ~ ~ ~ ](//setblock ~ ~ ~ minecraft:){- to pick the blocks to replace.' tell @s 'Or replace {C[\[air\]](/function blingedit:replace_random_air)' - + /gamerule sendCommandFeedback false end - + function replace_random_air() /setblock 0 2 0 air perform_random_replace() - + /gamerule sendCommandFeedback false end - + function perform_random_replace() @s.random_replace = True @s.state = $EditSource - + @s.fill_random() @s.random_replace = False tell @s 'Replaced (replaced_blocks) blocks.' end - + function clone() if @s.state == $EditSource @s.get_minmax() @@ -588,20 +588,20 @@ define @Player = @Entity[type=player] = -
= ( + ) / 2
-=
% scale + - + player = &@s @s.get_cursor_position() if @s.clone_in_place =
end - + as @Corner if @s.player == player and @s.type == $Type_Source = @s. -
bottom_center = False if @s.center_x and @s.center_z and @s.y == ymin bottom_center = True end - + as create @Corner @s.type = $Type_Dest @s. = + @@ -613,19 +613,19 @@ define @Player = @Entity[type=player] end end end - + move @Corner ~ ~ ~ - + if @s.clone_in_place @s.state = $EditDest end - + unless @s.clone_in_place @s.moving = moving @s.state = $MovingDest @s.enable_click() end - + @s.from_display = create @CloneDisplay as @s.from_display /replaceitem entity @s weapon.mainhand diamond_sword @@ -640,11 +640,11 @@ define @Player = @Entity[type=player] /replaceitem entity @s armor.head player_head{SkullOwner:"SethBling"} /team join dest end - + @s.clone_rotation = 0 @s.clone_flip_x = False @s.clone_flip_z = False - + tell @s '' tell @s 'Move {BDest{w: {C[\[Up\]](/function blingedit:move_up) [\[Down\]](/function blingedit:move_down) [\[Left\]](/function blingedit:move_left) [\[Right\]](/function blingedit:move_right) [\[Forward\]](/function blingedit:move_forward) [\[Backward\]](/function blingedit:move_backward)' tell @s "Clone Options: {g[\[Do Clone Air\]](/function blingedit:clone_air) [\[Don't Clone Air\]](/function blingedit:dont_clone_air)" @@ -657,14 +657,14 @@ define @Player = @Entity[type=player] else tell @s "You can't clone a box right now." end - + /gamerule sendCommandFeedback false end - + function confirm_clone() if @s.state == $EditDest @s.perform_clone() - if loaded + if loaded = - @s.cancel() as @Corner if @s.player == player and @s.type == $Type_Source @@ -684,19 +684,19 @@ define @Player = @Entity[type=player] else tell @s "You can't confirm a clone right now." end - + /gamerule sendCommandFeedback false end - + function clone_and_repeat() if @s.state == $EditDest okay_rotation = True if @s.clone_rotation == 90 then okay_rotation = False if @s.clone_rotation == 270 then okay_rotation = False - + if okay_rotation @s.perform_clone() - if loaded + if loaded = - as @Corner if @s.player == player @s. += @@ -709,15 +709,15 @@ define @Player = @Entity[type=player] else tell @s "You can't confirm a clone right now." end - - /gamerule sendCommandFeedback false + + /gamerule sendCommandFeedback false end - + function clone_brush() can_do = False if @s.state == $EditDest then can_do = True if @s.state == $MovingDest then can_do = True - + if can_do @s.state = $CloneBrush @s.enable_click() @@ -729,32 +729,32 @@ define @Player = @Entity[type=player] else tell @s "You can't confirm a clone right now." end - + /gamerule sendCommandFeedback false end - + function perform_clone() unless @Position do create @Position /spreadplayers 0 0 1 1 false @Position - + /setblock 0 1 0 stone /execute store success score Global loaded run setblock 0 1 0 sandstone - + unless loaded tell @s "Chunk 0,0 wasn't loaded. Try again \(or use {C/forceload add 0 0{W\)" end if loaded @s.get_minmax() - + unless has_box tell @s "You don't currently have a region selected." end if has_box @s.get_dest_minmax() - + = clone_air = @s.clone_air - + if dest_xmin <= xmin start_dx = 0 end_dx = size_x @@ -785,31 +785,31 @@ define @Player = @Entity[type=player] end_dz = 0 step_dz = -scale end - + /bossbar set progress players @s store_tile_drops() - + rotation = 0 rotation = @s.clone_rotation flip_x = @s.clone_flip_x flip_z = @s.clone_flip_z - + dest_start_y = dest_ymin - + if rotation == 0 dest_start_x = dest_xmin dest_start_z = dest_zmin flipped_x = dest_xmax flipped_z = dest_zmax end - + if rotation == 90 dest_start_x = dest_xmax dest_start_z = dest_zmin flipped_x = dest_xmin flipped_z = dest_zmax end - + if rotation == 180 dest_start_x = dest_xmax dest_start_z = dest_zmax @@ -823,10 +823,10 @@ define @Player = @Entity[type=player] flipped_x = dest_xmax flipped_z = dest_zmin end - + if flip_x then dest_start_x = flipped_x if flip_z then dest_start_z = flipped_z - + unless @Position do create @Position unless @Position2 do create @Position2 as @Position @@ -844,7 +844,7 @@ define @Player = @Entity[type=player] skip = True end end - + unless skip if rotation == 0 then = if rotation == 90 then = <-dz, dy, dx> @@ -852,7 +852,7 @@ define @Player = @Entity[type=player] if rotation == 270 then = if flip_x then dest_dx = dest_dx * -1 if flip_z then dest_dz = dest_dz * -1 - + @Position2. = + at @Position2 /clone 0 1 0 0 1 0 ~ ~ ~ @@ -862,12 +862,12 @@ define @Player = @Entity[type=player] end end end - + restore_tile_drops() end end end - + function cancel() handled = False can_cancel = False @@ -884,17 +884,17 @@ define @Player = @Entity[type=player] @s.tell_actions() handled = True end - + if not handled tell @s "You can't cancel right now." end - + /gamerule sendCommandFeedback false end function delete() @s.get_minmax() - + if has_box tell @s 'Deleting (box_xmin), (box_ymin), (box_zmin) to (box_xmax), (box_ymax), (box_zmax)' /bossbar set progress players @s @@ -914,11 +914,11 @@ define @Player = @Entity[type=player] end restore_tile_drops() end - + unless has_box tell @s 'You must select a region first.' end - + /gamerule sendCommandFeedback false end @@ -927,23 +927,23 @@ define @Player = @Entity[type=player] @s.state = $FillWait /gamerule sendCommandFeedback false end - + function replace() tell @s 'Use {w[/setblock ~ ~ ~ ](//setblock ~ ~ ~ minecraft:){- to pick the block to be replaced.' tell @s 'Or pick {C[\[air\]](/function blingedit:replace1_air){-' @s.state = $ReplaceWait1 /gamerule sendCommandFeedback false end - + function replace1_air() /setblock ~ ~ ~ air @s.tell_replace2() /gamerule sendCommandFeedback false end - + function tell_replace2() check_loaded() - + if loaded /clone ~ ~ ~ ~ ~ ~ 0 2 0 @s.state = $ReplaceWait2 @@ -955,24 +955,24 @@ define @Player = @Entity[type=player] tell @s "Chunk 0,0 wasn't loaded. Try again \(or use {C/forceload add 0 0{W\)" end end - + function replace2_air() /setblock ~ ~ ~ air @s.perform_replace() /gamerule sendCommandFeedback false end - + function perform_replace() check_loaded() - + if loaded /clone ~ ~ ~ ~ ~ ~ 0 1 0 - + @s.get_minmax() - + if has_box tell @s 'Replacing (box_xmin), (box_ymin), (box_zmin) to (box_xmax), (box_ymax), (box_zmax)' - + /bossbar set progress players @s store_tile_drops() count = 0 @@ -997,18 +997,18 @@ define @Player = @Entity[type=player] end end restore_tile_drops() - + tell @s 'Replaced (count) blocks.' @s.state = $EditSource end /setblock ~ ~ ~ air - + unless has_box tell @s 'You must select a box first.' end end end - + function move_up() type = None if @s.state == $EditSource @@ -1048,12 +1048,12 @@ define @Player = @Entity[type=player] end player = &@s ry = (@s.ry / scale) % 360 - + move_dir() - + /gamerule sendCommandFeedback false end - + function move_backward() type = None if @s.state == $EditSource @@ -1064,12 +1064,12 @@ define @Player = @Entity[type=player] end player = &@s ry = (@s.ry / scale + 180) % 360 - + move_dir() - + /gamerule sendCommandFeedback false end - + function move_left() type = None if @s.state == $EditSource @@ -1080,9 +1080,9 @@ define @Player = @Entity[type=player] end player = &@s ry = (@s.ry / scale - 90) % 360 - + move_dir() - + /gamerule sendCommandFeedback false end @@ -1096,21 +1096,21 @@ define @Player = @Entity[type=player] end player = &@s ry = (@s.ry / scale + 90) % 360 - + move_dir() /gamerule sendCommandFeedback false end - + function corner_target(type) player = &@s - + at @s ~ ~1.6 ~ = here at ^ ^ ^1 do = (here - ) - + @Corner.looking = False - + as @Corner[distance=..30] if @s.player == player and @s.type == type @s.highlight = False = (@s. + <0, 500, 0> - ) @@ -1118,14 +1118,14 @@ define @Player = @Entity[type=player] delta2 = * / scale tca2 = tca * tca / scale d2 = delta2 - tca2 - if d2 < 1700 and tca > 0 then @s.looking = True + if d2 < 1700 and tca > 0 then @s.looking = True end - + as @Corner[sort=nearest,limit=1,looking] @s.highlight = True end - - as @Corner[distance=..30] if @s.player == player and @s.type == type + + as @Corner[distance=..30] if @s.player == player and @s.type == type if @s.highlight /team join highlight @s.highlighted = True @@ -1139,24 +1139,24 @@ define @Player = @Entity[type=player] end end end - + function left_click_callback() @s.click() end - + function right_click_callback() @s.click() end - + function click() @Player.current = False @s.current = True @player = @Player[current,limit=1] - + move_dest = False if @s.state == $MovingDest then move_dest = True if @s.state == $CloneBrush then move_dest = True - + if @s.state == $EditSource as @Corner if @s.player == &@player and @s.type == $Type_Source and @s.highlighted /team join moving @@ -1176,7 +1176,7 @@ define @Player = @Entity[type=player] = / scale tell @player '2nd corner at {R(tx), (ty), (tz)' @player.tell_actions() - @player.tell_actions = False + @player.tell_actions = False end end end @@ -1208,7 +1208,7 @@ define @Player = @Entity[type=player] end @s.state = $EditingSource @s.tell_actions = True - + @s.pick2 = create @Corner as @s.pick2 @s.player = &@player @@ -1219,18 +1219,18 @@ define @Player = @Entity[type=player] @s.edit_zmax = True end @s.moving = @player.pick2 - + for ex = -1 to 1 for ey = -1 to 1 for ez = -1 to 1 skip = False sum = abs(ex + ey + ez) - + skip = False if ex == -1 and ey == -1 and ez == -1 then skip = True if ex == 1 and ey == 1 and ez == 1 then skip = True if ex == 0 and ey == 0 and ez == 0 then skip = True - + if not skip as create @Corner @s.player = &@player @@ -1239,7 +1239,7 @@ define @Player = @Entity[type=player] if ex == -1 then @s.edit_xmin = True if ex == 0 then @s.center_x = True if ex == 1 then @s.edit_xmax = True - + if ey == -1 then @s.edit_ymin = True if ey == 0 then @s.center_y = True if ey == 1 then @s.edit_ymax = True @@ -1256,7 +1256,7 @@ define @Player = @Entity[type=player] move @Corner ~ ~ ~ end end - end + end end function move_dir() @@ -1285,35 +1285,35 @@ reset /team add source /team modify source color red /team modify source collisionRule never - + /team add moving /team modify moving color yellow /team modify moving collisionRule never - + /team add highlight /team modify highlight color blue /team modify highlight collisionRule never - + /team add dest /team modify dest color green /team modify dest collisionRule never - + /execute store result score Global feedback run gamerule sendCommandFeedback /gamerule maxCommandChainLength 1000000000 - + /bossbar add progress "Progress" /bossbar set progress max 100 - + /scoreboard objectives remove used_carrot /scoreboard objectives add used_carrot minecraft.used:minecraft.carrot_on_a_stick - + /say Loaded BlingEdit v1.0.6 by SethBling end function check_loaded() /setblock 0 1 0 stone /execute store success score Global loaded run setblock 0 1 0 sandstone - + unless loaded tell @s "Chunk 0,0 wasn't loaded. Try again \(or use {C{U[/forceload add 0 0](//forceload add 0 0){u{W\)" end @@ -1396,11 +1396,11 @@ end clock main tick++ - + if feedback /gamerule sendCommandFeedback true end - + as @Entity[type=item] at @s @s[nbt={Item:{tag:{display:{Name:"{\"text\":\"BlingEdit\"}"}}}}].edit = True if @s.edit @@ -1409,7 +1409,7 @@ clock main if @s.edit @s.holding_item = True unless @s[nbt={SelectedItem:{}}] do @s.holding_item = False - unless @s.holding_item + unless @s.holding_item if @s.carrot_on_stick /replaceitem entity @s weapon.mainhand carrot_on_a_stick{display:{Name:"{\"text\":\"BlingEdit\"}"},Enchantments:[{lvl:5s,id:"minecraft:sharpness"}]} 1 end @@ -1417,7 +1417,7 @@ clock main /replaceitem entity @s weapon.mainhand diamond_sword{display:{Name:"{\"text\":\"BlingEdit\"}"}} 1 end found_player = True - + handled = False if @s.raycast_select @s.raycast_select = False @@ -1436,7 +1436,7 @@ clock main /kill @s end end - + for @player in @Player at @s unless @s.cursor_range >= 0 @@ -1445,12 +1445,12 @@ clock main unless @s.cursor_inside >= 0 @s.cursor_inside = True end - + if @s.used_carrot @s.click() end @s.used_carrot = 0 - + # Make sure there's a value in edit unless @s.edit do @s.edit = False @s.prev_edit = @s.edit @@ -1460,13 +1460,13 @@ clock main @s[nbt={"SelectedItem":{id:"minecraft:carrot_on_a_stick"}}].carrot_on_stick = True @s.disp_plugins = False - + if @s.prime_plugins @s.prime_plugins = False @s.disp_plugins = True tell @s '{cPlugins:' end - + if @s.edit unless @s.prev_edit @s.state = $Pick1 at @s ~ ~200 ~ @@ -1482,7 +1482,7 @@ clock main end @s.enable_click() end - + if @s.prev_edit unless @s.edit @s.pick1 = None @s.pick2 = None @@ -1495,7 +1495,7 @@ clock main end end end - + @s.get_minmax() if has_box and @s.particles @s.grid_display++ @@ -1503,19 +1503,19 @@ clock main @s.grid_display = 0 = - <450, -175, 450> = + <450, 1075, 450> - + draw_particle_box() - + @s.get_dest_minmax() if has_dest_box = - <450, -175, 450> = + <450, 1075, 450> - + draw_particle_box() end end end - + if @s.state == $Pick1 @s.get_cursor_position() corner_exists = False @@ -1527,19 +1527,19 @@ clock main /tp @s ~ ~ ~ end end - + if not corner_exists tell @s "BlingEdit doesn't work in peaceful mode." @s.state = $Closed end end - + @s.get_minmax() if has_box vol = box_size_x * box_size_y * box_size_z actionbar @s "Size: {y{D(box_size_x){-x{y{D(box_size_y){-x{y{D(box_size_z){- Volume: {y{D(vol){-" end - + @s.get_dest_minmax() if has_dest_box at @s ^7 ^6 ^10 @@ -1556,7 +1556,7 @@ clock main @s.from_display = None @s.to_display = None end - + if @s.state == $EditingSource @s.get_cursor_position() unless @Position do create @Position @@ -1594,20 +1594,20 @@ clock main end end end - + if @s.state == $EditSource @s.corner_target($Type_Source) end - - + + if @s.state == $EditDest @s.corner_target($Type_Dest) end - + move_dest = False if @s.state == $MovingDest then move_dest = True if @s.state == $CloneBrush then move_dest = True - + if move_dest @s.get_cursor_position() unless @Position do create @Position @@ -1623,17 +1623,17 @@ clock main end end end - + if @s.state == $FillWait at @s unless block ~ ~ ~ air check_loaded() - + if loaded /clone ~ ~ ~ ~ ~ ~ 0 1 0 @s.get_minmax() - + if has_box tell @s 'Filling (box_xmin), (box_ymin), (box_zmin) to (box_xmax), (box_ymax), (box_zmax)' - + /bossbar set progress players @s store_tile_drops() unless @Position do create @Position @@ -1650,29 +1650,29 @@ clock main end end restore_tile_drops() - + @s.state = $EditSource end /setblock ~ ~ ~ air - + unless has_box tell @s 'You must select a box first.' end end end - + if @s.state == $ReplaceWait1 at @s unless block ~ ~ ~ air - @s.tell_replace2() + @s.tell_replace2() end - + if @s.state == $ReplaceWait2 at @s unless block ~ ~ ~ air @s.perform_replace() end - + if @s.state == $ReplaceWaitRandom at @s unless block ~ ~ ~ air /clone ~ ~ ~ ~ ~ ~ 0 2 0 /setblock ~ ~ ~ air - + @s.perform_random_replace() end end @@ -1690,14 +1690,14 @@ function collect_garbage() /effect give @s invisibility 1000000 0 true move @s ~ ~ ~ end - + as @CloneDisplay @s.absorption = 100 @s.fire = 0 @s. = 0 move @s ~ ~ ~ end - + @Corner.kill = True @CloneDisplay.kill = True as @Player @@ -1714,9 +1714,9 @@ function collect_garbage() end end end - + as @e[kill] at @s move @s ~ -100 ~ /kill @s end -end \ No newline at end of file +end diff --git a/Scripts/archived 1.15 scripts/blingedit_dropfill.cbscript b/Scripts/archived 1.15 scripts/blingedit_dropfill.cbscript index 131b996..1bfa1a3 100644 --- a/Scripts/archived 1.15 scripts/blingedit_dropfill.cbscript +++ b/Scripts/archived 1.15 scripts/blingedit_dropfill.cbscript @@ -32,12 +32,12 @@ define @Player = @Entity[type=player] if loaded tell @s: Performing drop fill... /bossbar set progress players @s - + as create @Marker for x = box_xmin to box_xmax percent = (x - box_xmin) * 100 / (box_xmax - box_xmin) /execute store result bossbar progress value run scoreboard players get Global percent - + for z = box_zmin to box_zmax /setblock 0 1 0 air for y = box_ymax to box_ymin by -1 @@ -49,13 +49,13 @@ define @Player = @Entity[type=player] end end end - + /kill @s end tell @s: Drop fill complete. end end - + /gamerule sendCommandFeedback false end end @@ -70,4 +70,4 @@ end reset -end \ No newline at end of file +end diff --git a/Scripts/archived 1.15 scripts/blingedit_spline.cbscript b/Scripts/archived 1.15 scripts/blingedit_spline.cbscript index ef9d2d1..0d45b38 100644 --- a/Scripts/archived 1.15 scripts/blingedit_spline.cbscript +++ b/Scripts/archived 1.15 scripts/blingedit_spline.cbscript @@ -52,7 +52,7 @@ define @Player = @Entity[type=player] end end end - + for x = box_xmin to box_xmax percent = (x - box_xmin) * 100 / (box_xmax - box_xmin) /execute store result bossbar progress value run scoreboard players get Global percent @@ -62,17 +62,17 @@ define @Player = @Entity[type=player] weighted_y = 0 first = True @s. = - + at @s as @Marker[control_point, sort=nearest, limit=10] dx = @s.x - x dz = @s.z - z dist = dx^2+dz^2 - + weight = 10000 / (10*dist + 1) weighted_y += weight * (@s.height * 10 + 5) total_weight += weight - + if first first = False nearest_dist = dist @@ -85,13 +85,13 @@ define @Player = @Entity[type=player] @s.closest = True end end - + @s. = @Marker[control_point, closest, limit=1]. @s.y = @Marker[control_point, closest, limit=1].height at @s /clone ~ ~ ~ ~ ~ ~ 0 1 0 end - + @s. = at @s /clone 0 1 0 0 1 0 ~ ~ ~ @@ -99,7 +99,7 @@ define @Player = @Entity[type=player] end end end - + /kill @Marker[control_point] /kill @s end @@ -121,4 +121,4 @@ end reset -end \ No newline at end of file +end diff --git a/Scripts/archived 1.15 scripts/blingedit_vegetate.cbscript b/Scripts/archived 1.15 scripts/blingedit_vegetate.cbscript index a928582..f95c0b2 100644 --- a/Scripts/archived 1.15 scripts/blingedit_vegetate.cbscript +++ b/Scripts/archived 1.15 scripts/blingedit_vegetate.cbscript @@ -115,4 +115,4 @@ clock main tell @s: {C[\[Vegetate\]](/function blingedit_vegetate:run) end end -end \ No newline at end of file +end diff --git a/Scripts/archived 1.15 scripts/block_switch_test.cbscript b/Scripts/archived 1.15 scripts/block_switch_test.cbscript index 424d064..3f5612f 100644 --- a/Scripts/archived 1.15 scripts/block_switch_test.cbscript +++ b/Scripts/archived 1.15 scripts/block_switch_test.cbscript @@ -9,7 +9,7 @@ end clock main test_step++ - + if test_step >= 3 test_step = 0 diff --git a/Scripts/archived 1.15 scripts/boot.cbscript b/Scripts/archived 1.15 scripts/boot.cbscript index cee77a1..0aab6a7 100644 --- a/Scripts/archived 1.15 scripts/boot.cbscript +++ b/Scripts/archived 1.15 scripts/boot.cbscript @@ -17,7 +17,7 @@ define @Entity = @e rx = Rotation[1] float on_ground = OnGround byte 1 no_gravity = NoGravity byte 1 - + function get_facing_dir() at @s rotated @s at ^ ^ ^1 do = here - @s. end @@ -40,7 +40,7 @@ end reset /kill @HorseBase /kill @Horse - + at @Player do create @HorseBase end @@ -50,10 +50,10 @@ clock main @s.no_gravity = True = @s. tell @a: (Global.x) (Global.y) (Global.z) - + = @s. tell @a: (Global.vx) (Global.vy) (Global.vz) - + @s.vy = 100 end end diff --git a/Scripts/archived 1.15 scripts/breed_blocks.cbscript b/Scripts/archived 1.15 scripts/breed_blocks.cbscript index 0086d80..0e9a32c 100644 --- a/Scripts/archived 1.15 scripts/breed_blocks.cbscript +++ b/Scripts/archived 1.15 scripts/breed_blocks.cbscript @@ -22,7 +22,7 @@ $Piston = 4 $Mario = [ (0, 12), (4, 12), - (12, 12), + (12, 12), (20, 8), (24, 12), (32, 15), @@ -167,10 +167,10 @@ clock main end end end - + for $i in $range($len($Blocks)) $breed_item = $Blocks[$i][1] - + for @pushable in @Pushable[breed_type == $i] at @s if @s.hop_cooldown > 0 @@ -199,8 +199,8 @@ clock main /playsound minecraft:entity.slime.jump neutral @a end end - - + + if @s.willing at ~ ~1 ~ if @s.heart_cooldown > 0 @@ -221,18 +221,18 @@ clock main sticky = False @Pushable[willing, distance=0.1..1.2, breed_type == $i,limit=1].target = True end - + as @Entity[target] @s.willing = 0 @pushable.willing = 0 breed_type = @s.breed_type as create @BabyBlock ~ 300 ~ $block_type, $breed_item, $particle = $Blocks[$i] - + @s.breed_type = $i - + /tp @s ~ ~ ~ - + id = &@s @s.tinyblock = create @TinyBlock @s.sticky = sticky @@ -245,12 +245,12 @@ clock main /replaceitem entity @s weapon.mainhand $block_type end end - + /particle minecraft:$particle ~ ~ ~ 0.5 0.5 0.5 0.5 10 normal /summon experience_orb /summon experience_orb /summon experience_orb - + if @s.breed_type == $NoteBlock $num_songs = $len($Songs) @s.song = rand(0, $num_songs) @@ -276,7 +276,7 @@ clock main @s.willing = 300 end end - + @s.solidify++ if @s.solidify >= 100 unless @Position do create @Position @@ -298,7 +298,7 @@ clock main end end end - + as @SolidBlock[distance=..2] @s.kill_me = True end @@ -311,7 +311,7 @@ clock main end end end - + as @Slime unless @s[tag=BabyBlock] at @s if success /kill @e[type=item,nbt={Item:{id:"minecraft:iron_ingot"}},distance=..2] @@ -327,14 +327,14 @@ clock main @s.willing-- end end - + /tp @SolidBlock[kill_me] ~ -200 ~ - + as @BabyBlock at @s switch @s.song case $s in $range($len($Songs)) $song = $Songs[$s] - + for $note in $song $t = $note[0] $p = $note[1] @@ -344,7 +344,7 @@ clock main end end end - + @s.age++ /effect give @s invisibility 10 1 true as @s.tinyblock @@ -397,4 +397,4 @@ end function kill_all() /kill @BabyBlock /kill @TinyBlock[babyblock] -end \ No newline at end of file +end diff --git a/Scripts/archived 1.15 scripts/build_rotated.cbscript b/Scripts/archived 1.15 scripts/build_rotated.cbscript index b882460..c4d153c 100644 --- a/Scripts/archived 1.15 scripts/build_rotated.cbscript +++ b/Scripts/archived 1.15 scripts/build_rotated.cbscript @@ -17,7 +17,7 @@ define @Entity = @e rx = Rotation[1] float on_ground = OnGround byte 1 no_gravity = NoGravity byte 1 - + function get_facing_dir() at @s rotated @s at ^ ^ ^1 do @s. = here - @s. end @@ -40,7 +40,7 @@ define @Center = @Marker[center] end @rot = @Marker[rot, limit=1] bottom_y = @s.y - + for angle = ry to ry + 360*scale by scale /tp @base ~ ~ ~ /tp @rot ~ ~ ~ @@ -48,7 +48,7 @@ define @Center = @Marker[center] @base.rx = 0 @rot.rx = 0 @rot.ry = angle - + for x = 1 to @s.size for y = 1 to @s.size at @base @@ -89,11 +89,11 @@ clock main /spreadplayers 0 0 1 1 false @s /kill @s end - + /setblock 0 1 0 stone /execute store success score Global loaded run setblock 0 1 0 sandstone - - if loaded + + if loaded size = @s.size /kill @s tell @a: Rotating structure with size (Global.size) @@ -107,4 +107,4 @@ clock main tell @a: Done! end end -end \ No newline at end of file +end diff --git a/Scripts/archived 1.15 scripts/cape_flight.cbscript b/Scripts/archived 1.15 scripts/cape_flight.cbscript index 8139694..75cc100 100644 --- a/Scripts/archived 1.15 scripts/cape_flight.cbscript +++ b/Scripts/archived 1.15 scripts/cape_flight.cbscript @@ -11,7 +11,7 @@ reset /scoreboard objectives add swoop minecraft.custom:minecraft.sneak_time /scoreboard objectives add jump minecraft.custom:minecraft.jump /scoreboard objectives add thrust minecraft.used:minecraft.carrot_on_a_stick - + for $i in $range($Bossbars) /bossbar add p_bar$i "P Meter" /bossbar set p_bar$i max 30 @@ -65,7 +65,7 @@ clock main @s.p_meter = 0 end end - + if @s.p_meter unless @s.p_bar >= 0 assign_bossbar() @@ -76,13 +76,13 @@ clock main clear_bossbar() end end - + if @s.p_meter >= 30 /effect give @s speed 1 0 true if @s.jump @s.takeoff = 40 end - + if not @s.on_ground if @s.takeoff at @s @s.takeoff-- @@ -114,23 +114,23 @@ clock main end end end - + ry = @s.ry % 360000 prev_ry = @s.prev_ry - + dry = (ry - prev_ry + 180000) % 360000 - 180000 - + dry /= 1000 - + @s.cum_dry += dry - + if dry >= 0 and @s.prev_dry <= 0 @s.cum_dry = 0 end if dry <= 0 and @s.prev_dry >= 0 @s.cum_dry = 0 end - + spin = False if @s.cum_dry >= 360 @s.cum_dry = 0 @@ -144,8 +144,8 @@ clock main /playsound minecraft:entity.cat.purreow neutral @a ~ ~ ~ 2 2 /effect give @Entity[distance=0.1..2] instant_damage 2 0 true end - - + + @s.prev_ry = @s.ry @s.prev_dry = dry end @@ -153,4 +153,4 @@ clock main @Player.sprint = 0 @Player.swoop = 0 @Player.jump = 0 -end \ No newline at end of file +end diff --git a/Scripts/archived 1.15 scripts/chess.cbscript b/Scripts/archived 1.15 scripts/chess.cbscript index 74abf18..f42b69b 100644 --- a/Scripts/archived 1.15 scripts/chess.cbscript +++ b/Scripts/archived 1.15 scripts/chess.cbscript @@ -40,9 +40,9 @@ define @Piece : @Entity[tag=Piece] dc = valid_col - @s.col my_row = @s.row my_col = @s.col - + valid_move = True - + if @s.type == $King if dc == 2 as @Piece[type==$Rook] if @s.row == my_row and @s.col == 7 @@ -56,7 +56,7 @@ define @Piece : @Entity[tag=Piece] if check then valid_move = False end end - + if @s.type == $Pawn if valid_row == ep_row and valid_col == ep_col as @Piece[moved_2] @@ -64,33 +64,33 @@ define @Piece : @Entity[tag=Piece] end end end - + @s.row = valid_row @s.col = valid_col - + if this_color == $White other_color = $Black else other_color = $White end - + as @Piece[type==$King] if @s.color == this_color king_row = @s.row king_col = @s.col end - + as @Piece if @s.color == other_color and @s.row >= 0 if @s.square_in_range(king_row, king_col) valid_move = False end end - - + + as @Piece @s.row = @s.undo_row @s.col = @s.undo_col end - + return valid_move else return False @@ -101,10 +101,10 @@ define @Piece : @Entity[tag=Piece] color = @s.color dr = target_row - @s.row dc = target_col - @s.col - + adc = abs(dc) adr = abs(dr) - + switch @s.type case $Pawn if @s.color == $Black @@ -114,7 +114,7 @@ define @Piece : @Entity[tag=Piece] edr = dr er = @s.row end - + if er == 1 and edr == 2 and dc == 0 return @s.path_available(True, False) else if edr == 1 and dc == 0 @@ -191,12 +191,12 @@ define @Piece : @Entity[tag=Piece] castle_col = 0 target_col = 1 end - + castle_available = False as @Piece[type==$Rook] if @s.color == color and not @s.has_moved and @s.col == castle_col castle_available = True end - + if castle_available return @s.path_available(True, False) else @@ -209,7 +209,7 @@ define @Piece : @Entity[tag=Piece] end end end - + function path_available(blocked_by_enemy, requires_enemy) # Only call this function if the target is in-line, diagonally or horizontally/vertically # Set target_row and target_col before calling @@ -218,7 +218,7 @@ define @Piece : @Entity[tag=Piece] color = @s.color ur = sign(target_row-row) uc = sign(target_col-col) - + finished = False step = 0 while not finished @@ -229,7 +229,7 @@ define @Piece : @Entity[tag=Piece] tell @Player 'Error, non-terminating loop trying to move from (source_row), (source_col) to (target_row), (target_col)' finished = True end - + row += ur col += uc if row == target_row and col == target_col @@ -327,7 +327,7 @@ function create_piece(piece_type, piece_color, square_row, square_col) @s.x = GameX + square_row*2000 + 1000 @s.z = GameZ + square_col*2000 + 1000 @s.y = GameY - + at @s switch piece_type case $Pawn @@ -381,7 +381,7 @@ function create_piece(piece_type, piece_color, square_row, square_col) @s.row = square_row @s.col = square_col @s.has_moved = False - + at @s if piece_color == $White /tp @s ~ ~ ~ -90 ~ @@ -444,17 +444,17 @@ define @Player : @Player end end end - + function join_white() /team join white @s.team = $White end - + function join_black() /team join black @s.team = $Black end - + function promotion() if @s.team == current_player if game_state == $StatePromotion @@ -475,7 +475,7 @@ define @Player : @Player tell @s "It's not your turn!" end end - + function start_game() if game_state == $StateNone current_player = $White @@ -485,14 +485,14 @@ define @Player : @Player /kill @InvisPiece create_starting_pieces() switch_state($StatePlayerUnselected) - + tell @Player 'Starting new game!' tell @Player '{R[\[Concede\]](/trigger concede)' else tell @s 'The game has already started.' end end - + function concede() @Player.conceded = False @s.conceded = True @@ -502,10 +502,10 @@ define @Player : @Player tell @Player '(@a[conceded]) has conceded for team $color_name!' end end - + switch_state($StateNone) end - + function cancel_move() if @s.team == current_player switch_state($StatePlayerUnselected) @@ -513,7 +513,7 @@ define @Player : @Player tell @s "It's not your turn!" end end - + function get_hover_coords() unless @Position do create @Position at @s eyes ^ ^ ^ as @Position @@ -532,11 +532,11 @@ define @Player : @Player hover_col = (ground_z - GameZ) / 2000 end end - + function click_callback() unless @Position do create @Position handled = False - + switch game_state case $StatePlayerUnselected get_hover_coords() @@ -548,11 +548,11 @@ define @Player : @Player end end end - + @Piece.current_piece = False @s.current_piece = True @s.selectable = False - + switch_state($StatePlayerSelected) handled = True else @@ -569,7 +569,7 @@ define @Player : @Player /kill @s end end - + unless @Position do create @Position as @Position @s.x = GameX + hover_row * 2000 + 1000 @@ -583,9 +583,9 @@ define @Player : @Player my_col = @s.col @s.row = hover_row @s.col = hover_col - + @s.has_moved = True - + if @s.type == $King if dc == 2 as @Piece[type==$Rook, col==7] if @s.row == my_row as @Position @@ -611,24 +611,24 @@ define @Player : @Player end end end - + if @s.type == $Pawn and @s.row == ep_row and @s.col == ep_col /kill @Piece[moved_2] as @KnightRider at @s unless @Piece[distance=..2] /kill @s end end - + ep_row = -1 ep_col = -1 @Piece.moved_2 = False - + if @s.type == $Pawn and abs(dr) == 2 @s.moved_2 = True ep_row = my_row + sign(dr) ep_col = my_col end - + promote = False if @s.color == $White and @s.row == 7 and @s.type == $Pawn promote = True @@ -636,7 +636,7 @@ define @Player : @Player if @s.color == $Black and @s.row == 0 and @s.type == $Pawn promote = True end - + if promote @Piece.promote_piece = False @s.promote_piece = True @@ -691,12 +691,12 @@ function unhighlight_all() at @Position /clone ~ ~-2 ~ ~15 ~-2 ~15 ~ ~-1 ~ end - + as @Piece @s.glowing = False @s.selectable = False end - + unless game_state == $StatePlayerSelected move @InvisPiece ~ -200 ~ /kill @InvisPiece @@ -708,12 +708,12 @@ reset /team add white /team modify white color white /team modify white displayName "White" - + /team remove black /team add black /team modify black color black /team modify white displayName "Black" - + for $trigger in $Triggers /scoreboard objectives add $trigger trigger end @@ -724,7 +724,7 @@ reset unless current_player >= 0 current_player = $White end - + unless GameX >= -10000000 GameX = 0 end @@ -734,24 +734,24 @@ reset unless GameZ >= -10000000 GameZ = 0 end - + @Player.display_menu() end function switch_state(new_state) exit_state(game_state) - + game_state = new_state - + enter_state(game_state) - + @Player.display_menu() end function exit_state(state) switch state case $StateNone - + end end end @@ -764,16 +764,16 @@ function enter_state(state) end case $StatePlayerUnselected unhighlight_all() - + check = False as @Piece if @s.color == other_player if @s.square_in_range(cur_king_row, cur_king_col) check = True end end - + any_valid_moves = False - + as @Piece @s.glowing = False @s.selectable = False @@ -782,7 +782,7 @@ function enter_state(state) cur_king_row = @s.row cur_king_col = @s.col end - + for test_row = 0 to 7 for test_col = 0 to 7 if @s.valid_move(test_row, test_col) @@ -794,26 +794,26 @@ function enter_state(state) end end end - + if current_player == $White other_player = $Black else other_player = $White end - + if check and not any_valid_moves if other_player == $White title @Player 10 100 10 'Check mate!' subtitle @Player 10 100 10 '{D{WWhite{-{D wins!' - + tell @Player 'Check mate! {D{WWhite{-{D wins!' else title @Player 10 100 10 'Check mate!' subtitle @Player 10 100 10 '{D{KBlack{-{D wins!' - + tell @Player 'Check mate! {D{KBlack{-{D wins!' end - + switch_state($StateNone) else if check if current_player == $White @@ -827,15 +827,15 @@ function enter_state(state) if current_player == $White title @Player 10 100 10 '{DStale Mate!' subtitle @Player 10 100 10 '{D{WWhite{-{D has no valid moves. Game over!' - + tell @Player '{DStale Mate! {D{WWhite{-{D has no valid moves. Game over!' else title @Player 10 100 10 '{DStale Mate!' subtitle @Player 10 100 10 '{D{KBlack{-{D has no valid moves. Game over!' - + tell @Player '{DStale Mate! {D{KBlack{-{D has no valid moves. Game over!' end - + switch_state($StateNone) end end @@ -852,16 +852,16 @@ end function run_state(state) switch state case $StateNone - - end + + end case $StatePlayerUnselected @Piece.selected = False as @Player if @s.team == current_player @s.enable_click() - + @s.get_hover_coords() - + as @Piece if @s.row == hover_row and @s.col == hover_col and @s.selectable at @s @s.selected = True @s.was_selected = True @@ -871,7 +871,7 @@ function run_state(state) @s.disable_click() end end - + as @Piece[not selected, was_selected] at @s /clone ~-1 ~-2 ~-1 ~ ~-2 ~ ~-1 ~-1 ~-1 @s.was_selected = False @@ -885,13 +885,13 @@ function run_state(state) as @InvisKnightRider /effect give @s invisibility 10 0 true end - + as @Player if @s.team == current_player @s.enable_click() - + @s.get_hover_coords() - + as @InvisPiece if @s.row == hover_row and @s.col == hover_col at @s @s.selected = True @s.was_selected = True @@ -901,7 +901,7 @@ function run_state(state) @s.disable_click() end end - + as @InvisPiece[not selected, was_selected] at @s /clone ~-1 ~-2 ~-1 ~ ~-2 ~ ~-1 ~-1 ~-1 @s.was_selected = False @@ -923,8 +923,8 @@ end clock main run_state(game_state) clear_triggers() - + as @Entity @s.fire = 0 end -end \ No newline at end of file +end diff --git a/Scripts/archived 1.15 scripts/chest_sidescroller.cbscript b/Scripts/archived 1.15 scripts/chest_sidescroller.cbscript index b8b7938..28f6eaf 100644 --- a/Scripts/archived 1.15 scripts/chest_sidescroller.cbscript +++ b/Scripts/archived 1.15 scripts/chest_sidescroller.cbscript @@ -64,7 +64,7 @@ function reload() inventory[$i] = 0 end selected_item = 0 - + $x, $y, $z = $Chest /setblock $x $y $z chest[facing=south,type=right] $x, $y, $z = $Chest2 @@ -73,13 +73,13 @@ end function fill_chest() clicked_chest = False - + for $row in $range(6) for $col in $range(9) $x, $y, $z = $Chest $x = $x + $row / 3 $slot = ($row % 3) * 9 + $col - + $wx = $col - 4 $wy = 3 - $row + 0.5 unless [$x $y $z].{Items[{Slot:$slotb}]} @@ -97,7 +97,7 @@ function fill_chest() if block ~ ~ ~ water /replaceitem block $x $y $z container.$slot minecraft:blue_stained_glass_pane end - + /loot replace block $x $y $z container.$slot mine ~ ~ ~ diamond_pickaxe{Enchantments:[{id:"minecraft:silk_touch",lvl:1s}]} if block ~ ~ ~ grass /replaceitem block $x $y $z container.$slot grass @@ -106,19 +106,19 @@ function fill_chest() /replaceitem block $x $y $z container.$slot grass end end - + [$x $y $z].{Items[$slot]} += {tag:{display:{Name:"\"\""}}} end end - + $x, $y, $z = $Chest /replaceitem block $x $y $z container.22 minecraft:player_head [$x $y $z].{Items[22]} += {tag:{display:{Name:"\"\""}}} - + $x = $x + 1 /replaceitem block $x $y $z container.4 minecraft:leather_chestplate [$x $y $z].{Items[4]} += {tag:{display:{Name:"\"\""}}} - + /execute positioned $x $y $z as @Player[distance=..7] run function chest_sidescroller:clear_player end @@ -138,7 +138,7 @@ end function world_screen() fill_chest() - + if clicked_chest if click_row == 0 as @Steve at @s if block ~ ~2 ~ passable can_jump = False @@ -198,7 +198,7 @@ function world_screen() can_mine = True for $i in $range($len($InventorySlots)) $item_name, $drop, $tool, $can_place = $InventorySlots[$i] - + if $tool == $NoTool if block ~ ~ ~ $item_name inventory[$i]++ @@ -253,24 +253,24 @@ function inventory_screen_setup() $x, $y, $z = $Chest $x = $x + $row / 3 $slot = ($row % 3) * 9 + $col - + /replaceitem block $x $y $z container.$slot air end end $x, $y, $z = $Chest /replaceitem block $x $y $z container.7 dispenser{display:{Name:"{\"text\":\"Close Inventory\",\"italic\":\"false\"}"}} /replaceitem block $x $y $z container.8 barrier{display:{Name:"{\"text\":\"Close Inventory\",\"italic\":\"false\"}"}} - + for $i in $range($len($InventorySlots)) $item_name, $drop, $tool, $can_place = $InventorySlots[$i] $row = $i / 4 $col = $i % 4 - + $x, $y, $z = $Chest $x = $Chest[0] + $row / 3 - + $slot = ($row * 9 + $col) % 27 - + switch inventory[$i] case $count in $range(1, 65) /replaceitem block $x $y $z container.$slot $drop $count @@ -286,23 +286,23 @@ function inventory_screen() (3, 4), (3, 8), (4, 4), (4, 8), (5, 4), (5, 5), (5, 6), (5, 7), (5, 8), - + ] $x, $y, $z = $Chest - + crafting_count = 0 - + for $row in $range(6) for $col in $range(9) $x = $Chest[0] + $row / 3 $slot = ($row % 3) * 9 + $col - + for $cr, $cc in $CraftingTables if $row == $cr and $col == $cc /replaceitem block $x $y $z container.$slot crafting_table end end - + if $row >= 2 and $row <= 4 and $col >= 5 and $col <= 7 if [$x $y $z].{Items[{Slot:$slotb}]} crafting_count++ @@ -310,7 +310,7 @@ function inventory_screen() end end end - + if crafting_count == 1 and [<$Chest2>].{Items[{id:"minecraft:oak_log",Slot:6b}]} wood_count = [Chest at <$Chest2>].qty[6] if inventory[0] >= wood_count @@ -319,7 +319,7 @@ function inventory_screen() inventory_screen_setup() end end - + if crafting_count == 2 and [<$Chest2>].{Items[{id:"minecraft:oak_planks",Slot:6b}]} and [<$Chest>].{Items[{id:"minecraft:oak_planks",Slot:24b}]} plank1 = [Chest at <$Chest2>].qty[6] plank2 = [Chest at <$Chest>].qty[24] @@ -328,14 +328,14 @@ function inventory_screen() else planks = plank1 end - + if inventory[1] > planks * 2 inventory[1] -= planks*2 inventory[2] += planks*4 inventory_screen_setup() end end - + if crafting_count == 5 and [<$Chest>].{Items[{id:"minecraft:oak_planks",Slot:24b}]} and [<$Chest>].{Items[{id:"minecraft:oak_planks",Slot:23b}]} and [<$Chest>].{Items[{id:"minecraft:oak_planks",Slot:25b}]} and [<$Chest2>].{Items[{id:"minecraft:stick",Slot:6b}]} and [<$Chest2>].{Items[{id:"minecraft:stick",Slot:15b}]} if inventory[2] >= 2 and inventory[1] >= 3 inventory[2] -= 2 @@ -344,7 +344,7 @@ function inventory_screen() inventory_screen_setup() end end - + if crafting_count == 5 and [<$Chest>].{Items[{id:"minecraft:cobblestone",Slot:24b}]} and [<$Chest>].{Items[{id:"minecraft:cobblestone",Slot:23b}]} and [<$Chest>].{Items[{id:"minecraft:cobblestone",Slot:25b}]} and [<$Chest2>].{Items[{id:"minecraft:stick",Slot:6b}]} and [<$Chest2>].{Items[{id:"minecraft:stick",Slot:15b}]} if inventory[2] >= 2 and inventory[5] >= 3 inventory[2] -= 2 @@ -353,7 +353,7 @@ function inventory_screen() inventory_screen_setup() end end - + if crafting_count == 3 and [<$Chest2>].{Items[{id:"minecraft:iron_ingot",Slot:5b}]} and [<$Chest2>].{Items[{id:"minecraft:iron_ingot",Slot:7b}]} and [<$Chest2>].{Items[{id:"minecraft:iron_ingot",Slot:15b}]} if inventory[7] >= 3 inventory[7] -= 3 @@ -361,7 +361,7 @@ function inventory_screen() inventory_screen_setup() end end - + unless [<$Chest>].{Items[{id:"minecraft:barrier",Slot:8b}]} screen = $World give_open_inventory_item() @@ -389,8 +389,8 @@ function inventory_screen() inventory_screen_setup() end end - - + + $x, $y, $z = $Chest /clear @s crafting_table /clear @s barrier @@ -406,7 +406,7 @@ clock main /execute positioned $x $y $z as @Player[distance=..7,limit=1] run function chest_sidescroller:inventory_screen end end - + as @Steve at @s if block ~ ~ ~ ladder @s.no_gravity = True @@ -415,11 +415,11 @@ clock main else @s.no_gravity = False end - + if @s.no_gravity if clicked_chest and click_row == 5 at @Steve if block ~ ~-1 ~ passable move @Steve ~ ~-1 ~ end end end -end \ No newline at end of file +end diff --git a/Scripts/archived 1.15 scripts/colored_slime_blocks.cbscript b/Scripts/archived 1.15 scripts/colored_slime_blocks.cbscript index 2fcfa6b..5884aed 100644 --- a/Scripts/archived 1.15 scripts/colored_slime_blocks.cbscript +++ b/Scripts/archived 1.15 scripts/colored_slime_blocks.cbscript @@ -102,7 +102,7 @@ $Piston = 2 define @SlimeMarker: @Entity[type=area_effect_cloud,tag=SlimeMarker] create {Tags:["SlimeMarker"], Duration:-1,Age:-2147483648,WaitTime:-2147483648} - + array piston_types[6] end @@ -148,15 +148,15 @@ reset $c = $Colors[$i] /scoreboard objectives add place_slime$i minecraft.used:minecraft.$c end - + unless push_limit > 0 push_limit = 12 end - + tell @a 'Loaded {RColored {GSlime {BBlocks{- by SethBling' end -clock main +clock main as @PushMarker[move_timer > 0] @s.move_timer-- if @s.move_timer == 0 @@ -178,7 +178,7 @@ clock main /kill @s end end - + as @SlimeMarker at @s if @s.move_timer @s.move_timer-- @@ -213,7 +213,7 @@ clock main if [Moving].face == $d and [Moving].extending == 0 and [Moving].source == 1 and [Moving].progress == 0 and @s.piston_types[$d] == $StickyPiston at @s $dx, $dy, $dz = $PullDeltas[$d] - + $op = $OppositeDir[$d] @s.move_dir = $op @s.move_timer = 3 @@ -221,12 +221,12 @@ clock main end end end - + # 0-tick push then pull at ~<$PullDeltas[$d]> if [Moving].face == $d and [Moving].extending == 0 and [Moving].source == 1 and [Moving].progress == 0 /say 0 tick - + $op = $OppositeDir[$d] at @s get_pushable_list{$d}(True) @@ -240,7 +240,7 @@ clock main end end end - + # Regular 3 tick push at ~<$Deltas[$d]> if [Moving].face == $d and [Moving].extending and not [Moving].source and [Moving].progress == 0 @@ -252,13 +252,13 @@ clock main end end end - + at @s unless block ~ ~ ~ sticky unless block ~ ~ ~ barrier if @s.move_timer == 0 /kill @s end end end - + @MovingBlockPos.move_timer-- @MovingBlock.move_timer-- as @MovingBlockPos @@ -283,7 +283,7 @@ clock main /kill @s end end - + as @Player at @s eyes ^ ^ ^ for $i in $range(16) $color = $Colors[$i] @@ -301,12 +301,12 @@ clock main end steps++ end - + @s.place_slime[$i] = False end end end - + as @ObserverScheduler at @s for $d in ['north', 'south', 'east', 'west', 'up', 'down'] if block ~ ~ ~ observer[facing=$d,powered=false] @@ -324,11 +324,11 @@ end # Enacts a recursive push/pull function get_pushable_list{$d}(instant) push_count = 0 - + at @s recursive_pushed{$d}() end - + if push_count <= push_limit at @BreakMarker /setblock ~ ~ ~ air destroy @@ -357,7 +357,7 @@ function get_pushable_list{$d}(instant) @s.move_timer = 3 /setblock ~ ~ ~ barrier /setblock ~$dx ~$dy ~$dz barrier - + block_id = @s.block_id $mdx = $dx / 2.0 $mdy = $dy / 2.0 @@ -423,11 +423,11 @@ function recursive_pushed{$d}() at ~<$Deltas[$d]> recursive_pushed{$d}() end - + for $i in $range(16) $color = $Colors[$i] $dx, $dy, $dz = $Deltas[$d] - + # Check one block over for a piston tile entity with a sticky color sticky_color = -1 /execute if data block ~$dx ~$dy ~$dz {blockState:{Name:"minecraft:$color"}} run scoreboard players set Global sticky_color $i @@ -466,18 +466,18 @@ function recursive_push{$d, $force_sticky}() sticky = True end end - + if sticky for $side_delta in $SideDeltas[$d] at ~<$side_delta> unless @Pushing[distance=..0.1,limit=1] get_pushable{$d}() - + if $force_sticky check_force_sticky() - else + else check_sticky() end - + recursive_create_push{$d}() end end @@ -527,13 +527,13 @@ end function get_pushable{$direction}() pushable = $Undefined - + $dx,$dy,$dz = $Deltas[$direction] - + /execute if data block ~$dx ~$dy ~$dz {id:"minecraft:piston", source:0b, progress:0.0f, extending:1b, facing: $direction} run scoreboard players set Global pushable $Pushed $op = $OppositeDir[$direction] /execute if data block ~$dx ~$dy ~$dz {id:"minecraft:piston", source:0b, progress:0.0f, extending:0b, facing: $op} run scoreboard players set Global pushable $Pushed - + get_pushable_here() end @@ -541,7 +541,7 @@ function get_pushable_here() if pushable == $Undefined /execute if data block ~ ~ ~ {} run scoreboard players set Global pushable $BlockPush end - + if pushable == $Undefined if block ~ ~ ~ piston[extended=false] pushable = $Pushable @@ -559,4 +559,4 @@ function get_pushable_here() pushable = $Break end end -end \ No newline at end of file +end diff --git a/Scripts/archived 1.15 scripts/controllable_robot_arm.cbscript b/Scripts/archived 1.15 scripts/controllable_robot_arm.cbscript index d1b5762..2c9c916 100644 --- a/Scripts/archived 1.15 scripts/controllable_robot_arm.cbscript +++ b/Scripts/archived 1.15 scripts/controllable_robot_arm.cbscript @@ -32,7 +32,7 @@ function refresh() $create_control_block(-794, 56, 89, 2, "gold_block") $create_control_block(-792, 56, 89, 3, "iron_block") $create_control_block(-790, 56, 89, 4, "emerald_block") - + at @p seg = 0 while seg < $NumSegments @@ -57,20 +57,20 @@ function refresh() end @s.seg = seg @s.piece = piece - + @s.nonstick = True end end - + as create @Marker @s.seg = seg @s.drx = -25000 @s.dry = 20000 - + @s.nonstick = True end end - + as create @MiniBlock /replaceitem entity @s armor.head white_banner @s.claw_left = True @@ -82,7 +82,7 @@ function refresh() @s.nonstick = True end end - + @Physics.nonstick = True @SolidBlock.nonstick = True @Disguise.nonstick = True @@ -103,10 +103,10 @@ function apply_rotation() if @s.drx < -180000 @s.drx += 360000 end - + crx += @s.drx cry += @s.dry - + local_ry = cry local_rx = crx @@ -130,7 +130,7 @@ function apply_rotation() @s.rot_y = local_ry @s.update() end - + move @s ^ ^ ^0.6 end = @s. @@ -140,10 +140,10 @@ end clock main live = False - + apply_rotation() basedist = tdist - + if @Entity[hooked, not drop] @MiniBlock[claw_left].rot_x = 165000 @MiniBlock[claw_right].rot_x = 165000 @@ -154,7 +154,7 @@ clock main @MiniBlock[claw_right].rot_x = 135000 @MiniBlock[claw_right].rot_y = 180000 end - + at @Marker[seg==$NumSegments] @MiniBlock[claw_left].update() @MiniBlock[claw_right].update() @@ -168,15 +168,15 @@ clock main end end end - - + + @Entity[hooked, not drop, limit=1]. = - <0, 2000, 0> /data merge entity @Entity[hooked, not drop, limit=1] {NoGravity:1b} /data merge entity @Entity[hooked, drop, limit=1] {NoGravity:0b} move @MiniBlock ~ ~ ~ move @Entity[hooked, not drop, limit=1] ~ ~ ~ - + @Marker[seg==1].dry = (@Pushable[arm_control==1,limit=1].z * 20) % 360000 - 180000 @Marker[seg==2].drx = (@Pushable[arm_control==2,limit=1].z * 20 - 100000) % 360000 - 180000 @Marker[seg==3].dry = (@Pushable[arm_control==3,limit=1].z * 20) % 360000 - 180000 @@ -184,11 +184,11 @@ clock main drop = False /execute if block -787 56 91 redstone_lamp[lit=true] run scoreboard players set Global drop 1 - + if drop @Entity[hooked].drop = True end - + as @Entity[hooked, drop] at @s unless @MiniBlock[claw_left,distance=..3] @s.hooked = False @s.drop = False diff --git a/Scripts/archived 1.15 scripts/creative_flight_settings.cbscript b/Scripts/archived 1.15 scripts/creative_flight_settings.cbscript index 2a5088a..f2e016b 100644 --- a/Scripts/archived 1.15 scripts/creative_flight_settings.cbscript +++ b/Scripts/archived 1.15 scripts/creative_flight_settings.cbscript @@ -237,12 +237,12 @@ clock main tell @s '{RNo Momentum Disabled. {G[\[Enable\]](/trigger FlightSettings set 7)' end tell @s 'Type {w[/trigger FlightSettings](//trigger FlightSettings){- at any time to bring up this menu.' - + display_flight_settings() @s.FlightSettings = 0 /scoreboard players enable @s FlightSettings end - + = @s. as @s.marker = @s. @@ -251,17 +251,17 @@ clock main @s.marker = create @Marker end end - + if == @s.stop_count++ else = - speedsq = dx^2 + dy^2 + dz^2 - + /gamerule sendCommandFeedback false /gamemode spectator @s[gamemode=creative, noclip] /gamerule sendCommandFeedback true - + oldspeedsq = @s.speedsq * 9 / 10 if speedsq < oldspeedsq @s.stop_count++ @@ -269,10 +269,10 @@ clock main @s[stop_count > 6].stop_count = 0 @s[stop_count > 0].stop_count-- end - + @s.speedsq = speedsq - - if @s.vflight + + if @s.vflight unless @Position do create @Position at @s /tp @Position ~ ~ ~ 0 ~ @@ -281,23 +281,23 @@ clock main move @Position ^ ^ ^1 = @Position. - slope = fy * 1000 / fz - + at @s /tp @Position ~ ~ ~ ~ 0 end = @Position. move @Position ^ ^ ^1 = @Position. - - + hmag = dx^2+dz^2 hspeed = sqrt(hmag) nx = dx * 1000 / hspeed nz = dz * 1000 / hspeed - + mult = (nx*fx + nz*fz) / 1000 - + vmove = hspeed * slope / 1000 * mult / 1000 - + for $exp in [512, 256, 128, 64, 32, 16, 8, 4, 2, 1] $scaled = $float($exp) / 1000 $nexp = -$exp @@ -311,7 +311,7 @@ clock main end end end - + as @s.marker @s. = @player. end @@ -329,4 +329,4 @@ clock main end end end -end \ No newline at end of file +end diff --git a/Scripts/archived 1.15 scripts/deluminator.cbscript b/Scripts/archived 1.15 scripts/deluminator.cbscript index 34e9e0c..7725f22 100644 --- a/Scripts/archived 1.15 scripts/deluminator.cbscript +++ b/Scripts/archived 1.15 scripts/deluminator.cbscript @@ -17,7 +17,7 @@ define @Entity = @e rx = Rotation[1] float on_ground = OnGround byte 1 no_gravity = NoGravity byte 1 - + function get_facing_dir() at @s rotated @s at ^ ^ ^1 do @s. = here - @s. end @@ -60,7 +60,7 @@ clock main /kill @s end end - + for @torch in @Torch as @s.player(@Player) = @s. diff --git a/Scripts/archived 1.15 scripts/detect_right_click.cbscript b/Scripts/archived 1.15 scripts/detect_right_click.cbscript index 82b2861..1087d6e 100644 --- a/Scripts/archived 1.15 scripts/detect_right_click.cbscript +++ b/Scripts/archived 1.15 scripts/detect_right_click.cbscript @@ -15,4 +15,4 @@ end clock main -end \ No newline at end of file +end diff --git a/Scripts/archived 1.15 scripts/ender_clock.cbscript b/Scripts/archived 1.15 scripts/ender_clock.cbscript index feed832..c0bb4c2 100644 --- a/Scripts/archived 1.15 scripts/ender_clock.cbscript +++ b/Scripts/archived 1.15 scripts/ender_clock.cbscript @@ -22,7 +22,7 @@ reset /kill @Enderman /fill -10 56 179 29 66 190 air /fill -10 55 179 29 55 190 red_sandstone - + at @p for x = 17 to 27 for y = 56 to 58 @@ -35,12 +35,12 @@ reset end end end - + create @Enderman 20 56 185 as @Marker[pile] at @s /setblock ~ ~ ~ diamond_block end - + for digit = 1 to 4 for vseg = 1 to 3 for piece = 1 to 5 @@ -50,7 +50,7 @@ reset @s.digit = digit @s.vseg = vseg @s.piece = piece - + @s.x = scale * (-16 + digit * 7 + piece) + 500 if digit >= 3 @s.x += 3 * scale @@ -58,9 +58,9 @@ reset @s.y = scale * (52 + vseg * 4) + 500 @s.z = 180 * scale + 500 end - end + end end - + for hseg = 1 to 2 for vseg = 1 to 2 for piece = 1 to 5 @@ -71,7 +71,7 @@ reset @s.hseg = hseg @s.vseg = vseg @s.piece = piece - + @s.x = scale * (-19 + digit * 7 + hseg * 4) + (scale / 2) if digit >= 3 @s.x += 3000 @@ -82,49 +82,49 @@ reset end end end - end - + end + /setblock 6 59 180 diamond_block /setblock 6 61 180 diamond_block - + hour = 9 minute = 58 second = 0 clock_tick = 0 - + tell @a '{C[\[Add 20 Seconds\]](/scoreboard players add Global second 20) {Y[\[Add 10 Minutes\]](/scoreboard players add Global minute 10) {G[\[Add Hour\]](/scoreboard players add Global hour 1)' end clock main @Enderman.vx = 0 @Enderman.vz = 0 - + clock_tick++ if clock_tick >= 20 clock_tick -= 20 second++ end - + if second >= 60 second -= 60 minute++ end - + if minute >= 60 minute -= 60 hour++ end - + if hour >= 13 hour -= 12 end - + for digit = 1 to 4 if digit == 1 then val = hour / 10 if digit == 2 then val = hour % 10 if digit == 3 then val = minute / 10 if digit == 4 then val = minute % 10 - + as @Marker[segment] if @s.digit == digit @s.on = False if val == 0 @@ -173,15 +173,15 @@ clock main end end end - + as @Marker[segment, not on] at @s ~ ~-20 ~ /setblock ~ ~ ~ iron_block end - + as @Marker[segment, on] at @s ~ ~-20 ~ /setblock ~ ~ ~ diamond_block end - + as @Marker[segment, not on] at @s if block ~ ~-20 ~ diamond_block @s.on = True @@ -191,41 +191,41 @@ clock main end #as @Marker[segment, not on] at @s - # /setblock ~ ~ ~ air + # /setblock ~ ~ ~ air #end #as @Marker[segment, on] at @s - # /setblock ~ ~ ~ diamond_block + # /setblock ~ ~ ~ diamond_block #end - + unless @Position do create @Position - + cooldown++ if cooldown >= 25 cooldown = 0 - + as @Marker at @s @s.has_block = False unless block ~ ~ ~ air @s.has_block = True end - + @s.available = False if block ~ ~1 ~ air @s.available = True end - + @s.supported = False unless block ~ ~-1 ~ air @s.supported = True end end - + found = False i = 0 while not found and i < 500 i++ @Marker.current = False - + type = rand(2) attached = False if type == 0 @@ -257,7 +257,7 @@ clock main if dx >= -400 and dx <= 400 and dy == -2 dy-- end - + check_x = @s.x + dx check_y = @s.y + dy * scale - 500 if check_y == 56000 @@ -265,11 +265,11 @@ clock main end check_z = @s.z + dz @Position. = - + at @Position unless block ~ ~-1 ~ air if block ~ ~ ~ air and block ~ ~1 ~ air and block ~ ~2 ~ air found = True end - end + end end end if found @@ -283,7 +283,7 @@ clock main /tp @s ~ ~ ~ end end - + if cooldown == 5 if type == 0 @Marker[pile].current_pile = False @@ -297,7 +297,7 @@ clock main end end end - + if cooldown == 10 if type == 0 as @Marker[current_pile] at @s @@ -312,7 +312,7 @@ clock main end end end - + if cooldown == 15 if type == 0 as @Enderman @@ -325,10 +325,10 @@ clock main end end if type == 1 - + end end - + if cooldown == 20 if type == 1 @Marker[pile].current_pile = False @@ -342,7 +342,7 @@ clock main end end end - + if cooldown == 23 if type == 0 as @Marker[current] at @s @@ -366,6 +366,6 @@ clock main @s.fall = 0 end end - + /effect give @Enderman instant_health 1 1 true end diff --git a/Scripts/archived 1.15 scripts/evolution.cbscript b/Scripts/archived 1.15 scripts/evolution.cbscript index 24ac4b0..3603eb3 100644 --- a/Scripts/archived 1.15 scripts/evolution.cbscript +++ b/Scripts/archived 1.15 scripts/evolution.cbscript @@ -53,7 +53,7 @@ $GeneNames = [ 'Target AI: TNT Cooldown', 'Target AI: TNT Fuse', ] - + $SlotNames = [ 'feet', @@ -77,7 +77,7 @@ define @Body : @Entity[type=zombie, tag=Body] array genes[$NumGenes] custom_name_visible: CustomNameVisible byte 1 is_baby: IsBaby byte 1 - + function set_rotation() unless @Position do create @Position /tp @Position ~ ~ ~ ~ ~ @@ -87,7 +87,7 @@ define @Body : @Entity[type=zombie, tag=Body] @s.boredom++ @s.targetting = True end - + function initialize() for $slot in $range(4) $slot_name = $SlotNames[$slot] @@ -100,14 +100,14 @@ define @Body : @Entity[type=zombie, tag=Body] end /execute store result entity @s ArmorItems[$slot].tag.display.color int 1 run scoreboard players get Global color end - + @s.cooldown = 20 @s.boredom = 0 @s.force_wander = 0 @s.rot_y = rand(0, 360000) @s.children = 0 end - + function update_energy() switch @s.energy case $e in $range(1000) @@ -118,12 +118,12 @@ define @Body : @Entity[type=zombie, tag=Body] end end end - + function create_adult() @Body.current = False @s.current = True @baby = @Body[current,distance=0,limit=1] - + at @s as create @Body /tp @s ~ ~ ~ ~ ~ @@ -176,7 +176,7 @@ function create_body() for gene = 0 to $NumGenes-1 @s.genes[gene] = rand($GeneMax) end - + @s.is_baby = True @s.energy = 100 @s.generation = 0 @@ -206,13 +206,13 @@ function walls() /fill -100 54 -100 100 100 -101 stone_bricks /fill -100 54 100 100 100 101 stone_bricks /fill -100 54 -100 -101 100 100 stone_bricks - /fill 100 54 -100 101 100 100 stone_bricks + /fill 100 54 -100 101 100 100 stone_bricks end reset tell @a '{G[\[Create Body\]](call create_body) {R[\[Kill Bodies\]](call kill_all_bodies) {B[\[Populate 40\]](call populate40) {W[\[Create Walls\]](call walls)' as @Body do @s.custom_name_visible = True - + $NewGenes = [] for $gene in $NewGenes as @Body @@ -224,7 +224,7 @@ end clock main = rand_wander = rand(-30, 30) - + unless @Position do create @Position for @body in @Body @@ -232,25 +232,25 @@ clock main @s.age++ @s.fire = 0 /effect give @s minecraft:slowness 1 10 true - + @s.part_cooldown-- - + @s. += * @s.genes[$Jitter] / 1000 - + @s.vy += (@s.genes[$AntiGrav] - $GeneMax / 2) * 180 / $GeneMax @s.targetting = False - + at ~ ~0.5 ~ if block ^ ^ ^1 air @s.blocked = False else @s.blocked = True end - + if @s.boredom > @s.genes[$BoredomTime] @s.force_wander = @s.genes[$BoredomWander] @s.boredom = 0 end - + if @s.force_wander @s.force_wander-- if @s.part_cooldown <= 0 @@ -260,8 +260,8 @@ clock main @s.part_cooldown = 3 end end - - + + @s.wander = True @s.willing = False @@ -274,7 +274,7 @@ clock main @s.part_cooldown = 4 end end - + @s.seeking_mate = False if @s.willing as @Body[distance=1..$SightRange,sort=nearest,limit=1,willing] @@ -283,17 +283,17 @@ clock main at @body facing @s @body.set_rotation() end - + at @s if @body[distance=..2] /particle flash ~ ~ ~ 0 0 0 0 1 force @s.willing = False @body.willing = False - + @s.boredom = 0 @body.boredom = 0 - + baby_energy = @s.genes[$BabyEnergy] / 5 + @body.genes[$BabyEnergy] / 5 - + @s.energy -= @s.genes[$BabyEnergy] / 5 @s.update_energy() @body.energy -= @body.genes[$BabyEnergy] / 5 @@ -302,18 +302,18 @@ clock main @Body.mate = False @s.mate = True @mate = @Body[mate,limit=1,distance=..5] - + as create @Body for $gene in $range($NumGenes) randomize_gene = rand(16) - + if randomize_gene == 0 @s.genes[$gene] = rand($GeneMax) else prop = rand(100) @s.genes[$gene] = @body.genes[$gene] * prop / 100 + @mate.genes[$gene] * (100-prop) / 100 + rand(-$MutationRate,$MutationRate) end - + if @s.genes[$gene] < 0 @s.genes[$gene] = 0 end @@ -324,41 +324,41 @@ clock main @s.energy = baby_energy @s.is_baby = True @s.update_energy() - + if @body.generation > @mate.generation @s.generation = @body.generation + 1 else @s.generation = @mate.generation + 1 end - + @body.children++ @mate.children++ - + @s.initialize() end end end end - + unless @s.seeking_mate if @s.force_wander == 0 as @Food[distance=..$SightRange,limit=1,sort=nearest] @body.wander = False at @body facing @s @body.set_rotation() end end - + if @s.wander if @s.blocked @s.rot_y += (@s.genes[$BlockedWander] - ($GeneMax / 2)) * 30 end - + @s.ry = @s.rot_y @s.rot_y += rand_wander * @s.genes[$WanderDRY] @s.rx = 0 - + @s.boredom = 0 end - + @s[cooldown > 0].cooldown-- if @s.cooldown == 0 at @s if @s.blocked @@ -379,8 +379,8 @@ clock main fuse = @s.genes[$WanderFuse] end end - - + + as @Position /tp @s ~ ~ ~ ~ ~ = @s. @@ -393,13 +393,13 @@ clock main at ~ ~1 ~ @s.energy-- @s.update_energy() - + as create @TNTCarrier /tp @s ~ ~ ~ ~ ~ @s.fuse = fuse * 80 / $GeneMax id = &@s end - + as create @TNTPhysics /tp @s ~ ~ ~ ~ ~ @s. = * (up - $GeneMax / 2) / $GeneMax @@ -407,7 +407,7 @@ clock main /playsound minecraft:entity.tnt.primed hostile @a @s.carrier = id end - + as @DummyTNT[distance=..2] unless @s.initialized @s.fuse = fuse * 80 / $GeneMax + 1 v = @s.fuse @@ -415,7 +415,7 @@ clock main end end end - + food_eaten = 0 /execute store result score Global food_eaten run kill @Food[distance=..1] @s.energy += food_eaten * 20 @@ -423,11 +423,11 @@ clock main if food_eaten > 0 @s.boredom = 0 end - + if @s.energy <= 0 /kill @s end - + if @s.age > $AdultTicks and @s.is_baby == 1 @s.create_adult() /tp @s ~ -100 ~ @@ -435,14 +435,14 @@ clock main end end end - + as @DummyTNT at @s if @s.fuse == @s.prev_fuse # This is necessary because TNT doesn't tick down if it's far enough away /kill @s end @s.prev_fuse = @s.fuse - + if @s.fuse == 1 /particle minecraft:explosion ~ ~ ~ 2 2 2 0 5 force /playsound minecraft:entity.generic.explode hostile @a @@ -452,13 +452,13 @@ clock main = @s. y2 += scale distsq = ((x1-x2)^2 + (y1-y2)^2 + (z1-z2)^2) / scale - + @s. += ((@s. + <0, scale, 0>) - ) * scale * 3 / distsq end /kill @s end end - + as @TNTPhysics at @s as @s.carrier /tp @s ~ ~ ~ ~ ~ @@ -466,7 +466,7 @@ clock main /kill @s end end - + cleanup_timer++ if cleanup_timer >= 20 cleanup() @@ -488,14 +488,14 @@ clock hover @s.glowing = False end end - + as @Body[hover_timer == 10] for $gene in $range($NumGenes) val = @s.genes[$gene] $gene_name = $GeneNames[$gene] tell @a '(val) - $gene_name' end - + age = @s.age / 1200 tell @a 'Age: (age) minutes' generation = @s.generation @@ -505,18 +505,18 @@ clock hover end end -function cleanup() +function cleanup() as @TNTCarrier unless @s.fuse > 0 /kill @s - end + end end as @Food @s.on_ground = False @s.time = 1 end - + as @FoodCarrier unless @s.time > 0 /kill @s diff --git a/Scripts/archived 1.15 scripts/falling_blocks.cbscript b/Scripts/archived 1.15 scripts/falling_blocks.cbscript index 43c5ae3..6fdf560 100644 --- a/Scripts/archived 1.15 scripts/falling_blocks.cbscript +++ b/Scripts/archived 1.15 scripts/falling_blocks.cbscript @@ -16,6 +16,6 @@ end clock main as @Player[limit=1] - + end -end \ No newline at end of file +end diff --git a/Scripts/archived 1.15 scripts/fast_ladders.cbscript b/Scripts/archived 1.15 scripts/fast_ladders.cbscript index b622e2c..1731046 100644 --- a/Scripts/archived 1.15 scripts/fast_ladders.cbscript +++ b/Scripts/archived 1.15 scripts/fast_ladders.cbscript @@ -18,7 +18,7 @@ clock main /tp @s ~ ~ ~ end end - + @s.prev_y = @s.y end -end \ No newline at end of file +end diff --git a/Scripts/archived 1.15 scripts/flamethrower.cbscript b/Scripts/archived 1.15 scripts/flamethrower.cbscript index f714752..0d9b087 100644 --- a/Scripts/archived 1.15 scripts/flamethrower.cbscript +++ b/Scripts/archived 1.15 scripts/flamethrower.cbscript @@ -8,7 +8,7 @@ define @Flame: @Entity[type=pig, tag=Flame] end reset - + end clock main @@ -24,15 +24,15 @@ clock main end end end - + if @s.fuel > 0 @s.fuel-- - + @s.get_aim() - + rx = @s.rx ry = @s.ry - + at ^ ^1 ^2 /tp @Position ~ ~ ~ ~ ~ as create @Flame ~ ~ ~ @@ -69,4 +69,4 @@ clock main /kill @s end end -end \ No newline at end of file +end diff --git a/Scripts/archived 1.15 scripts/flowing_snow.cbscript b/Scripts/archived 1.15 scripts/flowing_snow.cbscript index 2cfafac..74eefda 100644 --- a/Scripts/archived 1.15 scripts/flowing_snow.cbscript +++ b/Scripts/archived 1.15 scripts/flowing_snow.cbscript @@ -12,16 +12,16 @@ $Neighbors = [ define @SnowMarker: @Entity[type=area_effect_cloud,tag=SnowMarker] create {Tags:["SnowMarker"], Duration:-1,Age:-2147483648,WaitTime:-2147483648} - + function check_neighbors() if @s.source my_level = 8 else my_level = @s.level end - + max_neighbor = 0 - + for $dx, $dz in $Neighbors at @s ~$dx ~ ~$dz as @SnowMarker[distance=..0.01,limit=1] @@ -42,12 +42,12 @@ define @SnowMarker: @Entity[type=area_effect_cloud,tag=SnowMarker] end end end - + if my_level >= max_neighbor unless @s.source @s.update_level(@s.level-1) end end - + function update_level(new_level) at @s @s.level = new_level @@ -115,7 +115,7 @@ clock main end end end - + as @SnowMarker at @s @s.tick++ if @s.tick >= 5 diff --git a/Scripts/archived 1.15 scripts/giant_fireworks.cbscript b/Scripts/archived 1.15 scripts/giant_fireworks.cbscript index 728b5f0..e39403e 100644 --- a/Scripts/archived 1.15 scripts/giant_fireworks.cbscript +++ b/Scripts/archived 1.15 scripts/giant_fireworks.cbscript @@ -42,7 +42,7 @@ clock main @s.age++ if @s.age == 40 /playsound minecraft:entity.firework_rocket.large_blast neutral @a ~ ~ ~ 1 0 0.7 - + for ry = 0 to 350000 by 20000 for rx = -80000 to 80000 by 10000 as create @GiantItem ~2 ~-6 ~-4 @@ -56,13 +56,13 @@ clock main end @s. = @s.vy /= 2 - + /team join no_collision /replaceitem entity @s weapon.mainhand blue_wool end end end - + /kill @s end end @@ -73,4 +73,4 @@ clock main /kill @s end end -end \ No newline at end of file +end diff --git a/Scripts/archived 1.15 scripts/gif_recorder.cbscript b/Scripts/archived 1.15 scripts/gif_recorder.cbscript index cf16a36..9476dac 100644 --- a/Scripts/archived 1.15 scripts/gif_recorder.cbscript +++ b/Scripts/archived 1.15 scripts/gif_recorder.cbscript @@ -37,7 +37,7 @@ $map_z = -64 reset /gamerule maxCommandChainLength 1000000000 /gamerule randomTickSpeed 0 - + /bossbar add progress "Progress" /bossbar set progress max 128 @@ -46,7 +46,7 @@ reset unless @Texture do create @Texture tell @a "{Y[\[Record\]](/function gif_recorder:record) [\[Setup\]](/function gif_recorder:setup)" - + @a.render = False @a.recording = False @@ -66,7 +66,7 @@ end function setup() fill_ceiling() - + /bossbar set progress players @s for $x in $range($map_x-8, $map_x+128+8, 8) $dx = $x - $map_x @@ -115,7 +115,7 @@ clock recording @s. = @s. end end - get_looking_at() + get_looking_at() end for @player in @Player[recording] @@ -140,7 +140,7 @@ end function stop_recording() @s.last_frame = @s.frame - 1 @s.recording = False - + tell @s "{G[\[Render\]](/function gif_recorder:start_render)" end @@ -176,14 +176,14 @@ clock render @s.end_id = @s.start_id + @s.last_frame @s.render_id = @s.map_id end - end - + end + if @s.render_id and @s.map_id == @s.render_id @s.give_map_delay = 40 @s.render_id++ end end - + @Player[give_map_delay].give_map_delay-- as @Player[give_map_delay == 1] /replaceitem entity @s weapon map @@ -227,11 +227,11 @@ function take_picture() /bossbar set progress players @a $clone_overlay(0, 63) $clone_overlay(1, 69) - + at @s /tp @Scan ~ ~1.8 ~ ~ ~ end - + move @Scan ^$Radius ^$Radius ^10 at $map_x-1 128 $map_z col = 0 @@ -240,7 +240,7 @@ function take_picture() row = 0 /execute store result bossbar progress value run scoreboard players get Global col take_picture_col() - + col++ move @Scan ^-$PixelMove ^$Diameter ^ = @Scan. @@ -254,7 +254,7 @@ macro $take_picture_col_recurse($dy) # Copy the block into the map area /clone 0 1 0 0 1 0 ~ ~ ~ /fill ~ ~1 ~ ~ 253 ~ air - + # Move on to the next row row++ move @Scan ^ ^-$PixelMove ^ @@ -271,18 +271,18 @@ function take_picture_col() at @s ~ ~1.8 ~ facing @Scan ray_trace_step() end - + handled = False if face_x $take_picture_col_recurse(-1) handled = True end - + if face_y and not handled $take_picture_col_recurse(1) handled = True end - + if face_z and not handled $take_picture_col_recurse(0) handled = True @@ -297,7 +297,7 @@ function ray_trace_step() at ^ ^ ^$Step do ray_trace_step() handled = True end - + if not handled at ^ ^ ^-$Step fine_step = 0 @@ -321,18 +321,18 @@ end function ray_trace_fine_step() $FineStep = 0.02 - + handled = False if block ~ ~ ~ none and fine_step < 11 fine_step++ at ^ ^ ^$FineStep do ray_trace_fine_step() handled = True end - + if not handled $create_map_block_at(0, 1, 0) - - # Compute which face was crossed first + + # Compute which face was crossed first as @Position /tp @s ~ ~ ~ ~ ~ = @s. @@ -342,7 +342,7 @@ function ray_trace_fine_step() = % 1000 = - = + - + if bx2 > 1000 px = (1000-bx1) * 100 / dx end @@ -352,7 +352,7 @@ function ray_trace_fine_step() if bx2 >= 0 and bx2 < 1000 px = 0 end - + if by2 > 1000 py = (1000-by1) * 100 / dy top_face = False @@ -366,7 +366,7 @@ function ray_trace_fine_step() if by2 >= 0 and by2 < 1000 py = 0 end - + if bz2 > 1000 pz = (1000-bz1) * 100 / dz end @@ -376,7 +376,7 @@ function ray_trace_fine_step() if bz2 >= 0 and bz2 < 1000 pz = 0 end - + if face_x and block ~ ~ ~ grass_block $set_texture(70) end @@ -386,7 +386,7 @@ function ray_trace_fine_step() if face_y and bottom_face and block ~ ~ ~ grass_block $set_texture(70) end - + if px face_x = True face_y = False @@ -394,7 +394,7 @@ function ray_trace_fine_step() u = by1 v = bz1 end - + if py face_x = False face_y = True @@ -402,7 +402,7 @@ function ray_trace_fine_step() u = bz1 v = bx1 end - + if pz face_x = False face_y = False @@ -410,14 +410,14 @@ function ray_trace_fine_step() u = by1 v = bx1 end - + if fine_step >= 11 face_x = False face_y = True face_z = False /setblock 0 1 0 light_blue_wool end - + $get_texture("oak_planks", 63) $get_texture("bricks", 64) $get_texture("spruce_leaves", 66) @@ -434,7 +434,7 @@ clock draw for @itemframe in @ItemFrame map_id = 0 map_id = @s.map - + unless @s.start_id if map_id as @Player if map_id >= @s.start_id and map_id <= @s.end_id @@ -444,15 +444,15 @@ clock draw end end end - + if @s.start_id @s.map++ if @s.map > @s.end_id then @s.map = @s.start_id end - + unless @s.frame >= @s.start_id @s.frame = @s.start_id @s.map = @s.frame end end -end \ No newline at end of file +end diff --git a/Scripts/archived 1.15 scripts/glass_pipes.cbscript b/Scripts/archived 1.15 scripts/glass_pipes.cbscript index 13f0ba7..1339902 100644 --- a/Scripts/archived 1.15 scripts/glass_pipes.cbscript +++ b/Scripts/archived 1.15 scripts/glass_pipes.cbscript @@ -33,10 +33,10 @@ define @Marker: @Marker @s.done = True else @s.initialize = False - + = @s. = -@s. - + searching = True first = True while searching @@ -46,7 +46,7 @@ define @Marker: @Marker else r = rand(0, 6) end - + switch r case $i in $range(6) @@ -71,7 +71,7 @@ end define @Player: @Player marker: @Marker - + function get_facing_dir() rx = @s.rx ry = @s.ry % 360000 @@ -101,21 +101,21 @@ function is_pipe() else glass_x = 0 end - + if block ~ ~1 ~ glass and block ~ ~-1 ~ glass glass_y = 1 else glass_y = 0 end - + if block ~ ~ ~1 glass and block ~ ~ ~-1 glass glass_z = 1 else glass_z = 0 end - + glass = glass_x + glass_y + glass_z - + if glass == 2 and block ~ ~ ~ air return True else @@ -142,7 +142,7 @@ function is_entry() unless block ~ ~$d ~$d3 air do start_yz = 0 end end - + if start_xy + start_xz + start_yz > 0 return True else @@ -158,7 +158,7 @@ clock main unless @Position do create @Position /tp @Position ~ ~ ~ ~ ~ @Position. += @s. * 750 - + at @Position if block ~ ~ ~ air if @player.pipe_slow @s. += @s. * 250 @@ -170,15 +170,15 @@ clock main @s.x = @s.x / 1000 * 1000 + 500 end if my == 0 - @s.y = @s.y / 1000 * 1000 + @s.y = @s.y / 1000 * 1000 end if mz == 0 @s.z = @s.z / 1000 * 1000 + 500 end - + @s.ry = @player.ry @s.rx = @player.rx - + /tp @player ~ 128 ~ at @s /tp @player ~ ~ ~ @@ -195,7 +195,7 @@ clock main at @s /tp @player ~ ~ ~ end - + /kill @s @player.travel = None @player.force_exit = True @@ -205,7 +205,7 @@ clock main else @s.exit_junction = False end - end + end else @s.pick_dir() if @s.done @@ -237,7 +237,7 @@ clock main end end end - + if @s.pipe_sound > 0 at @s switch @s.pipe_sound case 15 @@ -287,4 +287,4 @@ function play_pipe_sound() /playsound minecraft:block.note_block.bit block @a ~ ~ ~ 1 1 /playsound minecraft:block.note_block.bit block @a ~ ~ ~ 1 1.5 /playsound minecraft:block.note_block.bit block @a ~ ~ ~ 1 2 -end \ No newline at end of file +end diff --git a/Scripts/archived 1.15 scripts/guided_missile.cbscript b/Scripts/archived 1.15 scripts/guided_missile.cbscript index c550cae..59ccbb4 100644 --- a/Scripts/archived 1.15 scripts/guided_missile.cbscript +++ b/Scripts/archived 1.15 scripts/guided_missile.cbscript @@ -15,7 +15,7 @@ end @Player = @Entity[type=player] reset - /scoreboard objectives add shot minecraft.used:minecraft.bow + /scoreboard objectives add shot minecraft.used:minecraft.bow end clock main diff --git a/Scripts/archived 1.15 scripts/katamari.cbscript b/Scripts/archived 1.15 scripts/katamari.cbscript index dcaf0f1..640f9a6 100644 --- a/Scripts/archived 1.15 scripts/katamari.cbscript +++ b/Scripts/archived 1.15 scripts/katamari.cbscript @@ -34,12 +34,12 @@ end reset /team add katamari /team modify katamari collisionRule pushOtherTeams - + move @Ball ~ -100 ~ /kill @Ball /kill @Angle /kill @e[stuck > 0] - + as @a at @s ~ ~1.6 ~ at ^ ^ ^5 @s.ball = create @Ball as @s.ball @@ -49,7 +49,7 @@ reset /team join katamari @s end end - + Debug = 0 end @@ -59,7 +59,7 @@ clock main at @s ~ ~1.6 ~ at ^ ^ ^5 create @Marker end - + @CurMarker = @Marker[limit=1] @CurMarker.nonstick = True as @CurMarker @@ -71,21 +71,21 @@ clock main end move @s ~ ~0.3 ~ end - + as @s.ball(@Ball) @Ball.current_ball = True @CurBall = @Ball[current_ball,limit=1] dx = @CurMarker.x - @s.x dz = @CurMarker.z - @s.z - + do_roll = False speedsq = @s.vx^2 + @s.vz^2 if speedsq >= 2000 do_roll = True end - + dist = sqrt(dx^2 + dz^2) - + @s.vx /= 3 @s.vz /= 3 at @s if @CurMarker[distance=..5] and dist > 100 @@ -94,43 +94,43 @@ clock main if speedsq < 2000 at @s unless block ~ ~-1.5 ~ air @s.vy = 30 end - + @s.vx = dx * 60 / dist @s.vz = dz * 60 / dist - + do_roll = True end at @s unless @CurMarker[distance=..5] @s.vx = 0 @s.vz = 0 end - - if do_roll + + if do_roll roll_rotate_entities() end - + ballx = @CurBall.x bally = @CurBall.y ballz = @CurBall.z - + for @CurEnt in @Entity[stuck] @s.x = ballx + @s.dx @s.y = bally + @s.dy @s.z = ballz + @s.dz end - + /data merge entity @s {OnGround:0b} - + at @s for @CurEntity in @Entity[type=!player,distance=..5] unless @s.nonstick @s.dx = @s.x - ballx @s.dy = @s.y - bally @s.dz = @s.z - ballz - + distsq = @s.dx^2 + @s.dy^2 + @s.dz^2 sizesq = (2 * @CurBall.radius)^2 - + @s.mass = 20 @s[type=chicken].mass = 15 @s[type=pig].mass = 35 @@ -201,7 +201,7 @@ clock main @s[type=zombie_pigman].mass = 50 @s[type=zombie_villager].mass = 50 mass_ratio = @CurBall.mass / @s.mass - + if distsq < sizesq and mass_ratio > 4 @s.nonstick = True @s.stuck = @CurBall @@ -217,13 +217,13 @@ clock main end end end - + @Ball.current_ball = False end - - + + /kill @CurMarker - end + end end function roll_rotate_entities() @@ -234,7 +234,7 @@ function roll_rotate_entities() ballvx = @s.vx ballvy = @s.vy ballvz = @s.vz - + # Get direction of movement as create @Angle @s.forward = True @@ -243,7 +243,7 @@ function roll_rotate_entities() @s.y = bally + ballvy @s.z = ballz + ballvz end - + # Get perpendicular "roll axis" as create @Angle @s.left = True @@ -262,52 +262,52 @@ function roll_rotate_entities() mradius = -radius rollarc = 4000 / @CurBall.radius minradsq = radius^2 * 3 / 4 - + /kill @Angle # Handle each entity as @Entity if @s.stuck == @CurBall._id @s.current = True @CurEnt = @e[current,limit=1] - + curdx = @s.dx curdy = @s.dy curdz = @s.dz - + # Teleport to the same position relative to the ball @s.x = ballx + curdx @s.y = bally + curdy @s.z = ballz + curdz - + # Get offset projected onto roll axis dot = ((@s.dx * leftx) + (@s.dy * lefty) + (@s.dz * leftz)) / 256 px = dot * leftx / 256 py = dot * lefty / 256 pz = dot * leftz / 256 - + if dot > radius then dot = r if dot < mradius then dot = mradius - + as create @Angle /tp @s @CurBall # Start at projected location along roll axis @s.x = ballx + px @s.y = bally + py @s.z = ballz + pz - + # Roll angle about roll axis at @s /tp @s ~ ~ ~ facing entity @CurEnt end - + obj_angle = @s.ry - + roll_dir = 1 arc_delta = (((obj_angle - roll_angle) + 360) % 360) if arc_delta > 90 and arc_delta < 270 roll_dir = -1 end - + # Entity is behind the roll axis, roll upward if roll_dir == -1 ang = @s.rx @@ -317,7 +317,7 @@ function roll_rotate_entities() if ang < flipangle flip = True end - + if flip @s.rx = -180 + rollarc - ang @s.ry += 180 @@ -326,17 +326,17 @@ function roll_rotate_entities() @s.rx = ang - rollarc end end - + # Entity is in front of the roll axis, roll downward if roll_dir == 1 ang = @s.rx - + flip = False flipangle = 90 - rollarc if ang > flipangle flip = True end - + if flip @s.rx = 180 - rollarc - ang @s.ry += 180 @@ -347,10 +347,10 @@ function roll_rotate_entities() end x_angle = @s.rx - + # Get unit vector of rolled angle move @s ^ ^ ^1 - + dirx = @s.x - (ballx + px) diry = @s.y - (bally + py) dirz = @s.z - (ballz + pz) @@ -361,23 +361,23 @@ function roll_rotate_entities() pdx = curdx - px pdy = curdy - py pdz = curdz - pz - + pdist = sqrt(pdx^2 + pdy^2 + pdz^2) - + # Add roll axis projected vector with offset from projection @s.dx = px + (dirx * pdist / 256) @s.dy = py + (diry * pdist / 256) @s.dz = pz + (dirz * pdist / 256) - + distsq = @s.dx^2 + @s.dy^2 + @s.dz^2 - + # Store new entity offset @s.x = ballx + @s.dx @s.y = bally + @s.dy @s.z = ballz + @s.dz - + @s.current = False - + if Debug > 0 tell @a: leftxyz (Global.leftx) (Global.lefty) (Global.leftz) tell @a: curdxyz (Global.curdx) (Global.curdy) (Global.curdz) diff --git a/Scripts/archived 1.15 scripts/lightning.cbscript b/Scripts/archived 1.15 scripts/lightning.cbscript index 4d460d3..ce24c07 100644 --- a/Scripts/archived 1.15 scripts/lightning.cbscript +++ b/Scripts/archived 1.15 scripts/lightning.cbscript @@ -14,7 +14,7 @@ end clock main as @Lightning = @s. - + tell @a '(x) (y) (z)' end -end \ No newline at end of file +end diff --git a/Scripts/archived 1.15 scripts/limbo.cbscript b/Scripts/archived 1.15 scripts/limbo.cbscript index 5c2ec86..6af3306 100644 --- a/Scripts/archived 1.15 scripts/limbo.cbscript +++ b/Scripts/archived 1.15 scripts/limbo.cbscript @@ -77,7 +77,7 @@ define @BoyPos : 0-0-0-0-0xB0110C (@Entity[type=area_effect_cloud]) } } ] - } + } end define @Boy : 0-0-0-0-0xB01 (@Entity[type=armor_stand]) @@ -101,13 +101,13 @@ function reload() /kill @Boy /tp @Player $ResetX $ResetY $ResetZ 90 0 - + /kill @Vindicator /kill @Creeper /kill @Spider create @Vindicator -259 86.0 148 create @Creeper -259 86 146 - + dead_amount = 0 dead = False end @@ -115,7 +115,7 @@ end clock main unless @BoyPos do create @BoyPos $GameX 86 164.5 unless @BoyPhysics do create @BoyPhysics $GameX 86 164.5 - + as @Entity[run] @s.ry = 180000 move @s ~ ~ ~-0.4 @@ -123,12 +123,12 @@ clock main /kill @s end end - - as @Player[limit=1] at @s + + as @Player[limit=1] at @s at @s eyes /particle minecraft:squid_ink ^ ^ ^0.15 3 3 3 0 3000 force end - + if dead if dead_amount < 100 dead_amount += 4 @@ -142,13 +142,13 @@ clock main end end @BoyPhysics.vz /= 2 - + if @s.z > @BoyPhysics.z + 200 @BoyPhysics.vz += 170 if @BoyPhysics.vz > 300 @BoyPhysics.vz = 300 end - + if running_amount < 100 running_amount += 10 end @@ -157,7 +157,7 @@ clock main if @BoyPhysics.vz < -300 @BoyPhysics.vz = -300 end - + if running_amount < 100 running_amount += 10 end @@ -166,7 +166,7 @@ clock main running_amount -= 10 end end - + if @BoyPhysics.on_ground if @BoyPhysics.vz > 0 @Boy.ry = 0 @@ -175,13 +175,13 @@ clock main @Boy.ry = 180000 end end - + at @BoyPos if block ~ ~0.5 ~ death dead = True end end - + if @BoyPos and @BoyPos.z < 154000 @Vindicator.run = True @Creeper.run = True @@ -195,25 +195,25 @@ clock main z1 = @BoyPos.z z2 = @s.z y = @BoyPos.y - + if @BoyPos.z >= @s.z and @BoyPos.z <= @s.z + 5000 and @BoyPos.y >= 85000 dead = True end end end - + as @Spider if @s.z < 0 /kill @s end end - + at @BoyPhysics ~ ~-0.5 ~ /tp @BoyPos ~ ~ ~ @BoyPos.air = 0 @BoyPos.air = 1 end - + if @s.z < @BoyPhysics.z - 750 /setblock ~ ~ ~-1 barrier else @@ -225,9 +225,9 @@ clock main /setblock ~ ~ ~1 air end - + get_pose() - + @s.jumped = 0 end end @@ -252,7 +252,7 @@ end function get_blended(slot) temp_pose = running_pose(slot) * running_amount / 100 pose = (death_pose(slot) * dead_amount + temp_pose * (100 - dead_amount)) / 100 - + return pose end @@ -269,4 +269,4 @@ end function death_pose(slot) return 90 -end \ No newline at end of file +end diff --git a/Scripts/archived 1.15 scripts/magnet.cbscript b/Scripts/archived 1.15 scripts/magnet.cbscript index 69e5347..b1b4e50 100644 --- a/Scripts/archived 1.15 scripts/magnet.cbscript +++ b/Scripts/archived 1.15 scripts/magnet.cbscript @@ -25,7 +25,7 @@ end clock main for @m1 in @Magnet for @m2 in @Magnet - + end end end diff --git a/Scripts/archived 1.15 scripts/magnitude_test.cbscript b/Scripts/archived 1.15 scripts/magnitude_test.cbscript index 657bd6a..30b60b6 100644 --- a/Scripts/archived 1.15 scripts/magnitude_test.cbscript +++ b/Scripts/archived 1.15 scripts/magnitude_test.cbscript @@ -17,7 +17,7 @@ define @Entity = @e rx = Rotation[1] float on_ground = OnGround byte 1 no_gravity = NoGravity byte 1 - + function get_facing_dir() at @s rotated @s at ^ ^ ^1 do @s. = here - @s. end @@ -47,7 +47,7 @@ clock main end tell @a: (s) /say Done - + /say Lookat method for i = 1 to 5000 as @mark @@ -63,10 +63,10 @@ clock main if uy == 0 s = z * scale / uz end - end + end end end end tell @a: (s) /say Done -end \ No newline at end of file +end diff --git a/Scripts/archived 1.15 scripts/map_grid_puzzle.cbscript b/Scripts/archived 1.15 scripts/map_grid_puzzle.cbscript index 18c2dd4..fad479d 100644 --- a/Scripts/archived 1.15 scripts/map_grid_puzzle.cbscript +++ b/Scripts/archived 1.15 scripts/map_grid_puzzle.cbscript @@ -10,7 +10,7 @@ end reset /kill @Frame - + for dx = 0 to 4 by 1 for dy = 0 to 0 by 1 for dz = 0 to 4 by 1 @@ -47,7 +47,7 @@ clock main update = False unless map == @s.prev_map do update = True unless rotation == @s.prev_rotation do update = True - + if update at (<-800, 55, 151> + <@s.puzzle_x*5, 0, @s.puzzle_z*5>) * 1000 switch map @@ -71,4 +71,4 @@ clock main @s.prev_map = map @s.prev_rotation = rotation end -end \ No newline at end of file +end diff --git a/Scripts/archived 1.15 scripts/map_video.cbscript b/Scripts/archived 1.15 scripts/map_video.cbscript index a867f7d..75e76c7 100644 --- a/Scripts/archived 1.15 scripts/map_video.cbscript +++ b/Scripts/archived 1.15 scripts/map_video.cbscript @@ -19,7 +19,7 @@ end define @Frame = @Entity[type=item_frame] map = Item.tag.map int 1 silent = Silent byte 1 -end +end reset /kill @Marker @@ -34,7 +34,7 @@ function setup() tell @s: Running setup. This may take several minutes... /setworldspawn 0 201 0 /tp @s 0 201 3 - + for $cx in: range(-3, 10) for $cz in: range(-10, 10) $xmin: cx*8 @@ -77,7 +77,7 @@ clock recording @s.frame = @player.frame end end - + as @Marker if @s.owner == @player._id @s.age++ end @@ -98,8 +98,8 @@ function ray_trace() unless block ~ ~ ~ none /clone ~ ~ ~ ~ ~ ~ 0 1 0 end - - if block ~ ~ ~ none + + if block ~ ~ ~ none at ^ ^ ^1 ray_trace() end @@ -233,10 +233,10 @@ clock rendering end end - + /kill @Pixel end - + /kill @s end @@ -258,10 +258,10 @@ clock playing for @player in @a[playing] @s.frame++ frame = @s.frame - + if @s.frame == @s.end_frame @s.playing = False tell @s: {GDone playing! end end -end \ No newline at end of file +end diff --git a/Scripts/archived 1.15 scripts/minecraft_earth.cbscript b/Scripts/archived 1.15 scripts/minecraft_earth.cbscript index a7bb4d5..7a3fa6f 100644 --- a/Scripts/archived 1.15 scripts/minecraft_earth.cbscript +++ b/Scripts/archived 1.15 scripts/minecraft_earth.cbscript @@ -140,10 +140,10 @@ reset unless game_mode > 0 do game_mode = $ModeNone click_detector_reset() - + /team add tappable /team modify stasis_target color yellow - + unless build_plate[0] >= 0 for $x in $range(8) for $y in $range(3) @@ -163,11 +163,11 @@ function refresh_landscape(force) /replaceitem entity @s armor.head player_head end end - + unless @Position do create @Position base_x = @s.x / 10000 * 10000 base_z = @s.z / 10000 * 10000 - + if base_x == @s.base_x and base_z == @s.base_z and not force else @Terrain.unused = True @@ -180,7 +180,7 @@ function refresh_landscape(force) end /kill @Terrain[unused] end - + @s.base_x = base_x @s.base_z = base_z end @@ -192,7 +192,7 @@ function create_terrain() y = 255 * scale z = base_z + (col - $Diameter / 2) * 10 * scale @s. = - + used_existing = False as @Terrain unless used_existing if @s.terrain_x == x and @s.terrain_z == z @@ -245,18 +245,18 @@ function move_landscape() = ( - / 10000 * 10000) * 6 / 100 ry = @s.ry unless @Position do create @Position - + as @Position /tp @s ~ ~ ~ ~ ~ move @s ^ ^ ^5 - + at @s ~ ~1.1 ~ as @MiniBlock[player_head] @s.rot_y = ry @s.update() end end - + @s. -= at @s for $row in $range($Diameter) @@ -283,9 +283,9 @@ function handle_tappables() move @s ^ ^ ^5 end end - + tappable_count = 0 - + as @Tappable at @s = @s. - = / scale @@ -302,17 +302,17 @@ function handle_tappables() else @s. = @s. end - + if dsq < 10000 tappable_count++ end end - + if tappable_count < 10 as create @TinyBlock @s.tappable = True @s. = + - + @s.type = rand(0, $NumTappableTypes) for $type in $range($len($TappableTypes)) if @s.type == $type @@ -365,7 +365,7 @@ function switch_mode(mode) end end end - + # Set up the new mode switch mode case $ModeWorld @@ -405,7 +405,7 @@ function switch_mode(mode) if drop[2] == drop[1] then finished = False end end - end + end end case $ModePlacingPlate @Player[limit=1].create_click() @@ -443,14 +443,14 @@ end clock main unless @Position do create @Position - + as @Player if @s[nbt={SelectedItem:{id:"minecraft:dirt",tag:{display:{Name:"{\"text\":\"Minecraft Earth\"}"}}}}] @s.hold_earth = True else @s.hold_earth = False end - + if @s.hold_earth and game_mode == $ModeNone switch_mode($ModeWorld) end @@ -458,13 +458,13 @@ clock main switch_mode($ModeNone) end @s.was_hold_earth = @s.hold_earth - + if @s[nbt={SelectedItem:{id:"minecraft:light_weighted_pressure_plate",tag:{display:{Name:"{\"text\":\"Build Plate\"}"}}}}] @s.hold_plate = True else @s.hold_plate = False end - + if @s.hold_plate and game_mode == $ModeNone switch_mode($ModePlacingPlate) end @@ -473,7 +473,7 @@ clock main end @s.was_hold_plate = @s.hold_plate end - + switch game_mode case $ModeWorld refresh_landscape(False) @@ -501,7 +501,7 @@ clock main end end end - + if tap_count >= 5 reward_type = @Tappable[current_tappable,limit=1].type switch_mode($ModeReward) @@ -551,8 +551,8 @@ clock main end end end - end - + end + switch_mode($ModeWorld) end end @@ -575,11 +575,11 @@ clock main @s. += end end - + as @PlateBlock @s.time = 1 end - + as @Player[limit=1] if @s.check_clicked() as @Position @@ -592,8 +592,8 @@ clock main switch_mode($ModeBuilding) end end - - + + end case $ModeBuilding = (@Player[limit=1]. - ) / scale @@ -602,7 +602,7 @@ clock main end end end - + click_detector_tick() end @@ -620,7 +620,7 @@ function spawn_reward_tiny_block(drop, vx, vz) end end end - end + end /data merge entity @s {Pose:{RightArm:[-45f,0f,0f]}} facing @Player[limit=1] /tp @s ~ ~ ~ ~ ~ @@ -721,4 +721,4 @@ function create_falling_block(id) /summon armor_stand ~ ~ ~ {Tags:["PlateBlockPos"], Marker:1b, Invisible:1b, Invulnerable:1b, NoGravity:1b, Passengers:[{id:"falling_block", Time:1b, NoGravity:1b, BlockState:{$falling_block_nbt}, Tags:["PlateBlock"]}]} end end -end \ No newline at end of file +end diff --git a/Scripts/archived 1.15 scripts/minecraft_in_minecraft.cbscript b/Scripts/archived 1.15 scripts/minecraft_in_minecraft.cbscript index b889c81..a2e5fca 100644 --- a/Scripts/archived 1.15 scripts/minecraft_in_minecraft.cbscript +++ b/Scripts/archived 1.15 scripts/minecraft_in_minecraft.cbscript @@ -15,17 +15,17 @@ $screen_z_max = $screen_z define @Marker = @Entity[type=area_effect_cloud,name=Marker] create: {"CustomName":"\"Marker\"", Duration:-1,Age:-2147483648,WaitTime:-2147483648} - + function move_to_coordinates() rem = frame y = rem / 128 rem %= 128 - + z = rem - 64 - + y *= 64000 z *= 1000 - + @s.x = -64000 @s.y = y @s.z = z @@ -35,13 +35,13 @@ end define @Camera = @Entity[type=armor_stand, tag=Camera] create: {Tags:["Camera"], Invulnerable:1b, NoBasePlate:0b} end - + reset /gamerule maxCommandChainLength 1000000000 /kill @Marker /kill @Camera - + tell @a: {y\ [[look up](/function minecraft_in_minecraft:look_up)\] tell @a: {y\[[look left](/function minecraft_in_minecraft:look_left)\] {y\[[look right](/function minecraft_in_minecraft:look_right)\] tell @a: {y\ [[look down](/function minecraft_in_minecraft:look_down)\] @@ -50,9 +50,9 @@ reset create @Camera /tp @Camera @s end - + move_forward = False - + $background_z: screen_z + 1 /fill $screen_x $screen_y $background_z $screen_x_max $screen_y_max $background_z light_blue_concrete end @@ -116,8 +116,8 @@ function ray_trace() unless block ~ ~ ~ none /clone ~ ~ ~ ~ ~ ~ 0 1 0 end - - if block ~ ~ ~ none + + if block ~ ~ ~ none at ^ ^ ^1 ray_trace() end @@ -131,7 +131,7 @@ function get_converted_block() /clone 0 1 0 0 1 0 0 3 0 handled = True end - + if not handled if block 0 1 0 lime_concrete /setblock 0 3 0 lime_concrete @@ -224,7 +224,7 @@ clock rendering /gamerule sendCommandFeedback true period-- - + if move_forward as @Camera at @s ^ ^ ^1 if @s.on_ground @@ -236,27 +236,27 @@ clock rendering end end end - - + + if period <= 0 period = 15 - + /fill $screen_x $screen_y $screen_z $screen_x_max $screen_y_max $screen_z_max air - + as @Camera at @s ~ ~1.6 ~ rotated @s for $row in: range(height) for $col in: range(width) - + $left: col - 23.5 $up: row - 23.5 step = 0 /setblock 0 1 0 barrier /setblock 0 3 0 barrier /execute facing ^$left ^$up ^30 run function minecraft_in_minecraft:ray_trace - + get_converted_block() - + $x: screen_x + col $y: screen_y + row $z: screen_z @@ -265,4 +265,4 @@ clock rendering end end end -end \ No newline at end of file +end diff --git a/Scripts/archived 1.15 scripts/modify_player_inventory.cbscript b/Scripts/archived 1.15 scripts/modify_player_inventory.cbscript index be20108..8a500ba 100644 --- a/Scripts/archived 1.15 scripts/modify_player_inventory.cbscript +++ b/Scripts/archived 1.15 scripts/modify_player_inventory.cbscript @@ -14,19 +14,19 @@ function increment() [~ ~ ~].[Items] += {id:"minecraft:stone", Count:1, Slot:0} while :{inv[-1]} slot = :inv[-1].Slot - + :inv[-1].Count++ :{inv[-1]} += {Slot:0b} - + [~ ~ ~].{Items[0]} = :inv[-1] - + replace_with_loot_item(slot) - + remove :inv[-1] end - + /setblock ~ ~ ~ air - + /gamerule sendCommandFeedback false end @@ -58,4 +58,4 @@ end clock main /gamerule sendCommandFeedback true -end \ No newline at end of file +end diff --git a/Scripts/archived 1.15 scripts/monkey_ball.cbscript b/Scripts/archived 1.15 scripts/monkey_ball.cbscript index 0c2ab6d..09aedac 100644 --- a/Scripts/archived 1.15 scripts/monkey_ball.cbscript +++ b/Scripts/archived 1.15 scripts/monkey_ball.cbscript @@ -17,7 +17,7 @@ define @Entity = @e rx = Rotation[1] float on_ground = OnGround byte 1 no_gravity = NoGravity byte 1 - + function get_facing_dir() at @s rotated @s at ^ ^ ^1 do @s. = here - @s. end @@ -33,7 +33,7 @@ define @Ball = @Entity[type=slime,name=Ball,limit=1] create: {CustomName:"\"Ball\"", Silent:1b, Size:1, Invulnerable:1} size = Size int 1 hp = AbsorptionAmount float 1 -end +end reset /tp @Ball ~ -200 ~ @@ -48,12 +48,12 @@ end clock main = @Player. - @Player. - + dot = * @Player. / 1000 - + rolling_dot = rolling_dot * 4 / 5 + dot / 5 angle = 45000 + rolling_dot * 50 - + as @Player at @s rotated @s as create @Marker /tp @s @Player @@ -70,7 +70,7 @@ clock main /tp @Player ~ ~ ~ @Player. = here end - + at @Player as create @Marker /tp @s @Player @@ -83,9 +83,9 @@ clock main /kill @s end end - + as @Ball @s.on_ground = False @s. += / 5 end -end \ No newline at end of file +end diff --git a/Scripts/archived 1.15 scripts/mountable_bees.cbscript b/Scripts/archived 1.15 scripts/mountable_bees.cbscript index 4db8e89..d862ba3 100644 --- a/Scripts/archived 1.15 scripts/mountable_bees.cbscript +++ b/Scripts/archived 1.15 scripts/mountable_bees.cbscript @@ -7,7 +7,7 @@ import left_right_click_detector define @Pig : @Entity[type=pig, tag=SaddleHolder] create {Tags:["SaddleHolder"], NoAI:1, Silent:1, Absorption:100} saddle = Saddle byte 1 - + bee: @Bee end @@ -36,13 +36,13 @@ clock main end if @s[nbt={RootVehicle:{Entity:{Tags:["SaddleHolder"]}}}] and @s[nbt={SelectedItem:{id:"minecraft:poppy"}}] @s.enable_click() - + unless @Position do create @Position /tp @Position ~ ~ ~ ~ ~ = @Position. move @Position ^ ^ ^0.2 = @Position. - - + at @s ~ ~-0.4 ~ as @Pig[sort=nearest,limit=1,distance=..0.1] as @s.bee if @s.dash @@ -51,7 +51,7 @@ clock main else @s. = end - + @s.rx = @Position.rx @s.ry = @Position.ry end @@ -60,7 +60,7 @@ clock main @s.disable_click() end end - + as @Pig at @s /effect give @s invisibility 1 1 true @s.absorption = 100 @@ -88,10 +88,10 @@ clock main end end end - + as @Bee as @s.pig - + else @s.pig = None end @@ -108,4 +108,4 @@ end function left_click_callback() -end \ No newline at end of file +end diff --git a/Scripts/archived 1.15 scripts/multi_fireworks.cbscript b/Scripts/archived 1.15 scripts/multi_fireworks.cbscript index 82a061a..3b99b3c 100644 --- a/Scripts/archived 1.15 scripts/multi_fireworks.cbscript +++ b/Scripts/archived 1.15 scripts/multi_fireworks.cbscript @@ -41,7 +41,7 @@ clock main end end end - + for @firework in @Firework if @s.multi at @s if @s.life == @s.lifetime - 10 @@ -58,7 +58,7 @@ clock main end end end - + as @Player[nbt={"SelectedItem":{id:"minecraft:stick",tag:{display:{Name:"{\"text\":\"Sparkler\"}"}}}}] at @s eyes ^ ^ ^1 /particle flame ~ ~ ~ 0 0 0 0.005 1 force @a @s.audio_cooldown-- @@ -67,7 +67,7 @@ clock main @s.audio_cooldown = rand(5) end end - + as @Player[nbt={"SelectedItem":{id:"minecraft:fishing_rod",tag:{display:{Name:"{\"text\":\"Sparkler\"}"}}}}] at @s eyes ^-0.5 ^-0.1 ^0.7 /particle flame ~ ~ ~ 0 0 0 0.005 1 force @a @s.audio_cooldown-- @@ -76,7 +76,7 @@ clock main @s.audio_cooldown = rand(5) end end - + as @PopIt at @s if @s.tracker as @s.tracker @@ -91,7 +91,7 @@ clock main end end end - + as @Marker[popit] at @s as @s.popit (@PopIt) else @@ -100,4 +100,4 @@ clock main /kill @s end end -end \ No newline at end of file +end diff --git a/Scripts/archived 1.15 scripts/nether_portal_block.cbscript b/Scripts/archived 1.15 scripts/nether_portal_block.cbscript index 16fa1ef..b11f609 100644 --- a/Scripts/archived 1.15 scripts/nether_portal_block.cbscript +++ b/Scripts/archived 1.15 scripts/nether_portal_block.cbscript @@ -4,21 +4,21 @@ desc "Nether portal cubes" import common define @PortalFacePos: @Entity[type=armor_stand] - create {Tags:["PortalFacePos", "NewPortalFacePos"], Marker:1b, Invisible:1b, Invulnerable:1b, NoGravity:1b, Passengers:[{id:"falling_block", Time:1b, NoGravity:1b, BlockState:{Name:"nether_portal",Properties:{axis:"$portal_axis"}}, Tags:["PortalFace","NewPortalFace"]}]} + create {Tags:["PortalFacePos", "NewPortalFacePos"], Marker:1b, Invisible:1b, Invulnerable:1b, NoGravity:1b, Passengers:[{id:"falling_block", Time:1b, NoGravity:1b, BlockState:{Name:"nether_portal",Properties:{axis:"$portal_axis"}}, Tags:["PortalFace","NewPortalFace"]}]} end define @PortalFace: @Entity[type=falling_block, tag=PortalFace] create {Tags:["PortalFace"],BlockState:{Name:"nether_portal",Properties:{axis:"$portal_axis"},NoGravity:1,Time:1}} time: Time byte 1 -end +end define @PortalObsidianPos: @Entity[type=armor_stand] - create {Tags:["PortalObsidianPos", "NewPortalObsidianPos"], Marker:1b, Invisible:1b, Invulnerable:1b, NoGravity:1b, Passengers:[{id:"falling_block", Time:1b, NoGravity:1b, BlockState:{Name:"obsidian"}, Tags:["PortalObsidian","NewPortalObsidian"]}]} + create {Tags:["PortalObsidianPos", "NewPortalObsidianPos"], Marker:1b, Invisible:1b, Invulnerable:1b, NoGravity:1b, Passengers:[{id:"falling_block", Time:1b, NoGravity:1b, BlockState:{Name:"obsidian"}, Tags:["PortalObsidian","NewPortalObsidian"]}]} end define @PortalObsidian: @Entity[type=falling_block, tag=PortalObsidian] time: Time byte 1 -end +end reset tell @Player '[\[Create Nether Portal Block\]](call create_block)' @@ -51,4 +51,4 @@ clock main as @PortalObsidian @s.time = 1 end -end \ No newline at end of file +end diff --git a/Scripts/archived 1.15 scripts/performance_test.cbscript b/Scripts/archived 1.15 scripts/performance_test.cbscript index df99902..d137000 100644 --- a/Scripts/archived 1.15 scripts/performance_test.cbscript +++ b/Scripts/archived 1.15 scripts/performance_test.cbscript @@ -20,7 +20,7 @@ function run_test() unless @Marker[$i] do create @Marker[$i] @Marker[$i].val = $i end - + for i = 1 to 10000 idx = randint(1000) switch idx @@ -29,6 +29,6 @@ function run_test() end end end - + tell @a '[\[Run Test\]](call run_test)' -end \ No newline at end of file +end diff --git a/Scripts/archived 1.15 scripts/permatext.cbscript b/Scripts/archived 1.15 scripts/permatext.cbscript index cbbad00..0402044 100644 --- a/Scripts/archived 1.15 scripts/permatext.cbscript +++ b/Scripts/archived 1.15 scripts/permatext.cbscript @@ -22,7 +22,7 @@ clock main end end end - + for @frame in @ItemFrame unless @s.{Item} at @s align xyz at ~0.5 ~0.5 ~0.5 @s.no_text = False @@ -34,4 +34,4 @@ clock main end end end -end \ No newline at end of file +end diff --git a/Scripts/archived 1.15 scripts/pi_digits.cbscript b/Scripts/archived 1.15 scripts/pi_digits.cbscript index f41c852..f2ecaf5 100644 --- a/Scripts/archived 1.15 scripts/pi_digits.cbscript +++ b/Scripts/archived 1.15 scripts/pi_digits.cbscript @@ -15,11 +15,11 @@ end clock main if q * 4 + r - t < m * t tell @a '(m)' - + qp = q rp = r mp = m - + q *= 10 r = 10*(rp-mp*t) m = (10*(3*qp+rp)) / t - 10*mp @@ -30,7 +30,7 @@ clock main kp = k mp = m xp = x - + q *= kp r = (2*qp+rp)*xp t *= xp @@ -38,4 +38,4 @@ clock main m = (qp*(7*kp+2)+rp*xp) / (tp*xp) x += 2 end -end \ No newline at end of file +end diff --git a/Scripts/archived 1.15 scripts/pickpocket.cbscript b/Scripts/archived 1.15 scripts/pickpocket.cbscript index 2397a1f..8df1533 100644 --- a/Scripts/archived 1.15 scripts/pickpocket.cbscript +++ b/Scripts/archived 1.15 scripts/pickpocket.cbscript @@ -30,9 +30,9 @@ end clock main @StealItem.live = False - + @Player.pickpocketing = False - + for @player in @Player at @s pickpocketed = False @@ -41,7 +41,7 @@ clock main @s.pickpocketing = True end if @s.always_show then pickpocketed = True - + if pickpocketed for $slot in $range(27) handled = False @@ -76,7 +76,7 @@ clock main end end end - + for @player in @Player[pickpocketing] @s.was_stealing = @s.stealing @s.stealing = None @@ -87,7 +87,7 @@ clock main rx = @Position.rx ry = @Position.ry end - + at ~ ~1.7 ~ at ^ ^ ^3 as @StealItem[distance=..3, has_item] at @s ^-0.0625 ^0.5 ^0.375 at ~ ~-1 ~ facing @player /tp @Position ~ ~ ~ ~ ~ @@ -99,7 +99,7 @@ clock main end end end - + handled = False if @s.stealing and @s.stealing == @s.was_stealing handled = True @@ -131,18 +131,18 @@ clock main tell @s 'Stole (count)x(@Item[new]) from (@Player[target,limit=1])' end end - + if @s.was_stealing and not @s.stealing /bossbar set pickpocket players end - + if not handled then @s.steal_progress = 0 - + end as @Player[not pickpocketing] @s.destroy_click() end - + /kill @StealItem[not live] @a.pickpocket = 0 -end \ No newline at end of file +end diff --git a/Scripts/archived 1.15 scripts/piranha_plant_farming.cbscript b/Scripts/archived 1.15 scripts/piranha_plant_farming.cbscript index 0d01d86..f17478b 100644 --- a/Scripts/archived 1.15 scripts/piranha_plant_farming.cbscript +++ b/Scripts/archived 1.15 scripts/piranha_plant_farming.cbscript @@ -13,11 +13,11 @@ $BigHead = 5 define @Plant : @Entity[type=area_effect_cloud, tag=PiranhaPlant] create {Tags:["PiranhaPlant"], Duration:-1,Age:-2147483648,WaitTime:-2147483648} - + array stalk[0 to 7] array miniblocks[0 to 11] array mouth[0 to 5] - + function kill() for $i in $range(8) as @s.stalk[$i] @@ -45,7 +45,7 @@ end reset /scoreboard objectives add plant_wheat minecraft.used:minecraft.wheat_seeds - + tell @a '{G[\[Give Piranha Plant Seed\]](call give_seed)' end @@ -73,9 +73,9 @@ clock main @s.holding_seed = False end end - + @Player.plant_wheat = 0 - + as @Plant at @s stage = -1 for $i in $range(8) @@ -190,7 +190,7 @@ clock main end end end - + for $i in $range(6) id = &@s as @s.mouth[$i] @@ -226,22 +226,22 @@ clock main if stage == 7 @s.anim_timer = 0 end - + @s.current_stage = stage end if stage == 7 update_anim_timer() - + if @s.shoot_fire if @s.anim_timer == 80 spawn_fireball() end - + if @s.anim_timer == 100 spawn_fireball() end end - + if @s.eat_time > 0 @s.eat_time-- end @@ -255,9 +255,9 @@ clock main end end end - - - + + + as @Entity[type=armor_stand] if @s.type == $Mouth update_anim_timer() @@ -271,7 +271,7 @@ clock main @s.dy += 120 end end - + @s.fire = 10 switch @s.anim_timer % 15 case 0 to 6 @@ -284,19 +284,19 @@ clock main end end end - + if @s.type == $Stalk and @s.segment >= 4 and @s.stage == 7 update_anim_timer() @s.fire = 10 small_updown() end - + if @s.type == $Leaf and @s.stage == 7 update_anim_timer() @s.fire = 10 small_updown() end - + if @s.type == $BigHead update_anim_timer() @s.fire = 10 @@ -312,7 +312,7 @@ clock main end end end - + as @Fireball at @s /effect give @s invisibility 10 0 true kill = False @@ -324,7 +324,7 @@ clock main end @s.vx = @s.dx @s.vz = @s.dz - + at ~ ~-1 ~ if @Player[distance=..1.2] /effect give @Player[distance=..1.2] instant_damage 1 0 true kill = True @@ -339,7 +339,7 @@ clock main /kill @s end end - + for @seeds in @Entity[type=item,nbt={Item:{id:"minecraft:wheat_seeds", Count:1b}}] at @s unless @s[nbt={Item:{tag:{piranha:1b}}}] as @Entity[type=item,nbt={Item:{id:"minecraft:mushroom_stew",Count:1b}},distance=..0.5,limit=1] at @s /kill @s @@ -395,4 +395,4 @@ function spawn_fireball() @s.dz = dz/2 end end -end \ No newline at end of file +end diff --git a/Scripts/archived 1.15 scripts/pointer_test.cbscript b/Scripts/archived 1.15 scripts/pointer_test.cbscript index 09b0c19..d552bb9 100644 --- a/Scripts/archived 1.15 scripts/pointer_test.cbscript +++ b/Scripts/archived 1.15 scripts/pointer_test.cbscript @@ -34,13 +34,13 @@ clock main /say Marked snowball end end - + for @Current in @Snowball as @s.tracker /tp @s @Current end - end - + end + for @Current in @Snowmarker tracking = False as @s.snowball diff --git a/Scripts/archived 1.15 scripts/polaroid.cbscript b/Scripts/archived 1.15 scripts/polaroid.cbscript index da463c9..3a347a7 100644 --- a/Scripts/archived 1.15 scripts/polaroid.cbscript +++ b/Scripts/archived 1.15 scripts/polaroid.cbscript @@ -54,22 +54,22 @@ clock main /execute as @a[nbt={"SelectedItem":{"id":"minecraft:filled_map"}}] run scoreboard players set @s take_picture 1 as @Player if @s.map_id == 0 then @s.take_picture = False - + if @s.take_picture at @s ~ ~1.6 ~ do create @Basis - + at @s ~ ~1.6 ~ do create @Pixel @Pixel.ry = @s.ry @Pixel.rx = @s.rx move @Pixel ^4 ^4 ^5 - + at @Basis do create @Ray - /tp @Ray @Basis - + /tp @Ray @Basis + row = -64 col = -64 step = 0 - + @s.map_id = 0 end end @@ -79,21 +79,21 @@ clock main loop_step++ move @Ray ^ ^ ^1 step++ - + collided = True at @Ray if block ~ ~ ~ air then collided = False if block ~ ~ ~ grass then collided = False if block ~ ~ ~ rose_bush then collided = False end - + if collided then step = 200 if step >= 100 at @Ray /clone ~ ~ ~ ~ ~ ~ 0 3 0 replace end - + @Ray.x = col*1000 @Ray.z = row*1000 at @Ray ~ 1 ~ @@ -102,7 +102,7 @@ clock main /clone 0 3 0 0 3 0 ~ ~ ~ replace move end /setblock 0 3 0 minecraft:barrier - + col++ move @Pixel ^-0.0625 ^ ^ if col >= 64 @@ -126,6 +126,6 @@ clock main step = 0 end end - + move @Ray ~ ~ ~ end diff --git a/Scripts/archived 1.15 scripts/predicate_test.cbscript b/Scripts/archived 1.15 scripts/predicate_test.cbscript index a0f1074..d8b02cb 100644 --- a/Scripts/archived 1.15 scripts/predicate_test.cbscript +++ b/Scripts/archived 1.15 scripts/predicate_test.cbscript @@ -53,7 +53,7 @@ define @Player : @Player } } } - + predicate survival { condition: 'entity_properties', entity: 'this', @@ -79,8 +79,8 @@ clock main at @Player if predicate night /say night end - + as @Player[survival] /say survival end -end \ No newline at end of file +end diff --git a/Scripts/archived 1.15 scripts/pushables.cbscript b/Scripts/archived 1.15 scripts/pushables.cbscript index c0af693..ab8ac37 100644 --- a/Scripts/archived 1.15 scripts/pushables.cbscript +++ b/Scripts/archived 1.15 scripts/pushables.cbscript @@ -36,12 +36,12 @@ function remove_here() /kill @FakeBlock[distance=..1] /kill @SolidBlock[distance=..1] end - + function create_block() align xyz at ~0.5 ~ ~0.5 as create @Pushable @s.physics = create @Physics - + for $block_type in $BlockTypes if block ~ ~ ~ $block_type /summon armor_stand ~ ~ ~ {Tags:["Disguise", "New"], Marker:1b, Invisible:1b, Invulnerable:1b, NoGravity:1b, Passengers:[{id:"falling_block", Time:1b, NoGravity:1b, BlockState:{Name:"minecraft:$block_type"}, Tags:["FakeBlock"]}]} @@ -78,7 +78,7 @@ function create_block() @s.disguise = &@Disguise[tag=New, limit=1] end /tag @Disguise[tag=New] remove New - + if not handled then @s.disguise = create @Disguise end end @@ -102,15 +102,15 @@ clock main end @s[sound_cooldown > 0].sound_cooldown-- end - + @s.holding_wand = False @s[nbt={SelectedItem:{id:"minecraft:carrot_on_a_stick"}}].holding_wand = True - + if not @s.holding_wand @s.wand_active = False @s.controlling = None - end - + end + if @s.use_wand handled = False if @s.wand_active @@ -126,10 +126,10 @@ clock main end end end - + @s.use_wand = False end - + if @s.wand_active at @s ~ ~1 ~ at ^ ^ ^3 = here @@ -147,7 +147,7 @@ clock main end end end - + for @pushable in @Pushable at @s as @Pushable[distance= .. 1] at @s unless @s._id == @pushable._id @@ -163,7 +163,7 @@ clock main end end end - + as @Pushable at @s as @s.disguise /tp @s ~ ~ ~ @@ -171,9 +171,9 @@ clock main as @s.physics /tp @s ~ ~ ~ end - + = @s. % 1000 - + stairs_east = False /execute if block ~0.25 ~ ~ #minecraft:stairs[facing=east,half=bottom] run scoreboard players set Global stairs_east 1 if stairs_east @@ -184,7 +184,7 @@ clock main @s.vy += 350 end end - + stairs_west = False /execute if block ~-0.26 ~ ~ #minecraft:stairs[facing=west,half=bottom] run scoreboard players set Global stairs_west 1 if stairs_west @@ -195,7 +195,7 @@ clock main @s.vy += 350 end end - + stairs_south = False /execute if block ~ ~ ~0.25 #minecraft:stairs[facing=south,half=bottom] run scoreboard players set Global stairs_south 1 if stairs_south @@ -206,7 +206,7 @@ clock main @s.vy += 350 end end - + stairs_north = False /execute if block ~ ~ ~-0.26 #minecraft:stairs[facing=north,half=bottom] run scoreboard players set Global stairs_north 1 if stairs_north @@ -217,7 +217,7 @@ clock main @s.vy += 350 end end - + if @s.hot at @s if block ~ ~ ~ air /setblock ~ ~ ~ fire end @@ -227,14 +227,14 @@ clock main end if @s.cold do @s.fire_timer = 0 end - + as @FakeBlock @s.on_ground = False @s.time = 1 end - + /effect give @SolidBlock invisibility 1000000 1 true - + for @player in @Player[sneak_dist > 0] at @s ~ ~1 ~ at ^ ^ ^1 as @Pushable[distance = ..1,limit=1,sort=nearest] @@ -247,22 +247,22 @@ clock main end end end - + @s.sneak_dist = 0 - end - - + end + + as @Pushable[bishop] @s.get_velocity_signs() - + avg = (avx + avz) / 2 @s.vx = sx * avg @s.vz = sz * avg end - + as @Pushable[rook] @s.get_velocity_signs() - + if avx > avz @s.vz = 0 end @@ -270,10 +270,10 @@ clock main @s.vx = 0 end end - + as @Pushable[queen] @s.get_velocity_signs() - + handled = False if havx > avz @s.vz = 0 @@ -287,9 +287,9 @@ clock main avg = (avx + avz) / 2 @s.vx = sx * avg @s.vz = sz * avg - end + end end - + as @Pushable[knight] if @s.on_ground @s.ground_timer++ @@ -313,9 +313,8 @@ clock main @s.vx = avz / 2 * sx end end - + as @Pushable[lock_x] @s.vx = 0 end end - diff --git a/Scripts/archived 1.15 scripts/randomize_blocks.cbscript b/Scripts/archived 1.15 scripts/randomize_blocks.cbscript index d9a9010..21ce05b 100644 --- a/Scripts/archived 1.15 scripts/randomize_blocks.cbscript +++ b/Scripts/archived 1.15 scripts/randomize_blocks.cbscript @@ -10,11 +10,11 @@ array Mapping[0 to $NumBlocks-1] reset tell @a '[\[Start Randomizing\]](call start_randomizing)' - + for i = 0 to $NumBlocks-1 Mapping[i] = i end - + for i = 0 to $NumBlocks-2 j = randint(i, $NumBlocks) val1 = Mapping[i] @@ -28,9 +28,9 @@ clock main unless @Position do create @Position doTileDrops = result /gamerule doTileDrops - + /gamerule doTileDrops false - + as @Player at @s if Randomize if MidChunk @@ -43,7 +43,7 @@ clock main end end end - + if doTileDrops /gamerule doTileDrops true end @@ -54,13 +54,13 @@ function find_fresh_chunk(x, z) CenterZ = z / 16 * 16 SubX = 0 SubZ = 0 - - for search_size = 0 to 15 + + for search_size = 0 to 15 MinX = CenterX - search_size * 16 MaxX = CenterX + search_size * 16 MinZ = CenterZ - search_size * 16 MaxZ = CenterZ + search_size * 16 - + for d = -search_size to search_size ChunkX = MinX ChunkZ = MinZ + d * 16 @@ -83,7 +83,7 @@ function find_fresh_chunk(x, z) end end end - + if MidChunk d = 1000 end @@ -216,4 +216,4 @@ function randomize_block() end end end -end \ No newline at end of file +end diff --git a/Scripts/archived 1.15 scripts/ray_trace_test.cbscript b/Scripts/archived 1.15 scripts/ray_trace_test.cbscript index 5cbd400..d44ba79 100644 --- a/Scripts/archived 1.15 scripts/ray_trace_test.cbscript +++ b/Scripts/archived 1.15 scripts/ray_trace_test.cbscript @@ -22,4 +22,4 @@ clock main step = 0 ray_trace() end -end \ No newline at end of file +end diff --git a/Scripts/archived 1.15 scripts/realistic_explosions.cbscript b/Scripts/archived 1.15 scripts/realistic_explosions.cbscript index 1c251b0..3a97751 100644 --- a/Scripts/archived 1.15 scripts/realistic_explosions.cbscript +++ b/Scripts/archived 1.15 scripts/realistic_explosions.cbscript @@ -17,18 +17,18 @@ define @ExplosionMarker: @Entity[type=area_effect_cloud,tag=ExplosionMarker] WaitTime:-0x80000000 } age: Age int 1 - + function get_block_id() switch block at ~ ~ ~ case air - + end default @s.block_id = $block_id end end end - + function spawn_exploding_block() = @s. switch block @s.block_id @@ -68,7 +68,7 @@ define @ParticleEmitter : @Entity[type=area_effect_cloud,tag=ParticleEmitter] end reset - + end clock main @@ -80,7 +80,7 @@ clock main end end /kill @ExplosionMarker - + as @ParticleEmitter at @s /particle explosion_emitter ~ ~ ~ 3 3 3 0 2 force @a @s.age++ @@ -88,7 +88,7 @@ clock main /kill @s end end - + as @ExplodingTNT at @s if particles then create @ParticleEmitter = @s. / scale * scale + <500, 0, 500> @@ -116,4 +116,4 @@ clock main /particle campfire_signal_smoke ~ ~ ~ 0 0 0 0 1 force @a end end -end \ No newline at end of file +end diff --git a/Scripts/archived 1.15 scripts/recursion_test.cbscript b/Scripts/archived 1.15 scripts/recursion_test.cbscript index e09aec0..5fa01c0 100644 --- a/Scripts/archived 1.15 scripts/recursion_test.cbscript +++ b/Scripts/archived 1.15 scripts/recursion_test.cbscript @@ -9,7 +9,7 @@ function recurse(x, y) recurse(x-1, y+1) tell @a '(x) (y)' end -end +end function factorial(n) if n <= 1 diff --git a/Scripts/archived 1.15 scripts/ripples.cbscript b/Scripts/archived 1.15 scripts/ripples.cbscript index 7ea4614..e6f815d 100644 --- a/Scripts/archived 1.15 scripts/ripples.cbscript +++ b/Scripts/archived 1.15 scripts/ripples.cbscript @@ -24,10 +24,10 @@ end define @MiniBlock = @Entity[type=armor_stand,name=MiniBlock] create: {CustomName:"\"MiniBlock\"", Pose:{Head:[0.0001f,0f,0f]}, $marker} - + pose_rot_x = Pose.Head[0] float 1000 pose_rot_y = Pose.Head[1] float 1000 - + function update() as create @Marker base_x = @s.x @@ -38,14 +38,14 @@ define @MiniBlock = @Entity[type=armor_stand,name=MiniBlock] @s.x = base_x + @s.dx @s.y = base_y + @s.dy - 1700 @s.z = base_z + @s.dz - + /data merge entity @s {Pose:{Head:[0.0001f,0.0001f,0.0001f]}} @s.pose_rot_x = @s.rot_x @s.pose_rot_y = @s.rot_y - + my_rx = @s.rot_x my_ry = @s.rot_y - + as create @Marker x1 = @s.x y1 = @s.y @@ -54,24 +54,24 @@ define @MiniBlock = @Entity[type=armor_stand,name=MiniBlock] @s.rx = my_rx @s.ry = my_ry move @s ^ ^0.287 ^ - + dx = @s.x - x1 dy = @s.y - y1 dz = @s.z - z1 - + /kill @s end - + @s.x -= dx @s.y -= dy @s.z -= dz - - /data merge entity @s {Fire:32767s} - + + /data merge entity @s {Fire:32767s} + at @s rotated @s /tp @s ~ ~ ~ 0 0 end - end + end end reset @@ -99,4 +99,4 @@ clock main @s.update() end end -end \ No newline at end of file +end diff --git a/Scripts/archived 1.15 scripts/robot_arm.cbscript b/Scripts/archived 1.15 scripts/robot_arm.cbscript index fed07ae..e476f39 100644 --- a/Scripts/archived 1.15 scripts/robot_arm.cbscript +++ b/Scripts/archived 1.15 scripts/robot_arm.cbscript @@ -29,20 +29,20 @@ end define @MiniBlock = @Entity[type=armor_stand,name=MiniBlock] create '{CustomName:"\"MiniBlock\"", Pose:{Head:[0.0001f,0f,0f]}, $marker}' - + pose_rot_x = Pose.Head[0] float pose_rot_y = Pose.Head[1] float - + function update() @s. = here - <0, 1700, 0> - + /data merge entity @s {Pose:{Head:[0.0001f,0.0001f,0.0001f]}} @s.pose_rot_x = @s.rot_x @s.pose_rot_y = @s.rot_y - + my_rx = @s.rot_x my_ry = @s.rot_y - + as create @Marker = @s. @@ -50,26 +50,26 @@ define @MiniBlock = @Entity[type=armor_stand,name=MiniBlock] @s.rx = my_rx @s.ry = my_ry move @s ^ ^0.287 ^ - + = - @s. - + /kill @s end - + @s. += - - /data merge entity @s {Fire:32767s} - + + /data merge entity @s {Fire:32767s} + at @s rotated @s /tp @s ~ ~ ~ 0 0 end - end + end end reset /kill @MiniBlock /kill @Marker - + at @p seg = 0 while seg < $NumSegments @@ -82,20 +82,20 @@ reset @s.seg = seg @s.piece = piece - + @s.nonstick = True end end - + as create @Marker @s.seg = seg @s.drx = -25000 @s.dry = 20000 - + @s.nonstick = True end end - + as create @MiniBlock /replaceitem entity @s armor.head white_banner @s.claw_left = True @@ -123,33 +123,33 @@ function apply_rotation() if @s.drx < -180000 @s.drx += 360000 end - + crx += @s.drx cry += @s.dry - + if seg == 4 and crx < 30000 crx = 30000 end - + if seg == 4 and crx > 170000 crx = 170000 end - + if seg == 1 and crx > 50000 crx = 50000 end - + if seg == 1 and crx < -170000 crx = -170000 end - + if crx > 180000 crx -= 360000 end if crx < -180000 crx += 360000 end - + local_ry = cry local_rx = crx @@ -173,15 +173,15 @@ function apply_rotation() @s.rot_y = local_ry @s.update() end - + move @s ^ ^ ^0.6 end = @s. end end - + = - - + tdist = sqrt(dx^2+dy^2+dz^2) end @@ -203,17 +203,17 @@ clock main if @s.hooked = <101500, 63500, 129500> end - + unless @s.hooked = @s. end end - + live = False - + apply_rotation() basedist = tdist - + @Marker[seg==1].drx += 50 apply_rotation() dist1x = tdist - basedist @@ -254,7 +254,7 @@ clock main dist4y = tdist - basedist @Marker[seg==4].dry -= 50 - + mag = sqrt(dist1x^2 + dist1y^2 + dist2x^2 + dist2y^2 + dist3x^2 + dist3y^2 + dist4x^2 + dist4y^2) if basedist > 500 @@ -266,12 +266,12 @@ clock main @Marker[seg==3].dry -= dist3y * 2000 / mag @Marker[seg==4].drx -= dist4x * 2000 / mag @Marker[seg==4].dry -= dist4y * 2000 / mag - + live = True - + apply_rotation() end - + if @Entity[target, hooked, not drop] @MiniBlock[claw_left].rot_x = 165000 @MiniBlock[claw_right].rot_x = 165000 @@ -282,12 +282,12 @@ clock main @MiniBlock[claw_right].rot_x = 135000 @MiniBlock[claw_right].rot_y = 180000 end - + at @MiniBlock[claw_left].update() @MiniBlock[claw_right].update() end - + if tdist > 18000 then @Entity[target,not hooked].target = False if tdist < 750 then @Entity[target, hooked].drop = True if tdist < 750 then @Entity[target].hooked = True @@ -297,4 +297,3 @@ clock main move @MiniBlock ~ ~ ~ end - diff --git a/Scripts/archived 1.15 scripts/rope.cbscript b/Scripts/archived 1.15 scripts/rope.cbscript index 5edb5f6..3542423 100644 --- a/Scripts/archived 1.15 scripts/rope.cbscript +++ b/Scripts/archived 1.15 scripts/rope.cbscript @@ -17,7 +17,7 @@ end define @Segment = @Entity[type=slime,name=Segment] create: {CustomName:"{\"text\":\"Segment\"}", Invulnerable:1b, Silent:1b} on_ground = OnGround byte 1 - + function create_children() /team join rope if n == 0 @@ -32,23 +32,23 @@ define @Segment = @Entity[type=slime,name=Segment] end end end - + function apply_tension() if @s.next my_x = @s.x my_y = @s.y my_z = @s.z - + as @s.next(@Segment) dx = @s.x - my_x dy = @s.y - my_y dz = @s.z - my_z - + dvx = dx * 80 / 100 dvy = dy * 80 / 100 dvz = dz * 80 / 100 - - + + dvsq = dvx^2 + dvy^2 + dvz^2 while dvsq > 100000000 dvx /= 2 @@ -56,21 +56,21 @@ define @Segment = @Entity[type=slime,name=Segment] dvz /= 2 dvsq = dvx^2 + dvy^2 + dvz^2 end - + @s.vx -= dvx @s.vy -= dvy @s.vz -= dvz @s.on_ground = False - - if @s.last + + if @s.last stuck = False at @s unless block ~ ~-1 ~ air then stuck = True at @s unless block ~1 ~ ~ air then stuck = True at @s unless block ~ ~ ~1 air then stuck = True at @s unless block ~-1 ~ ~ air then stuck = True at @s unless block ~ ~ ~-1 air then stuck = True - + @s.stuck = False /data merge entity @s {NoGravity:0b} if stuck and dvsq < 10000000 @@ -82,21 +82,21 @@ define @Segment = @Entity[type=slime,name=Segment] end end end - + @s.vx += dvx @s.vy += dvy @s.vz += dvz - + as @s.next(@Segment) @s.apply_tension() end - + #@s.vx = @s.vx * 99 / 100 #@s.vy = @s.vy * 99 / 100 #@s.vz = @s.vz * 99 / 100 end end - + function throw() @s.vx += throwx @s.vy += throwy @@ -127,7 +127,7 @@ function create_rope() @s.create_children() end @s.last = last - + at @s ~ ~200 ~ @s.click = create @ClickDetector end @@ -143,7 +143,7 @@ reset /kill @ClickDetector /kill @Marker /kill @Physics - + /team add rope /team modify rope collisionRule pushOtherTeams @@ -156,7 +156,7 @@ end clock main for @CurPlayer in @Player - at @s ~ ~1.6 ~ rotated @s at ^ ^ ^15 + at @s ~ ~1.6 ~ rotated @s at ^ ^ ^15 as @s.rope(@Segment) /tp @s ~ ~ ~ @s.apply_tension() @@ -166,13 +166,13 @@ clock main clicked = False as @s.click(@ClickDetector) /tp @s ~ ~ ~ - + if @s.hp <= 97 clicked = True end @s.hp = 100 end - + if clicked stuck = False as @s.last do stuck = @s.stuck @@ -183,13 +183,13 @@ clock main y1 = @s.y + 2000 z1 = @s.z end - + as @s.physics(@Physics) /team join rope dx = (x1 - @s.x) / 10 dy = (y1 - @s.y) / 10 dz = (z1 - @s.z) / 10 - + @s.vx = dx @s.vy = dy @s.vz = dz @@ -215,7 +215,7 @@ clock main @s.throw() end end - + if @s.rope == 0 create_rope() as create @Marker diff --git a/Scripts/archived 1.15 scripts/rotator.cbscript b/Scripts/archived 1.15 scripts/rotator.cbscript index 403feb3..c7be5b6 100644 --- a/Scripts/archived 1.15 scripts/rotator.cbscript +++ b/Scripts/archived 1.15 scripts/rotator.cbscript @@ -24,7 +24,7 @@ advancement placed_rotator { define @Player: @Player function placed_rotator() /advancement revoke @s only rotator:placed_rotator - + at @s eyes ^ ^ ^ steps = 0 while steps < 60 at feet ^ ^ ^0.1 @@ -32,7 +32,7 @@ define @Player: @Player if block ~ ~ ~ redstone_lamp steps = 1000000 as create @RotatorMarker - + end end end @@ -66,7 +66,7 @@ end clock main as @RotatorMarker at @s # Check for piston pushes, and move if so - + unless block ~ ~ ~ redstone_lamp moved = False for $direction in $range(6) @@ -74,10 +74,10 @@ clock main $dx, $dy, $dz = $Deltas[$direction] moved_dir = False /execute if data block ~$dx ~$dy ~$dz {id:"minecraft:piston", source:0b, progress:0.0f, extending:1b, facing: $direction} run scoreboard players set Global moved_dir 1 - + $op = $OppositeDir[$direction] /execute if data block ~$dx ~$dy ~$dz {id:"minecraft:piston", source:0b, progress:0.0f, extending:0b, facing: $op} run scoreboard players set Global moved_dir 1 - + if moved_dir moved = True @s.moving_timer = 3 @@ -85,14 +85,14 @@ clock main end end end - + unless @s.moving_timer > 0 /kill @s else moving_timer-- end end - + if @s.powered if block ~ ~ ~ redstone_lamp[lit=false] @s.powered = False @@ -136,10 +136,10 @@ end function rotate_clockwise(id) switch block id case piston[extended=true] - + end case sticky_piston[extended=true] - + end case *[facing=north] $rotated_block_state = $block_state.$replace('facing=north', 'facing=east') @@ -158,4 +158,4 @@ function rotate_clockwise(id) /setblock ~ ~ ~ $rotated_block_state end end -end \ No newline at end of file +end diff --git a/Scripts/archived 1.15 scripts/sanic.cbscript b/Scripts/archived 1.15 scripts/sanic.cbscript index 5edc594..27bc805 100644 --- a/Scripts/archived 1.15 scripts/sanic.cbscript +++ b/Scripts/archived 1.15 scripts/sanic.cbscript @@ -69,14 +69,14 @@ end @Ring = @Entity[type=item,nbt={Item:{id:"minecraft:gold_nugget"}, OnGround:1b}] @Emerald = @Entity[type=item,nbt={Item:{id:"minecraft:emerald"}}] - + reset tell @a '{B[\[Summon Sanic\]](call sanic) {G[\[Summon Robuttnik\]](call robuttnik) {R[\[Kill All Sanics\]](call kill_sanics)' - + /team add super /team modify super color yellow /team modify super collisionRule never - + end function sanic() @@ -139,7 +139,7 @@ function kill_sanics() as @s.rmini_blocks[$i] /kill @s end - end + end end /kill @Sanic /kill @Robuttnik @@ -152,7 +152,7 @@ clock main /effect give @s invisibility 1 1 true @s.fire = 0 @s.foot_angle += 50000 - + for $i in $range($len($SanicMiniblocks)) as @s.mini_blocks[$i] (@MiniBlock) if $i == 0 @@ -182,7 +182,7 @@ clock main end end end - + for $i in $range($len($SanicTinyblocks)) as @s.tiny_blocks[$i] (@TinyBlock) $tinyblock = $SanicTinyblocks[$i] @@ -197,7 +197,7 @@ clock main end /kill @Ring[distance=..2] - + if @Emerald[distance=..2] @s.vy = 2000 /kill @Emerald[distance=..2] @@ -207,7 +207,7 @@ clock main if @s.pre_super and @s.vy <= 0 @s.pre_super = false /particle flash ~ ~ ~ 0 0 0 0 1 force - + for $i in $range($len($SanicMiniblocks)) as @s.mini_blocks[$i] (@MiniBlock) $miniblock = $SanicMiniblocks[$i] @@ -217,7 +217,7 @@ clock main /team join super @s end end - + for $i in $range($len($SanicTinyblocks)) as @s.tiny_blocks[$i] (@TinyBlock) $tinyblock = $SanicTinyblocks[$i] @@ -242,12 +242,12 @@ clock main end end end - + for @robuttnik in @Robuttnik at @s /effect give @s invisibility 1 1 true @s.fire = 0 - + for $i in $range($len($RobuttnikMiniblocks)) as @s.rmini_blocks[$i] (@MiniBlock) @s.rot_x = 0 @@ -265,14 +265,14 @@ clock main /particle minecraft:flame ^ ^0.8 ^-1.4 0.1 0.1 0.1 0.05 5 force @a end end - + as @AITarget at @s unless @Ring[distance=..4] move @s ~ -100 ~ /kill @s end end - + as @Ring at @s unless @AITarget[distance=..4] as create @AITarget ~ ~100 ~ diff --git a/Scripts/archived 1.15 scripts/sethbling_golem.cbscript b/Scripts/archived 1.15 scripts/sethbling_golem.cbscript index 1a83ddb..9ab924a 100644 --- a/Scripts/archived 1.15 scripts/sethbling_golem.cbscript +++ b/Scripts/archived 1.15 scripts/sethbling_golem.cbscript @@ -34,16 +34,16 @@ end define @Golem : @Entity[type=armor_stand, tag=SethBlingGolem] left_arm_rx : Pose.LeftArm[0] float left_arm_ry : Pose.LeftArm[1] float - + right_arm_rx : Pose.RightArm[0] float right_arm_ry : Pose.RightArm[1] float - + array arm_state[2] array arm_block[2] array state_delay[2] array next_state[2] array arm_target[2] - + create { ShowArms: 1, Invulnerable: 1, @@ -55,11 +55,11 @@ define @Golem : @Entity[type=armor_stand, tag=SethBlingGolem] LeftArm: [0.001f, 0.001f, 0.001f] } } - + function point_at(pointx, pointy, pointz, arm) unless @Position do create @Position @Position. = - + if arm == $RightArm at @s ^-0.3 ^1 ^ facing @Position /tp @Position ~ ~ ~ ~ ~ @@ -74,7 +74,7 @@ define @Golem : @Entity[type=armor_stand, tag=SethBlingGolem] @s.lt_ry = @Position.ry - @s.ry end end - + function move_arm(arm) $MoveAmount = 5000 if arm == $RightArm @@ -87,17 +87,17 @@ define @Golem : @Entity[type=armor_stand, tag=SethBlingGolem] @s.left_arm_ry = result_ry end end - + function get_random_target_block(arm) found_target = False create @Position find_step = 0 - + while not found_target and find_step < 100 at @s eyes ^ ^ ^ /tp @Position ~ ~ ~ end - + @Position.rx = randint(-90000, 90000) @Position.ry = randint(0, 360000) at @Position @@ -118,11 +118,11 @@ define @Golem : @Entity[type=armor_stand, tag=SethBlingGolem] step++ end end - + find_step++ end end - + function run_ai() for arm = $LeftArm to $RightArm switch @s.arm_state[arm] @@ -217,7 +217,7 @@ define @Golem : @Entity[type=armor_stand, tag=SethBlingGolem] else player_found = False end - + if player_found @s.point_at(x, y+1000, z, arm) @s.arm_state[arm] = $ArmPointAtPlayer @@ -232,18 +232,18 @@ define @Golem : @Entity[type=armor_stand, tag=SethBlingGolem] @s. = ( - @s.) / 15 + <0, 400, 0> @s.no_gravity = False end - @s.arm_state[arm] = $ArmIdle + @s.arm_state[arm] = $ArmIdle end end end end - + function delay_next_state(arm, delay, state) @s.state_delay[arm] = delay @s.next_state[arm] = state @s.arm_state[arm] = $ArmWaiting end - + function move_position_to_arm_socket(arm) create @Position if arm == $LeftArm at @s ^0.3 ^1 ^ @@ -252,7 +252,7 @@ define @Golem : @Entity[type=armor_stand, tag=SethBlingGolem] /tp @Position ~ ~ ~ end end - + function put_block_at_arm_end(arm) @s.move_position_to_arm_socket(arm) if arm == $RightArm @@ -267,7 +267,7 @@ define @Golem : @Entity[type=armor_stand, tag=SethBlingGolem] /tp @s @Position end end - + function destroy() for arm = 1 to 2 as @s.arm_block[arm] @@ -311,7 +311,7 @@ function get_updated_rotations(rx, ry, trx, try, amount) main = dry slope = drx * 1000 / dry end - + if main > amount delta = amount rotation_done = False @@ -322,9 +322,9 @@ function get_updated_rotations(rx, ry, trx, try, amount) delta = main rotation_done = True end - + other = slope * delta / 1000 - + if adrx > adry result_rx = rx + delta result_ry = ry + other @@ -361,4 +361,4 @@ clock main /particle flame ~ ~ ~ 0.6 0.6 0.6 0 1 force end end -end \ No newline at end of file +end diff --git a/Scripts/archived 1.15 scripts/shaded_camera.cbscript b/Scripts/archived 1.15 scripts/shaded_camera.cbscript index 6c47198..ccc678f 100644 --- a/Scripts/archived 1.15 scripts/shaded_camera.cbscript +++ b/Scripts/archived 1.15 scripts/shaded_camera.cbscript @@ -28,7 +28,7 @@ $map_z: -64 reset /gamerule maxCommandChainLength 1000000000 /gamerule randomTickSpeed 0 - + /bossbar add progress "Progress" /bossbar set progress max 128 @@ -51,7 +51,7 @@ end function setup() fill_ceiling() - + /bossbar set progress players @s for $x in: range(map_x, map_x+128, 8) $dx: x - map_x @@ -67,11 +67,11 @@ end function take_picture() /bossbar set progress players @s - + at @s /tp @Scan ~ ~1.8 ~ ~ ~ end - + move @Scan ^$Radius ^$Radius ^10 $x_start: map_x-1 at $x_start 128 $map_z @@ -81,7 +81,7 @@ function take_picture() row = 0 /execute store result bossbar progress value run scoreboard players get Global col take_picture_col() - + col++ move @Scan ^-$PixelMove ^$Diameter ^ = @Scan. @@ -95,7 +95,7 @@ macro $take_picture_col_recurse($dy) # Copy the block into the map area /clone 0 1 0 0 1 0 ~ ~ ~ /fill ~ ~1 ~ ~ 254 ~ air - + # Move on to the next row row++ move @Scan ^ ^-$PixelMove ^ @@ -112,18 +112,18 @@ function take_picture_col() at @s ~ ~1.8 ~ facing @Scan ray_trace_step() end - + handled = False if face_x $take_picture_col_recurse(-1) handled = True end - + if face_y and not handled $take_picture_col_recurse(1) handled = True end - + if face_z and not handled $take_picture_col_recurse(0) handled = True @@ -138,7 +138,7 @@ function ray_trace_step() at ^ ^ ^$Step do ray_trace_step() handled = True end - + if not handled at ^ ^ ^-$Step fine_step = 0 @@ -163,18 +163,18 @@ end function ray_trace_fine_step() $FineStep: 0.02 - + handled = False if block ~ ~ ~ none and fine_step < 11 fine_step++ at ^ ^ ^$FineStep do ray_trace_fine_step() handled = True end - + if not handled $create_map_block_at(0, 1, 0) - - # Compute which face was crossed first + + # Compute which face was crossed first as @Position /tp @s ~ ~ ~ ~ ~ = @s. @@ -184,7 +184,7 @@ function ray_trace_fine_step() = % 1000 = - = + - + if bx2 > 1000 px = (1000-bx1) * 100 / dx end @@ -194,7 +194,7 @@ function ray_trace_fine_step() if bx2 >= 0 and bx2 < 1000 px = 0 end - + if by2 > 1000 py = (1000-by1) * 100 / dy top_face = False @@ -208,7 +208,7 @@ function ray_trace_fine_step() if by2 >= 0 and by2 < 1000 py = 0 end - + if bz2 > 1000 pz = (1000-bz1) * 100 / dz end @@ -218,7 +218,7 @@ function ray_trace_fine_step() if bz2 >= 0 and bz2 < 1000 pz = 0 end - + if face_x and block ~ ~ ~ grass_block $set_texture(70) end @@ -228,7 +228,7 @@ function ray_trace_fine_step() if face_y and bottom_face and block ~ ~ ~ grass_block $set_texture(70) end - + if px face_x = True face_y = False @@ -236,7 +236,7 @@ function ray_trace_fine_step() u = by1 v = bz1 end - + if py face_x = False face_y = True @@ -244,7 +244,7 @@ function ray_trace_fine_step() u = bz1 v = bx1 end - + if pz face_x = False face_y = False @@ -252,14 +252,14 @@ function ray_trace_fine_step() u = by1 v = bx1 end - + if fine_step >= 11 face_x = False face_y = True face_z = False /setblock 0 1 0 light_blue_wool end - + $get_texture("oak_planks", 63) $get_texture("bricks", 64) $get_texture("spruce_leaves", 66) diff --git a/Scripts/archived 1.15 scripts/shockwave.cbscript b/Scripts/archived 1.15 scripts/shockwave.cbscript index 0a076b2..4529ebf 100644 --- a/Scripts/archived 1.15 scripts/shockwave.cbscript +++ b/Scripts/archived 1.15 scripts/shockwave.cbscript @@ -21,13 +21,13 @@ end function create_waveblock(mag) switch block at ~ ~ ~ case air - + end default /summon falling_block ~ ~ ~ {Time:1b, BlockState:{$falling_block_nbt}, Tags:["WaveBlock", "NewWaveBlock"], Motion:[0d, 0.2d, 0d]} end end - + /setblock ~ ~ ~ air as @NewWaveBlock @s.mag = mag diff --git a/Scripts/archived 1.15 scripts/shrink_ray.cbscript b/Scripts/archived 1.15 scripts/shrink_ray.cbscript index 3f7edfa..ebea794 100644 --- a/Scripts/archived 1.15 scripts/shrink_ray.cbscript +++ b/Scripts/archived 1.15 scripts/shrink_ray.cbscript @@ -46,16 +46,16 @@ clock main @p.shooting = True /kill @s end - + at @a[shooting] create @Source /tp @Source @p - + create @Dest /tp @Dest @p - + move @Dest ~ ~1.6 ~ - + step = 0 while step < 200 step++ @@ -65,21 +65,21 @@ clock main /particle minecraft:end_rod ^ ^ ^5 0.25 0.25 0.25 0 5 force @a end end - + if step < 300 /kill @Source /kill @Dest end - + if @Dest - /playsound + /playsound end - + at @Dest ~-8 ~-8 ~-8 do create @Scanner destx = @Dest[limit=1].x desty = @Dest[limit=1].y destz = @Dest[limit=1].z - + as @Scanner /execute at @s align xyz run tp @s ~ ~ ~ x = 0 @@ -119,26 +119,26 @@ clock main sumz += @s.z count++ end - + @Mini[not calc].avex = sumx / count @Mini[not calc].avey = sumy / count @Mini[not calc].avez = sumz / count - + @Mini.calc = True - + @a.shooting = False /kill @Scanner /kill @Source /kill @Dest pitch = 0 end - + if @Mini[not miniature] i=0 convert = count / 80 + 1 while i < convert i++ - as @Mini[not miniature, sort=random, limit=1] + as @Mini[not miniature, sort=random, limit=1] at @s ~-0.5625 ~0.375 ~-0.125 for $bl in: blocks /execute if block ~ ~ ~ $bl run replaceitem entity @s weapon.mainhand $bl @@ -154,7 +154,7 @@ clock main end end end - + unless @Mini[not miniature] i = 0 while i < convert @@ -165,23 +165,23 @@ clock main dx = @s.x - @s.avex dy = @s.y - @s.avey dz = @s.z - @s.avez - + dx = dx * 6 / 16 dz = dz * 6 / 16 dy = dy * 6 / 16 - + @s.x = @s.avex + dx @s.y = @s.avey + dy @s.z = @s.avez + dz - move @s ~ ~ ~ - + move @s ~ ~ ~ + @s.finalized = True end i++ end end - + if @Mini[not miniature] pitch++ for $p in: range(90) @@ -199,7 +199,7 @@ clock main end end end - + unless @Mini[not miniature] if @Mini[not finalized] pitch-- for $p in: range(90) diff --git a/Scripts/archived 1.15 scripts/slopes.cbscript b/Scripts/archived 1.15 scripts/slopes.cbscript index 943e24b..e7bda58 100644 --- a/Scripts/archived 1.15 scripts/slopes.cbscript +++ b/Scripts/archived 1.15 scripts/slopes.cbscript @@ -57,12 +57,12 @@ function create_slope() else if block ~ ~ ~-1 air unless block ~ ~ ~1 air ry = 180000 end - + unless ry == -1 @s.ry = ry @Marker.current = False @s.current = True - + for $i in $range($len($offsets)) rotated @s at ^<$offsets[$i]> @s.blocks[$i] = create @MiniBlock ^ ^-1.6 ^-0.22 @@ -95,7 +95,7 @@ function create_slope() if @s.ry == 270000 /setblock ~ ~ ~ tripwire[north=true,south=true] end - + as create @Physics ~ ~-1 ~ /tp @s ~ ~ ~ @s.ry = ry @@ -147,14 +147,14 @@ clock main /kill @s end end - + as @Player if @s.slide at @s if @Slope[distance=..1.3,limit=1] @s.slide_count++ else @s.slide_count = 0 end - + at @s[slide_count] rotated @Slope[distance=..1.3,limit=1] switch @s.slide_count case $i in $range(50) @@ -162,7 +162,7 @@ clock main $vdist = -$dist /tp @s ^ ^$vdist ^$dist end - case 50 to 100000 + case 50 to 100000 $dist = $float(50) * 0.01 $vdist = -$dist /tp @s ^ ^$vdist ^$dist @@ -174,7 +174,7 @@ clock main end end end - + if @s[nbt={"SelectedItem":{tag:{display:{Name:"{\"text\":\"Sloper\"}"}}}}] and @s.create_slope steps = 0 at @s ~ ~1.6 ~ @@ -188,15 +188,15 @@ clock main end end end - + @Player.create_slope = False - + as @Player[slide] at @s rotated @Slope[distance=..1,limit=1] /tp @s ^ ^ ^0.1 end @Player.slide = 0 - + as @MiniBlock[slope] @s.fire = 10 end -end \ No newline at end of file +end diff --git a/Scripts/archived 1.15 scripts/sort_chest.cbscript b/Scripts/archived 1.15 scripts/sort_chest.cbscript index fc27b26..41ba826 100644 --- a/Scripts/archived 1.15 scripts/sort_chest.cbscript +++ b/Scripts/archived 1.15 scripts/sort_chest.cbscript @@ -5,7 +5,7 @@ import common define @ItemHolder: @Entity[type=armor_stand,tag=ItemHolder] create {Tags:["ItemHolder"], Marker:1b, Invisible:1b, NoGravity:1b, Invulnerable:1b, Silent:1b} - + item_count: HandItems[0].Count byte 1 end @@ -54,7 +54,7 @@ reset /team add highlight /team modify highlight color blue /team modify highlight collisionRule never - + /bossbar add sort_chest "Sort" /bossbar set sort_chest max 20 end @@ -63,24 +63,24 @@ clock main at -778 57 73 sort_container() end - + @ChestUI.live = False - + for @player in @Player at @s ~ ~1.7 ~ unless @Position do create @Position as @Position /tp @s ~ ~ ~ ~ ~ - + rx = @s.rx ry = @s.ry - + for step = 0 to 12 move @s ^ ^ ^0.5 - at @s align xyz at ~0.5 ~0.3 ~0.5 if block ~ ~ ~ chest + at @s align xyz at ~0.5 ~0.3 ~0.5 if block ~ ~ ~ chest step = 100 unless @ChestUI[distance=0] do create @ChestUI - + as @ChestUI[distance=0] @s.live = True at @player ~ ~1.7 ~ facing @s @@ -111,6 +111,6 @@ clock main end end end - + /kill @ChestUI[not live] end diff --git a/Scripts/archived 1.15 scripts/source_block.cbscript b/Scripts/archived 1.15 scripts/source_block.cbscript index 8669e11..b2afc14 100644 --- a/Scripts/archived 1.15 scripts/source_block.cbscript +++ b/Scripts/archived 1.15 scripts/source_block.cbscript @@ -54,7 +54,7 @@ clock main end end end - + switch dist case $dist in $range(30) $volume = 2 - ($dist / 30.0) @@ -69,10 +69,10 @@ clock main end end end - + unless @Position do create @Position unless @Position2 do create @Position2 - + as @Player[distance=..30] @Position. = at @s ~ ~0.5 ~ @@ -81,10 +81,10 @@ clock main at @Position facing @Position2 /tp @Position ~ ~ ~ ~ ~ end - + = @s. - dist = sqrt( * ) / 1000 - + mag = 30 - dist prog = 0 @@ -99,7 +99,7 @@ clock main /particle instant_effect ~ ~ ~ 0.1 0.1 0.1 0 1 force end end - + if randint(0, $i*100) == 0 /effect give @s night_vision 1 0 true end @@ -113,4 +113,4 @@ clock main end end end -end \ No newline at end of file +end diff --git a/Scripts/archived 1.15 scripts/splash_potion_range_finder.cbscript b/Scripts/archived 1.15 scripts/splash_potion_range_finder.cbscript index de202c4..12a985b 100644 --- a/Scripts/archived 1.15 scripts/splash_potion_range_finder.cbscript +++ b/Scripts/archived 1.15 scripts/splash_potion_range_finder.cbscript @@ -18,20 +18,20 @@ clock main for @player in @Player holding_potion = False /execute if entity @s[nbt={SelectedItem:{id:"minecraft:splash_potion"}}] run scoreboard players set Global holding_potion 1 - + if holding_potion unless @Position do create @Position as @Position at @player /tp @s ~ ~ ~ ~ ~ end - + = @s. move @s ^ ^ ^1 = (@s. - ) / 2 - + += <0, 23000, 0> - + for i = 1 to 100 *= 990 /= 1000 diff --git a/Scripts/archived 1.15 scripts/spyglass.cbscript b/Scripts/archived 1.15 scripts/spyglass.cbscript index 23b6756..661738b 100644 --- a/Scripts/archived 1.15 scripts/spyglass.cbscript +++ b/Scripts/archived 1.15 scripts/spyglass.cbscript @@ -6,7 +6,7 @@ import miniblock define @Magnified: @Entity[type=falling_block, tag=Magnified] time: Time byte 1 -end +end define @NewPosition = @Entity[type=area_effect_cloud,tag=Position,limit=1] create {Tags:["NewPosition"], Duration:-1,Age:-2147483648,WaitTime:-2147483648} @@ -30,21 +30,21 @@ clock main end end @s.magnification = magnification - + if magnification > 0 if @s.rx == @s.prev_rx and @s.ry == @s.prev_ry and @s. == @s. and @s.prev_mag == @s.magnification else /kill @Magnified - + rx = @s.rx ry = @s.ry - + first_match = True - + drx = 0 dry = 0 cast_magnifier_ray() - + for dx = 0 to 10000 by 2000 for dy = 0 to 10000 by 2000 drx = dx / magnification @@ -95,8 +95,8 @@ clock main end end end - - + + @s.prev_rx = @s.rx @s.prev_ry = @s.ry @s. = @s. @@ -104,10 +104,10 @@ clock main /kill @Magnified /kill @MiniBlock[side >= 0] end - + @s.prev_mag = magnification end - + for @bamboo in @Entity[type=item,nbt={Item:{id:"minecraft:bamboo", Count:1b}}] for $c in $range(2, 65) at @s unless @s[nbt={Item:{tag:{spyglass:1b}}}] as @Entity[type=item,nbt={Item:{id:"minecraft:glass_pane",Count:$cb}},distance=..0.5,limit=1] at @s @@ -118,7 +118,7 @@ clock main end end end - + as @Magnified @s.time = 1 end @@ -129,31 +129,31 @@ function cast_magnifier_ray() /tp @s ~ ~ ~ ~ ~ @s.rx += drx @s.ry += dry - + at @s feet ^ ^ ^ /tp @s ~ ~ ~ end - + for step = 1 to 400 at @s feet ^ ^ ^0.25 /tp @s ~ ~ ~ end - + at @s align xyz at ~0.5 ~0.5 ~0.5 unless block ~ ~ ~ air if first_match first_match = False = @s. - (@Player[limit=1]. + <0, 1600, 0>) = - / magnification end - + /tp @s ~ ~ ~ @s. -= - + # = @s. - @Player[limit=1]. # = - / magnification #/tp @s ~ ~ ~ #@s. -= - + create_magnified_block() step = 1000000 end @@ -169,4 +169,4 @@ function create_magnified_block() end end end -end \ No newline at end of file +end diff --git a/Scripts/archived 1.15 scripts/sqrt_test.cbscript b/Scripts/archived 1.15 scripts/sqrt_test.cbscript index 7067104..4a9f185 100644 --- a/Scripts/archived 1.15 scripts/sqrt_test.cbscript +++ b/Scripts/archived 1.15 scripts/sqrt_test.cbscript @@ -10,4 +10,4 @@ reset s = sqrt(v) tell @a 'sqrt\((v)\) = (s)' end -end \ No newline at end of file +end diff --git a/Scripts/archived 1.15 scripts/stardew_fishing.cbscript b/Scripts/archived 1.15 scripts/stardew_fishing.cbscript index ebc94be..a71982d 100644 --- a/Scripts/archived 1.15 scripts/stardew_fishing.cbscript +++ b/Scripts/archived 1.15 scripts/stardew_fishing.cbscript @@ -44,14 +44,14 @@ clock main playing = True end_game = False win = False - + /kill @Fish /kill @Bar create @Fish height = 0 vel = 0 acc = 0 - + reelheight = 0 reelvel = 0 @@ -62,7 +62,7 @@ clock main as @Fish at @s rotated @s /tp @s ^ ^ ^7 end - + bottom = @Fish.y at @Fish for $i in: range(10) @@ -76,23 +76,23 @@ clock main end @Reel.offset += 180 end - + @s.caught = 0 - + progress = 0 - + /bossbar add stardew_fishing:progress "Reel" /bossbar set stardew_fishing:progress value 0 /bossbar set stardew_fishing:progress max 100 /bossbar set stardew_fishing:progress players @s end end - + if playing acc += rand(-1, 2) vel += acc height += vel - + if height > 480 height = 480 end @@ -107,7 +107,7 @@ clock main vel = -10 acc = 1 end - + if @p.shift > 0 @p.shift = 0 reelvel += 4 @@ -122,11 +122,11 @@ clock main reelheight = 420 reelvel = -3 * reelvel / 4 end - + as @Reel @s.y = bottom + reelheight + @s.offset end - + reelmax = reelheight + 80 reelmin = reelheight - 80 scoring = False @@ -135,10 +135,10 @@ clock main end if scoring then progress++ if not scoring then progress-- - - @Fish.y = bottom + height + + @Fish.y = bottom + height /execute store result bossbar stardew_fishing:progress value run scoreboard players get Global progress - + end_game = False if progress < 0 then end_game = True if progress >= 100 @@ -175,7 +175,7 @@ clock main /kill @Fish /kill @Bar /kill @Reel - /bossbar remove stardew_fishing:progress + /bossbar remove stardew_fishing:progress playing = False end end diff --git a/Scripts/archived 1.15 scripts/stasis.cbscript b/Scripts/archived 1.15 scripts/stasis.cbscript index f7917c2..9c24b3f 100644 --- a/Scripts/archived 1.15 scripts/stasis.cbscript +++ b/Scripts/archived 1.15 scripts/stasis.cbscript @@ -12,7 +12,7 @@ define @Vector = @Entity[type=slime,tag=Vector] create {CustomName:"\"Vector\"", Tags:["Vector"], NoGravity:1b, NoAI: 1b, Invisible:1b, Silent:1b, Size:0, Invulnerable:1b} end @Frozen = @Entity[stasis_timer > 0,limit=1] - + reset /team add stasis_target /team modify stasis_target color yellow @@ -50,17 +50,17 @@ clock main @s.glowing = False /tag @s remove stasis_target end - + @Player[stasis_cooldown > 0].stasis_cooldown-- - + for @player in @Player[nbt={SelectedItem:{id:"minecraft:carrot_on_a_stick",tag:{display:{Name:"{\"text\":\"Stasis\"}"}}}}] unless @s.stasis_cooldown > 0 at @s ~ ~1.6 ~ steps = 0 - + while steps < 100 at ^ ^ ^0.1 at ~ ~-1 ~ as @Entity[type=!player,distance=..1,limit=1,sort=nearest] unless @s[type=area_effect_cloud] at @s ~ ~1 ~ steps = 1000000 - + /tag @s add stasis_target @s.glowing = True /team join stasis_target @s @@ -79,9 +79,9 @@ clock main @s.hit_mag = 0 @s.old_invuln = @s.invulnerable @s.invulnerable = True - + refresh_hit_detector() - + for i = 1 to 40 as create @Vector ~ ~50 ~ /tp @s ~ ~ ~ @@ -90,7 +90,7 @@ clock main @s.glowing = True end end - + $playsound('entity.iron_golem.hurt', 0) end end @@ -101,20 +101,20 @@ clock main @s.stasis_cooldown = 0 end end - + @Frozen.stasis_timer-- - + as @HitDetector /effect give @s invisibility 10 1 true end as @Vector /effect give @s invisibility 10 1 true end - + as @Frozen at @s @s. = @s. - + if @s.stasis_timer > 128 if @s.stasis_timer % 32 == 0 $playsound('block.note_block.guitar', 24) @@ -140,7 +140,7 @@ clock main /team join stasis_freeze end end - + if @HitDetector.absorption < 100 as @Player[sort=nearest,limit=1] at @s unless @Position do create @Position @@ -148,19 +148,19 @@ clock main = @Position. /tp @Position ^ ^ ^1 = @Position. - - + @Frozen. = @Frozen.hit_mag++ if @Frozen.hit_mag > 8 @Frozen.hit_mag = 8 end - + switch @Frozen.hit_mag case $i in $range(9) $playsound('block.note_block.bit', $i) end end - + = @Frozen. * @Frozen.hit_mag as @Vector @s. = @Frozen. + * @s.part / 60 + <0, 1000, 0> @@ -169,7 +169,7 @@ clock main refresh_hit_detector() end end - + as @Entity[stasis_timer == 1] at @s @s.noai = @s.old_noai @s.no_gravity = @s.old_nograv @@ -183,9 +183,9 @@ clock main @s. = @s. * @s.hit_mag / 2 @Player.stasis_cooldown = 0 end - + @Player.apply_stasis = 0 - + unless @Frozen /tp @Vector ~ -200 ~ /kill @Vector diff --git a/Scripts/archived 1.15 scripts/telescope.cbscript b/Scripts/archived 1.15 scripts/telescope.cbscript index fffb97d..b59bbfa 100644 --- a/Scripts/archived 1.15 scripts/telescope.cbscript +++ b/Scripts/archived 1.15 scripts/telescope.cbscript @@ -6,7 +6,7 @@ import miniblock define @Magnified: @Entity[type=falling_block, tag=Magnified] time: Time byte 1 -end +end define @NewPosition = @Entity[type=area_effect_cloud,tag=Position,limit=1] create {Tags:["NewPosition"], Duration:-1,Age:-2147483648,WaitTime:-2147483648} @@ -30,21 +30,21 @@ clock main end end @s.magnification = magnification - + if magnification > 0 if @s.rx == @s.prev_rx and @s.ry == @s.prev_ry and @s. == @s. and @s.prev_mag == @s.magnification else /kill @Magnified - + rx = @s.rx ry = @s.ry - + first_match = True - + drx = 0 dry = 0 cast_magnifier_ray() - + for dx = 0 to 10000 by 2000 for dy = 0 to 10000 by 2000 drx = dx / magnification @@ -95,8 +95,8 @@ clock main end end end - - + + @s.prev_rx = @s.rx @s.prev_ry = @s.ry @s. = @s. @@ -104,10 +104,10 @@ clock main /kill @Magnified /kill @MiniBlock[side >= 0] end - + @s.prev_mag = magnification end - + for @bamboo in @Entity[type=item,nbt={Item:{id:"minecraft:bamboo", Count:1b}}] for $c in $range(65) at @s unless @s[nbt={Item:{tag:{telescope:1b}}}] as @Entity[type=item,nbt={Item:{id:"minecraft:glass_pane",Count:$cb}},distance=..0.5,limit=1] at @s @@ -119,7 +119,7 @@ clock main end end end - + as @Magnified @s.time = 1 end @@ -130,31 +130,31 @@ function cast_magnifier_ray() /tp @s ~ ~ ~ ~ ~ @s.rx += drx @s.ry += dry - + at @s feet ^ ^ ^ /tp @s ~ ~ ~ end - + for step = 1 to 400 at @s feet ^ ^ ^0.25 /tp @s ~ ~ ~ end - + at @s align xyz at ~0.5 ~0.5 ~0.5 unless block ~ ~ ~ air if first_match first_match = False = @s. - (@Player[limit=1]. + <0, 1600, 0>) = - / magnification end - + /tp @s ~ ~ ~ @s. -= - + # = @s. - @Player[limit=1]. # = - / magnification #/tp @s ~ ~ ~ #@s. -= - + create_magnified_block() step = 1000000 end @@ -170,4 +170,4 @@ function create_magnified_block() end end end -end \ No newline at end of file +end diff --git a/Scripts/archived 1.15 scripts/test2.cbscript b/Scripts/archived 1.15 scripts/test2.cbscript index c112d87..2b19e9b 100644 --- a/Scripts/archived 1.15 scripts/test2.cbscript +++ b/Scripts/archived 1.15 scripts/test2.cbscript @@ -19,4 +19,4 @@ end clock main -end \ No newline at end of file +end diff --git a/Scripts/archived 1.15 scripts/test_json_objects.cbscript b/Scripts/archived 1.15 scripts/test_json_objects.cbscript index 88096f3..ef9ff5f 100644 --- a/Scripts/archived 1.15 scripts/test_json_objects.cbscript +++ b/Scripts/archived 1.15 scripts/test_json_objects.cbscript @@ -12,4 +12,4 @@ reset else /say entity_tag fail end -end \ No newline at end of file +end diff --git a/Scripts/archived 1.15 scripts/tetris.cbscript b/Scripts/archived 1.15 scripts/tetris.cbscript index 27bae88..ed163cf 100644 --- a/Scripts/archived 1.15 scripts/tetris.cbscript +++ b/Scripts/archived 1.15 scripts/tetris.cbscript @@ -22,7 +22,7 @@ $StateLineAnimation = 2 reset unless game_state >= 0 game_state = $StateIntro - + /kill @Background for $x in [1.5, 4.5] for $y in [79, 82, 85, 88] @@ -30,7 +30,7 @@ reset create @Background <$pos> end end - + /kill @ScoreDigit for i = 0 to 5 @Position.x = 12000 - i * 800 @@ -42,7 +42,7 @@ reset end end end - + /kill @LevelDigit for i = 0 to 1 @Position.x = 11000 - i * 800 @@ -54,7 +54,7 @@ reset end end end - + /kill @LineDigit for i = 0 to 2 @Position.x = 11000 - i * 800 @@ -73,11 +73,11 @@ reset if game_state == $StateIntro tell @a '{GLeft click{- with a {GTetris item{- to start the game.' end - + /scoreboard objectives add shift minecraft.custom:minecraft.sneak_time /scoreboard objectives add jump minecraft.custom:minecraft.jump /scoreboard objectives add login minecraft.custom:minecraft.leave_game - + update_score(0) update_level(0) update_lines(0) @@ -358,12 +358,12 @@ function restart_game() update_lines(0) level = 0 update_level(0) - + /kill @FallingBlock /kill @NextBlock spawn_random() spawn_new_piece = True - + game_state = $StateFalling end @@ -372,25 +372,25 @@ function spawn_shape(shape) falling_y = 18 falling_rotation = 0 falling_shape = next_shape - + as @NextBlock @s.next = False @s.falling = True end reposition_falling() - + next_shape = shape - + @Position.x = 9000 @Position.y = 80300 @Position.z = -700 - + at @Position switch shape case $shape in $range($len($shape_offsets)) for $i in $range(4) $dx, $dy = $shape_offsets[$shape][0][$i] - + $dx = $Scale * $dx $dy = $Scale * $dy @@ -404,7 +404,7 @@ function spawn_shape(shape) @s.update() end end - + end rotation = 0 end @@ -420,7 +420,7 @@ function space_available(x, y, shape, rotation) case $r in $range(4) for $i in $range(4) $dx, $dy = $shape_offsets[$shape][$r][$i] - + cx = x + $dx cy = y + $dy @@ -433,7 +433,7 @@ function space_available(x, y, shape, rotation) end end end - + return available end @@ -491,7 +491,7 @@ function reposition_falling() case $r in $range(4) for $i in $range(4) $dx, $dy = $shape_offsets[$shape][$r][$i] - + $dx = $Scale * $dx $dy = $Scale * $dy @@ -521,7 +521,7 @@ function land() @Position.x = 300 + falling_x * 600 @Position.y = 79300 + falling_y * 600 @Position.z = -500 - + at @Position switch falling_shape case $shape in $range($len($shape_offsets)) @@ -531,7 +531,7 @@ function land() as @FallingBlock[block_num == $i] @s.falling = False @s.fixed = True - + $dx, $dy = $shape_offsets[$shape][$r][$i] @s.block_x = falling_x + $dx @s.block_y = falling_y + $dy @@ -542,9 +542,9 @@ function land() end end end - + check_for_full_lines() - + if line_count > 0 and line_count < 4 as @Player at @s /playsound item.trident.riptide_1 block @s ~ ~ ~ 0.5 0 @@ -556,9 +556,9 @@ function land() /playsound block.beacon.activate block @s ~ ~ ~ 1 2 end end - + switch line_count - case 0 + case 0 update_score(drop_streak) end case 1 @@ -574,15 +574,15 @@ function land() update_score(1200 + drop_streak) end end - + update_lines(line_count) if lines >= (level+1)*10 update_level(1) end - + drop_streak = 0 @Player.drop_cooldown = 8 - + spawn_new_piece = True fall_timer = 0 end @@ -601,7 +601,7 @@ function check_for_full_lines() line_complete = False end end - + if line_complete full_lines[line_count] = y line_count++ @@ -642,10 +642,10 @@ end clock main unless @Position do create @Position - + as @Player at @s /effect give @s saturation 1 0 true - + if @s.was_holding unless @s[nbt={SelectedItem:{id:"minecraft:carrot_on_a_stick",tag:{display:{Name:"{\"text\":\"Tetris\"}"}}}}] dummy = 0 if success @@ -660,16 +660,16 @@ clock main end end end - + if @s[nbt={SelectedItem:{id:"minecraft:carrot_on_a_stick",tag:{display:{Name:"{\"text\":\"Tetris\"}"}}}}] @s.enable_click() - + if @s.jump if game_state == $StateFalling rotate_left() end end - + if @s.shift @s.drop_cooldown-- if @s.drop_cooldown <= 0 @@ -683,22 +683,22 @@ clock main drop_streak++ end end - + @s.was_shifting = True else @s.drop_cooldown = 0 @s.was_shifting = False drop_streak = 0 end - + @s.was_holding = True else @s.disable_click() @s.drop_cooldown = 0 - + @s.was_holding = False end - + if @s.login tell @s 'Running {GTetris{- by SethBling and MrMakistein.' tell @s 'Click {B{U[here](call give_tetris_item){- to get a Tetris item to play.' @@ -706,7 +706,7 @@ clock main tell @s '{GLeft click{- with a {GTetris item{- to start the game.' end end - + @s.right_click = 0 @s.shift = 0 @s.jump = 0 @@ -750,13 +750,13 @@ clock main for i = 0 to line_count-1 clear_line(full_lines[i]) end - + fall_timer = 0 game_state = $StateFalling end end end - + as @ScoreDigit at @s facing @Player[limit=1, sort=nearest] /tp @s ~ ~ ~ ~ 0 end @@ -784,7 +784,7 @@ function update_score(add_amount) if score > 999999 score = 999999 end - + score_remainder = score for i = 0 to 5 as @ScoreDigit if @s.score_digit == i @@ -809,7 +809,7 @@ function update_lines(add_amount) if lines > 999 lines = 999 end - + lines_remainder = lines for i = 0 to 2 as @LineDigit if @s.line_digit == i @@ -834,7 +834,7 @@ function update_level(add_amount) if level > 99 level = 99 end - + level_remainder = level for i = 0 to 2 as @LevelDigit if @s.level_digit == i @@ -852,4 +852,4 @@ function update_level(add_amount) level_remainder /= 10 end end -end \ No newline at end of file +end diff --git a/Scripts/archived 1.15 scripts/tetris_test.cbscript b/Scripts/archived 1.15 scripts/tetris_test.cbscript index 23e4c42..bad93ce 100644 --- a/Scripts/archived 1.15 scripts/tetris_test.cbscript +++ b/Scripts/archived 1.15 scripts/tetris_test.cbscript @@ -216,43 +216,43 @@ $blocks = [ function respawn_square() shape = 0 - + spawn_shape() end function respawn_line() shape = 1 - + spawn_shape() end function respawn_l() shape = 2 - + spawn_shape() end function respawn_lr() shape = 3 - + spawn_shape() end function respawn_s() shape = 4 - + spawn_shape() end function respawn_z() shape = 5 - + spawn_shape() end function respawn_t() shape = 6 - + spawn_shape() end @@ -265,7 +265,7 @@ function spawn_shape() at @s ~ ~1.6 ~ at ^ ^ ^3 for $i in $range(4) $dx, $dy = $shape_offsets[$shape][0][$i] - + $dx = $Scale * $dx $dy = $Scale * $dy @@ -278,7 +278,7 @@ function spawn_shape() @s.update() end end - + end as create @Marker @s.bottom_left = True @@ -291,19 +291,19 @@ end function rotate_left() rotation-- - + reorient() end function rotate_right() rotation++ - + reorient() end function reorient() rotation %= 4 - + at @Marker[bottom_left,limit=1] switch shape case $shape in $range($len($shape_offsets)) @@ -311,7 +311,7 @@ function reorient() case $r in $range(4) for $i in $range(4) $dx, $dy = $shape_offsets[$shape][$r][$i] - + $dx = $Scale * $dx $dy = $Scale * $dy @@ -333,4 +333,4 @@ end function click_callback() /say click -end \ No newline at end of file +end diff --git a/Scripts/archived 1.15 scripts/thrust.cbscript b/Scripts/archived 1.15 scripts/thrust.cbscript index d6b20e3..5f3f1b6 100644 --- a/Scripts/archived 1.15 scripts/thrust.cbscript +++ b/Scripts/archived 1.15 scripts/thrust.cbscript @@ -34,13 +34,13 @@ function on_creeper_damage() if @s.lockout /advancement revoke @s only thrust:thrust_damage /effect clear @s resistance - + /tag @Player remove current /tag @s add current @player = @Player[tag=current] - + = @s. - + unless @Position do create @Position as @Position @s. = @@ -84,16 +84,16 @@ function armor_stand_thrust() end @s.motion = create @Motion @s. = @s. - + at @s do get_aim() id = &@s - + as @s.motion @s. = * 3 @s.player = id end end - + if @s.on_ground unless @s.was_on_ground if @s.motion as @s.motion /kill @s @@ -103,19 +103,19 @@ function armor_stand_thrust() @s.was_on_ground = @s.on_ground = @s. - @s. as @s.motion - + @s. += * 5 at @s /tp @player 0 0 0 /tp @player ~ ~ ~ end - + if @s.on_ground /kill @s @player.motion = None end end @s. = @s. - + end -end \ No newline at end of file +end diff --git a/Scripts/archived 1.15 scripts/tnt_cannon.cbscript b/Scripts/archived 1.15 scripts/tnt_cannon.cbscript index 5e2ad85..abea9f8 100644 --- a/Scripts/archived 1.15 scripts/tnt_cannon.cbscript +++ b/Scripts/archived 1.15 scripts/tnt_cannon.cbscript @@ -13,12 +13,12 @@ reset @s.rot_x = 0 @s.rot_y = 0 @s.seg = i - + /replaceitem entity @s weapon.mainhand diamond_block end end end - + rx = 0 ry = 0 end @@ -28,14 +28,14 @@ clock main if swap_timer >= 40 rx += -10000 #ry += -20000 - + unless @Position do create @Position @Position.rx = rx @Position.ry = ry = @Position. move @Position ^ ^ ^0.325 = @Position. - - + as @TinyBlock @Position. = <$TestPos> + * @s.seg @s.rot_x = rx @@ -44,9 +44,9 @@ clock main @s.update_tiny() end end - + swap_timer = 0 end - -end \ No newline at end of file + +end diff --git a/Scripts/archived 1.15 scripts/tntbreed.cbscript b/Scripts/archived 1.15 scripts/tntbreed.cbscript index da76372..67803c7 100644 --- a/Scripts/archived 1.15 scripts/tntbreed.cbscript +++ b/Scripts/archived 1.15 scripts/tntbreed.cbscript @@ -9,7 +9,7 @@ define @TNT: @Entity[type=tnt] end @Gunpowder = @Entity[type=item,nbt={Item:{id:"minecraft:gunpowder"}}] - + reset end @@ -21,7 +21,7 @@ clock main at @s facing @player /tp @s ~ ~ ~ ~ ~ end - + if @s.hop_timer > 0 @s.hop_timer-- else @@ -31,14 +31,14 @@ clock main @s.hop_timer = 50 end end - + if @s.fuse < 32 @s.fuse += 16 end end end end - + as @TNT at @s if @Gunpowder[distance=..1] /kill @Gunpowder[distance=..1] @@ -46,4 +46,4 @@ clock main @s.ready = 400 end end -end \ No newline at end of file +end diff --git a/Scripts/archived 1.15 scripts/tornado.cbscript b/Scripts/archived 1.15 scripts/tornado.cbscript index b262079..882ab15 100644 --- a/Scripts/archived 1.15 scripts/tornado.cbscript +++ b/Scripts/archived 1.15 scripts/tornado.cbscript @@ -49,9 +49,9 @@ clock main as create @Spit @s. = <-dz, 200, dx> / 4 end - end + end end - + @s. += @s. @s. += end @@ -59,10 +59,10 @@ clock main as @Spit @s.air = 1 @s.air = 0 - + @s.age++ if @s.age >= 20 /kill @s end end -end \ No newline at end of file +end diff --git a/Scripts/archived 1.15 scripts/tracer.cbscript b/Scripts/archived 1.15 scripts/tracer.cbscript index 845b08f..8ae7276 100644 --- a/Scripts/archived 1.15 scripts/tracer.cbscript +++ b/Scripts/archived 1.15 scripts/tracer.cbscript @@ -160,25 +160,25 @@ end clock teleport @Player.cooldown += 0 - + at @Player do create @Tracker - + @Tracker.age++ /kill @Tracker[age >= 3] - + if @Player.cooldown > 0 then @Player.cooldown-- - + if @Player.shift > 0 and @Player.cooldown == 0 @Current = @Tracker[age==2,limit=1] @Prev = @Tracker[age==1,limit=1] dx = @Current.x - @Prev.x dz = @Current.z - @Prev.z - + do_teleport = True if dx == 0 and dz == 0 do_teleport = False end - + if do_teleport at @Current /tp @Current ~ ~ ~ facing entity @Prev @@ -189,40 +189,40 @@ clock teleport at @Player /teleport @Current ~ ~ ~ end - + @Player.cooldown = 5 - - continue = True + + continue = True ticks = 0 while ticks < 40 continue = False at @Current if block ~ ~ ~ horizontally_non_colliding then continue = True - + if continue at @Current /tp @Current ^ ^ ^0.25 end end - + if not continue at @Current /tp @Current ^ ^ ^-1 end ticks = 40 end - + ticks = ticks + 1 end - + at @Current /teleport @Player ~ ~ ~ /playsound minecraft:entity.enderman.teleport player @Player end end - + /kill @Tracker end - + if @Player.shift > 0 then @Player.shift = 0 -end \ No newline at end of file +end diff --git a/Scripts/archived 1.15 scripts/transformers.cbscript b/Scripts/archived 1.15 scripts/transformers.cbscript index 29dcc8a..59180f3 100644 --- a/Scripts/archived 1.15 scripts/transformers.cbscript +++ b/Scripts/archived 1.15 scripts/transformers.cbscript @@ -9,15 +9,15 @@ define @TransformerBlockPos : @Entity[type=armor_stand, tag=TransformerBlockPos] y_axis = True z_axis = True blocked = False - + = @s. = @s. - + /tp @Position @s - + @s.check_axis_blocked(rand(3)) @s. = - + r = rand(2) if r == 0 if x_axis @@ -38,7 +38,7 @@ define @TransformerBlockPos : @Entity[type=armor_stand, tag=TransformerBlockPos] end @s.check_axis_blocked(axis) @s. = - + if x_axis axis = 0 else if y_axis @@ -47,7 +47,7 @@ define @TransformerBlockPos : @Entity[type=armor_stand, tag=TransformerBlockPos] axis = 2 end @s.check_axis_blocked(axis) - + if not blocked @s.stops = 2 end @@ -93,10 +93,10 @@ define @TransformerBlockPos : @Entity[type=armor_stand, tag=TransformerBlockPos] end end end - + = end - + function check_blocked() at @s if @TransformerBlockPos[distance=..0.01] then blocked = True @@ -117,15 +117,15 @@ end reset /gamerule maxCommandChainLength 1000000000 - + /scoreboard objectives add use_transformer minecraft.used:minecraft.carrot_on_a_stick - + unless anim_ticks > 0 anim_ticks = 1 end - + tell @a 'Loaded Transformers by SethBling' - + tell @a '[\[Animate 1->2\]](call animate12)' tell @a 'Animation Speed: [\[Slow\]](call slow) [\[Fast\]](call fast)' end @@ -152,9 +152,9 @@ end function trigger_animation(id1, id2) @BlockMarker.matched = False - + as @BlockMarker if @s.structure_id == id1 at @s - block_id = @s.block_id + block_id = @s.block_id matched = False as @BlockMarker[not matched, sort=random] dummy = 0 @@ -164,19 +164,19 @@ function trigger_animation(id1, id2) = @s. end end - - + + @Position. = + @s. + <500, 0, 500> at @Position create_transformer_block(block_id) /setblock ~ ~ ~ air end - + as @NewTransformerBlock p = &@s /tag @s remove NewTransformerBlock end - + as @NewTransformerBlockPos @s. = + + <500, 0, 500> @s.block_id = block_id @@ -189,7 +189,7 @@ end clock main unless @Position do create @Position - + as @Player at @s if @s[nbt={"SelectedItem":{tag:{display:{Name:"{\"text\":\"Transformer\"}"}}}}] and @s.use_transformer steps = 0 @@ -203,10 +203,10 @@ clock main end end end - + @s.use_transformer = 0 end - + init_timer++ if init_timer >= anim_ticks init_timer = 0 @@ -224,7 +224,7 @@ clock main end end end - + if not succeeded as @TransformerBlockPos[not initiated,sort=random,limit=1] @s.initiated = True @@ -234,14 +234,14 @@ clock main end end end - - + + as @TransformerBlockPos[initiated] at @s $AnimationTimeSteps = 8 @s.age++ - + stop = (@s.age+($AnimationTimeSteps-1)) / $AnimationTimeSteps - + if stop > @s.stops = @s. else if stop == 1 @@ -249,7 +249,7 @@ clock main else if stop == 2 = @s. end - + if @s.age % $AnimationTimeSteps == 0 @s. = if stop > @s.stops @@ -263,7 +263,7 @@ clock main end end end - + as @TransformerBlock @s.time = 1 if @s.kill @@ -276,7 +276,7 @@ function finish_animation() at @s set_block(@s.block_id) end - + as @s.trans_block @s.kill = True /kill @s @@ -290,7 +290,7 @@ function compute_center() ymin = 0 first = True count = 0 - + as @BlockMarker if @s.structure_id == structure_id = @s. if first @@ -305,11 +305,11 @@ function compute_center() sz += z count++ end - + cx = sx / count / 1000 * 1000 cz = sz / count / 1000 * 1000
= - + as @BlockMarker if @s.structure_id == structure_id @s. = @s. -
end @@ -319,20 +319,20 @@ function select_structure() tell @a 'Mapping structure...' block_count = 0 structure_id++ - + map_structure_recursive() - + @BlockMarker.counted = False matching = True # Check that each block has a matching block in structure_1 as @BlockMarker dummy = 0 - + # Only continue if it's matching if matching and @s.structure_id == structure_id matched = False id = @s.block_id - + # Find a matching uncounted block in structure_1 as @BlockMarker[not counted] # Do not continue if there was a match already @@ -344,27 +344,27 @@ function select_structure() end end end - + if not matched matching = False end end end - + # Check that there are no remaining blocks in structure_1 as @BlockMarker[not counted] if @s.structure_id == structure_1 matching = False end - + compute_center() if matching structure_2 = structure_id =
= = - + get_combined_bounding_box() - + anim_ready = True tell @a 'Structure matches!' tell @a '[\[Animate 1->2\]](call animate12)' @@ -376,7 +376,7 @@ function select_structure() = anim_ready = False end - + @BlockMarker.keep = False as @BlockMarker if @s.structure_id == structure_1 @s.keep = True @@ -385,13 +385,13 @@ function select_structure() @s.keep = True end /kill @BlockMarker[not keep] - + tell @a 'Blocks: (block_count)' if block_count > 0 /= 1000 /= 1000 end - + @BlockMarker.counted = False as @BlockMarker dummy = 0 @@ -413,7 +413,7 @@ function get_combined_bounding_box() = - = - = - - + if dxmin1 < dxmin2 dxmin = dxmin1 else @@ -429,7 +429,7 @@ function get_combined_bounding_box() else dzmin = dzmin2 end - + if dxmax1 < dxmax2 dxmax = dxmax1 else @@ -482,7 +482,7 @@ function map_structure_recursive() end end block_count++ - + for $delta in [ (0, 0, 1), (0, 0, -1), @@ -501,7 +501,7 @@ end function create_transformer_block(id) switch block id default - /summon armor_stand ~ ~ ~ {Tags:["TransformerBlockPos", "NewTransformerBlockPos"], Marker:1b, Invisible:1b, Invulnerable:1b, NoGravity:1b, Passengers:[{id:"falling_block", Time:1b, NoGravity:1b, BlockState:{$falling_block_nbt}, Tags:["TransformerBlock","NewTransformerBlock"]}]} + /summon armor_stand ~ ~ ~ {Tags:["TransformerBlockPos", "NewTransformerBlockPos"], Marker:1b, Invisible:1b, Invulnerable:1b, NoGravity:1b, Passengers:[{id:"falling_block", Time:1b, NoGravity:1b, BlockState:{$falling_block_nbt}, Tags:["TransformerBlock","NewTransformerBlock"]}]} end end end @@ -529,4 +529,4 @@ function say_count(id, qty) tell @a '(qty)x$block_state' end end -end \ No newline at end of file +end diff --git a/Scripts/archived 1.15 scripts/undo_redo.cbscript b/Scripts/archived 1.15 scripts/undo_redo.cbscript index 33e6561..b2bada3 100644 --- a/Scripts/archived 1.15 scripts/undo_redo.cbscript +++ b/Scripts/archived 1.15 scripts/undo_redo.cbscript @@ -37,7 +37,7 @@ end define @BlockMarker: @Entity[type=area_effect_cloud,tag=BlockMarker] create {Tags:["BlockMarker"], Duration:-1, Age:-0x80000000, WaitTime:-0x80000000} - + function update_marker() if == @s. at @s @@ -51,7 +51,7 @@ define @BlockMarker: @Entity[type=area_effect_cloud,tag=BlockMarker] @UndoStack.undo_to_id = block_id /data modify entity @UndoStack HandItems[0].tag.RedoStack set value [] @s.block_id = block_id - + while @UndoStack.{HandItems[0].tag.UndoStack[10000]} remove @UndoStack.HandItems[0].tag.UndoStack[0] end @@ -63,7 +63,7 @@ define @BlockMarker: @Entity[type=area_effect_cloud,tag=BlockMarker] get_block_id() @s.block_id = block_id end - end + end end end @@ -81,7 +81,7 @@ end reset spawn_block_markers() - + tell @a '{R[\[Undo\]](call undo) [\[Undo 5\]](call undo5) [\[Undo 25\]](call undo25) [\[Undo 100\]](call undo100) [\[Clear Undo History\]](call clear_undo)' tell @a '{G[\[Redo\]](call redo) [\[Redo 5\]](call redo5) [\[Redo 25\]](call redo25) [\[Redo 100\]](call redo100)' end @@ -143,7 +143,7 @@ function execute_undo(count) end @UndoStack.[HandItems[0].tag.RedoStack] += @UndoStack.HandItems[0].tag.UndoStack[-1] remove @UndoStack.HandItems[0].tag.UndoStack[-1] - + update_specific_marker() performed++ end @@ -158,7 +158,7 @@ function execute_undo(count) actionbar @s "{rThere's nothing to undo." end else - + success_tick = undo_redo_tick tell @s '{RUndo/redo only works with a single player online.' end @@ -183,7 +183,7 @@ function execute_redo(count) end @UndoStack.[HandItems[0].tag.UndoStack] += @UndoStack.HandItems[0].tag.RedoStack[-1] remove @UndoStack.HandItems[0].tag.RedoStack[-1] - + update_specific_marker() performed++ end @@ -200,7 +200,7 @@ function execute_redo(count) else tell @s '{RUndo/redo only works with a single player online.' end - + disable_feedback() end @@ -237,7 +237,7 @@ clock main unless @BlockMarker[0] spawn_block_markers() end - + as @Player[limit=1] at @s eyes ^ ^ ^ at ~-$Radius ~-$Radius ~-$Radius = @s. / scale - <$Radius, $Radius, $Radius> = - % $Diameter @@ -252,13 +252,13 @@ clock main end end end - + /scoreboard players enable @s undo /scoreboard players enable @s redo end undo_clock = 2 end - + undo_clock-- else /kill @BlockMarker @@ -273,7 +273,7 @@ function get_block_id() default block_id = $block_id end - end + end end function set_block() diff --git a/Scripts/archived 1.15 scripts/video.cbscript b/Scripts/archived 1.15 scripts/video.cbscript index de3e3d4..a67d1e7 100644 --- a/Scripts/archived 1.15 scripts/video.cbscript +++ b/Scripts/archived 1.15 scripts/video.cbscript @@ -13,17 +13,17 @@ end define @Marker = @Entity[type=area_effect_cloud,name=Marker] create: {"CustomName":"\"Marker\"", Duration:-1,Age:-2147483648,WaitTime:-2147483648} - + function move_to_coordinates() rem = frame y = rem / 128 rem %= 128 - + z = rem - 64 - + y *= 64000 z *= 1000 - + @s.x = -64000 @s.y = y @s.z = z @@ -731,7 +731,7 @@ function setup() tell @s: Running setup. This may take several minutes... /setworldspawn 0 201 0 /tp @s 0 201 3 - + for $cx in: range(-3, 10) for $cz in: range(-10, 10) $xmin: cx*8 @@ -785,7 +785,7 @@ clock recording @s.frame = @player.frame end end - + as @Marker if @s.owner == @player._id @s.age++ end @@ -799,8 +799,8 @@ function ray_trace() unless block ~ ~ ~ none /clone ~ ~ ~ ~ ~ ~ 0 1 0 end - - if block ~ ~ ~ none + + if block ~ ~ ~ none at ^ ^ ^1 ray_trace() end @@ -919,10 +919,10 @@ clock rendering end end end - + /kill @s end - + as create @Marker @s.move_to_coordinates() at @s @@ -930,7 +930,7 @@ clock rendering end /kill @s end - + if @s.frame == @s.end_frame @s.rendering = False tell @s: {GDone rendering! \[[play](/function video:play)\] @@ -952,7 +952,7 @@ clock playing @s.frame_step = 0 @s.frame++ frame = @s.frame - + as create @Marker @s.move_to_coordinates() at @s @@ -960,7 +960,7 @@ clock playing end /kill @s end - + if @s.frame == @s.end_frame @s.playing = False tell @s: {GDone playing! diff --git a/Scripts/archived 1.15 scripts/watermill.cbscript b/Scripts/archived 1.15 scripts/watermill.cbscript index c482534..ffdee9c 100644 --- a/Scripts/archived 1.15 scripts/watermill.cbscript +++ b/Scripts/archived 1.15 scripts/watermill.cbscript @@ -44,7 +44,7 @@ function get_water_level() for $level in $range(8) /execute if block ~ ~ ~ water[level=$level] run scoreboard players set Global level $level end - + return level end @@ -60,9 +60,9 @@ clock main at ^ ^-1 ^1 do forward_level = get_water_level() at ^ ^-1 ^ do here_level = get_water_level() at ^ ^-1 ^-1 do backward_level = get_water_level() - + id = &@s - if forward_level >= 0 and here_level >= 0 and backward_level >= 0 and forward_level > here_level and here_level > backward_level + if forward_level >= 0 and here_level >= 0 and backward_level >= 0 and forward_level > here_level and here_level > backward_level @s.spin_vel += 1000 as @Spoke if @s.mill == id @s.spin_vel += 1000 @@ -71,7 +71,7 @@ clock main end end end - + as @Spoke at @s @s.spin_vel *= 98 @s.spin_vel /= 100 @@ -79,7 +79,7 @@ clock main @s.rot_x %= 360000 @Position. = @s. at @Position - @s.update() + @s.update() end end as @Watermill at @s @@ -122,7 +122,7 @@ clock main as @Player[distance=..8,placed_mill] ry = @s.ry end - + as create @Watermill @s.ry = ry id = &@s @@ -139,20 +139,20 @@ clock main @s.mill = id end end - + /tp @s ~ -200 ~ /kill @s end - + @Player.placed_mill = False - + as @Player[crafted_mill] while @s.crafted_mill mill_eggs = result /clear @s sheep_spawn_egg{mill:1b} normal_eggs = result /clear @s sheep_spawn_egg - + while mill_eggs > 0 /give @s sheep_spawn_egg{mill:1b, EntityTag:{Tags:["SpawnMill"]}, display:{Name:"{\"text\":\"Watermill\"}"}} 1 mill_eggs-- @@ -169,4 +169,4 @@ clock main end end # TODO: Add nbt to sheep_spawn_egg for @Player[crafted_mill] -end \ No newline at end of file +end diff --git a/Scripts/archived 1.15 scripts/wireframe.cbscript b/Scripts/archived 1.15 scripts/wireframe.cbscript index 91dbb67..0cb59b2 100644 --- a/Scripts/archived 1.15 scripts/wireframe.cbscript +++ b/Scripts/archived 1.15 scripts/wireframe.cbscript @@ -44,7 +44,7 @@ define [Line] at <$LineStorage> new_z1: RecordItem.tag.lines[-1].z1 int 1 new_z2: RecordItem.tag.lines[-1].z2 int 1 new_id: RecordItem.tag.lines[-1].id int 1 - + cur_x1: RecordItem.tag.line_iter[-1].x1 int 1 cur_x2: RecordItem.tag.line_iter[-1].x2 int 1 cur_y1: RecordItem.tag.line_iter[-1].y1 int 1 @@ -56,19 +56,19 @@ end define @Line : @Entity[type=area_effect_cloud,tag=Line] create {Tags:["Line"], Duration:-1,Age:-2147483648,WaitTime:-2147483648} - + function get_transformed_pos() = @s. apply_animation() apply_camera_transform() = - + = @s. apply_animation() apply_camera_transform() = end - + function apply_animation() switch Animation case $RandomSpin @@ -79,14 +79,14 @@ define @Line : @Entity[type=area_effect_cloud,tag=Line] end end end - + function random_spin_transform() rotate_around_z_axis(t*2/3) rotate_around_y_axis(t) rotate_around_x_axis(t/2) += end - + function slime_jump_transform() if t < 10 = @@ -102,24 +102,24 @@ define @Line : @Entity[type=area_effect_cloud,tag=Line] t = 0 end end - + function get_perspective_pos() pz1 = z1 + 500 px1 = x1 * 10000 / pz1 py1 = y1 * 10000 / pz1 - + pz2 = z2 + 500 px2 = x2 * 10000 / pz2 py2 = y2 * 10000 / pz2 - + dpx = px2 - px1 dpy = py2 - py1 length = sqrt(dpx^2 + dpy^2) - + unit_x = dpx * 1000 / length unit_y = dpy * 1000 / length end - + function get_angles_and_angle_offsets() as @Position /tp @s ~ ~ ~ @@ -130,7 +130,7 @@ define @Line : @Entity[type=area_effect_cloud,tag=Line] angle = @s.ry pose_angle = 260000 - angle end - + # Get offset from shoulder to tip of arm @s.ry = angle + 100000 = @s. @@ -138,21 +138,21 @@ define @Line : @Entity[type=area_effect_cloud,tag=Line] = @s. - end end - + function render_line() @s.get_transformed_pos() - + if z1 >= 0 and z2 >= 0 @s.get_perspective_pos() if px1 >= -30000 and px1 <= 30000 and px2 >= -30000 and px2 <= 30000 and py1 >= -20000 and py1 <= 20000 and py2 >= -20000 and py2 <= 20000 @s.get_angles_and_angle_offsets() - + segments = length / 1000 id = &@s - + base_x = $BaseX + px1 + 250 + ox base_y = $BaseY + py1 - 1600 + oz - + store_line_properties() else segments = -1 @@ -180,7 +180,7 @@ define @Segment : @Entity[type=armor_stand, tag=Segment] Silent:1b } pose_angle: Pose.RightArm[0] float 1000 - + function hide() unless not @s.was_visibile /replaceitem entity @s weapon.mainhand air @@ -210,7 +210,7 @@ define @Segment : @Entity[type=armor_stand, tag=Segment] function render_segment() get_line_properties() - + if @s.segment <= segments + 2 if @s.segment > 0 and (@s.segment+1) * 1000 - 150 > length # special case for over-extension @@ -218,16 +218,16 @@ define @Segment : @Entity[type=armor_stand, tag=Segment] else seg_off = @s.segment * 1000 + 150 end - + if @s.segment <= segments @s.show() else @s.hide() end - + @s.x = base_x + unit_x * seg_off / 1000 @s.y = base_y + unit_y * seg_off / 1000 - + @s.pose_angle = pose_angle else @s.hide() @@ -241,17 +241,17 @@ function create_die_faces() = <0, 100, 4000> = <0, -100, 4000> create_line() - + #6 material = 6 = <-2000, -2100, -4000> = <-2000, -1900, -4000> create_line() - + = <0, -2100, -4000> = <0, -1900, -4000> create_line() - + = <2000, -2100, -4000> = <2000, -1900, -4000> create_line() @@ -259,53 +259,53 @@ function create_die_faces() = <-2000, 1900, -4000> = <-2000, 2100, -4000> create_line() - + = <0, 1900, -4000> = <0, 2100, -4000> create_line() - + = <2000, 1900, -4000> = <2000, 2100, -4000> create_line() - + #2 material = 2 = <-2000, 4000, -2100> = <-2000, 4000, -1900> create_line() - + = <2000, 4000, 2100> = <2000, 4000, 1900> create_line() - + #5 material = 5 = <-2000, -4000, -2100> = <-2000, -4000, -1900> create_line() - + = <2000, -4000, -2100> = <2000, -4000, -1900> create_line() - + = <2000, -4000, 1900> = <2000, -4000, 2100> create_line() - + = <-2000, -4000, 1900> = <-2000, -4000, 2100> create_line() - + = <0, -4000, -100> = <0, -4000, 100> create_line() - + #3 material = 3 = <4000, 0, -100> = <4000, 0, 100> create_line() - + = <4000, -2000, -2100> = <4000, -2000, -1900> create_line() @@ -313,7 +313,7 @@ function create_die_faces() = <4000, 2000, 1900> = <4000, 2000, 2100> create_line() - + #4 material = 4 = <-4000, -2000, -2100> @@ -323,7 +323,7 @@ function create_die_faces() = <-4000, 2000, 1900> = <-4000, 2000, 2100> create_line() - + = <-4000, 2000, -2100> = <-4000, 2000, -1900> create_line() @@ -335,7 +335,7 @@ end function create_cube(radius) material = -1 - + # Y Axis = <-radius, -radius, -radius> = <-radius, radius, -radius> @@ -352,7 +352,7 @@ function create_cube(radius) = = create_line() - + # X Axis = <-radius, -radius, -radius> = @@ -369,7 +369,7 @@ function create_cube(radius) = <-radius, radius, radius> = create_line() - + # Z Axis = <-radius, -radius, -radius> = <-radius, -radius, radius> @@ -390,64 +390,64 @@ end function create_creeper_face() material = -1 - + # Left Eye = <-3000, 2000, 4000> = <-1000, 2000, 4000> create_line() - + = <-3000, 2000, 4000> = <-3000, 0000, 4000> create_line() - + = <-1000, 2000, 4000> = <-1000, -1000, 4000> create_line() - + # Right Eye = <3000, 2000, 4000> = <1000, 2000, 4000> create_line() - + = <3000, 2000, 4000> = <3000, 0000, 4000> create_line() - + = <1000, 2000, 4000> = <1000, -1000, 4000> create_line() - + # Mouth - + # Top of mouth + bottom of eyes = <-3000, 0000, 4000> = <3000, 0000, 4000> create_line() - + = <-2000, -1000, 4000> = <-1000, -1000, 4000> create_line() - + = <2000, -1000, 4000> = <1000, -1000, 4000> create_line() - + = <-2000, -1000, 4000> = <-2000, -4000, 4000> create_line() - + = <2000, -1000, 4000> = <2000, -4000, 4000> create_line() - + = <-1000, -3000, 4000> = <-1000, -4000, 4000> create_line() - + = <1000, -3000, 4000> = <1000, -4000, 4000> create_line() - + = <-1000, -3000, 4000> = <1000, -3000, 4000> create_line() @@ -470,9 +470,9 @@ macro $create_line($x1, $y1, $z1, $x2, $y2, $z2) end function create_tie_fighter() - + create_cube(1500) - + # Wing arms $create_line(1500, 1500, 1500, 6000, 800, 800) $create_line(1500, -1500, 1500, 6000, -800, 800) @@ -482,7 +482,7 @@ function create_tie_fighter() $create_line(-1500, -1500, 1500, -6000, -800, 800) $create_line(-1500, 1500, -1500, -6000, 800, -800) $create_line(-1500, -1500, -1500, -6000, -800, -800) - + for $m in [-1, 1] $create_line(-6000*$m, -2000, -4000, -6000*$m, 2000, -4000) $create_line(-6000*$m, -2000, 4000, -6000*$m, 2000, 4000) @@ -503,23 +503,23 @@ function delete_object() /setblock $LineStoragePos air /setblock $LineStoragePos jukebox [<$LineStorage>].{RecordItem} = {id:"minecraft:diamond", Count:1, tag:{lines:[]}} - - + + line_id = 0 end reset spawn_cube(4000) #spawn_tie_fighter() - + = <0, 0, -10000> camera_rx = 0 camera_ry = 0 - + as @Player draw_buttons() end - + unless Material >= 0 Material = 0 end @@ -529,10 +529,10 @@ function create_line() as create @Line @s. = @s. = - + = - length = sqrt(*) - + id = &@s @s.line_id = line_id for i = 0 to (length * 2 / 1000) @@ -541,13 +541,13 @@ function create_line() @s.segment = i @s.material = material @s.line_id = line_id - + @s. = <$BaseX, $BaseY, $BaseZ> move @s ~ ~ ~ end end end - + line_id++ end @@ -561,7 +561,7 @@ function new_create_line() [Line].new_x2 = x2 [Line].new_y2 = y2 [Line].new_z2 = z2 - + line_id++ [Line].new_id = line_id end @@ -613,21 +613,21 @@ clock main /gamerule sendCommandFeedback true unless @Position do create @Position - + t += 2 @Line.render_line() @Segment.render_segment() - + if AngleUp then camera_rx -= 2000 if AngleDown then camera_rx += 2000 if AngleLeft then camera_ry -= 2000 if AngleRight then camera_ry += 2000 - + = <0, 500, 0> = = - + if MoveForward then += if MoveBackward then -= if MoveLeft then -= @@ -649,7 +649,7 @@ function draw_buttons() else tell @s "\ {w[\[up\]](call angle_up)" end - + if AngleLeft tell @s "\ {W[\[LEFT\]](call angle_left) {w[\[right\]](call angle_right)" else if AngleRight @@ -657,7 +657,7 @@ function draw_buttons() else tell @s "\ {w[\[left\]](call angle_left) {w[\[right\]](call angle_right)" end - + if AngleDown tell @s "\ {W[\[DOWN\]](call angle_down)" else @@ -665,7 +665,7 @@ function draw_buttons() end tell @s '\ {YMove' - + if MoveForward tell @s "{Y[\[FORWARD\]](call move_forward) {y[\[backward\]](call move_backward)" else if MoveBackward @@ -673,13 +673,13 @@ function draw_buttons() else tell @s "{y[\[forward\]](call move_forward) {y[\[backward\]](call move_backward)" end - + if MoveUp tell @s "\ {Y[\[UP\]](call move_up)" else tell @s "\ {y[\[up\]](call move_up)" end - + if MoveLeft tell @s "\ {Y[\[LEFT\]](call move_left) {y[\[right\]](call move_right)" else if MoveRight @@ -687,7 +687,7 @@ function draw_buttons() else tell @s "\ {y[\[left\]](call move_left) {y[\[right\]](call move_right)" end - + if MoveDown tell @s "\ {Y[\[DOWN\]](call move_down)" else @@ -776,4 +776,4 @@ end function destroy() /kill @Line /kill @Segment -end \ No newline at end of file +end diff --git a/Scripts/archived 1.15 scripts/wireframe4d.cbscript b/Scripts/archived 1.15 scripts/wireframe4d.cbscript index 5c82ef1..0c56195 100644 --- a/Scripts/archived 1.15 scripts/wireframe4d.cbscript +++ b/Scripts/archived 1.15 scripts/wireframe4d.cbscript @@ -35,19 +35,19 @@ array pose_angle[$NumLines] define @Line : @Entity[type=area_effect_cloud,tag=Line] create {Tags:["Line"], Duration:-1,Age:-2147483648,WaitTime:-2147483648} - + function get_transformed_pos() = @s. apply_animation() apply_camera_transform() = - + = @s. apply_animation() apply_camera_transform() = end - + function apply_animation() switch Animation case $RandomSpin @@ -58,14 +58,14 @@ define @Line : @Entity[type=area_effect_cloud,tag=Line] end end end - + function random_spin_transform() rotate_around_z_axis(t*2/3) rotate_around_y_axis(t) rotate_around_x_axis(t/2) += end - + function slime_jump_transform() if t < 10 = @@ -81,24 +81,24 @@ define @Line : @Entity[type=area_effect_cloud,tag=Line] t = 0 end end - + function get_perspective_pos() pz1 = z1 + 500 px1 = x1 * 10000 / pz1 py1 = y1 * 10000 / pz1 - + pz2 = z2 + 500 px2 = x2 * 10000 / pz2 py2 = y2 * 10000 / pz2 - + dpx = px2 - px1 dpy = py2 - py1 length = sqrt(dpx^2 + dpy^2) - + unit_x = dpx * 1000 / length unit_y = dpy * 1000 / length end - + function get_angles_and_angle_offsets() as @Position /tp @s ~ ~ ~ @@ -109,7 +109,7 @@ define @Line : @Entity[type=area_effect_cloud,tag=Line] angle = @s.ry pose_angle = 260000 - angle end - + # Get offset from shoulder to tip of arm @s.ry = angle + 100000 = @s. @@ -117,21 +117,21 @@ define @Line : @Entity[type=area_effect_cloud,tag=Line] = @s. - end end - + function render_line() @s.get_transformed_pos() - + if z1 >= 0 and z2 >= 0 @s.get_perspective_pos() if px1 >= -30000 and px1 <= 30000 and px2 >= -30000 and px2 <= 30000 and py1 >= -20000 and py1 <= 20000 and py2 >= -20000 and py2 <= 20000 @s.get_angles_and_angle_offsets() - + segments = length / 1000 id = &@s - + base_x = $BaseX + px1 + 250 + ox base_y = $BaseY + py1 - 1600 + oz - + store_line_properties() else segments = -1 @@ -159,7 +159,7 @@ define @Segment : @Entity[type=armor_stand, tag=Segment] Silent:1b } pose_angle: Pose.RightArm[0] float 1000 - + function hide() unless not @s.was_visibile /replaceitem entity @s weapon.mainhand air @@ -189,7 +189,7 @@ define @Segment : @Entity[type=armor_stand, tag=Segment] function render_segment() get_line_properties() - + if @s.segment <= segments + 2 if @s.segment > 0 and (@s.segment+1) * 1000 - 150 > length # special case for over-extension @@ -197,16 +197,16 @@ define @Segment : @Entity[type=armor_stand, tag=Segment] else seg_off = @s.segment * 1000 + 150 end - + if @s.segment <= segments @s.show() else @s.hide() end - + @s.x = base_x + unit_x * seg_off / 1000 @s.y = base_y + unit_y * seg_off / 1000 - + @s.pose_angle = pose_angle else @s.hide() @@ -220,17 +220,17 @@ function create_die_faces() = <0, 100, 4000> = <0, -100, 4000> create_line() - + #6 material = 6 = <-2000, -2100, -4000> = <-2000, -1900, -4000> create_line() - + = <0, -2100, -4000> = <0, -1900, -4000> create_line() - + = <2000, -2100, -4000> = <2000, -1900, -4000> create_line() @@ -238,53 +238,53 @@ function create_die_faces() = <-2000, 1900, -4000> = <-2000, 2100, -4000> create_line() - + = <0, 1900, -4000> = <0, 2100, -4000> create_line() - + = <2000, 1900, -4000> = <2000, 2100, -4000> create_line() - + #2 material = 2 = <-2000, 4000, -2100> = <-2000, 4000, -1900> create_line() - + = <2000, 4000, 2100> = <2000, 4000, 1900> create_line() - + #5 material = 5 = <-2000, -4000, -2100> = <-2000, -4000, -1900> create_line() - + = <2000, -4000, -2100> = <2000, -4000, -1900> create_line() - + = <2000, -4000, 1900> = <2000, -4000, 2100> create_line() - + = <-2000, -4000, 1900> = <-2000, -4000, 2100> create_line() - + = <0, -4000, -100> = <0, -4000, 100> create_line() - + #3 material = 3 = <4000, 0, -100> = <4000, 0, 100> create_line() - + = <4000, -2000, -2100> = <4000, -2000, -1900> create_line() @@ -292,7 +292,7 @@ function create_die_faces() = <4000, 2000, 1900> = <4000, 2000, 2100> create_line() - + #4 material = 4 = <-4000, -2000, -2100> @@ -302,7 +302,7 @@ function create_die_faces() = <-4000, 2000, 1900> = <-4000, 2000, 2100> create_line() - + = <-4000, 2000, -2100> = <-4000, 2000, -1900> create_line() @@ -314,7 +314,7 @@ end function create_cube(radius) material = -1 - + # Y Axis = <-radius, -radius, -radius> = <-radius, radius, -radius> @@ -331,7 +331,7 @@ function create_cube(radius) = = create_line() - + # X Axis = <-radius, -radius, -radius> = @@ -348,7 +348,7 @@ function create_cube(radius) = <-radius, radius, radius> = create_line() - + # Z Axis = <-radius, -radius, -radius> = <-radius, -radius, radius> @@ -369,64 +369,64 @@ end function create_creeper_face() material = -1 - + # Left Eye = <-3000, 2000, 4000> = <-1000, 2000, 4000> create_line() - + = <-3000, 2000, 4000> = <-3000, 0000, 4000> create_line() - + = <-1000, 2000, 4000> = <-1000, -1000, 4000> create_line() - + # Right Eye = <3000, 2000, 4000> = <1000, 2000, 4000> create_line() - + = <3000, 2000, 4000> = <3000, 0000, 4000> create_line() - + = <1000, 2000, 4000> = <1000, -1000, 4000> create_line() - + # Mouth - + # Top of mouth + bottom of eyes = <-3000, 0000, 4000> = <3000, 0000, 4000> create_line() - + = <-2000, -1000, 4000> = <-1000, -1000, 4000> create_line() - + = <2000, -1000, 4000> = <1000, -1000, 4000> create_line() - + = <-2000, -1000, 4000> = <-2000, -4000, 4000> create_line() - + = <2000, -1000, 4000> = <2000, -4000, 4000> create_line() - + = <-1000, -3000, 4000> = <-1000, -4000, 4000> create_line() - + = <1000, -3000, 4000> = <1000, -4000, 4000> create_line() - + = <-1000, -3000, 4000> = <1000, -3000, 4000> create_line() @@ -449,9 +449,9 @@ macro $create_line($x1, $y1, $z1, $x2, $y2, $z2) end function create_tie_fighter() - + create_cube(1500) - + # Wing arms $create_line(1500, 1500, 1500, 6000, 800, 800) $create_line(1500, -1500, 1500, 6000, -800, 800) @@ -461,7 +461,7 @@ function create_tie_fighter() $create_line(-1500, -1500, 1500, -6000, -800, 800) $create_line(-1500, 1500, -1500, -6000, 800, -800) $create_line(-1500, -1500, -1500, -6000, -800, -800) - + for $m in [-1, 1] $create_line(-6000*$m, -2000, -4000, -6000*$m, 2000, -4000) $create_line(-6000*$m, -2000, 4000, -6000*$m, 2000, 4000) @@ -479,22 +479,22 @@ end function delete_object() /kill @Line /kill @Segment - + line_id = 0 end reset spawn_cube(4000) #spawn_tie_fighter() - + = <0, 0, -10000> camera_rx = 0 camera_ry = 0 - + as @Player draw_buttons() end - + unless Material >= 0 Material = 0 end @@ -504,10 +504,10 @@ function create_line() as create @Line @s. = @s. = - + = - length = sqrt(*) - + id = &@s @s.line_id = line_id for i = 0 to (length * 2 / 1000) @@ -516,13 +516,13 @@ function create_line() @s.segment = i @s.material = material @s.line_id = line_id - + @s. = <$BaseX, $BaseY, $BaseZ> move @s ~ ~ ~ end end end - + line_id++ end @@ -574,21 +574,21 @@ clock main unless @Position do create @Position unless @Position2 do create @Position2 - + t += 2 @Line.render_line() @Segment.render_segment() - + if AngleUp then camera_rx -= 2000 if AngleDown then camera_rx += 2000 if AngleLeft then camera_ry -= 2000 if AngleRight then camera_ry += 2000 - + = <0, 500, 0> = = - + if MoveForward then += if MoveBackward then -= if MoveLeft then -= @@ -610,7 +610,7 @@ function draw_buttons() else tell @s "\ {w[\[up\]](call angle_up)" end - + if AngleLeft tell @s "\ {W[\[LEFT\]](call angle_left) {w[\[right\]](call angle_right)" else if AngleRight @@ -618,7 +618,7 @@ function draw_buttons() else tell @s "\ {w[\[left\]](call angle_left) {w[\[right\]](call angle_right)" end - + if AngleDown tell @s "\ {W[\[DOWN\]](call angle_down)" else @@ -626,7 +626,7 @@ function draw_buttons() end tell @s '\ {YMove' - + if MoveForward tell @s "{Y[\[FORWARD\]](call move_forward) {y[\[backward\]](call move_backward)" else if MoveBackward @@ -634,13 +634,13 @@ function draw_buttons() else tell @s "{y[\[forward\]](call move_forward) {y[\[backward\]](call move_backward)" end - + if MoveUp tell @s "\ {Y[\[UP\]](call move_up)" else tell @s "\ {y[\[up\]](call move_up)" end - + if MoveLeft tell @s "\ {Y[\[LEFT\]](call move_left) {y[\[right\]](call move_right)" else if MoveRight @@ -648,7 +648,7 @@ function draw_buttons() else tell @s "\ {y[\[left\]](call move_left) {y[\[right\]](call move_right)" end - + if MoveDown tell @s "\ {Y[\[DOWN\]](call move_down)" else @@ -737,4 +737,4 @@ end function destroy() /kill @Line /kill @Segment -end \ No newline at end of file +end diff --git a/Scripts/archived 1.15 scripts/yoshi.cbscript b/Scripts/archived 1.15 scripts/yoshi.cbscript index 4fcce6d..a25c1e9 100644 --- a/Scripts/archived 1.15 scripts/yoshi.cbscript +++ b/Scripts/archived 1.15 scripts/yoshi.cbscript @@ -47,7 +47,7 @@ define @Yoshi = @Entity[type=horse,name=Yoshi] @s.no_gravity = 1 @s.vy = 100 unless fly_snd_cooldown > 0 at @s - /playsound minecraft:entity.bat.ambient neutral @a ~ ~ ~ 1 0 0 + /playsound minecraft:entity.bat.ambient neutral @a ~ ~ ~ 1 0 0 fly_snd_cooldown = 4 end fly_snd_cooldown-- @@ -85,11 +85,11 @@ reset /kill @Yoshi /tp @ClickDetector ~ -200 ~ /kill @ClickDetector - + /team add nopush /team modify nopush collisionRule never - + at @p for $i in: range(len(blocks)) $block_id: blocks[i][3] @@ -99,7 +99,7 @@ reset @s.nonstick = True end end - + for $i in: range(len(tiny_blocks)) $block_id: tiny_blocks[i][3] as create @TinyBlock @@ -108,7 +108,7 @@ reset @s.nonstick = True end end - + as create @Yoshi /effect give @s minecraft:invisibility 1000000 0 true @s.animation = 0 @@ -117,7 +117,7 @@ reset prevy = @s.y prevz = @s.z end - + as create @ClickDetector @s.hp = 100 /effect give @s minecraft:invisibility 1000000 0 true @@ -152,7 +152,7 @@ clock main dy = -2000 while dy < 1000 dy += 1000 - + as create @Marker /tp @s @ClickDetector[limit=1] x1 = @s.x @@ -167,7 +167,7 @@ clock main @s.diry = dy/20 @s.dirz = dz/20 @s.y += dy*2 - end + end end /playsound minecraft:entity.blaze.shoot neutral @a ~ ~ ~ 1 1 0 end @@ -194,13 +194,13 @@ clock main end end end - + shell = False end end @s.hp = 100 end - + as @Sheep[shell] if @s.vx == 0 @s.dx = -@s.dx @@ -241,7 +241,7 @@ clock main is_shell = True color = @Sheep[stuck,limit=1].color end - + if is_shell then shell = True if not is_shell then shell = False @@ -249,11 +249,11 @@ clock main /playsound minecraft:entity.witch.drink neutral @a ~ ~ ~ 1 1 1 end - /tp @e[stuck] ~ -200 ~ + /tp @e[stuck] ~ -200 ~ /kill @e[stuck] end end - + as @Yoshi at @s rotated @s anim_frame = (@Yoshi.animation / 3) % 4 curx = @s.x @@ -270,13 +270,13 @@ clock main end @s.y += dy @s.z += (curz - prevz) * 3 - + @Yoshi.animation += 2 - + if curx == prevx and curz == prevz @Yoshi.animation = 0 end - + at @s rotated @s for $i in: range(len(blocks)) $x: blocks[i][0] * 0.6 @@ -296,7 +296,7 @@ clock main end end end - + for $i in: range(len(tiny_blocks)) $x: tiny_blocks[i][0] * 0.6 + 0.0625 $y: tiny_blocks[i][1] * 0.6 - 0.5 @@ -307,21 +307,21 @@ clock main end end end - + move @s ^ ^0.65 ^1 - + x1 = @s.x y1 = @s.y z1 = @s.z - + move @s ^ ^ ^1 - + dx = @s.x - x1 dz = @s.z - z1 - + move @s ^ ^ ^-1 move @s ^ ^-0.65 ^-1 - + part = 0 while part < 15 part++ @@ -350,23 +350,23 @@ clock main end end end - + at ^ ^1.2 ^1.15 /tp @ClickDetector ~ ~ ~ ~ ~ end end /kill @s end - + @s.no_gravity = 0 if shell and color == $Blue and @s.rx < 0 and not @s.on_ground @s.fly() end - + prevx = @s.x prevy = @s.y prevz = @s.z - + if shell and color == $Yellow and @s.on_ground and air_time >= 10 at @s as create @GroundPound @@ -375,7 +375,7 @@ clock main /playsound minecraft:entity.zombie.infect neutral @a ~ ~ ~ 1 1 0 end end - + if @s.on_ground air_time = 0 end @@ -383,7 +383,7 @@ clock main air_time++ end end - + as @GroundPound @s.radius++ angle = 0 @@ -406,26 +406,26 @@ clock main move @s ^ ^ ^-1 end end - + if @s.radius >= 8 /kill @s end end - + as @MiniBlock - /data merge entity @s {Fire:32767s} + /data merge entity @s {Fire:32767s} end as @TinyBlock - /data merge entity @s {Fire:32767s} + /data merge entity @s {Fire:32767s} end - + as @Fireball @s.age++ /kill @s[age >= 100] end - + moving = False unless @Yoshi[limit=1].vx == 0 do moving = True unless @Yoshi[limit=1].vz == 0 do moving = True if moving then @Yoshi.animation-- -end \ No newline at end of file +end diff --git a/Scripts/archived 1.15 scripts/zerog.cbscript b/Scripts/archived 1.15 scripts/zerog.cbscript index 1939465..7e25357 100644 --- a/Scripts/archived 1.15 scripts/zerog.cbscript +++ b/Scripts/archived 1.15 scripts/zerog.cbscript @@ -35,7 +35,7 @@ clock main unless @s.player > 0 at @s @s.player = @Player[distance=..3,limit=1] end - + as @s.player(@Player) @s. = @bobber. @s.bobber = @bobber @@ -45,13 +45,13 @@ clock main if @s.bobber bobber_exists = False as @s.bobber - bobber_exists = True + bobber_exists = True end - + if not bobber_exists @FlyingMachine[distance=..2,limit=1]. += (@s. - @s.) / 40 @s.bobber = None end end end -end \ No newline at end of file +end diff --git a/Scripts/archived 1.16 scripts/cbscript116test.cbscript b/Scripts/archived 1.16 scripts/cbscript116test.cbscript index 27664f4..f032e5b 100644 --- a/Scripts/archived 1.16 scripts/cbscript116test.cbscript +++ b/Scripts/archived 1.16 scripts/cbscript116test.cbscript @@ -12,8 +12,7 @@ clock main if @s.y > @s.prev_y tell @s "Going up!" end - + @s.prev_y = @s.y end end - diff --git a/Scripts/archived 1.16 scripts/speedrun_practice.cbscript b/Scripts/archived 1.16 scripts/speedrun_practice.cbscript index d050d39..dde9b5b 100644 --- a/Scripts/archived 1.16 scripts/speedrun_practice.cbscript +++ b/Scripts/archived 1.16 scripts/speedrun_practice.cbscript @@ -295,7 +295,7 @@ define @Player = @Player end tell @s '{c[\[Restore from Death\]](/trigger Practice set $RestoreDeath){-' end - + function perform_practice() switch @s.Practice case $DisplayOptions @@ -419,7 +419,7 @@ define @Player = @Player @s.strong_entrance = 2 /effect give @s resistance 5 4 true end - end + end case $ResetEnd reset_the_end(0) end @@ -503,15 +503,15 @@ define @Player = @Player end end end - + if @s.Practice > 0 @s.display_options() end - + @s.Practice = 0 /scoreboard players enable @s Practice end - + function random_spot() height = randint(2, 6) switch height @@ -521,7 +521,7 @@ define @Player = @Player end end end - + function post_village_hotbar() /clear /replaceitem entity @s hotbar.0 stone_axe @@ -539,11 +539,11 @@ define @Player = @Player for $slot in $range(9, 18) /replaceitem entity @s inventory.$slot white_bed end - + /effect give @s minecraft:instant_health 1 10 /effect give @s minecraft:saturation 1 5 end - + function post_nether_hotbar() /clear /replaceitem entity @s hotbar.0 stone_axe @@ -556,7 +556,7 @@ define @Player = @Player /replaceitem entity @s hotbar.7 netherrack 64 /replaceitem entity @s hotbar.8 bread 64 /replaceitem entity @s weapon.offhand shield - + /replaceitem entity @s inventory.0 cobblestone 16 /replaceitem entity @s inventory.1 oak_planks 16 /replaceitem entity @s inventory.2 stone_hoe @@ -564,11 +564,11 @@ define @Player = @Player /replaceitem entity @s inventory.4 flint_and_steel /replaceitem entity @s inventory.5 obsidian 5 /replaceitem entity @s inventory.6 respawn_anchor 2 - + for $slot in $range(9, 23) /replaceitem entity @s inventory.$slot white_bed end - + /effect give @s minecraft:instant_health 1 10 /effect give @s minecraft:saturation 1 5 end @@ -578,34 +578,34 @@ clock main as @Player unless @s.logged_in == 1 @s.display_options() end - + /scoreboard players reset * logged_in @Player.logged_in = 1 @Player.perform_practice() - + as @Player[find_village] at @s find_village() end - + as @Player[strong_entrance] at @s go_to_stronghold_entrance() end - + mark_end_crystals() - + track_crystal_shots() - + track_dragon_damage() - + track_death() - + as @Player @s. = @s. @s.prev_rx = @s.rx @s.prev_ry = @s.ry end - + in overworld /kill @Position /kill @Position2 @@ -621,7 +621,7 @@ clock main /kill @Position2 /kill @Position3 end - + if @Player[no_enders,limit=1] as @e[type=enderman] move @s ~ ~-500 ~ @@ -654,7 +654,7 @@ end function ground_at_cursor{$distance}() unless @Position do create @Position - + as @Position at ~ ~1.6 ~ at ^ ^ ^$distance /tp @s ~ ~ ~ while True at @s if block ground @@ -680,14 +680,14 @@ end function create_lava_pool() ground_at_cursor{15}() - + dx = 0 dz = 0 for i = 1 to 100 mv = randint(0, 4) r = randint(0, 7) nr = randint(-6, 1) - + switch mv case 0 if dx < r @@ -725,7 +725,7 @@ function create_lava_column() /setblock ~ ~ ~ lava /setblock ~ ~-1 ~ stone surround_with_stone() - + if depth == 2 /setblock ~ ~-1 ~ lava /setblock ~ ~-2 ~ stone @@ -779,28 +779,28 @@ function locate_nether_structure{$structure}() else $locate_nether_step(-1, 0) end - + at @Position2 do dist = result /locate $structure - + if xdist < dist xdir *= -1 end - + zdist = dist if zdir > 0 $locate_nether_step(0, 1) else $locate_nether_step(0, 1) end - + at @Position2 do dist = result /locate $structure - + if zdist < dist zdir *= -1 end - + steps++ end end @@ -836,28 +836,28 @@ function locate_overworld{$command}() else $locate_overworld_step(-1, 0) end - + at @Position do dist = result /$command - + if xdist < dist xdir *= -1 end - + zdist = dist if zdir > 0 $locate_overworld_step(0, 1) else $locate_overworld_step(0, -1) end - + at @Position do dist = result /$command - + if zdist < dist zdir *= -1 end - + steps++ end end @@ -878,11 +878,11 @@ end function go_to_stronghold_entrance() @s.strong_entrance-- - + if @s.strong_entrance == 0 in_stairs = False /tp @s ~ 64 ~ - for y = 64 to 0 by -1 + for y = 64 to 0 by -1 move @s ~ ~-1 ~ at @s for $dx,$dz in [[1,1],[-1,1],[1,-1],[-1,-1]] @@ -893,7 +893,7 @@ function go_to_stronghold_entrance() if in_stairs and block ~ ~ ~ passthrough unless block ~ ~-1 ~ passthrough y = 0 end - end + end end end end @@ -915,11 +915,11 @@ function find_village() at @s /spreadplayers ~ ~ 0 100 true @s end - + @s.find_village = False tell @s 'Found village!' end - + if @s.find_village go_to_random_village() end @@ -928,7 +928,7 @@ end function go_to_random_village() randomize_overworld_position() - at @Position do locate_overworld{'locate village'}() + at @Position do locate_overworld{'locate village'}() /tp @s @Position /effect give @s resistance 5 4 true end @@ -936,7 +936,7 @@ end function randomize_overworld_position() randx = randint(-1000000, 1000000) randz = randint(-1000000, 1000000) - + in overworld unless @Position do create @Position @Position. = * scale end @@ -945,9 +945,9 @@ function mark_end_crystals() as @Crystal at @s unless @CrystalMarker[distance=..0.25] in the_end unless @Position3 do create @Position3 create @CrystalMarker - + = @s. - + for dx = -2 to 2 for dy = -2 to 2 for dz = -2 to 2 @@ -959,7 +959,7 @@ function mark_end_crystals() end end end - + at @EnderDragon[limit=1] /bossbar set dragon players @Player[distance=..256] /execute store result bossbar dragon value run data get entity @EnderDragon[limit=1] Health 1 @@ -982,7 +982,7 @@ function reset_the_end(perch) east = randint(0, 2) ry = 100 * scale + randint(-4000, 4000) offset = randint(-2000, 2000) - + if east @Position3. = <15000, ry, offset> at @Position3 @@ -997,7 +997,7 @@ function reset_the_end(perch) else if perch == $NSPerch north = randint(0, 2) ry = 100 * scale + randint(-4000, 4000) - + if north @Position3. = <0, ry, 15000> at @Position3 @@ -1012,7 +1012,7 @@ function reset_the_end(perch) else create @EnderDragon 0 100 0 end - + # = #as @EnderDragon # @s. += @@ -1024,16 +1024,16 @@ function reset_the_end(perch) at @BarsMarker /setblock ~ ~ ~ iron_bars end - + /fill -2 40 -2 2 70 2 air replace end_portal /fill 0 40 0 0 75 0 air replace dragon_egg /fill -10 40 -10 10 75 10 air replace fire - + /bossbar add dragon "Ender Dragon" /bossbar set dragon max 200 /bossbar set dragon color pink end - + @Player.beds_clicked = 0 end @@ -1041,11 +1041,11 @@ function display_dimension() if predicate in_overworld tell @a 'overworld' end - + if predicate in_the_nether tell @a 'the_nether' end - + if predicate in_the_end tell @a 'the_end' end @@ -1067,18 +1067,18 @@ function track_crystal_shots() @s.old_gamemode = 0 end /gamemode spectator @s - + @s.tracking_shot = True end end end - + as @Player[tracking_shot] at @s if @Arrow[distance=..30,nbt={inGround:0b}] @s.not_tracking = 0 else @s.not_tracking++ - + if @s.not_tracking < 10 and @s.prev_rx == @s.rx and @s.prev_ry == @s.ry else in the_end unless @Position3 do create @Position3 @@ -1101,12 +1101,12 @@ end function track_dragon_damage() hp = @EnderDragon[limit=1].hp - + if hp < old_hp damage = old_hp - hp tell @Player '(damage) damage to dragon' end - + if hp <= 0 and old_hp > 0 as @Player tell @s "{wUsed {C(@s.beds_clicked) {wBeds" @@ -1117,7 +1117,7 @@ function track_dragon_damage() @Player.display_options() /fill -10 40 -10 10 75 10 air replace fire end - + old_hp = hp end @@ -1142,7 +1142,7 @@ function track_death() @s.last_dim = $End end end - + @s.prev_deaths = @s.deaths end -end \ No newline at end of file +end diff --git a/Scripts/archived 1.18 scripts/atari.cbscript b/Scripts/archived 1.18 scripts/atari.cbscript index 6b2055d..4770b0b 100644 --- a/Scripts/archived 1.18 scripts/atari.cbscript +++ b/Scripts/archived 1.18 scripts/atari.cbscript @@ -383,12 +383,12 @@ $BaseCycles = { 0xD8: 2, 0xB8: 2, 0x38: 2, - 0x78: 2, - 0xF8: 2, - 0xEA: 2, - 0xCA: 2, - 0x88: 2, - 0xE8: 2, + 0x78: 2, + 0xF8: 2, + 0xEA: 2, + 0xCA: 2, + 0x88: 2, + 0xE8: 2, 0xC8: 2 } @@ -517,10 +517,10 @@ function global_reset() /kill @Beam /kill @Buffer - + create @Beam 0 0 0 create @Buffer 0 0 0 - + for $addr in $MemoryAddresses /scoreboard objectives add Memory$addr dummy /scoreboard players set Global Memory$addr 0 @@ -530,20 +530,20 @@ function global_reset() /scoreboard objectives add GRP$playerBit$bit dummy end end - + # Fill in the pallete from 0, 0, -8 to 3, 15, -1 for $color_data in $atari_colors $color = $color_data[0] $minlum = $color_data[1] $maxlum = $color_data[2] $material = $color_data[3] - + $y = $color $zmin = $minlum - 8 $zmax = $maxlum - 8 /fill 0 $y $zmin 3 $y $zmax $material end - + # Clear the existing screen /fill 0 0 0 159 100 0 air /fill 0 101 0 159 200 0 air @@ -553,7 +553,7 @@ function global_reset() # Color mode, reset and select buttons released # SWCHB Memory642 = 0b00001011 - + Addr = 0 PC = 0 A = 0 @@ -566,12 +566,12 @@ function global_reset() Negative = False Interrupt = False Decimal = False - + HMOVE = False HMCLR = False RESP0 = False RESP1 = False - + for $player in $range(2) NUSIZ[$player] = 0 GRP[$player] = 0 @@ -579,11 +579,11 @@ function global_reset() PV[$player] = 0 ReflectP[$player] = False end - + VBLANK = True INPT45Control = False Scan = -68 - + # Initialize Palettes from Color 0 Lum 0 COLUPF = 0 /clone 0 0 -8 3 0 -8 0 254 -2 @@ -593,7 +593,7 @@ function global_reset() /clone 0 0 -8 3 0 -8 0 252 -1 COLUP1 = 0 /clone 0 0 -8 3 0 -8 0 253 -1 - + ReflectPF = 0 Clock = 0 ClockRate = 3 @@ -601,36 +601,36 @@ function global_reset() RunProcessor = True GameTicks = 0 Delay = 0 - + Halt = False Step = 0 Frame = 0 FrameSkip = 1 Skipped = 0 MCTick = 0 - + Up = False Down = False Left = False Right = False Button = False LatchedButton = False - + Difficulty0 = 0 Difficulty1 = 0 ColorMode = True SelectSwitch = True ResetSwitch = True - + /tp @Beam 10 250 0 - + StepsPerTick = 500 - + read_whole_rom() get_vectors() PC = Reset # Atari - + as @a draw_controller() end @@ -688,14 +688,14 @@ function check_right_click() @s.right_click = False as create @Marker /tp @s ~ ~ ~ ~ ~ - + # Raycast to find the block on the crosshair for i = 1 to 200 move @s ^ ^ ^2 at @s /particle minecraft:campfire_cosy_smoke ~ ~ ~ end - + # Find the lowest x,y,z coordinate in the block at @s unless block ~ ~ ~ air for j = 1 to 256 @@ -717,7 +717,7 @@ function check_right_click() tell @a "Loading ROM at (ROMX), (ROMY), (ROMZ)..." global_reset() end - + /kill @s end end @@ -768,7 +768,7 @@ end function button() WasPressed = Button if WasPressed then Button = False - unless WasPressed + unless WasPressed Button = True LatchedButton = True end @@ -809,15 +809,15 @@ function read_whole_rom() for z = 0 to 0x0F @s.z = ROMZ + z - at @s + at @s # Read Byte val = 0 for $bit in $range(8) $exp = 2 ** $bit if block ~ ~$bit ~ stone do val += $exp - end + end end - + ROM[(z+0xF0)*0x100 + x] = val end end @@ -837,7 +837,7 @@ function read_3bytes_rom(addr) # 6507 only has 13 address pins addr %= 0x2000 addr += 0xE000 - + switch addr case $addr in $range(0xF000, 0xFFFD) $addr2 = $addr+1 @@ -860,7 +860,7 @@ function read_addr(addr) raw_addr = addr # 6507 only has 13 address pins addr %= 0x2000 - + # Atari Stack Mirroring if addr >= 0x100 and addr < 0x200 addr -= 0x100 @@ -868,9 +868,9 @@ function read_addr(addr) if addr == $INSTAT update_clock() end - + $read_mirrors = $"lambda a: [a % 0x10 + i for i in range(0x00, 0x80, 0x10)]" - + switch addr case $addr in $MemoryAddresses /scoreboard players operation Global ReturnValue = Global Memory$addr @@ -916,7 +916,7 @@ function read_addr(addr) unless Down do val += 0x20 unless Left do val += 0x40 unless Right do val += 0x80 - + return val end case $SWCHB @@ -947,7 +947,7 @@ function read_addr(addr) return CXP0P1 * 0x80 + CXM0M1 * 0x40 end end - + if addr == $INTIM update_clock() return Ticks @@ -961,7 +961,7 @@ end clock main /gamerule sendCommandFeedback true /effect give @a night_vision 1000000 0 true - + check_right_click() if GRStep @@ -973,7 +973,7 @@ clock main MCTick++ for step = 0 to StepsPerTick skip = Frame % FrameSkip - + if RunProcessor > 0 read_instruction() get_base_cycles() @@ -1001,7 +1001,7 @@ function read_instruction() Addr = PC read_3bytes_rom(Addr) Instruction = rom1 - + # Get the opcode's function AddrMode = Instruction % 0x20 OpFamily = Instruction / 0x20 @@ -1016,14 +1016,14 @@ function read_instruction() Function = $func end end - + switch Instruction case $op in $OpCodes $func = $OpCodes[$op] Function = $func end end - + switch Function case $LENGTH1LOW to $LENGTH1HIGH OpLength = 1 @@ -1035,7 +1035,7 @@ function read_instruction() OpLength = 3 end end - + Push = 0 Pull = 0 Write = False # Write Byte to instructed memory address @@ -1067,7 +1067,7 @@ function get_addressing_mode() YIndexPost = False Constant = False Accumulator = False - + # Get Non-Standard Addressing Modes switch Instruction case $op in $AddrModes @@ -1086,10 +1086,10 @@ function get_addressing_mode() MemoryOp = False if Function >= $LENGTHVARLOW and Function <= $LENGTHVARHIGH then MemoryOp = True - + # JMP (addr) if Instruction == 0x6C then AddrAbs = True - + if MemoryOp switch AddrMode case 0x01 @@ -1125,7 +1125,7 @@ function get_addressing_mode() AddrZP = True XIndexPre = True Cycles = 4 - + if Instruction == 0x96 XIndexPre = False YIndexPre = True @@ -1146,7 +1146,7 @@ function get_addressing_mode() XIndexPre = True Cycles = 4 if Write then Cycles++ - + if Instruction == 0xBE XIndexPre = False YIndexPre = True @@ -1159,7 +1159,7 @@ function get_addressing_mode() if AddrZP then OpLength = 2 if AddrAbs then OpLength = 3 end - + # Read+write functions take an extra 2 cycles switch Function case $readwrite in [$ASL, $LSR, $ROL, $ROR, $INC, $DEC] @@ -1175,26 +1175,26 @@ function get_pc_data() # Read Operand 1 Addr++ Op1 = rom2 - + if OpLength >= 3 # Read Operand 2 Addr++ Op2 = rom3 - + Op12 = Op2 * 0x100 + Op1 end end - + if Debug display_instruction() end - + if PC == BreakOnExecute tell @a "Executed break point at (Addr). {G[\[Continue\]](/scoreboard players set Global Halt 0) {R[\[Remove Breakpoint\]](/scoreboard players set Global BreakOnExecute -1)" display_instruction() Halt = True end - + PC += OpLength if PC >= 0x10000 then PC -= 0x10000 end @@ -1207,10 +1207,10 @@ function display_instruction() hex_number(X, 12, 2) hex_number(Y, 14, 2) hex_number(Stack, 16, 2) - + # Get the mnemonic for the current instruction mnemonic() - + switch OpLength case 1 tell @a "$(@digit0)(@digit1)(@digit2)(@digit3): (@mnemonic)" @@ -1245,7 +1245,7 @@ function display_instruction() case 3 hex_number(Op1, 4, 2) hex_number(Op2, 6, 2) - + Handled = False if XIndexPre tell @a "$(@digit0)(@digit1)(@digit2)(@digit3): (@mnemonic) $(@digit6)(@digit7)(@digit4)(@digit5),X" @@ -1254,7 +1254,7 @@ function display_instruction() if YIndexPre tell @a "$(@digit0)(@digit1)(@digit2)(@digit3): (@mnemonic) $(@digit6)(@digit7)(@digit4)(@digit5),Y" Handled = True - end + end if not Handled tell @a "$(@digit0)(@digit1)(@digit2)(@digit3): (@mnemonic) $(@digit6)(@digit7)(@digit4)(@digit5)" end @@ -1273,47 +1273,47 @@ function run_branch_instruction() switch Function case $BCC get_pc_data() - + if not Carry then branch() end case $BCS get_pc_data() - + if Carry then branch() end case $BEQ get_pc_data() - + if Zero then branch() end case $BNE get_pc_data() - + if not Zero then branch() end case $BMI get_pc_data() - + if Negative then branch() end case $BPL get_pc_data() - + if not Negative then branch() end case $BVS get_pc_data() - + if Overflow then branch() end case $BVC get_pc_data() - + if not Overflow then branch() end end end - + if Debug and DisplayCycles tell @a "\ (Cycles) cycles" end @@ -1322,19 +1322,19 @@ end function branch() # 1 cycle penalty for branching Cycles++ - + BranchAmount = Op1 if BranchAmount >= 0x80 then BranchAmount -= 0x100 - + OldPage = PC / 0x100 - + PC += BranchAmount - + NewPage = PC / 0x100 - + # Additional 1 cycle penalty for crossing a page boundary unless OldPage == NewPage do Cycles++ - + if PC >= 0x10000 then PC -= 0x10000 if PC < 0 then PC += 0x10000 end @@ -1350,8 +1350,8 @@ function operate_memory_bus() end if Accumulator then Byte = A - if Constant then Byte = Op1 -end + if Constant then Byte = Op1 +end # Move the memory pointer to the direct-addressed memory function move_to_direct_addr() @@ -1374,7 +1374,7 @@ end # Read the direct-addressed memory function read_direct() SavedAddr = Addr - + if Pull Addr++ if Addr >= 0x100 then Addr -= 0x100 @@ -1383,28 +1383,28 @@ function read_direct() if Addr >= 0 Byte2 = -1 Byte = read_addr(Addr) - + if Pull >= 2 Addr++ if Addr >= 0x100 then Addr -= 0x100 Byte2 = read_addr(Addr) - + if Pull == 3 Addr++ if Addr >= 0x100 then Addr -= 0x100 - + Byte3 = read_addr(Addr) end end - + Stack += Pull if Stack >= 0x100 then Stack -= 0x100 - + if Indirect Addr++ Byte2 = read_addr(Addr) end - + if Instruction == 0x6C Addr++ Byte2 = read_addr(Addr) @@ -1412,7 +1412,7 @@ function read_direct() end Addr = SavedAddr - + if Debug and Addr >= 0 hex_number(Addr, 0, 4) hex_number(Byte, 4, 2) @@ -1432,7 +1432,7 @@ function move_to_indirect_addr() if Indirect Addr = Byte2 * 0x100 + Byte if YIndexPost - Addr += Y + Addr += Y if Addr >= 0x10000 then Addr -= 0x10000 end @@ -1443,7 +1443,7 @@ function move_to_indirect_addr() tell @a "\ Memory Indirect Read at Addr $(@digit0)(@digit1)(@digit2)(@digit3) -- Byte: $(@digit4)(@digit5)" clear_digits() end - end + end end # Run processor instructions @@ -1452,14 +1452,14 @@ function run_instruction() DecodeP = False # Decode the processor status bits Compare = -1 # Compare to this value to set N and Z bits TestZN = -1 # Test this value for N and Z bits - + if Function == $BRK GetP = True tell @a "BRK at address (PC) A=(A) X=(X) Y=(Y) S=(Stack) Scan=(@Beam.Scan)" Halt = True end if Function == $PHP then GetP = True - + if GetP P = 0 if Negative then P += 0x80 @@ -1469,28 +1469,28 @@ function run_instruction() if Zero then P += 0x02 if Carry then P += 0x01 end - + switch Function case $ADC operate_memory_bus() - + if Decimal la = A % 0x10 ha = A / 0x10 lb = Byte % 0x10 hb = Byte / 0x10 - + la += lb + Carry Carry = la / 10 la %= 10 - + ha += hb ha += Carry Carry = ha / 10 ha %= 10 A = ha * 0x10 + la end - + unless Decimal SignedA = A if SignedA >= 0x80 then SignedA -= 0x100 @@ -1498,10 +1498,10 @@ function run_instruction() if SignedByte >= 0x80 then SignedByte -= 0x100 SignedA += SignedByte SignedA += Carry - + Overflow = True if SignedA >= -0x80 and SignedA <= 0x7F then Overflow = False - + A += Byte A += Carry Carry = False @@ -1510,42 +1510,42 @@ function run_instruction() A -= 0x100 end end - + TestZN = A end case $AND operate_memory_bus() - + Byte2 = 0 for $exp in [128, 64, 32, 16, 8, 4, 2, 1] if A >= $exp and Byte >= $exp then Byte2 += $exp - + if Byte >= $exp then Byte -= $exp if A >= $exp then A -= $exp end A = Byte2 - + TestZN = A end case $ASL operate_memory_bus() - + Byte *= 2 Carry = False if Byte >= 0x100 Carry = True Byte -= 0x100 end - + TestZN = Byte end case $BIT operate_memory_bus() - + Byte2 = A Zero = True Negative = False - + if Byte2 >= 0x80 # If there are any bits in common, Zero is cleared if Byte >= 0x80 then Zero = False @@ -1561,60 +1561,60 @@ function run_instruction() for $exp in [64, 32, 16, 8, 4, 2, 1] # If there are any bits in common, Zero is cleared if Byte2 >= $exp and Byte >= $exp then Zero = False - + if Byte >= $exp then Byte -= $exp if Byte2 >= $exp then Byte2 -= $exp end end case $BRK operate_memory_bus() - + P += 16 # Set the break flag for the processor status - + Byte = PC / 0x100 Byte2 = PC % 0x100 Byte3 = P - PC = NMI + PC = NMI end case $CLC get_pc_data() - + Carry = False end case $CLD get_pc_data() - + Decimal = False end case $CLI get_pc_data() - + Interrupt = False end case $CLV get_pc_data() - + Overflow = False end case $CMP operate_memory_bus() - + Compare = A end case $CPX operate_memory_bus() - + Compare = X end case $CPY operate_memory_bus() - + Compare = Y end case $DEC operate_memory_bus() - + Byte-- if Byte < 0 then Byte += 0x100 @@ -1622,7 +1622,7 @@ function run_instruction() end case $DEX get_pc_data() - + X-- if X < 0 then X += 0x100 @@ -1630,7 +1630,7 @@ function run_instruction() end case $DEY get_pc_data() - + Y-- if Y < 0 then Y += 0x100 @@ -1638,22 +1638,22 @@ function run_instruction() end case $EOR operate_memory_bus() - + Byte2 = 0 for $exp in [128, 64, 32, 16, 8, 4, 2, 1] if A >= $exp and Byte < $exp then Byte2 += $exp if A < $exp and Byte >= $exp then Byte2 += $exp - + if Byte >= $exp then Byte -= $exp if A >= $exp then A -= $exp end A = Byte2 - + TestZN = A end case $INC operate_memory_bus() - + Byte++ if Byte >= 0x100 then Byte -= 0x100 @@ -1661,33 +1661,33 @@ function run_instruction() end case $INX get_pc_data() - + X++ if X >= 0x100 then X -= 0x100 TestZN = X end case $INY get_pc_data() - + Y++ if Y >= 0x100 then Y -= 0x100 TestZN = Y end - case $JMP + case $JMP if Instruction == 0x6C operate_memory_bus() - + PC = Byte2 * 0x100 + Byte end if Instruction == 0x4C get_pc_data() - + PC = Op12 end end case $JSR operate_memory_bus() - + PC-- Byte = PC / 0x100 Byte2 = PC % 0x100 @@ -1695,25 +1695,25 @@ function run_instruction() end case $LDA operate_memory_bus() - + A = Byte TestZN = A end case $LDX operate_memory_bus() - + X = Byte TestZN = X end case $LDY operate_memory_bus() - + Y = Byte TestZN = Y end case $LSR operate_memory_bus() - + Carry = Byte % 2 Byte /= 2 @@ -1724,44 +1724,44 @@ function run_instruction() end case $ORA operate_memory_bus() - + Byte2 = 0 for $exp in [128, 64, 32, 16, 8, 4, 2, 1] if A >= $exp then Byte2 += $exp if A < $exp and Byte >= $exp then Byte2 += $exp - + if Byte >= $exp then Byte -= $exp if A >= $exp then A -= $exp end A = Byte2 - + TestZN = A end case $PHA operate_memory_bus() - + Byte = A end case $PHP operate_memory_bus() - + Byte = P end case $PLA operate_memory_bus() - + A = Byte TestZN = A end case $PLP operate_memory_bus() - + P = Byte DecodeP = True end case $ROL operate_memory_bus() - + LowBit = Carry Byte *= 2 Carry = False @@ -1773,7 +1773,7 @@ function run_instruction() end case $ROR operate_memory_bus() - + LowBit = Byte % 2 Byte /= 2 if Carry then Byte += 0x80 @@ -1783,42 +1783,42 @@ function run_instruction() end case $RTI operate_memory_bus() - + PC = Byte3 * 0x100 + Byte2 P = Byte DecodeP = True end case $RTS operate_memory_bus() - + PC = Byte2 * 0x100 + Byte + 1 end case $SBC operate_memory_bus() - + if Decimal la = A % 0x10 ha = A / 0x10 lb = Byte % 0x10 hb = Byte / 0x10 - + la -= lb + 1 - Carry Carry = 1 if la < 0 Carry = 0 la += 10 end - + ha -= hb + 1 - Carry Carry = 1 if ha < 0 Carry = 0 ha += 10 end - + A = ha * 0x10 + la end - + unless Decimal SignedA = A if SignedA >= 0x80 then SignedA -= 0x100 @@ -1826,86 +1826,86 @@ function run_instruction() if SignedByte >= 0x80 then SignedByte -= 0x100 SignedA -= SignedByte if not Carry then SignedA-- - + Overflow = True if SignedA >= -0x80 and SignedA <= 0x7F then Overflow = False - + A -= Byte if not Carry then A-- Carry = True if A < 0 then Carry = False if A < 0 then A += 0x100 end - + TestZN = A end case $SEC get_pc_data() - + Carry = True end case $SED get_pc_data() - + Decimal = True end case $SEI get_pc_data() - + Interrupt = True end case $STA operate_memory_bus() - + Byte = A end case $STX operate_memory_bus() - + Byte = X end case $STY operate_memory_bus() - + Byte = Y end case $TAX get_pc_data() - + X = A TestZN = X end case $TAY get_pc_data() - + Y = A TestZN = Y end case $TSX get_pc_data() - + X = Stack TestZN = X end case $TXA get_pc_data() - + A = X TestZN = A end case $TXS get_pc_data() - + Stack = X end case $TYA get_pc_data() - + A = Y TestZN = A end end - + # Set new values for the processor status flags, from byte P if DecodeP Negative = False @@ -1914,7 +1914,7 @@ function run_instruction() Interrupt = False Zero = False Carry = False - + if P >= 0x80 Negative = True P -= 0x80 @@ -1922,7 +1922,7 @@ function run_instruction() if P >= 0x40 Overflow = True end - + P %= 0x10 if P >= 0x08 Decimal = True @@ -1940,20 +1940,20 @@ function run_instruction() Carry = True end end - + if Compare >= 0 Result = Compare - Byte Carry = False if Result >= 0 then Carry = True if Result < 0 then Result += 0x100 - + TestZN = Result end if TestZN >= 0 Zero = False if TestZN == 0 then Zero = True - + Negative = False if TestZN >= 0x80 then Negative = True end @@ -1964,15 +1964,15 @@ function get_pixel_count() Pixels = Cycles * 3 # Account for previously delayed register write Pixels -= Delay - + # Find the delay for the current register write get_delay() Pixels += Delay - + if Write and Addr == $WSYNC Pixels = $ScreenWidth - Scan - end - + end + Clock += Pixels end @@ -1984,7 +1984,7 @@ function update_clock() if Ticks < 0 # INSTAT Register Underflow Memory645 = 0b11000000 - + Ticks *= ClockRate Ticks /= 3 Ticks -= Clock / 3 @@ -2046,7 +2046,7 @@ function draw_beam() /tp @s ~ 250 ~ ScanLine = 0 end - + # Mark beam start point for color filling if Scan >= 0 start_point = Scan @@ -2054,16 +2054,16 @@ function draw_beam() if Scan < 0 start_point = 0 end - + end_point = Scan + Pixels - 1 if end_point >= $ScreenWidth $ScreenEnd = $ScreenWidth - 1 end_point = $ScreenEnd end - + # Draw all the pixels draw_range(start_point, end_point) - + Scan += Pixels if Scan >= $ScreenWidth @@ -2100,13 +2100,13 @@ function draw_pixels{$x, $reflect}() /execute unless blocks 0 254 -3 0 254 -3 $x ~ 0 all run clone 0 254 -3 0 254 -3 $x ~ ~ PFPixel = False end - + draw_sprites_missiles_ball() - + x++ - + $sub_pixel = ($x+1) % 4 - + if $sub_pixel != 0 and $x+1 < $ScreenWidth draw_pixels{$x+1, $reflect}() end @@ -2128,15 +2128,15 @@ function draw_four_pixels{$x, $reflect}() /execute unless blocks 0 254 -3 3 254 -3 $x ~ 0 all run clone 0 254 -3 3 254 -3 $x ~ 0 PFPixel = False end - + for $step in $range(4) if x <= x2 draw_sprites_missiles_ball() - + x++ end end - + if $x+4 < $ScreenWidth draw_four_pixels{$x+4, $reflect}() end @@ -2145,7 +2145,7 @@ end # Draw pixel at x for ball, sprites and missiles function draw_sprites_missiles_ball() - draw_ball_pixel() + draw_ball_pixel() draw_sprite_pixel{0}() draw_sprite_pixel{1}() draw_missile_pixel{0}() @@ -2159,10 +2159,10 @@ function draw_ball_pixel() if x >= BLX and x < BallEnd @Self.x = x at @Self - /clone 0 254 -2 0 254 -2 ~ ~ ~ + /clone 0 254 -2 0 254 -2 ~ ~ ~ end BallPixel = True - + if PFPixel then CXBLPF = True end end @@ -2172,10 +2172,10 @@ end function draw_sprite_pixel{$player}() if GRP[$player] PlayerPixel[$player] = False - + dx = (x - PX[$player]) / Stretch[$player] copy = dx / Spread[$player] - + if copy >= 0 and copy < Copies[$player] if ReflectP[$player] do bit = dx % Spread[$player] unless ReflectP[$player] then bit = 7 - (dx % Spread[$player]) @@ -2190,7 +2190,7 @@ function draw_sprite_pixel{$player}() $y = 252 + $player /clone 0 $y -1 0 $y -1 ~ ~ ~ end - + PlayerPixel[$player] = True if $player == 1 if PlayerPixel[0] then CXP0P1 = True @@ -2210,7 +2210,7 @@ function draw_sprite_pixel{$player}() if $player == 1 CXP1BL = True end - end + end end end end @@ -2223,10 +2223,10 @@ end function draw_missile_pixel{$player}() if ENAM[$player] MissilePixel[$player] = False - + dx = x - MX[$player] copy = dx / Spread[$player] - + if copy >= 0 and copy < Copies[$player] bit = dx % Spread[$player] if bit >= 0 and bit < MissileSize[$player] @@ -2235,9 +2235,9 @@ function draw_missile_pixel{$player}() $y = 252 + $player /clone 0 $y -1 0 $y -1 ~ ~ ~ end - + MissilePixel[$player] = True - + if $player == 1 if MissilePixel[0] then CXM0M1 = True end @@ -2289,23 +2289,23 @@ function write_to_memory() clear_digits() Halt = True end - + if not Accumulator write_addr(Addr, Byte) end - + if Accumulator then A = Byte end - + if Push >= 1 Addr = Stack # + 256 # Atari stack mirroring write_addr(Addr, Byte) - + if Push >= 2 Addr-- if Addr < 0 then Addr += 0x100 write_addr(Addr, Byte2) - + if Push >= 3 Addr-- if Addr < 0 then Addr += 0x100 @@ -2313,7 +2313,7 @@ function write_to_memory() write_addr(Addr, Byte3) end end - + Stack -= Push if Stack < 0 then Stack += 0x100 end @@ -2326,18 +2326,18 @@ function write_addr(addr, val) tell @a "\ Memory Write at Addr $(@digit0)(@digit1)(@digit2)(@digit3) -- Byte: $(@digit4)(@digit5)" clear_digits() end - + # Atari Stack Mirroring if addr >= 0x100 and addr < 0x200 addr -= 0x100 end - + if addr == BreakOnWrite tell @a "Wrote (val) to break point (Addr). {G[\[Continue\]](/scoreboard players set Global Halt 0) {R[\[Remove Breakpoint\]](/scoreboard players set Global BreakOnWrite -1)" display_instruction() Halt = True end - + $write_mirrors = $"lambda a: [a % 0x40 + i for i in range(0, 0x80, 0x40)]" switch addr case $addr in $MemoryAddresses @@ -2381,14 +2381,14 @@ function write_addr(addr, val) case $i in $write_mirrors($COLUBK) unless Byte == COLUBK COLUBK = Byte - + Lum = (COLUBK % 0x10) / 2 Color = (COLUBK / 0x10) - + as @Buffer @s.y = Color @s.z = Lum - 8 - + at @s /clone 0 ~ ~ 3 ~ ~ 0 254 -3 end @@ -2398,14 +2398,14 @@ function write_addr(addr, val) case $i in $write_mirrors($COLUPF) unless Byte == COLUPF COLUPF = Byte - + Lum = (COLUPF % 0x10) / 2 Color = (COLUPF / 0x10) - + as @Buffer @s.y = Color @s.z = Lum - 8 - + at @s /clone 0 ~ ~ 3 ~ ~ 0 254 -2 end @@ -2413,16 +2413,16 @@ function write_addr(addr, val) end end case $i in $write_mirrors($COLUP0) - unless Byte == COLUP0 + unless Byte == COLUP0 COLUP0 = Byte - + Lum = (COLUP0 % 0x10) / 2 Color = (COLUP0 / 0x10) - + as @Buffer @s.y = Color @s.z = Lum - 8 - + at @s /clone 0 ~ ~ 0 ~ ~ 0 252 -1 end @@ -2430,16 +2430,16 @@ function write_addr(addr, val) end end case $i in $write_mirrors($COLUP1) - unless Byte == COLUP1 + unless Byte == COLUP1 COLUP1 = Byte - + Lum = (COLUP1 % 0x10) / 2 Color = (COLUP1 / 0x10) - + as @Buffer @s.y = Color @s.z = Lum - 8 - + at @s /clone 0 ~ ~ 0 ~ ~ 0 253 -1 end @@ -2452,14 +2452,14 @@ function write_addr(addr, val) if not VBLANK and was_vblank Frame++ end - + INPT45Control = (Byte / 0x40) % 2 LatchedButton = Button end case $i in $write_mirrors($PF0) unless Byte == PF0 PF0 = Byte - + PFByte = PF0 / 0x10 for $bit in $range(4) PFBit[$bit] = PFByte % 2 @@ -2470,7 +2470,7 @@ function write_addr(addr, val) case $i in $write_mirrors($PF1) unless Byte == PF1 PF1 = Byte - + PFByte = PF1 for $bit in $range(8) PFBit[$bit+4] = PFByte / 0x80 @@ -2482,7 +2482,7 @@ function write_addr(addr, val) case $i in $write_mirrors($PF2) unless Byte == PF2 PF2 = Byte - + PFByte = PF2 for $bit in $range(8) PFBit[$bit+12] = PFByte % 2 @@ -2507,13 +2507,13 @@ function write_addr(addr, val) if VDELP1 GRP1A = Byte end - if VDELP0 + if VDELP0 GRP[0] = GRP0A $UpdateGRPBits(0) end if VDELBL ENABL = ENABLA - + # Make sure ball-object collisions aren't triggered while disabled BallPixel = False end @@ -2547,15 +2547,15 @@ function write_addr(addr, val) VDELBL = Byte % 2 end case $i in $write_mirrors($VDELP1) - VDELP1 = Byte % 2 + VDELP1 = Byte % 2 end case $TIM1T to $TIM1024T Ticks = Byte - 1 Clock = 0 - + # Clear INSTAT Read Flag Memory645 %= 0x80 - + if Addr == $TIM1T then ClockRate = 3 if Addr == $TIM8T then ClockRate = 24 if Addr == $TIM64T then ClockRate = 192 @@ -2563,7 +2563,7 @@ function write_addr(addr, val) end case $i in $write_mirrors($CTRLPF) ReflectPF = Byte % 2 - + switch (Byte / 0x10) % 0x04 case $bits in $range(4) $size = 2 ** $bits @@ -2574,14 +2574,14 @@ function write_addr(addr, val) end case $i in $write_mirrors($ENAM0) ENAM[0] = (Byte / 2) % 2 - + # Make sure missile-object collisions aren't triggered while disabled MissilePixel[0] = False end case $i in $write_mirrors($ENAM1) ENAM[1] = (Byte / 2) % 2 # Make sure missile-object collisions aren't triggered while disabled - MissilePixel[1] = False + MissilePixel[1] = False end case $i in $write_mirrors($ENABL) if VDELBL @@ -2596,7 +2596,7 @@ function write_addr(addr, val) case $i in $write_mirrors($RESP0) PX[0] = Scan + 5 if PX[0] < 0 then PX[0] = 3 - end + end case $i in $write_mirrors($RESP1) PX[1] = Scan + 5 if PX[1] < 0 then PX[1] = 3 @@ -2635,7 +2635,7 @@ function write_addr(addr, val) CXM1BL = False CXBLPF = False CXP0P1 = False - CXM0M1 = False + CXM0M1 = False end end end @@ -2643,7 +2643,7 @@ end macro $UpdateGRPBits($player) # Make sure player-object collisions aren't triggered while disabled PlayerPixel[$player] = False - + GRP = GRP[$player] for $bit in $range(8) bit = GRP % 2 @@ -2696,7 +2696,7 @@ macro $UpdateNumSize($player) Copies[$player] = 1 end end - + MissileSizeBits = (NUSIZ[$player] / 0x10) % 0x04 switch MissileSizeBits case $bits in $range(4) @@ -2744,4 +2744,4 @@ function mnemonic() end end end -end \ No newline at end of file +end diff --git a/Scripts/archived 1.18 scripts/minedas_touch.cbscript b/Scripts/archived 1.18 scripts/minedas_touch.cbscript index c7457ff..231d633 100644 --- a/Scripts/archived 1.18 scripts/minedas_touch.cbscript +++ b/Scripts/archived 1.18 scripts/minedas_touch.cbscript @@ -20,42 +20,42 @@ clock main # /gamerule doTileDrops true # /effect give @s night_vision 100 0 true # end - + unless @Position do create @Position - + as @Player[gamemode=!spectator] at @s eyes /tp @Position ^ ^ ^ end @Position.rx = @s.rx @Position.ry = @s.ry - + = @Position. - + move @Position ^ ^ ^1 - + = @Position. = - adx = abs(dx) ady = abs(dy) adz = abs(dz) - + at @s eyes /tp @Position ^ ^ ^ end - - + + for step = 1 to 100 = @Position. - + distsq = ((x - x1)/100)^2 + ((y - y1)/100)^2 + ((z - z1)/100)^2 if distsq <= 28 * (scale / 100) * (scale / 100) at @Position mine_block() end - + $Large = 1000000000 - + if dx == 0 xcomp = $Large x_dx = $Large @@ -66,7 +66,7 @@ clock main if dx < 0 xcomp -= scale + 1 end - + x_dx = xcomp x_dy = xcomp * dy / dx x_dz = xcomp * dz / dx @@ -82,7 +82,7 @@ clock main if dy < 0 ycomp -= scale + 1 end - + y_dx = ycomp * dx / dy y_dy = ycomp y_dz = ycomp * dz / dy @@ -95,22 +95,22 @@ clock main z_dz = $Large else zcomp = scale - z % scale - + if dz < 0 zcomp -= scale + 1 end - + z_dx = zcomp * dx / dz z_dy = zcomp * dy / dz z_dz = zcomp end - + if debug_cursor if @s.selected_slot + 1 == step at @Position /particle minecraft:bubble end - + title @a 0 10 0 "" ix = x / scale fx = x % scale @@ -122,7 +122,7 @@ clock main end end - + # Use the most sensitive axis to determine which dimension # has the smallest step (since the step will always be largest # along that axis) @@ -144,7 +144,7 @@ function move_along_smallest(x_d, y_d, z_d) x_ad = abs(x_d) y_ad = abs(y_d) z_ad = abs(z_d) - + if x_ad < y_ad and x_ad < z_ad @Position. += else if y_ad < z_ad diff --git a/Scripts/archived 1.18 scripts/perf.cbscript b/Scripts/archived 1.18 scripts/perf.cbscript index ffcba72..6a623c0 100644 --- a/Scripts/archived 1.18 scripts/perf.cbscript +++ b/Scripts/archived 1.18 scripts/perf.cbscript @@ -19,7 +19,7 @@ function test() for i=1 to 90 create @Marker end - + tell @a "Test A: All entities on each command" count = 0 @@ -40,6 +40,6 @@ function test() end end tell @a "Test B Complete" - + /kill @Marker end diff --git a/Scripts/better_click_detector.cblib b/Scripts/better_click_detector.cblib index 1437049..5225289 100644 --- a/Scripts/better_click_detector.cblib +++ b/Scripts/better_click_detector.cblib @@ -26,7 +26,7 @@ advancement damage_click_detector { function click_advancement_reward() /advancement revoke @s only $namespace:damage_click_detector @s.destroy_click() - + if @s.enable_click @s.create_click() click_callback() @@ -35,7 +35,7 @@ end define @BigClickDetector : @Entity[type=slime, tag=BigClickDetector] create {CustomName:"\"ClickDetector\"", Tags:["BigClickDetector"], NoGravity:1b, NoAI: 1b, Silent:1b, Size:18, AbsorptionAmount: 100f} - + function tick_click_detector() /effect give @s invisibility 10 0 true /tp @s ~ ~-6 ~ @@ -46,14 +46,14 @@ end define @Player : @Player click: @BigClickDetector - + function enable_click() unless @s.enable_click @s.enable_click = True @s.create_click() end end - + function create_click() at @s eyes ^ ^ ^ @s.click = create @BigClickDetector ~ ~1000 ~ @@ -64,12 +64,12 @@ define @Player : @Player end end end - + function disable_click() @s.enable_click = False @s.destroy_click() end - + function destroy_click() as @s.click @s.kill = True @@ -95,9 +95,9 @@ clock click_detector_clock end end end - + as @BigClickDetector[kill] /tp @s ~ -200 ~ /kill @s end -end \ No newline at end of file +end diff --git a/Scripts/block_pixels.cblib b/Scripts/block_pixels.cblib index 03a9db6..5fdd7c3 100644 --- a/Scripts/block_pixels.cblib +++ b/Scripts/block_pixels.cblib @@ -684,4 +684,4 @@ end define block iron_block heavy_weighted_pressure_plate iron_trapdoor -end \ No newline at end of file +end diff --git a/Scripts/blocket_league.cbscript b/Scripts/blocket_league.cbscript index c838305..df2d14b 100644 --- a/Scripts/blocket_league.cbscript +++ b/Scripts/blocket_league.cbscript @@ -15,7 +15,7 @@ end @BallBlock = @PhysicsBlock[tag=BallBlock,limit=1] define @RopeSegment = @Entity[type=block_display,tag=RopeSegment] create {block_state: {Name: "minecraft:blue_concrete", count: 0b}, teleport_duration: 1, interpolation_duration: 1, transformation:{left_rotation: [0f, 0f, 0f, 1f], translation: [0f, 0f, 0f], right_rotation: [0f, 0f, 0f, 1f], scale:[0.05f, 0.05f, 0.05f]}, Tags:["RopeSegment"]} - + tele_dur: teleport_duration int 1 interp_dur = interpolation_duration int 1 end @@ -26,7 +26,7 @@ end define @Glass = @Entity[type=block_display,tag=Glass] create {Tags:["Glass"], block_state:{Name:"minecraft:black_stained_glass"}, transformation:{left_rotation: [0f, 0f, 0f, 1f], translation: [-20f, -30f, -10f], right_rotation: [0f, 0f, 0f, 1f], scale:[40f, 60f, 20f]}, view_range:10f} - + : transformation.scale float 1000 scale_x : transformation.scale[0] float 1000 scale_y : transformation.scale[1] float 1000 @@ -78,26 +78,26 @@ $Triggers = [ reset /gamerule playersNetherPortalCreativeDelay 1000000 /gamerule playersNetherPortalDefaultDelay 1000000 - + /team add red "Red" /team modify red color red /team modify red seeFriendlyInvisibles false /team add blue "Blue" /team modify blue color blue /team modify blue seeFriendlyInvisibles false - + for $trigger in $Triggers /scoreboard objectives add $trigger trigger end - + /scoreboard objectives add leave_game minecraft.custom:minecraft.leave_game - + /scoreboard objectives add score dummy "Score" - + as @Player tell_options() end - + /kill @RopeSegment if DisplayAcc create @RopeSegment @@ -116,10 +116,10 @@ function join_red_team() /team join red @s /gamemode adventure @s tell @a "(@s) joined the {Rred team{-." - + @s.needs_spawn = True end - + tell_options() end @@ -130,10 +130,10 @@ function join_blue_team() /team join blue @s /gamemode adventure @s tell @a "(@s) joined the {Bblue team{-." - + @s.needs_spawn = True end - + tell_options() end @@ -150,25 +150,25 @@ function spectate() end tell @a "(@s) is now spectating." end - + tell_options() end function start_game() if gamemode == $Lobby /kill @Glass[tag=Board] - + start_tipoff() - + Red.score = 0 Blue.score = 0 game_timer.score = -1 game_timer = 20*60*5 overtime = False - + /scoreboard players display numberformat game_timer score fixed "5:00" /scoreboard players display name game_timer score "Time" - + /scoreboard objectives setdisplay sidebar score else tell @s "The game has already begun!" @@ -196,7 +196,7 @@ function tell_settings() else tell @s "Sphere Mode: {R{U[\[Disabled\]](/trigger setting_sphere)" end - + tell @s "{Y{U[\[Back\]](/trigger tell_options)" end @@ -212,7 +212,7 @@ function setting_sphere() as @PlayerBlock player_block_init_shape() end - + tell_settings() end @@ -255,11 +255,11 @@ end function start_lobby() spawn_players() reset_ball() - + @Player.tell_options() gamemode = $Lobby - + @Position. = at @Position as create @Glass @@ -269,7 +269,7 @@ function start_lobby() /tag @s add Board end end - + @Position. = at @Position as create @Glass @@ -285,25 +285,25 @@ end function reset_game() initialize_transforms() - + destroy_colliders() /kill @PlayerInteraction - + as @Playing /ride @s dismount end - + /kill @Glass - + YnegPlane = 56000 YposPlane = YnegPlane + 36000 XposPlane = 45600 ZposPlane = 30000 XnegPlane = -XposPlane + 1000 ZnegPlane = -ZposPlane + 1000 - + JumpPlane = YnegPlane + 2000 - + @Position. = <(XnegPlane + XposPlane) / 2, (YnegPlane + YposPlane) / 2, ZposPlane> at 0.5 74.0 30.0 as create @Glass @@ -311,7 +311,7 @@ function reset_game() @s. = <(XnegPlane - XposPlane) / 2, (YnegPlane - YposPlane) / 2, 0> end end - + @Position. = <(XnegPlane + XposPlane) / 2, (YnegPlane + YposPlane) / 2, ZnegPlane> at @Position as create @Glass @@ -328,7 +328,7 @@ function reset_game() /data modify entity @s block_state.Name set value "minecraft:red_stained_glass" end end - + @Position. = at @Position as create @Glass @@ -337,7 +337,7 @@ function reset_game() /data modify entity @s block_state.Name set value "minecraft:blue_stained_glass" end end - + @Position. = <(XnegPlane + XposPlane) / 2, YposPlane, (ZnegPlane + ZposPlane) / 2> at @Position as create @Glass @@ -345,7 +345,7 @@ function reset_game() @s. = <(XnegPlane - XposPlane) / 2, 0, (ZnegPlane - ZposPlane) / 2> end end - + PortalHeight = 9000 PortalWidth = 13000 @@ -357,7 +357,7 @@ function reset_game() # /data modify entity @s block_state.Name set value "minecraft:purple_wool" # end #end - + #@Position. = #at @Position # as create @Glass @@ -369,7 +369,7 @@ function reset_game() ObsidianHeight = PortalHeight + 2000 ObsidianWidth = PortalWidth + 2000 - + #@Position. = #at @Position # as create @Glass @@ -378,7 +378,7 @@ function reset_game() # /data modify entity @s block_state.Name set value "minecraft:obsidian" # end #end - + #@Position. = #at @Position # as create @Glass @@ -392,22 +392,22 @@ function reset_game() # Disable world collisions colliders.world_collisions = False - + # Enable Impact Sounds transforms.impact_sounds = True - + Restitution = 2000 Gravity = 20 PlayerGravity = 30 - Gravity GoalGravity = 8 - Gravity Friction = 1000 - + SphereDrag = 990 CubeSize = $BallSize CubeInvMass = 1200 CubeInvRotInt = 200 - + sphere_mode = False with @@ -417,14 +417,14 @@ function reset_game() /tag @s add BallBlock @s.BallBlock = True end - + collider_1.recent_motion = 0 collider_1.recent_rotation = 0 - + CubeSize = $PlayerSize CubeInvMass = 200 CubeInvRotInt = 1000 - + start_lobby() end @@ -441,21 +441,21 @@ clock tick unless gamemode stop_game() end - + # Handle triggers as @Player unless @s.leave_game == 0 spectate() @s.leave_game = 0 end - + for $trigger in $Triggers /execute if score @s $trigger >= c1 Constant run function $namespace:$trigger /scoreboard players set @s $trigger 0 /scoreboard players enable @s $trigger end end - + allow_movement = False if gamemode == $Lobby allow_movement = True @@ -479,11 +479,11 @@ clock tick /scoreboard players display numberformat game_timer score fixed "$(min):$(sec)" end end - + if game_timer == 1200 title @a 0 35 15 "1 Minute" end - + if game_timer > 0 and game_timer <= 100 and game_timer % 20 == 0 seconds = game_timer / 20 title @a 0 15 5 "(seconds)" @@ -495,7 +495,7 @@ clock tick if gamemode == $Scored scored_timer-- - + if scored_timer == 0 if overtime /scoreboard players reset game_timer score @@ -507,29 +507,29 @@ clock tick end end end - + if gamemode == $Tipoff display_time = False - + if tipoff_timer <= 60 display_time = True end - + if tipoff_timer <= 100 unless overtime display_time = True end - + if display_time and tipoff_timer % 20 == 0 tipoff_seconds = tipoff_timer / 20 title @a 0 15 5 "(tipoff_seconds)" - + if tipoff_seconds <= 3 as @Player at @s /playsound minecraft:block.note_block.bit master @a ~ ~ ~ 1 1 end end - + tipoff_timer-- - + if tipoff_timer == 0 title @a 0 15 5 "Go!" gamemode = $Playing @@ -538,39 +538,39 @@ clock tick end end end - + as @Player[gamemode=survival] /gamemode adventure @s end - + create @Position 0.0 0.0 0.0 - + as @PlayerInteraction on attacker @s.boosting = 10 end - + on target @s.jumping = True end /data remove entity @s attack /data remove entity @s interaction end - + if gamemode == $Playing and game_timer == 1 unless overtime as @a at @s /playsound minecraft:block.bell.use master @s end end - + tick_players() - + as @BallBlock at @s if gamemode == $Scored and @s.collider_id == 1 /particle explosion ~ ~ ~ 2 2 2 0 10 force end end - + as @PlayerInteraction id = @s.id as @Player if @s.id == id @@ -578,7 +578,7 @@ clock tick /kill @s end end - + as @PlayerBlock current_id = @s.player_id as @Playing if @s.id == current_id @@ -586,7 +586,7 @@ clock tick else player = False end - + if not player with $(collider) = @s.collider_id @@ -594,7 +594,7 @@ clock tick /kill @s end end - + as @PlayerHead current_id = @s.player_id if sphere_mode as @Playing if @s.id == current_id @@ -603,16 +603,16 @@ clock tick /kill @s end end - + as @Player if @s.needs_spawn spawn_additional_player() @s.needs_spawn = False end - + if gamemode == $StartingGame start_tipoff() end - + colliders_physics_tick() if sphere_mode colliders_get_sphere_bounds() @@ -621,24 +621,24 @@ clock tick else colliders_get_new_collisions() end - + ball_old_vx = collider_1.velocity_x ball_old_vy = collider_1.velocity_y ball_old_vz = collider_1.velocity_z - + get_plane_collisions() collision_game_logic() colliders_resolve_collisions() colliders_finalize_tick() - + ball_new_vx = collider_1.velocity_x ball_new_vy = collider_1.velocity_y ball_new_vz = collider_1.velocity_z - + if gamemode == $Playing check_for_save() end - + if DisplayAcc as @PlayerBlock @Position. = @s. @@ -647,7 +647,7 @@ clock tick facing @Position as @RopeSegment len = sqrt(player_acc_x*player_acc_x + player_acc_z*player_acc_z) - + /data modify storage $namespace:global scale set value [0.05f, 0.05f, 0.05f] /execute store result storage $namespace:global scale[2] float 0.001 run scoreboard players get Global len /data modify entity @s transformation.scale set from storage $namespace:global scale @@ -671,7 +671,7 @@ clock tick else player = False end - + if player @s. = @s.y += 500 @@ -688,10 +688,10 @@ clock tick else /kill @s end - + as @PlayerHead if @s.player_id == current_id @s. = - + if collider_id with $(collider) = collider_id @@ -708,50 +708,50 @@ function tick_players() /effect give @s minecraft:instant_health infinite 5 true /effect give @s minecraft:saturation infinite 5 true /effect give @s minecraft:invisibility infinite 5 true - + at @s ~ ~ ~ at @s ^ ^ ^ /tp @Position ~ ~ ~ = @Position. end - + at @s ^ ^ ^1 /tp @Position ~ ~ ~ = @Position. - end - + /tp @Position 0 0 0 - + mx = @s.vx mz = @s.vz - + speed = sqrt(mx*mx + mz*mz) - + horiz_mag = sqrt(dx*dx + dz*dz) if DisplayAcc horiz_mag = 1000 end - + dx = mx * horiz_mag / speed dz = mz * horiz_mag / speed - + unless @s.id player_id++ @s.id = player_id end - + current_id = @s.id - + jumping = @s.jumping @s.jumping = False - + @s.boosting-- boosting = @s.boosting - + if @s.menu_cooldown @s.menu_cooldown-- end - + if @s[team=red] team = $Red else if @s[team=blue] @@ -759,7 +759,7 @@ function tick_players() else team = None end - + as @PlayerInteraction if @s.id == current_id /tp @s ~ ~-2 ~ else @@ -771,12 +771,12 @@ function tick_players() as @PlayerBlock at @s if @s.player_id == current_id dismounted = result /ride @player mount @s - + if dismounted as @player unless @s.menu_cooldown > 0 tell_options() @s.menu_cooldown = 20 end - + unless team == @s.team if team == $Red /team join red @@ -787,47 +787,47 @@ function tick_players() @s.team = team player_block_init_shape() end - + with $(collider) = @s.collider_id do define name collider = "collider_$(collider)" - + if collider.id vx = collider.velocity_x vy = collider.velocity_y vz = collider.velocity_z - + if allow_movement horiz_vel = sqrt(vx*vx + vz*vz) norm_vx = vx * $Precision / horiz_vel norm_vz = vz * $Precision / horiz_vel - + braking_dot = -(dx * norm_vx + dz * norm_vz) / $Precision - + if braking_dot > 0 dx = dx * ($Precision + braking_dot) / $Precision dz = dz * ($Precision + braking_dot) / $Precision end - + if jumping and collider.y <= JumpPlane vy = 500 @s.braking = False /playsound minecraft:entity.goat.long_jump master @a ~ ~ ~ end - + if boosting and @s.boost_meter > 0 @s.boost_meter-- else if @s.boost_meter < 100 @s.boost_meter++ boosting = 0 end - + if boosting vx += dx / 20 vy += dy / 20 vz += dz / 20 - + if boosting == 9 /playsound minecraft:entity.blaze.shoot master @a ~ ~ ~ 0.2 2 end @@ -836,17 +836,17 @@ function tick_players() vx += dx / 30 vy += dy / 80 vz += dz / 30 - + if dx == 0 and dz == 0 else /particle minecraft:flame ~ ~ ~ 0 0 0 0 1 force end end end - + player_acc_x = dx player_acc_z = dz - + if gamemode == $Scored vy -= GoalGravity else @@ -857,13 +857,13 @@ function tick_players() collider.velocity_x = vx collider.velocity_y = vy collider.velocity_z = vz - + collider_wake_up() with macros else tell @a "Error: No collider with id (@s.collider_id) for (@player)" end end - + with $(id) = current_id do @@ -872,14 +872,14 @@ function tick_players() else @PhysicsBlock.block_age = 1 add_player_block() - as @PhysicsBlock + as @PhysicsBlock @s.block_age++ if @s.block_age == 1 @s.player_id = current_id /tag @s add PlayerBlock /ride @player mount @s @s.boost_meter = 100 - + with $(id) = current_id do @@ -887,30 +887,30 @@ function tick_players() /bossbar set boost_$(id) players @player /bossbar set boost_$(id) value 100 end - + if team == $Red /team join red else if team == $Blue /team join blue end @s.team = team - + /data modify entity @s Glowing set value 1b - end + end end - + /item modify entity @PhysicsBlock[block_age==1,limit=1] container.0 $namespace:set_head - + as @PhysicsBlock if @s.block_age == 1 # This must be done after the player head is set player_block_init_shape() end - + as @PhysicsBlock[block_age==1] /data modify storage $namespace:global name set from entity @s item.tag.SkullOwner.Name end - + as create @NameTag @s.player_id = current_id /data modify entity @s CustomName set from storage $namespace:global name @@ -923,24 +923,24 @@ function tick_players() @s.team = team end end - + if sphere_mode as @PlayerHead if @s.player_id == current_id else @PlayerHead.head_age++ create @PlayerHead @PlayerHead.head_age++ - + /item modify entity @PlayerHead[head_age==1,limit=1] container.0 $namespace:set_head as @PlayerHead if @s.head_age == 1 @s.player_id = current_id end end end - + @s.boosting = boosting end - + if @s.demo_sound at @s @s.demo_sound = False /playsound minecraft:entity.generic.explode master @s ~ ~ ~ 1 1 0.5 @@ -954,14 +954,14 @@ function get_plane_collisions() $(collider) = collider_iter do define name collider = "collider_$(collider)" - + if collider.id define name collider_axis_0 = "collider_$(collider)" - + y = collider.min_y if y <= YnegPlane pen = YnegPlane - y - + if pen > collider.max_pen with $(vertex) = collider.min_y_vertex @@ -976,23 +976,23 @@ function get_plane_collisions() z = vertex.z end end - + nx = 0 ny = $Precision nz = 0 - + create_plane_collision() with macros end - + if collider_iter == 1 and gamemode == $Playing and game_timer <= 0 unless overtime end_game_time() end end - + y = collider.max_y if y >= YposPlane pen = y - YposPlane - + if pen > collider.max_pen with $(vertex) = collider.max_y_vertex @@ -1007,11 +1007,11 @@ function get_plane_collisions() z = vertex.z end end - + nx = 0 ny = -$Precision nz = 0 - + create_plane_collision() with macros end end @@ -1019,7 +1019,7 @@ function get_plane_collisions() x = collider.min_x if x <= XnegPlane pen = XnegPlane - x - + if pen > collider.max_pen with $(vertex) = collider.min_x_vertex @@ -1034,8 +1034,8 @@ function get_plane_collisions() z = vertex.z end end - - if gamemode == $Playing and collider_iter == 1 + + if gamemode == $Playing and collider_iter == 1 goal = $Blue if y <= YnegPlane + PortalHeight and z >= (ZnegPlane + ZposPlane) / 2 - PortalWidth / 2 and z <= (ZnegPlane + ZposPlane) / 2 + PortalWidth / 2 score_goal() @@ -1043,19 +1043,19 @@ function get_plane_collisions() check_near_miss() end end - + nx = $Precision ny = 0 nz = 0 - + create_plane_collision() with macros end end - + x = collider.max_x if x >= XposPlane pen = x - XposPlane - + if pen > collider.max_pen with $(vertex) = collider.max_x_vertex @@ -1070,8 +1070,8 @@ function get_plane_collisions() z = vertex.z end end - - if gamemode == $Playing and collider_iter == 1 + + if gamemode == $Playing and collider_iter == 1 goal = $Red if y <= YnegPlane + PortalHeight and z >= (ZnegPlane + ZposPlane) / 2 - PortalWidth / 2 and z <= (ZnegPlane + ZposPlane) / 2 + PortalWidth / 2 score_goal() @@ -1079,11 +1079,11 @@ function get_plane_collisions() check_near_miss() end end - + nx = -$Precision ny = 0 nz = 0 - + create_plane_collision() with macros end end @@ -1091,7 +1091,7 @@ function get_plane_collisions() z = collider.min_z if z <= ZnegPlane pen = ZnegPlane - z - + if pen > collider.max_pen with $(vertex) = collider.min_z_vertex @@ -1106,19 +1106,19 @@ function get_plane_collisions() y = vertex.y end end - + nx = 0 ny = 0 nz = $Precision - + create_plane_collision() with macros end end - + z = collider.max_z if z >= ZposPlane pen = z - ZposPlane - + if pen > collider.max_pen with $(vertex) = collider.max_z_vertex @@ -1133,11 +1133,11 @@ function get_plane_collisions() y = vertex.y end end - + nx = 0 ny = 0 nz = -$Precision - + create_plane_collision() with macros end end @@ -1148,7 +1148,7 @@ end function create_plane_collision() define name collider = "collider_$(collider)" - + id = get_unused_collision_id() with $(collision) = id @@ -1157,17 +1157,17 @@ function create_plane_collision() collision.id = id collision.type = 0 collision.pen = pen - + collision.x = x collision.y = y collision.z = z - + collision.nx = nx collision.ny = ny collision.nz = nz - + collision.restitution = 600 - + collision.collider1 = collider_iter end @@ -1185,10 +1185,10 @@ end function start_overtime() overtime = True - + title @a 0 40 20 "Overtime!" subtitle @a 0 40 20 "Next goal wins!" - + start_tipoff() tipoff_timer = 120 end @@ -1197,17 +1197,17 @@ function end_game() if Red.score > Blue.score title @a 0 55 25 "{RRed{- Team Wins!" end - + if Red.score < Blue.score title @a 0 55 25 "{BBlue{- Team Wins!" end - + if Red.score == Blue.score title @a 0 55 25 "Draw!" end - + /scoreboard players reset game_timer score - + start_lobby() end @@ -1220,19 +1220,19 @@ function spawn_players() as @Playing[team=blue] @s.team = $Blue end - + as @Playing @s.spawn_seed = result /random value 1..999999999 @s.spawned = False end - + team = $Red spawn_team() - + team = $Blue spawn_team() - + spawned_players = True end @@ -1241,15 +1241,15 @@ function spawn_team() lowest_seed = $Billion as @Playing is_lower = True - + unless @s.team == team is_lower = False end - + if @s.spawned is_lower = False end - + if @s.spawn_seed > lowest_seed is_lower = False end @@ -1258,7 +1258,7 @@ function spawn_team() lowest_id = @s.id end end - + if lowest_seed < $Billion as @Playing if @s.id == lowest_id spawn_player_slot() @@ -1272,14 +1272,14 @@ end function spawn_additional_player() @Player[team=red].team = $Red @Player[team=blue].team = $Blue - + team = @s.team spawn = 0 - + as @Player if @s.team == team spawn++ end - + spawn_player_slot() end @@ -1297,28 +1297,28 @@ function spawn_player_slot() spawn_dx = 30000 spawn_dz = 2000 end - + if team == $Blue spawn_dx *= -1 spawn_dz *= -1 end - + spawn_player() end function spawn_player() spawn_x = $Half + spawn_dx spawn_y = YnegPlane + CubeSize / 2 - + if spawn_offset spawn_y += spawn_offset spawn_offset = 0 end - + spawn_z = $Half + spawn_dz - + id = @s.id - + as @PlayerBlock if @s.player_id == id with $(collider) = @s.collider_id @@ -1328,19 +1328,19 @@ function spawn_player() collider.y = spawn_y collider.z = spawn_z collider_clear_velocity() with macros - + collider_clear_rotation() with macros collider.w = $Precision collider.i = 0 collider.j = 0 collider.k = 0 end - + @s. = - + @s.boost_meter = 100 end - + @s.spawned = True end @@ -1358,7 +1358,7 @@ function reset_ball() collider.i = 0 collider.j = 0 collider.k = 0 - + collider_quaternion_to_transform() with macros collider_set_transform() with macros collider_sleep() with macros @@ -1373,16 +1373,16 @@ function score_goal() since_blue = time - last_blue_time since_red = time - last_red_time - + if goal == $Red if overtime title @a 0 60 20 "{BBlue{- team wins!" else title @a 0 60 20 "Goal scored by {BBlue{-!" end - + Blue.score++ - + if since_blue <= 80 as @Playing if @s.id == last_blue_hit subtitle @a 0 60 20 "Scored by {B(@s){-!" @@ -1398,7 +1398,7 @@ function score_goal() else title @a 0 60 20 "Goal scored by {RRed{-!" end - + Red.score++ if since_red <= 80 @@ -1411,53 +1411,53 @@ function score_goal() end end end - + for collider_iter = 2 to max_collider with $(collider) = collider_iter do define name collider = "collider_$(collider)" - + if collider.id dx = (collider.x - x) / 10 dy = (collider.y - y) / 10 dz = (collider.z - z) / 10 - + vx = collider.velocity_x vy = collider.velocity_y vz = collider.velocity_z - + dist = sqrt(dx*dx + dy*dy + dz*dz) - + vx += dx * $Precision / dist * 3 vy += dy * $Precision / dist * 3 vz += dz * $Precision / dist * 3 - + vx /= 2 vy /= 2 vz /= 2 - + if collider.y <= JumpPlane vy = 750 end - + collider.velocity_x = vx collider.velocity_y = vy collider.velocity_z = vz - + collider.rotation_x /= 4 collider.rotation_y /= 4 collider.rotation_z /= 4 end end end - + scored_timer = 100 end function start_tipoff() gamemode = $Tipoff - + spawn_players() reset_ball() tipoff_timer = 100 @@ -1465,9 +1465,9 @@ end function set_player_head_transformation() define name collider = "collider_$(collider)" - + size = collider.size * 11 / 10 - + d00 = collider.t00 * size / $Precision d01 = collider.t01 * size / $Precision d02 = collider.t02 * size / $Precision @@ -1480,14 +1480,14 @@ function set_player_head_transformation() dx = d01 * 250 / $Precision dy = d11 * 250 / $Precision dz = d21 * 250 / $Precision - + for $pair in [[0,"d00"], [1,"d01"], [2,"d02"], [3,"dx"], [4,"d10"], [5,"d11"], [6,"d12"], [7,"dy"], [8,"d20"], [9,"d21"], [10,"d22"], [11,"dz"]] $idx = $pair[0] $var = $pair[1] $downscale = 1.0 / $Precision /execute store result storage $namespace:global transformation[$idx] float $downscale run scoreboard players get Global $var end - + /data modify entity @s transformation set from storage $namespace:global transformation /data modify entity @s start_interpolation set value 0 end @@ -1498,10 +1498,10 @@ function colliders_get_sphere_bounds() $(collider) = collider_iter do define name collider = "collider_$(collider)" - + if collider.id halfsize = collider.halfsize - + collider.min_x = collider.x - halfsize collider.max_x = collider.x + halfsize collider.min_y = collider.y - halfsize @@ -1522,7 +1522,7 @@ function get_sphere_sphere_collisions() do define name collider1 = "collider_$(collider1)" define name collider2 = "collider_$(collider2)" - + if collider1.id and collider2.id get_sphere_sphere_collision() with macros end @@ -1534,32 +1534,32 @@ end function get_sphere_sphere_collision() define name collider1 = "collider_$(collider1)" define name collider2 = "collider_$(collider2)" - + x1 = collider1.x y1 = collider1.y z1 = collider1.z - + dx = collider2.x - x1 dy = collider2.y - y1 dz = collider2.z - z1 - + halfsize1 = collider1.halfsize halfsize = halfsize1 + collider2.halfsize - + block_halfsize = halfsize / $Precision + 2 - + block_dx = dx / $Precision block_dy = dy / $Precision block_dz = dz / $Precision - + block_dist_sq = block_dx*block_dx + block_dy*block_dy + block_dz*block_dz - + if block_dist_sq < block_halfsize * block_halfsize dist_sq = dx*dx + dy*dy + dz*dz - + if dist_sq <= halfsize*halfsize dist = sqrt(dist_sq) - + pen = halfsize - dist nx = dx * -$Precision / dist ny = dy * -$Precision / dist @@ -1568,9 +1568,9 @@ function get_sphere_sphere_collision() x = x1 - nx * halfsize1 / $Precision y = y1 - ny * halfsize1 / $Precision z = z1 - nz * halfsize1 / $Precision - + id = get_unused_collision_id() - + with $(collision) = id do @@ -1578,15 +1578,15 @@ function get_sphere_sphere_collision() collision.id = id collision.type = 0 collision.pen = pen - + collision.x = x collision.y = y collision.z = z - + collision.nx = nx collision.ny = ny collision.nz = nz - + collision.collider1 = collider1 collision.collider2 = collider2 end @@ -1610,8 +1610,8 @@ function angular_momentum_drag() $(collider) = collider_iter do define name collider = "collider_$(collider)" - - if collider.id + + if collider.id collider.rotation_x = (collider.rotation_x * SphereDrag + $Half) / $Precision collider.rotation_y = (collider.rotation_y * SphereDrag + $Half) / $Precision collider.rotation_z = (collider.rotation_z * SphereDrag + $Half) / $Precision @@ -1627,15 +1627,15 @@ function collision_game_logic() do define name collision = "collision_$(collision)" define name collider = "collider_$(collider)" - - if collision.id + + if collision.id collider1 = collision.collider1 collider2 = collision.collider2 - + as @BallBlock if @s.collider_id == collider1 as @PlayerBlock if @s.collider_id == collider2 @Position. = - + with $(collider) = collider1 do @@ -1643,7 +1643,7 @@ function collision_game_logic() v1y = collider.velocity_y v1z = collider.velocity_z end - + with $(collider) = collider2 do @@ -1651,14 +1651,14 @@ function collision_game_logic() v2y = collider.velocity_y v2z = collider.velocity_z end - + dvx = v2x - v1x dvy = v2y - v1y dvz = v2z - v1z - + dsq = (dvx*dvx + dvy*dvy + dvz*dvz) $Threshold = 200 - + if dsq >= $Threshold * $Threshold at @Position /playsound minecraft:block.note_block.basedrum master @a ~ ~ ~ 1 1 @@ -1675,10 +1675,10 @@ function collision_game_logic() end end end - + player_id1 = None player_id2 = None - + if collider1 as @PlayerBlock if @s.collider_id == collider1 with $(collider) = collider1 @@ -1687,11 +1687,11 @@ function collision_game_logic() v1y = collider.velocity_y v1z = collider.velocity_z end - + player_id1 = @s.player_id team1 = @s.team end - + if collider2 as @PlayerBlock if @s.collider_id == collider2 with $(collider) = collider2 @@ -1705,11 +1705,11 @@ function collision_game_logic() player_id2 = @s.player_id team2 = @s.team end - - if player_id1 and player_id2 unless team1 == team2 + + if player_id1 and player_id2 unless team1 == team2 v1 = sqrt(v1x*v1x + v1y*v1y + v1z*v1z) v2 = sqrt(v2x*v2x + v2y*v2y + v2z*v2z) - + if v1 > v2 and v1 > $DemoVelocity demolish(player_id1, player_id2) delete_collision() with macros @@ -1731,12 +1731,12 @@ function demolish(demolishing, demolished) if @s.id == demolishing @s.demolishing = True end - + if @s.id == demolished @s.demolished = True end end - + as @Playing if @s.id == demolishing tell @s "You demolished (@Playing[demolished])!" @@ -1748,14 +1748,14 @@ function demolish(demolishing, demolished) /playsound minecraft:entity.generic.explode master @a ~ ~ ~ 1 1 0.5 @s.demo_sound = True end - + @s.demolished = True tell @s "You were demolished by (@Playing[demolishing])!" - + as @PlayerBlock if @s.player_id == demolished team = @s.team end - + spawn = 3 spawn_offset = 10000 spawn_player_slot() @@ -1765,7 +1765,7 @@ function demolish(demolishing, demolished) end end end - + tell @a[not demolished, not demolishing] "(@Playing[demolishing]) demolished (@Playing[demolished])" end @@ -1777,14 +1777,14 @@ function check_for_save() x_plane = XnegPlane goal = $Blue end - + t = (x_plane - collider_1.x) / ball_old_vx - + if t > 0 and t <= 20 # Ball will hit wall within half a second y = collider_1.y + t * ball_old_vy z = collider_1.z + t * ball_old_vz - + if y <= YnegPlane + PortalHeight and z >= (ZnegPlane + ZposPlane) / 2 - PortalWidth / 2 and z <= (ZnegPlane + ZposPlane) / 2 + PortalWidth / 2 # Ball will hit portal t = (x_plane - collider_1.x) / ball_new_vx @@ -1794,10 +1794,10 @@ function check_for_save() else if t > 30 saved = True end - + y = collider_1.y + t * ball_new_vy z = collider_1.z + t * ball_new_vz - + if y > YnegPlane + 2 * PortalHeight saved = True else if z <= (ZnegPlane + ZposPlane) / 2 - PortalWidth @@ -1805,17 +1805,17 @@ function check_for_save() else if z >= (ZnegPlane + ZposPlane) / 2 + PortalWidth saved = True end - + if saved if goal == $Red - if time - last_red_time < 5 + if time - last_red_time < 5 as @Playing if @s.id == last_red_hit title @a "" subtitle @a 0 40 20 "Saved by {R(@s){-!" end end else - if time - last_blue_time < 5 + if time - last_blue_time < 5 as @Playing if @s.id == last_blue_hit title @a "" subtitle @a 0 40 20 "Saved by {B(@s){-!" @@ -1831,22 +1831,22 @@ function check_near_miss() yp = y - (YnegPlane + PortalHeight) zn = ((ZnegPlane + ZposPlane) / 2 - PortalWidth / 2) - z zp = z - ((ZnegPlane + ZposPlane) / 2 + PortalWidth / 2) - + dist = 0 if yp > dist dist = yp end - + if zn > dist dist = zn end - + if zp > dist dist = zp end - + dist += 100 - + if dist < 4000 dist_ones = dist / $Precision dist_tenths = dist / 100 % 10 @@ -1878,11 +1878,11 @@ function test_shot() collider_1.velocity_x = 1500 collider_1.velocity_y = 400 collider_1.velocity_z = 0 - + last_blue_time = time last_blue_hit = @Player[team=blue,limit=1].id - + with $(collider) = 1 collider_wake_up() -end \ No newline at end of file +end diff --git a/Scripts/blocks.json b/Scripts/blocks.json index f9c07d7..ff4d7cd 100644 --- a/Scripts/blocks.json +++ b/Scripts/blocks.json @@ -242045,4 +242045,4 @@ } ] } -} \ No newline at end of file +} diff --git a/Scripts/click_detector.cblib b/Scripts/click_detector.cblib index 6d0dc90..9462316 100644 --- a/Scripts/click_detector.cblib +++ b/Scripts/click_detector.cblib @@ -26,7 +26,7 @@ function click_detector_tick() @s.fire = 0 move @s ~ ~ ~ end - + @ClickDetector.kill = True for @player in @Player as @s.click @@ -43,7 +43,7 @@ end # Run as an entity to create a click detector for that entity function create_click() @s.destroy_click() - + at @s ~ ~50 ~ @s.click = create @ClickDetector at @s ~ ~1.6 ~ at ^ ^ ^2 at ~ ~-0.6 ~ @@ -68,7 +68,7 @@ end function check_clicked() click = False - + at @s ~ ~1.6 ~ at ^ ^ ^1.5 at ~ ~-0.6 ~ as @s.click (@ClickDetector) /tp @s ~ ~ ~ ~ ~ @@ -78,6 +78,6 @@ function check_clicked() end if click then create_click() end - + return click end diff --git a/Scripts/colliders.cblib b/Scripts/colliders.cblib index e7b4f30..06b499e 100644 --- a/Scripts/colliders.cblib +++ b/Scripts/colliders.cblib @@ -15,12 +15,12 @@ function colliders_physics_tick() end end end - + unless colliders.buoyancy == 0 # Apply buoyancy and drag for any colliders in water apply_buoyancy() end - + # Update the penetration and normal for active collisions update_active_collisions() end @@ -41,7 +41,7 @@ function colliders_get_new_collisions() end end end - + unless colliders.c_c_collisions == 0 # Get collisions between each pair of colliders for col1 = 1 to max_collider @@ -59,10 +59,10 @@ function colliders_resolve_collisions() # Remove all new collisions, except for new collisions that have # the deepest penetration for a collider cull_collisions() - + # Merge collision indices down so that there aren't any empties merge_collisions_down() - + # Resolve collisions resolve_collision_velocity() resolve_collision_penetration() @@ -90,9 +90,9 @@ function destroy_colliders() $(collider) = collider destroy_collider() end - + /kill @PhysicsBlock - + max_collider = 0 delete_collisions() @@ -100,21 +100,21 @@ end function destroy_collider() define name collider = "collider_$(collider)" - + id = collider.id - + if max_collider == id max_collider-- end - + as @PhysicsBlock if @s.collider_id == id /kill @s end end - + /scoreboard players reset collider_$(collider) - + for vertex = 0 to 7 with $(vertex) = vertex @@ -122,7 +122,7 @@ function destroy_collider() /scoreboard players reset collider_$(collider)_v$(vertex) end end - + for axis = 0 to 2 with $(axis) = axis @@ -138,7 +138,7 @@ function add_collider(x, y, z) with $(collider) = id create_collider(x, y, z, CubeSize, CubeInvMass, CubeInvRotInt) - + unless id <= max_collider max_collider = id end @@ -168,7 +168,7 @@ function get_unused_collider_id() end end end - + return return_id end @@ -180,7 +180,7 @@ function clear_save_state() /scoreboard players reset save_state_collider_$(collider) end end - + for collision_iter = 1 to save_state.max_collision with $(collision) = collision_iter @@ -188,7 +188,7 @@ function clear_save_state() /scoreboard players reset save_state_collision_$(collision) end end - + /scoreboard players reset save_state end @@ -196,47 +196,48 @@ function save_state() clear_save_state() save_state.max_collider = max_collider - + for collider_iter = 1 to max_collider with $(collider) = collider_iter do define name collider = "collider_$(collider)" define name save_state = "save_state_collider_$(collider)" - + if collider.id save_state.id = collider.id + save_state.shape = collider.shape - + save_state.x = collider.x save_state.y = collider.y save_state.z = collider.z - + save_state.velocity_x = collider.velocity_x save_state.velocity_y = collider.velocity_y save_state.velocity_z = collider.velocity_z - + save_state.rotation_x = collider.rotation_x save_state.rotation_y = collider.rotation_y save_state.rotation_z = collider.rotation_z - + save_state.size = collider.size - + save_state.inv_mass = collider.inv_mass save_state.inv_rot_int = collider.inv_rot_int - + save_state.w = collider.w save_state.i = collider.i save_state.j = collider.j save_state.k = collider.k - + save_state.recent_motion = collider.recent_motion save_state.recent_rotation = collider.recent_rotation save_state.sleeping = collider.sleeping end end end - + save_state.max_collision = max_collision for collision_iter = 1 to max_collision @@ -250,15 +251,15 @@ function save_state() save_state.id = collision.id save_state.active = collision.active save_state.pen = collision.pen - + save_state.x = collision.x save_state.y = collision.y save_state.z = collision.z - + save_state.nx = collision.nx save_state.ny = collision.ny save_state.nz = collision.nz - + save_state.type = collision.type save_state.collider1 = collision.collider1 save_state.collider2 = collision.collider2 @@ -291,41 +292,41 @@ function load_state() collision_frame = 0 max_collider = save_state.max_collider - + for collider_iter = 1 to save_state.max_collider with $(collider) = collider_iter do define name collider = "collider_$(collider)" define name save_state = "save_state_collider_$(collider)" - + if save_state.id create_collider(save_state.x, save_state.y, save_state.z, save_state.size, save_state.inv_mass, save_state.inv_rot_int, save_state.shape) with macros - + collider.velocity_x = save_state.velocity_x collider.velocity_y = save_state.velocity_y collider.velocity_z = save_state.velocity_z - + collider.rotation_x = save_state.rotation_x collider.rotation_y = save_state.rotation_y collider.rotation_z = save_state.rotation_z - + collider.w = save_state.w collider.i = save_state.i collider.j = save_state.j collider.k = save_state.k - + collider_quaternion_to_transform() with macros - + collider.recent_motion = save_state.recent_motion collider.recent_rotation = save_state.recent_rotation collider.sleeping = save_state.sleeping - + collider_set_transform() with macros end end end - + max_collision = save_state.max_collision for collision_iter = 1 to save_state.max_collision @@ -339,15 +340,15 @@ function load_state() collision.id = save_state.id collision.active = save_state.active collision.pen = save_state.pen - + collision.x = save_state.x collision.y = save_state.y collision.z = save_state.z - + collision.nx = save_state.nx collision.ny = save_state.ny collision.nz = save_state.nz - + collision.type = save_state.type collision.collider1 = save_state.collider1 collision.collider2 = save_state.collider2 @@ -394,36 +395,36 @@ function apply_buoyancy() unless collider.buoyancy collider.buoyancy = 200 end - + water_above = False with $(y) = collider.y / $Precision + 1 do /$execute if block $(x) $(y) $(z) minecraft:water run scoreboard players set Global water_above 1 end - + if water_above submerged = $Precision else submerged = $Precision - collider.y % $Precision end - + collider.velocity_y += submerged * collider.buoyancy / $Precision - + collider.velocity_x *= 9 collider.velocity_x /= 10 collider.velocity_y *= 9 collider.velocity_y /= 10 collider.velocity_z *= 9 collider.velocity_z /= 10 - + collider.rotation_x *= 9 collider.rotation_x /= 10 collider.rotation_y *= 9 collider.rotation_y /= 10 collider.rotation_z *= 9 collider.rotation_z /= 10 - + collider_wake_up() with macros end end diff --git a/Scripts/common.cblib b/Scripts/common.cblib index 9bcd09d..eb00b50 100644 --- a/Scripts/common.cblib +++ b/Scripts/common.cblib @@ -41,4 +41,4 @@ end define @Position3 : 0-0-0-0-0xC3 (@Entity[type=marker]) create {Duration:-1, Age:-0x80000000, WaitTime:-0x80000000, UUID: [I; 0,0,0,0xC3]} -end \ No newline at end of file +end diff --git a/Scripts/item_modifier_test.cbscript b/Scripts/item_modifier_test.cbscript index 13cc436..de929f2 100644 --- a/Scripts/item_modifier_test.cbscript +++ b/Scripts/item_modifier_test.cbscript @@ -13,4 +13,4 @@ reset /item replace entity @s hotbar.0 with minecraft:player_head 1 /item modify entity @s hotbar.0 $namespace:set_head end -end \ No newline at end of file +end diff --git a/Scripts/left_right_click_detector.cblib b/Scripts/left_right_click_detector.cblib index ee91246..d48c266 100644 --- a/Scripts/left_right_click_detector.cblib +++ b/Scripts/left_right_click_detector.cblib @@ -21,7 +21,7 @@ advancement damage_click_detector { function click_advancement_reward() /advancement revoke @s only $namespace:damage_click_detector @s.destroy_click() - + if @s.enable_click @s.create_click() left_click_callback() @@ -39,14 +39,14 @@ end define @Player : @Player click_pos: @ClickPos click_detector: @ClickDetector - + function enable_click() unless @s.enable_click @s.enable_click = True @s.create_click() end end - + function create_click() at @s eyes ^ ^ ^1 @s.click_pos = create @ClickPos ~ ~1000 ~ @@ -56,7 +56,7 @@ define @Player : @Player @s.air = 1 end end - + as @NewClickDetector /tag @s remove NewClickDetector /effect give @s invisibility 1 0 true @@ -65,12 +65,12 @@ define @Player : @Player end @s.click_detector = id end - + function disable_click() @s.enable_click = False @s.destroy_click() end - + function destroy_click() as @s.click_pos @s.kill = True @@ -104,7 +104,7 @@ clock left_right_click_clock /data merge entity @s {Air:1s} end end - + if @s.right_clicked right_click_callback() end @@ -123,4 +123,4 @@ end function right_click_callback() /say right_click callback not implemented -end \ No newline at end of file +end diff --git a/Scripts/map_blocks.cblib b/Scripts/map_blocks.cblib index 48509aa..6d34086 100644 --- a/Scripts/map_blocks.cblib +++ b/Scripts/map_blocks.cblib @@ -952,4 +952,4 @@ macro $create_map_block_at($x, $y, $z) /setblock $x $y $z black_glazed_terracotta handled = True end -end \ No newline at end of file +end diff --git a/Scripts/math.cblib b/Scripts/math.cblib index efcb007..48112a5 100644 --- a/Scripts/math.cblib +++ b/Scripts/math.cblib @@ -11,13 +11,13 @@ function sqrt(_x) else if _x >= 455779651 and _x <= 2147483647 sqrt.y = -2147483648 / (_x / 100000 + 26111) + 91181 end - + sqrt.y = (sqrt.y + _x / sqrt.y) / 2 - + if sqrt.y * sqrt.y > _x sqrt.y-- end - + return sqrt.y end @@ -36,7 +36,7 @@ function sin(_sin_angle) _sin_angle -= 180 mult = -1 end - + return 4000*_sin_angle*(180-_sin_angle)/(40500-_sin_angle*(180-_sin_angle)) * mult end @@ -49,10 +49,10 @@ function sin_precise(_sin_angle) _sin_angle -= 18000 mult = -1 end - + _angle_sq = _sin_angle * (18000 - _sin_angle) / 100 - - + + return 4 * _angle_sq * 100 / (4050000 - _angle_sq) * mult end @@ -72,4 +72,4 @@ function sign(n) else return 0 end -end \ No newline at end of file +end diff --git a/Scripts/miniblock.cblib b/Scripts/miniblock.cblib index f71d274..f25161b 100644 --- a/Scripts/miniblock.cblib +++ b/Scripts/miniblock.cblib @@ -2,28 +2,28 @@ import common define @MiniBlock: @Entity[type=armor_stand,tag=MiniBlock] create {Tags:["MiniBlock"], Pose:{Head:[0.0001f,0f,0f]}, Marker:1b, Invisible:1b, NoGravity:1b, Invulnerable:1b, Silent:1b} - + pose_rot_x: Pose.Head[0] float pose_rot_y: Pose.Head[1] float - + function update() at ~ ~-1.7 ~ /tp @s ~ ~ ~ end - + /data merge entity @s {Pose:{Head:[0.0001f,0.0001f,0.0001f]}} @s.pose_rot_x = @s.rot_x @s.pose_rot_y = @s.rot_y - + move @s ^ ^0.287 ^ @s.rx = @s.rot_x @s.ry = @s.rot_y move @s ^ ^-0.287 ^ - - /data merge entity @s {Fire:32767s} - + + /data merge entity @s {Fire:32767s} + at @s rotated @s /tp @s ~ ~ ~ 0 0 end - end -end \ No newline at end of file + end +end diff --git a/Scripts/mtg/cards.py b/Scripts/mtg/cards.py index 34e74dd..9ac66c6 100644 --- a/Scripts/mtg/cards.py +++ b/Scripts/mtg/cards.py @@ -3,16 +3,16 @@ Cards = {} -for dirpath, dirnames, filenames in os.walk('cards'): - for filename in filenames: - with open(os.path.join(dirpath, filename)) as file: - obj = json.load(file) - Cards[obj["Name"]] = obj - +for dirpath, dirnames, filenames in os.walk("cards"): + for filename in filenames: + with open(os.path.join(dirpath, filename)) as file: + obj = json.load(file) + Cards[obj["Name"]] = obj + CardNames = [] CardNumbers = {} i = 0 for name in Cards: - CardNames.append(name) - CardNumbers[name] = i - i += 1 \ No newline at end of file + CardNames.append(name) + CardNumbers[name] = i + i += 1 diff --git a/Scripts/mtg/cards/sample_card.json b/Scripts/mtg/cards/sample_card.json index f1d9769..6359998 100644 --- a/Scripts/mtg/cards/sample_card.json +++ b/Scripts/mtg/cards/sample_card.json @@ -7,4 +7,4 @@ "Power": 0, "Toughness": 0, "Abilities": [] -} \ No newline at end of file +} diff --git a/Scripts/mtg/common.cblib b/Scripts/mtg/common.cblib index bed29ce..a58f171 100644 --- a/Scripts/mtg/common.cblib +++ b/Scripts/mtg/common.cblib @@ -46,4 +46,4 @@ end define @Position3 : 0-0-0-0-0xAEC3 (@Entity[type=area_effect_cloud]) create {Duration:-1, Age:-0x80000000, WaitTime:-0x80000000, UUIDMost:0, UUIDLeast: 0xAEC3} -end \ No newline at end of file +end diff --git a/Scripts/mtg/left_right_click_detector.cblib b/Scripts/mtg/left_right_click_detector.cblib index ee91246..d48c266 100644 --- a/Scripts/mtg/left_right_click_detector.cblib +++ b/Scripts/mtg/left_right_click_detector.cblib @@ -21,7 +21,7 @@ advancement damage_click_detector { function click_advancement_reward() /advancement revoke @s only $namespace:damage_click_detector @s.destroy_click() - + if @s.enable_click @s.create_click() left_click_callback() @@ -39,14 +39,14 @@ end define @Player : @Player click_pos: @ClickPos click_detector: @ClickDetector - + function enable_click() unless @s.enable_click @s.enable_click = True @s.create_click() end end - + function create_click() at @s eyes ^ ^ ^1 @s.click_pos = create @ClickPos ~ ~1000 ~ @@ -56,7 +56,7 @@ define @Player : @Player @s.air = 1 end end - + as @NewClickDetector /tag @s remove NewClickDetector /effect give @s invisibility 1 0 true @@ -65,12 +65,12 @@ define @Player : @Player end @s.click_detector = id end - + function disable_click() @s.enable_click = False @s.destroy_click() end - + function destroy_click() as @s.click_pos @s.kill = True @@ -104,7 +104,7 @@ clock left_right_click_clock /data merge entity @s {Air:1s} end end - + if @s.right_clicked right_click_callback() end @@ -123,4 +123,4 @@ end function right_click_callback() /say right_click callback not implemented -end \ No newline at end of file +end diff --git a/Scripts/mtg/mtg.cbscript b/Scripts/mtg/mtg.cbscript index cbd3bdb..ddf6ded 100644 --- a/Scripts/mtg/mtg.cbscript +++ b/Scripts/mtg/mtg.cbscript @@ -6,9 +6,9 @@ import mtg_logic import cards.py reset - + end clock main -end \ No newline at end of file +end diff --git a/Scripts/mtg/mtg_constants.cblib b/Scripts/mtg/mtg_constants.cblib index 1307a40..cdc93b1 100644 --- a/Scripts/mtg/mtg_constants.cblib +++ b/Scripts/mtg/mtg_constants.cblib @@ -31,4 +31,4 @@ $ZoneHand = 1 $ZoneBattlefield = 2 $ZoneGraveyard = 3 $ZoneStack = 4 -$ZoneExile = 5 \ No newline at end of file +$ZoneExile = 5 diff --git a/Scripts/mtg/mtg_logic.cblib b/Scripts/mtg/mtg_logic.cblib index fed9dcf..e6732a1 100644 --- a/Scripts/mtg/mtg_logic.cblib +++ b/Scripts/mtg/mtg_logic.cblib @@ -33,7 +33,7 @@ function handle_beginning() end function handle_main() - + end function handle_combat() @@ -86,4 +86,4 @@ function next_turn() end Phase = $PhaseBeginning Step = $StepUntap -end \ No newline at end of file +end diff --git a/Scripts/music.cblib b/Scripts/music.cblib index fbbe517..e021d00 100644 --- a/Scripts/music.cblib +++ b/Scripts/music.cblib @@ -28,6 +28,6 @@ $Pitches = [ macro $playsound($sound, $note) $pitch = $Pitches[$note] - + /playsound minecraft:$sound block @a ~ ~ ~ 1 $pitch -end \ No newline at end of file +end diff --git a/Scripts/no_collision_box.cblib b/Scripts/no_collision_box.cblib index 60c80e3..bed2eb1 100644 --- a/Scripts/no_collision_box.cblib +++ b/Scripts/no_collision_box.cblib @@ -176,4 +176,4 @@ define block_tag no_collision void_air water lava -end \ No newline at end of file +end diff --git a/Scripts/perf.cbscript b/Scripts/perf.cbscript index 310a3af..b10b9b1 100644 --- a/Scripts/perf.cbscript +++ b/Scripts/perf.cbscript @@ -5,15 +5,15 @@ import common reset step = 0 - + tell @a "v6" end clock tick $iters = 200 - + step++ - + if step == 50 val_1.val = 0 tell @a "(val_1.val)" @@ -30,7 +30,7 @@ clock tick end tell @a "(val_1.val)" end - + if step == 70 val_1.val = 0 tell @a "(val_1.val)" @@ -64,4 +64,4 @@ function macro_call_2() end k = val.val + 1 val.val = k -end \ No newline at end of file +end diff --git a/Scripts/photo.cbscript b/Scripts/photo.cbscript index c36ae1c..56bf7ef 100644 --- a/Scripts/photo.cbscript +++ b/Scripts/photo.cbscript @@ -164,70 +164,70 @@ end reset unless @Position do create @Position - + /kill @e[type=block_display] - + photo_id++ - + as @Player[limit=1,sort=nearest] at @s eyes = @s. stored_rx = @s.rx stored_ry = @s.ry - + /tp @Position ^ ^ ^ = @Position. - + /tp @Position ^-3 ^2 ^2 = @Position. /tp @Position ^3 ^2 ^2 = @Position. /tp @Position ^-3 ^-2 ^2 = @Position. - + = - = - - + = ( - ) - + NumRows = 40 NumCols = 40 - + for row = 1 to NumRows = + * row / NumRows for col = 1 to NumCols /tp @Position ^0.2 ^ ^ - + = + * col / NumCols - + mag = sqrt(dx*dx + dy*dy + dz*dz) dx = dx * $Precision / mag dy = dy * $Precision / mag dz = dz * $Precision / mag - + raycast(ox, oy, oz, dx, dy, dz) end end - + $Downsize = 10 $AxisScale = $int($Precision / $Downsize) - + as @PhotoBlock = @s. - - + depth = sqrt(px*px + py*py + pz*pz) nx = px * $Precision / depth ny = py * $Precision / depth nz = pz * $Precision / depth - + nxx = nx * nx / $Precision nxy = nx * ny / $Precision nxz = nx * nz / $Precision nyy = ny * ny / $Precision nyz = ny * nz / $Precision nzz = nz * nz / $Precision - + # Scaling formula: https://www.mauriciopoppe.com/notes/computer-graphics/transformation-matrices/scale/ - + d00 = ($Precision + ($AxisScale - $Precision) * nxx / $Precision) d01 = (($AxisScale - $Precision) * nxy / $Precision) d02 = (($AxisScale - $Precision) * nxz / $Precision) @@ -240,7 +240,7 @@ reset dx = -$Half * depth_scale / $Precision dy = -$Half * depth_scale / $Precision dz = -$Half * depth_scale / $Precision - + /data modify storage $namespace:global transformation set value [1f,0f,0f,0f,0f,1f,0f,0f,0f,0f,1f,0f,0f,0f,0f,1f] for $pair in [[0,"d00"], [1,"d01"], [2,"d02"], [3,"dx"], [4,"d10"], [5,"d11"], [6,"d12"], [7,"dy"], [8,"d20"], [9,"d21"], [10,"d22"], [11,"dz"]] @@ -252,14 +252,14 @@ reset /data modify entity @s transformation set from storage $namespace:global transformation /data modify entity @s interpolation_duration set value 0 - + @s. = + / $Downsize * 9 / 10 end end - + move @Player ~ ~10 ~ move @PhotoBlock ~ ~10 ~ - + tell @a "{G[\[Reset Position\]](/function $namespace:reset_position)" end @@ -267,7 +267,7 @@ function reset_position() @Position. = @Position.rx = stored_rx @Position.ry = stored_ry - + at @Position /tp @s ~ ~10 ~ ~ ~ end @@ -285,36 +285,36 @@ function raycast(ray_ox, ray_oy, ray_oz, ray_dx, ray_dy, ray_dz) x = ray_ox y = ray_oy z = ray_oz - + next_x = x / $Precision * $Precision if ray_dx > 0 next_x += $Precision else - next_x -= 1 + next_x -= 1 end - + next_y = y / $Precision * $Precision if ray_dy > 0 next_y += $Precision else next_y -= 1 end - + next_z = z / $Precision * $Precision if ray_dz > 0 next_z += $Precision else next_z -= 1 end - + t = 0 - + next_t_x = (next_x - ray_ox) * $Precision / ray_dx next_t_y = (next_y - ray_oy) * $Precision / ray_dy next_t_z = (next_z - ray_oz) * $Precision / ray_dz - + @Position. = - + for i = 1 to 100 at @Position continue = False @@ -325,15 +325,15 @@ function raycast(ray_ox, ray_oy, ray_oz, ray_dx, ray_dy, ray_dz) if block ~ ~ ~ ignore continue = True end - + if continue if next_t_x < next_t_y and next_t_x < next_t_z t = next_t_x x = next_x - y = ray_oy + ray_dy * t / $Precision - z = ray_oz + ray_dz * t / $Precision - + y = ray_oy + ray_dy * t / $Precision + z = ray_oz + ray_dz * t / $Precision + if ray_dx > 0 next_x += $Precision else @@ -344,10 +344,10 @@ function raycast(ray_ox, ray_oy, ray_oz, ray_dx, ray_dy, ray_dz) else if next_t_y < next_t_z t = next_t_y - x = ray_ox + ray_dx * t / $Precision + x = ray_ox + ray_dx * t / $Precision y = next_y - z = ray_oz + ray_dz * t / $Precision - + z = ray_oz + ray_dz * t / $Precision + if ray_dy > 0 next_y += $Precision else @@ -358,19 +358,19 @@ function raycast(ray_ox, ray_oy, ray_oz, ray_dx, ray_dy, ray_dz) else t = next_t_z - x = ray_ox + ray_dx * t / $Precision - y = ray_oy + ray_dy * t / $Precision + x = ray_ox + ray_dx * t / $Precision + y = ray_oy + ray_dy * t / $Precision z = next_z - + if ray_dz > 0 next_z += $Precision else next_z -= $Precision end - + next_t_z = (next_z - ray_oz) * $Precision / ray_dz end - + @Position. = else # Non-passthrough block @@ -393,7 +393,7 @@ function create_photo_block() $(z) = block_z do define name pos = "b$(x)$(y)$(z)" - + unless pos.photo_id == photo_id pos.photo_id = photo_id at @Position align xyz at ~0.5 ~0.5 ~0.5 @@ -413,4 +413,4 @@ function create_photo_block() end end end -end \ No newline at end of file +end diff --git a/Scripts/physics_sandbox.cbscript b/Scripts/physics_sandbox.cbscript index 679c440..6c40241 100644 --- a/Scripts/physics_sandbox.cbscript +++ b/Scripts/physics_sandbox.cbscript @@ -27,25 +27,25 @@ reset CubeSize = 1500 CubeInvMass = 800 CubeInvRotInt = 400 - + tell_options() end clock tick define name collider = "collider_$(collider)" - + /kill @Position create @Position - + unless @Interaction at @nearest_player /summon minecraft:interaction ~ ~-5 ~ {width:10, height:10} end end - + left_clicked = False right_clicked = False - + as @Interaction on attacker left_clicked = True @@ -67,7 +67,7 @@ clock tick world_eye_x = @Position.x world_eye_y = @Position.y world_eye_z = @Position.z - + /tp @Position ^ ^ ^1 world_eye_dx = @Position.x - world_eye_x world_eye_dy = @Position.y - world_eye_y @@ -93,23 +93,23 @@ clock tick end end end - + if min_col_t < $Billion # There was a ray intersection $PunchPower = 1000 with $(collider) = min_col collider_apply_impulse(min_x, min_y, min_z, world_eye_dx * $PunchPower / scale, world_eye_dy * $PunchPower / scale, world_eye_dz * $PunchPower / scale) - + save_state() - + @Position. = at @Position /particle minecraft:crit ~ ~ ~ 0 0 0 0 1 force end end end - + if right_clicked at @nearest_player ^ ^1.6 ^3 /tp @Position ~ ~ ~ @@ -127,22 +127,22 @@ clock tick $(block_name) = "target" add_collider(x, y, z) end - + tell_options() end - + colliders_physics_tick() colliders_get_new_collisions() colliders_resolve_collisions() colliders_finalize_tick() - + if Particles for collision = 1 to max_collision with $(collision) = collision do define name collision = "collision_$(collision)" - + if collision.id @Position. = at @Position diff --git a/Scripts/plinko_demo.cbscript b/Scripts/plinko_demo.cbscript index fe96399..8b8e1dc 100644 --- a/Scripts/plinko_demo.cbscript +++ b/Scripts/plinko_demo.cbscript @@ -28,7 +28,7 @@ clock tick else @s.tele_duration = 1 end - + if collider.y < 52000 collider.y = 72000 end @@ -37,4 +37,4 @@ clock tick end end end -end \ No newline at end of file +end diff --git a/Scripts/pushable.cblib b/Scripts/pushable.cblib index 5c013f9..9d4a198 100644 --- a/Scripts/pushable.cblib +++ b/Scripts/pushable.cblib @@ -2,14 +2,14 @@ import common define @Pushable: @Entity[type=armor_stand, tag=Pushable] create {Tags:["Pushable"], Invisible:1b, Invulnerable:1b} - + disguise: @Disguise[distance=..2] physics: @Physics[distance=..2] - + function get_velocity_signs() vx = @s.vx vz = @s.vz - + if vx > 0 sx = 1 end @@ -24,7 +24,7 @@ define @Pushable: @Entity[type=armor_stand, tag=Pushable] end avx = abs(vx) avz = abs(vz) - + havx = avx / 2 havz = avz / 2 end diff --git a/Scripts/random.cblib b/Scripts/random.cblib index 95fd053..821d9b5 100644 --- a/Scripts/random.cblib +++ b/Scripts/random.cblib @@ -12,4 +12,4 @@ function randint(_rand_min, _rand_max) _random_seed *= 1664525 _random_seed += 1013904223 return ((_random_seed / 256) % _rand_range) + _rand_min -end \ No newline at end of file +end diff --git a/Scripts/separating_axis_demo.cbscript b/Scripts/separating_axis_demo.cbscript index 6087d58..ffd5431 100644 --- a/Scripts/separating_axis_demo.cbscript +++ b/Scripts/separating_axis_demo.cbscript @@ -11,56 +11,56 @@ $Half = 500 $Billion = 1000000000 reset unless @Position do create @Position - + do_reset = True end function do_reset() initialize_transforms() - + /team add red /team add green - + /team modify red color dark_purple /team modify green color aqua CubeSize = 1500 CubeInvMass = 800 CubeInvRotInt = 200 - + if block 0 54 0 sandstone destroy_colliders() - + for axis = 0 to 14 with $(block_name) = "chain_command_block" add_collider(x1 + axis * 6000, y1 + 58000, z1) - + with $(block_name) = "repeating_command_block" add_collider(x2 + axis * 6000, y2 + 58000, z2) end - + for axis = 0 to 14 with $(block_name) = "cyan_stained_glass" add_collider(x1 + axis * 6000, y1 + 58000, z1) - + with $(block_name) = "purple_stained_glass" add_collider(x2 + axis * 6000, y2 + 58000, z2) end - + pair = 1 init_cubes() - + as @PhysicsBlock - /data modify entity @s interpolation_duration set value 0 - + /data modify entity @s interpolation_duration set value 0 + if @s.collider_id <= 30 @s.glowing = True - + if @s.collider_id % 2 == 0 /team join red else @@ -68,9 +68,9 @@ function do_reset() end end end - + tell_options() - + do_reset = False end end @@ -88,7 +88,7 @@ function prev_pair() init_cubes() tell_options() end - + function next_pair() pair++ if pair > $MaxPair @@ -104,7 +104,7 @@ function init_cubes() i1 = 1000 j1 = 700 k1 = 500 - + x1 = 0 y1 = 0 z1 = -1000 @@ -113,18 +113,18 @@ function init_cubes() i2 = 800 j2 = 200 k2 = 600 - + x2 = 0 y2 = 0 z2 = 1100 end - + if pair == 2 w1 = 500 i1 = 1000 j1 = 700 k1 = 500 - + x1 = 0 y1 = 0 z1 = -900 @@ -133,18 +133,18 @@ function init_cubes() i2 = 800 j2 = 200 k2 = 600 - + x2 = 0 y2 = 0 z2 = 1050 end - + if pair == 3 w1 = 500 i1 = 1000 j1 = 700 k1 = 500 - + x1 = 0 y1 = 0 z1 = -925 @@ -153,7 +153,7 @@ function init_cubes() i2 = 800 j2 = 200 k2 = 600 - + x2 = 0 y2 = 0 z2 = 1075 @@ -164,7 +164,7 @@ function init_cubes() i1 = 3000 j1 = 700 k1 = 700 - + x1 = 700 y1 = 0 z1 = -700 @@ -173,14 +173,14 @@ function init_cubes() i2 = 800 j2 = 1000 k2 = 200 - + x2 = 0 y2 = 0 z2 = 1050 end - + define name collider = "collider_$(collider)" - + for axis = 0 to 14 with $(collider) = axis * 2 + 1 @@ -189,10 +189,10 @@ function init_cubes() collider.y = y1 + 58000 collider.z = z1 collider_set_orientation(w1, i1, j1, k1) with macros - + collider_calculate_vertex_world_positions() with macros end - + with $(collider) = axis * 2 + 2 do @@ -211,10 +211,10 @@ function init_cubes() collider.y = y1 + 58000 collider.z = z1 collider_set_orientation(w1, i1, j1, k1) with macros - + collider_calculate_vertex_world_positions() with macros end - + with $(collider) = axis * 2 + 2 + 30 do @@ -226,12 +226,12 @@ function init_cubes() collider_calculate_vertex_world_positions() with macros end end - + with $(collider1) = 1 $(collider2) = 2 - get_axes() - + get_axes() + scale_amount = 1500 end @@ -241,9 +241,9 @@ clock tick end colliders_finalize_tick() - + scale_amount -= 20 - + if scale_amount < -500 scale_amount = 1500 end @@ -253,11 +253,11 @@ clock tick if amount > 1000 amount = 1000 end - + if amount < 20 amount = 20 end - + get_scaling_transforms(amount) end @@ -266,13 +266,13 @@ function get_axes() define name axis_1 = "axis_$(axis_1)" define name collider_axis_2 = "collider_$(collider2)_a$(axis_1)" define name axis_2 = "axis_$(axis_2)" - + for axis = 0 to 2 with $(axis_1) = axis $(axis_2) = axis+3 do - + axis_1.x = collider_axis_1.x axis_1.y = collider_axis_1.y axis_1.z = collider_axis_1.z @@ -280,7 +280,7 @@ function get_axes() axis_2.x = collider_axis_2.x axis_2.y = collider_axis_2.y axis_2.z = collider_axis_2.z - + for axis_2 = 0 to 2 with $(axis_1) = axis @@ -289,17 +289,17 @@ function get_axes() do define name collider_axis_2 = "collider_$(collider2)_a$(axis_2)" define name axis = "axis_$(axis)" - + x = (collider_axis_1.y * collider_axis_2.z - collider_axis_1.z * collider_axis_2.y) / $Precision y = (collider_axis_1.z * collider_axis_2.x - collider_axis_1.x * collider_axis_2.z) / $Precision z = (collider_axis_1.x * collider_axis_2.y - collider_axis_1.y * collider_axis_2.x) / $Precision - + s = sqrt(x*x + y*y + z*z) - + x = x * $Precision / s y = y * $Precision / s z = z * $Precision / s - + axis.x = x axis.y = y axis.z = z @@ -319,26 +319,26 @@ function get_scaling_transforms(amount) ny = axis.y nz = axis.z end - + nxx = nx * nx / $Precision nxy = nx * ny / $Precision nxz = nx * nz / $Precision nyy = ny * ny / $Precision nyz = ny * nz / $Precision nzz = nz * nz / $Precision - + with $(collider1) = axis*2 + 1 $(collider2) = axis*2 + 2 do define name collider1 = "collider_$(collider1)" define name collider2 = "collider_$(collider2)" - + ox = (collider1.x + collider2.x) / 2 oy = (collider1.y + collider2.y) / 2 oz = (collider1.z + collider2.z) / 2 end - + scale_00 = $Precision + ((amount - $Precision) * ($Precision - nxx)) / $Precision scale_01 = (-(amount - $Precision) * nxy) / $Precision scale_02 = (-(amount - $Precision) * nxz) / $Precision @@ -348,11 +348,11 @@ function get_scaling_transforms(amount) scale_20 = (-(amount - $Precision) * nxz) / $Precision scale_21 = (-(amount - $Precision) * nyz) / $Precision scale_22 = $Precision + ((amount - $Precision) * ($Precision - nzz)) / $Precision - + with $(collider) = axis*2 + 1 collider_multiply_transform() - + with $(collider) = axis*2 + 2 collider_multiply_transform() @@ -361,7 +361,7 @@ end function collider_multiply_transform() define name collider = "collider_$(collider)" - + id = collider.id size = collider.size @@ -376,13 +376,13 @@ function collider_multiply_transform() t_20 = collider.t20 t_21 = collider.t21 t_22 = collider.t22 - + with $(m1) = "Global scale" $(m2) = "Global t" $(out) = "Global new_t" matrix_multiply() - + dcx = @s.x - ox dcy = @s.y - oy dcz = @s.z - oz @@ -393,9 +393,9 @@ function collider_multiply_transform() dpx = px - @s.x dpy = py - @s.y dpz = pz - @s.z - + interp = ($Precision - amount) - + /data modify storage $namespace:global transformation set value [1f,0f,0f,0f,0f,1f,0f,0f,0f,0f,1f,0f,0f,0f,0f,1f] d00 = new_t_00 * size / $Precision d01 = new_t_01 * size / $Precision @@ -416,7 +416,7 @@ function collider_multiply_transform() $downscale = 1.0 / $Precision /execute store result storage $namespace:global transformation[$idx] float $downscale run scoreboard players get Global $var end - + #@s.x = collider.x #@s.y = collider.y #@s.z = collider.z @@ -424,4 +424,4 @@ function collider_multiply_transform() /data modify entity @s interpolation_duration set value 0 end end -end \ No newline at end of file +end diff --git a/Scripts/stack.cblib b/Scripts/stack.cblib index 185a417..a4dda7f 100644 --- a/Scripts/stack.cblib +++ b/Scripts/stack.cblib @@ -13,7 +13,7 @@ define @Stack = @StackFrame[depth == 0, limit=1] end end end - + function pop() @StackFrame.depth-- unless @Stack @@ -29,4 +29,4 @@ function stack_init() as create @StackFrame @s.depth = 0 end -end \ No newline at end of file +end diff --git a/Scripts/stupid_mobile_game.cbscript b/Scripts/stupid_mobile_game.cbscript index 795dbd5..f870d45 100644 --- a/Scripts/stupid_mobile_game.cbscript +++ b/Scripts/stupid_mobile_game.cbscript @@ -13,7 +13,7 @@ reset /scoreboard objectives add absorbed minecraft.custom:minecraft.damage_dealt_absorbed initialize_transforms() - + CubeSize = 1500 CubeInvMass = 800 CubeInvRotInt = 400 @@ -21,7 +21,7 @@ end clock tick define name collider = "collider_$(collider)" - + # Apply gravity, integrate linear/angular velocity for collider = 1 to max_collider with @@ -29,7 +29,7 @@ clock tick do if not collider.sleeping collider_physics_tick() with macros - + water_here = False with $(x) = collider.x / $Precision @@ -43,42 +43,42 @@ clock tick unless collider.buoyancy collider.buoyancy = 200 end - + water_above = False with $(y) = collider.y / $Precision + 1 do /$execute if block $(x) $(y) $(z) minecraft:water run scoreboard players set Global water_above 1 end - + if water_above submerged = $Precision else submerged = $Precision - collider.y % $Precision end - + collider.velocity_y += submerged * collider.buoyancy / $Precision - + collider.velocity_x *= 9 collider.velocity_x /= 10 collider.velocity_y *= 9 collider.velocity_y /= 10 collider.velocity_z *= 9 collider.velocity_z /= 10 - + collider.rotation_x *= 9 collider.rotation_x /= 10 collider.rotation_y *= 9 collider.rotation_y /= 10 collider.rotation_z *= 9 collider.rotation_z /= 10 - + collider_wake_up() with macros end end end end - + # Update the penetration and normal for active collisions update_active_collisions() @@ -93,7 +93,7 @@ clock tick end end end - + # Get collisions between each pair of colliders for col1 = 1 to max_collider for col2 = col1+1 to max_collider @@ -103,11 +103,11 @@ clock tick get_collider_collider_collision() end end - + # Remove all new collisions, except for new collisions that have # the deepest penetration for a collider cull_collisions() - + # Merge collision indices down so that there aren't any empties merge_collisions_down() @@ -133,9 +133,9 @@ function destroy_colliders() for destroy.collider = max_collider to 1 by -1 destroy_collider() end - + /kill @PhysicsBlock - + max_collider = 0 end @@ -144,19 +144,19 @@ function destroy_collider() $(collider) = destroy.collider do define name collider = "collider_$(collider)" - + if max_collider == collider.id max_collider-- end - + as @PhysicsBlock if @s.collider_id == collider.id /kill @s end end - + /scoreboard players reset collider_$(collider) - + for vertex = 0 to 7 with $(vertex) = vertex @@ -164,7 +164,7 @@ function destroy_collider() /scoreboard players reset collider_$(collider)_v$(vertex) end end - + for axis = 0 to 2 with $(axis) = axis @@ -202,11 +202,11 @@ function add_collider() with $(collider) = id create_collider(new.x, new.y, new.z, CubeSize, CubeInvMass, CubeInvRotInt) - + as @PhysicsBlock[age == 1] @s.block_type = block_type end - + unless id <= max_collider max_collider = id end @@ -224,7 +224,7 @@ function get_unused_collider_id() end end end - + return return_id end @@ -234,7 +234,7 @@ function test_update_collision() $(collision) = collision do define name collision = "collision_$(collision)" - + old_id = collision.id old_type = collision.type old_pen = collision.pen @@ -245,7 +245,7 @@ function test_update_collision() old_ny = collision.ny old_nz = collision.nz update_collision() with macros - + same = True unless old_pen == collision.pen same = False @@ -268,7 +268,7 @@ function test_update_collision() unless old_nz == collision.nz same = False end - + unless same tell @a "Collision #(old_id) changed" if old_type == $CollisionCubePointWorldFace @@ -302,7 +302,7 @@ function clear_save_state() /scoreboard players reset save_state_collider_$(collider) end end - + for collision_iter = 1 to save_state.max_collision with $(collision) = collision_iter @@ -310,7 +310,7 @@ function clear_save_state() /scoreboard players reset save_state_collision_$(collision) end end - + /scoreboard players reset save_state end @@ -318,46 +318,46 @@ function save_state() clear_save_state() save_state.max_collider = max_collider - + for collider_iter = 1 to max_collider with $(collider) = collider_iter do define name collider = "collider_$(collider)" define name save_state = "save_state_collider_$(collider)" - + if collider.id save_state.id = collider.id - + save_state.x = collider.x save_state.y = collider.y save_state.z = collider.z - + save_state.velocity_x = collider.velocity_x save_state.velocity_y = collider.velocity_y save_state.velocity_z = collider.velocity_z - + save_state.rotation_x = collider.rotation_x save_state.rotation_y = collider.rotation_y save_state.rotation_z = collider.rotation_z - + save_state.size = collider.size - + save_state.inv_mass = collider.inv_mass save_state.inv_rot_int = collider.inv_rot_int - + save_state.w = collider.w save_state.i = collider.i save_state.j = collider.j save_state.k = collider.k - + save_state.recent_motion = collider.recent_motion save_state.recent_rotation = collider.recent_rotation save_state.sleeping = collider.sleeping end end end - + save_state.max_collision = max_collision for collision_iter = 1 to max_collision @@ -371,15 +371,15 @@ function save_state() save_state.id = collision.id save_state.active = collision.active save_state.pen = collision.pen - + save_state.x = collision.x save_state.y = collision.y save_state.z = collision.z - + save_state.nx = collision.nx save_state.ny = collision.ny save_state.nz = collision.nz - + save_state.type = collision.type save_state.collider1 = collision.collider1 save_state.collider2 = collision.collider2 @@ -412,41 +412,41 @@ function load_state() collision_frame = 0 max_collider = save_state.max_collider - + for collider_iter = 1 to save_state.max_collider with $(collider) = collider_iter do define name collider = "collider_$(collider)" define name save_state = "save_state_collider_$(collider)" - + if save_state.id create_collider(save_state.x, save_state.y, save_state.z, save_state.size, save_state.inv_mass, save_state.inv_rot_int) with macros - + collider.velocity_x = save_state.velocity_x collider.velocity_y = save_state.velocity_y collider.velocity_z = save_state.velocity_z - + collider.rotation_x = save_state.rotation_x collider.rotation_y = save_state.rotation_y collider.rotation_z = save_state.rotation_z - + collider.w = save_state.w collider.i = save_state.i collider.j = save_state.j collider.k = save_state.k - + collider_quaternion_to_transform() with macros - + collider.recent_motion = save_state.recent_motion collider.recent_rotation = save_state.recent_rotation collider.sleeping = save_state.sleeping - + collider_set_transform() with macros end end end - + max_collision = save_state.max_collision for collision_iter = 1 to save_state.max_collision @@ -460,15 +460,15 @@ function load_state() collision.id = save_state.id collision.active = save_state.active collision.pen = save_state.pen - + collision.x = save_state.x collision.y = save_state.y collision.z = save_state.z - + collision.nx = save_state.nx collision.ny = save_state.ny collision.nz = save_state.nz - + collision.type = save_state.type collision.collider1 = save_state.collider1 collision.collider2 = save_state.collider2 @@ -492,4 +492,4 @@ function load_state() end end end -end \ No newline at end of file +end diff --git a/Scripts/tetherblock.cbscript b/Scripts/tetherblock.cbscript index 28fac0d..3d36afc 100644 --- a/Scripts/tetherblock.cbscript +++ b/Scripts/tetherblock.cbscript @@ -17,7 +17,7 @@ end define @RopeSegment = @Entity[type=block_display,tag=RopeSegment] create {block_state: {Name: "minecraft:brown_concrete", count: 0b}, teleport_duration: 0, interpolation_duration: 0, transformation:{left_rotation: [0f, 0f, 0f, 1f], translation: [0f, 0f, 0f], right_rotation: [0f, 0f, 0f, 1f], scale:[0.05f, 0.05f, 0.05f]}, Tags:["RopeSegment"]} - + tele_dur: teleport_duration int 1 interp_dur = interpolation_duration int 1 end @@ -48,14 +48,14 @@ $CounterMax = $CounterXNegZPos reset /scoreboard objectives add absorbed minecraft.custom:minecraft.damage_dealt_absorbed - + /scoreboard objectives add normal_game trigger /scoreboard objectives add prev_game trigger /scoreboard objectives add next_game trigger /scoreboard objectives add restart_game trigger initialize_transforms() - + tell @a "{G[\[Normal Game\]](/trigger normal_game set 1) {C[\[Prev Game\]](/trigger prev_game set 1) [\[Next Game\]](/trigger next_game set 1) {Y[\[Restart Game\]](/trigger restart_game set 1)" end @@ -74,7 +74,7 @@ function clear_game() CubeInvRotInt = 200 GravityGun = False @Player.gravity_cube = None - + /bossbar remove score /bossbar add score ["Score"] /bossbar set score players @a @@ -106,11 +106,11 @@ end function start_normal_game() clear_game() - + gamemode = 1 - + /fill 0 56 0 0 67 0 minecraft:birch_fence - + PoleRadius = 125 PoleDiameter = PoleRadius * 2 PoleHeight = 12000 @@ -119,7 +119,7 @@ function start_normal_game() with $(block_name) = "target" add_tether_block(1000, 60000, 1000) - + /bossbar set score name "<-Counter Normal Clockwise->" finalize_game() @@ -127,11 +127,11 @@ end function start_multi_game() clear_game() - + gamemode = 5 /fill 0 56 0 0 67 0 minecraft:birch_fence - + PoleRadius = 125 PoleDiameter = PoleRadius * 2 PoleHeight = 12000 @@ -156,12 +156,12 @@ end function start_fat_game() clear_game() - + gamemode = 2 - + /fill 0 56 0 0 67 0 minecraft:birch_planks - + PoleRadius = 500 PoleDiameter = PoleRadius * 2 PoleHeight = 12000 @@ -178,11 +178,11 @@ end function start_obese_game() clear_game() - + gamemode = 3 - + /fill -1 56 -1 1 67 1 minecraft:birch_planks - + PoleRadius = 1500 PoleDiameter = PoleRadius * 2 PoleHeight = 12000 @@ -193,21 +193,21 @@ function start_obese_game() add_tether_block(2000, 60000, 0) /bossbar set score name "<-Counter Obese Clockwise->" - + finalize_game() end function start_cup_game() clear_game() - + gamemode = 4 PunchPower = 3000 - + /fill -4 68 -4 4 71 4 minecraft:black_stained_glass /fill -3 69 -3 3 71 3 minecraft:air /fill 0 56 0 0 75 0 minecraft:birch_fence - + PoleRadius = 125 PoleDiameter = PoleRadius * 2 PoleHeight = 12000 @@ -224,12 +224,12 @@ end function start_water_game() clear_game() - + gamemode = 6 /fill -9 56 -9 9 64 9 minecraft:water /fill 0 56 0 0 67 0 minecraft:birch_fence - + PoleRadius = 125 PoleDiameter = PoleRadius * 2 PoleHeight = 12000 @@ -240,17 +240,17 @@ function start_water_game() add_tether_block(1000, 60000, 1000) /bossbar set score name "<-Counter Water Clockwise->" - + finalize_game() end function start_gravity_game() clear_game() - + gamemode = 7 - + /fill 0 56 0 0 67 0 minecraft:birch_fence - + PoleRadius = 125 PoleDiameter = PoleRadius * 2 PoleHeight = 12000 @@ -261,13 +261,13 @@ function start_gravity_game() with $(block_name) = "target" add_tether_block(1000, 60000, 1000) - + CubeSize = $Precision CubeInvRotInt = 400 CubeInvMass = 200 /bossbar set score name "<-Counter Gravity Gun Clockwise->" - + finalize_game() end @@ -301,7 +301,7 @@ end clock tick /kill @Position create @Position - + as @Player at @s ~ ~ ~ if @s.id id = @s.id @@ -310,7 +310,7 @@ clock tick @s.id = player_id id = player_id end - + as @PlayerInteraction if @s.id == id /tp @s ~ ~ ~ else @@ -318,22 +318,22 @@ clock tick @s.id = id end end - + if @s.normal_game start_normal_game() @s.normal_game = False end - + if @s.next_game gamemode++ if gamemode > $MaxGame gamemode = 1 end start_selected_game() - + @s.next_game = False end - + if @s.prev_game gamemode-- if gamemode < 1 @@ -348,18 +348,18 @@ clock tick unless gamemode gamemode = 1 end - + start_selected_game() @s.restart_game = False end - + /scoreboard players enable @s normal_game /scoreboard players enable @s prev_game /scoreboard players enable @s next_game /scoreboard players enable @s restart_game end - + as @PlayerInteraction id = @s.id as @Player if @s.id == id @@ -367,7 +367,7 @@ clock tick /kill @s end end - + as @PlayerInteraction on attacker at @s eyes @@ -375,13 +375,13 @@ clock tick world_eye_x = @Position.x world_eye_y = @Position.y world_eye_z = @Position.z - + /tp @Position ^ ^ ^1 world_eye_dx = @Position.x - world_eye_x world_eye_dy = @Position.y - world_eye_y world_eye_dz = @Position.z - world_eye_z end - + if GravityGun if @s.gravity_cube gravity_cube = @s.gravity_cube @@ -393,21 +393,21 @@ clock tick collider.velocity_y = world_eye_dy collider.velocity_z = world_eye_dz collider_wake_up() with macros - + as @GravityBlock if @s.collider_id == gravity_cube @s.free = True end - + @s.gravity_cube = None end else get_targeted_block() - + if t < $GravityRange x = x / $Precision * $Precision + $Half y = y / $Precision * $Precision + $Half z = z / $Precision * $Precision + $Half - + got_block = False at @Position @@ -431,7 +431,7 @@ clock tick end end end - else + else min_col_t = $Billion # Find the nearest collider in the direction of the cursor ray @@ -452,10 +452,10 @@ clock tick end end end - + if min_col_t <= $AttackRange # There was a ray intersection - + @s.attacking = min_col @s.attack_x = min_x @s.attack_y = min_y @@ -463,14 +463,14 @@ clock tick @s.attack_dx = world_eye_dx @s.attack_dy = world_eye_dy @s.attack_dz = world_eye_dz - + end end end /data remove entity @s attack /data remove entity @s interaction end - + as @Player if @s.attacking with @@ -482,36 +482,36 @@ clock tick /particle minecraft:explosion ~ ~ ~ 0 0 0 0 1 force /playsound minecraft:entity.generic.small_fall block @a ~ ~ ~ 1 0 end - + @s.attacking = 0 end - + if @s.gravity_cube at @s eyes /tp @Position ^ ^ ^ world_eye_x = @Position.x world_eye_y = @Position.y world_eye_z = @Position.z - + /tp @Position ^ ^ ^1 world_eye_dx = @Position.x - world_eye_x world_eye_dy = @Position.y - world_eye_y world_eye_dz = @Position.z - world_eye_z - end - + end + hover_x = world_eye_x + world_eye_dx * 3 hover_y = world_eye_y + world_eye_dy * 3 hover_z = world_eye_z + world_eye_dz * 3 - + with $(collider) = @s.gravity_cube do define name collider = "collider_$(collider)" - + collider.velocity_x /= 2 collider.velocity_y /= 2 collider.velocity_z /= 2 - + collider.velocity_x += (hover_x - collider.x) / 2 collider.velocity_y += (hover_y - collider.y) / 2 collider.velocity_z += (hover_z - collider.z) / 2 @@ -520,7 +520,7 @@ clock tick end end end - + as @GravityBlock if @s.free at @s unless block ~ ~-0.6 ~ passthrough with $(collider) = @s.collider_id @@ -542,39 +542,39 @@ clock tick local_att_x = 0 local_att_y = CubeSize / 2 local_att_z = 0 - + with $(collider) = id collider_apply_spring_cable(spring_x, spring_y, spring_z, spring_neutral, spring_constant, local_att_x, local_att_y, local_att_z) end end - + colliders_physics_tick() colliders_get_new_collisions() colliders_resolve_collisions() colliders_finalize_tick() - + total_score = 0 score_count = 0 - + as @TetherBlock at @s ~ ~-1.5 ~ id = @s.collider_id segments = @s.segments free_length = @s.free_length - + as @RopeSegment if @s.id == id and @s.segment == segments # Handle the last segment - + with $(collider) = id collider_local_to_world(0, 750, 0, True) - + dx = world_x - @s.origin_x dy = world_y - @s.origin_y dz = world_z - @s.origin_z new_wrap_state = None unwrap = False - + switch @s.wrap_state case $Unwrapped if dx < 0 @@ -594,7 +594,7 @@ clock tick case $ClockXPosZPos if dz < 0 # Unwrap - unwrap = True + unwrap = True else if dx < 0 # Wrap wrapped_portion = PoleDiameter * 1000 / dz @@ -639,11 +639,11 @@ clock tick new_wrap_state = $ClockXPosZPos end end - + case $CounterXPosZPos if dx < 0 # Unwrap - unwrap = True + unwrap = True else if dz < 0 # Wrap wrapped_portion = PoleDiameter * 1000 / dx @@ -689,21 +689,21 @@ clock tick end end end - + if new_wrap_state wrapped_dy = dy * wrapped_portion / 1000 wrap_y = @s.origin_y + wrapped_dy # Compute the stretched length of the unbound tether len = sqrt(dx*dx + dy*dy + dz*dz) - + # Compute the amount of tether that's bound stretched_length = wrapped_portion * len / 1000 bound_length = wrapped_portion * free_length / 1000 free_length -= bound_length @s.bound_length = bound_length - + if Debug tell @a "Wrapping..." tell @a "new_wrap_state: (new_wrap_state)" @@ -719,10 +719,10 @@ clock tick /execute store result storage $namespace:global scale[2] float 0.001 run scoreboard players get Global stretched_length /data modify entity @s transformation.scale set from storage $namespace:global scale /data modify entity @s start_interpolation set value 0b - + @s.interp_dur = 0 @s.tele_dur = 0 - + bdx = wrap_x - @s.origin_x bdy = wrap_y - @s.origin_y bdz = wrap_z - @s.origin_z @@ -730,7 +730,7 @@ clock tick ix = bdx * 25 / bl iy = bdy * 25 / bl iz = bdz * 25 / bl - + @Position. = <@s.origin_x-ix, @s.origin_y-iy, @s.origin_z-iz> at @Position @Position. = @@ -738,7 +738,7 @@ clock tick /tp @s ~ ~ ~ ~ ~ end end - + at @Position as create @RopeSegment segments++ @@ -751,7 +751,7 @@ clock tick end end end - + if unwrap /kill @s segments-- @@ -760,10 +760,10 @@ clock tick end end end - + @s.segments = segments @s.free_length = free_length - + as @RopeSegment if @s.id == id and @s.segment == segments if not new_wrap_state dx = world_x - @s.origin_x @@ -771,24 +771,24 @@ clock tick dz = world_z - @s.origin_z len = sqrt(dx*dx + dy*dy + dz*dz) - + /data modify storage $namespace:global scale set value [0.05f, 0.05f, 0.05f] /execute store result storage $namespace:global scale[2] float 0.001 run scoreboard players get Global len /data modify entity @s transformation.scale set from storage $namespace:global scale /data modify entity @s start_interpolation set value 0b - + @s.tele_dur = 1 @s.interp_dur = 1 end - + @Position. = <@s.origin_x, @s.origin_y, @s.origin_z> - at @Position + at @Position @Position. = facing @Position /tp @s ~ ~ ~ ~ ~ end end - + if @s.wrap_state >= $ClockMin and @s.wrap_state <= $ClockMax total_score += 110 - free_length * 60 / TetherLength else if @s.wrap_state >= $CounterMin and @s.wrap_state <= $CounterMax @@ -806,11 +806,11 @@ clock tick @s.origin_z = TetherZ @s.wrap_state = $Unwrapped end - + @s.segments = 1 end end - + total_score /= score_count /execute store result bossbar score value run scoreboard players get Global total_score end @@ -819,7 +819,7 @@ function get_targeted_block() dx = world_eye_dx dy = world_eye_dy dz = world_eye_dz - + if dx == 0 then dx = 1 if dy == 0 then dy = 1 if dz == 0 then dz = 1 @@ -827,45 +827,45 @@ function get_targeted_block() x = world_eye_x y = world_eye_y z = world_eye_z - + next_x = x / $Precision * $Precision if dx > 0 next_x += $Precision else - next_x -= 1 + next_x -= 1 end - + next_y = y / $Precision * $Precision if dy > 0 next_y += $Precision else next_y -= 1 end - + next_z = z / $Precision * $Precision if dz > 0 next_z += $Precision else next_z -= 1 end - + t = 0 next_t_x = (next_x - world_eye_x) * $Precision / dx next_t_y = (next_y - world_eye_y) * $Precision / dy next_t_z = (next_z - world_eye_z) * $Precision / dz - + @Position. = - + for i = 1 to 100 at @Position if block ~ ~ ~ passthrough if next_t_x < next_t_y and next_t_x < next_t_z t = next_t_x x = next_x - y = world_eye_y + world_eye_dy * t / $Precision - z = world_eye_z + world_eye_dz * t / $Precision - + y = world_eye_y + world_eye_dy * t / $Precision + z = world_eye_z + world_eye_dz * t / $Precision + if dx > 0 next_x += $Precision else @@ -876,10 +876,10 @@ function get_targeted_block() else if next_t_y < next_t_z t = next_t_y - x = world_eye_x + world_eye_dx * t / $Precision + x = world_eye_x + world_eye_dx * t / $Precision y = next_y - z = world_eye_z + world_eye_dz * t / $Precision - + z = world_eye_z + world_eye_dz * t / $Precision + if dy > 0 next_y += $Precision else @@ -890,19 +890,19 @@ function get_targeted_block() else t = next_t_z - x = world_eye_x + world_eye_dx * t / $Precision - y = world_eye_y + world_eye_dy * t / $Precision + x = world_eye_x + world_eye_dx * t / $Precision + y = world_eye_y + world_eye_dy * t / $Precision z = next_z - + if dz > 0 next_z += $Precision else next_z -= $Precision end - + next_t_z = (next_z - world_eye_z) * $Precision / dz end - + @Position. = else # Non-passthrough block diff --git a/Scripts/tiny_block2.cblib b/Scripts/tiny_block2.cblib index dcbc4d6..e6eff45 100644 --- a/Scripts/tiny_block2.cblib +++ b/Scripts/tiny_block2.cblib @@ -2,22 +2,22 @@ import common define @TinyBlock: @Entity[type=armor_stand,tag=TinyBlock] create {Tags:["TinyBlock"], Pose:{RightArm:[-15f, -90f,0f]}, ShowArms:1b, Marker:1b, Invisible:1b, NoGravity:1b, Invulnerable:1b, Silent:1b} - + pose_rot_x: Pose.RightArm[0] float pose_rot_y: Pose.RightArm[1] float pose_rot_z: Pose.RightArm[2] float - + function update_tiny() #prot_x = @s.rot_x + 165000 #prot_y = @s.rot_y + 45000 - + prot_x = -@s.rot_x - 15000 prot_y = @s.rot_y + 225000 - + @s.pose_rot_x = prot_x #@s.pose_rot_y = prot_y @s.ry = prot_y - + unless @Position do create @Position /tp @Position ~ ~ ~ 0 0 @Position.ry = prot_y @@ -28,7 +28,7 @@ define @TinyBlock: @Entity[type=armor_stand,tag=TinyBlock] at @Position /tp @s ~ ~ ~ end - + /data merge entity @s {Fire:32767s} - end -end \ No newline at end of file + end +end diff --git a/Scripts/tinyblock.cblib b/Scripts/tinyblock.cblib index d72724f..b94d2ce 100644 --- a/Scripts/tinyblock.cblib +++ b/Scripts/tinyblock.cblib @@ -2,13 +2,13 @@ import common define @TinyBlock: @Entity[type=armor_stand,tag=TinyBlock] create {Tags:["TinyBlock"], Pose:{RightArm:[-15f,-45f,0f]}, ShowArms:1b, Marker:1b, Invisible:1b, NoGravity:1b, Invulnerable:1b, Silent:1b} - + function update_tiny() /data merge entity @s {Fire:32767s} - + /tp @s ~ ~ ~ ~ 0 at @s ^0.0625 ^-0.5 ^-0.375 /tp @s ~ ~ ~ ~ 0 end - end -end \ No newline at end of file + end +end diff --git a/Scripts/transform_demo.cbscript b/Scripts/transform_demo.cbscript index b7951d5..1d1280d 100644 --- a/Scripts/transform_demo.cbscript +++ b/Scripts/transform_demo.cbscript @@ -20,24 +20,24 @@ $Billion = 1000000000 reset anim = 0 rot_anim = 0 - + unless @Position do create @Position - + /kill @e[type=block_display] - + for col = 0 to 3 for row = 0 to 2 @Position. = at @Position /summon minecraft:block_display ~ ~ ~ {block_state:{Name:"minecraft:command_block",Count:0b}, interpolation_duration: 0, teleport_duration: 1, Tags:["transform_demo"]} end - + @Demo.age++ as @Demo[age == 1] @s.row = row @s.col = col @s.idx = col + row * 4 - + if col == row @s.base = 1000 else @@ -46,8 +46,8 @@ reset end end end - - /summon minecraft:block_display -10 57 0 {block_state:{Name:"minecraft:command_block",Count:0b}, interpolation_duration: 0, teleport_duration: 1, Tags:["rot_trans"]} + + /summon minecraft:block_display -10 57 0 {block_state:{Name:"minecraft:command_block",Count:0b}, interpolation_duration: 0, teleport_duration: 1, Tags:["rot_trans"]} end clock tick @@ -70,8 +70,8 @@ clock tick # Restore frame = anim - 80 val = -3000 + frame * 150 + @s.base - end - + end + if val < $Billion /data modify storage $namespace:global transformation set value [1f,0f,0f,0f,0f,1f,0f,0f,0f,0f,1f,0f,0f,0f,0f,1f] /execute store result storage $namespace:global transformation[$(idx)] float 0.001 run scoreboard players get Global val @@ -84,14 +84,14 @@ clock tick if anim >= 110 anim = 0 end - + as @rot_trans if rot_anim <= 0 /data modify storage $namespace:global rot_trans set value [1f,0f,0f,0f,0f,1f,0f,0f,0f,0f,1f,0f,0f,0f,0f,1f] /data modify entity @s transformation set from storage $namespace:global rot_trans /data modify entity @s start_interpolation set value 0b end - + rot_anim++ idx = rot_anim / 15 @@ -103,10 +103,10 @@ clock tick if idx == $idx $starting_val = $starting_vals[$idx] $val = $vals[$idx] - + delta = $val - $starting_val val = $starting_val + delta * frame / 10 - + with $(idx) = idx do @@ -117,10 +117,10 @@ clock tick end end end - + if rot_anim >= 15 * 12 + 55 rot_anim = -20 end - + end -end \ No newline at end of file +end diff --git a/Scripts/transforms.cblib b/Scripts/transforms.cblib index d56b418..d826fae 100644 --- a/Scripts/transforms.cblib +++ b/Scripts/transforms.cblib @@ -32,7 +32,7 @@ end function initialize_transforms() initialize_vertex_adjacency() - + Gravity = 49 Friction = 800 Restitution = 600 @@ -110,17 +110,17 @@ function get_closest_points_on_edges(o1x, o1y, o1z, d1x, d1y, d1z, o2x, o2y, o2z # Get the square magnitude of the normal, scaled up by the Precision nmagsq = (nx*nx + ny*ny + nz*nz) / $Precision - + # Difference of origins odx = o2x - o1x ody = o2y - o1y odz = o2z - o1z - + # Get a vector perpendicular to the normal and the second ray perpx = (d2y * nz - d2z * ny) / $Precision perpy = (d2z * nx - d2x * nz) / $Precision perpz = (d2x * ny - d2y * nx) / $Precision - + # Get the projected distance along the first ray t1 = (perpx * odx + perpy * ody + perpz * odz) / nmagsq @@ -133,10 +133,10 @@ function get_closest_points_on_edges(o1x, o1y, o1z, d1x, d1y, d1z, o2x, o2y, o2z perpx = (d1y * nz - d1z * ny) / $Precision perpy = (d1z * nx - d1x * nz) / $Precision perpz = (d1x * ny - d1y * nx) / $Precision - + # Get the projected distance along the second ray t2 = (perpx * odx + perpy * ody + perpz * odz) / nmagsq - + # Get the point on the second ray p2x = o2x + t2 * d2x / $Precision p2y = o2y + t2 * d2y / $Precision @@ -150,13 +150,13 @@ end function create_collider(x, y, z, size, inv_mass, inv_rot_int, shape) define name collider = "collider_$(collider)" - + unless shape shape = $Cube end - + /scoreboard players set collider_$(collider) id $(collider) - + collider.x = x collider.y = y collider.z = z @@ -164,17 +164,18 @@ function create_collider(x, y, z, size, inv_mass, inv_rot_int, shape) collider.halfsize = size / 2 collider.inv_mass = inv_mass collider.inv_rot_int = inv_rot_int + collider.shape = shape collider.w = $Precision collider.i = 0 collider.j = 0 collider.k = 0 - + collider_clear_velocity() with macros collider_clear_rotation() with macros collider_wake_up() with macros - + collider_quaternion_to_transform() with macros /$summon minecraft:item_display ~ ~ ~ {item:{id:"minecraft:$(block_name)",Count:1b}, item_display:"Fixed", interpolation_duration: 1, teleport_duration: 1, Tags:["physics_block"], view_range:10f} @@ -215,7 +216,7 @@ end function collider_sleep() define name collider = "collider_$(collider)" - + collider_clear_velocity() with macros collider_clear_rotation() with macros collider.sleeping = True @@ -223,7 +224,7 @@ end function collider_check_sleep() define name collider = "collider_$(collider)" - + if collider.recent_motion < 2500 and collider.recent_rotation < 2500 collider_sleep() with macros end @@ -231,26 +232,26 @@ end function collider_integrate() define name collider = "collider_$(collider)" - + collider_integrate_velocity() with macros collider_integrate_rotation() with macros end function collider_integrate_velocity() define name collider = "collider_$(collider)" - + collider.velocity_x = (collider.velocity_x * 995 + $Half) / $Precision collider.velocity_y = (collider.velocity_y * 995 + $Half) / $Precision collider.velocity_z = (collider.velocity_z * 995 + $Half) / $Precision - + collider.x += collider.velocity_x collider.y += collider.velocity_y collider.z += collider.velocity_z - + if DebugCollisions tell @a "#(collider.id) velocity update (collider.velocity_x), (collider.velocity_y), (collider.velocity_z)" end - + motion = (collider.velocity_x * collider.velocity_x + collider.velocity_y * collider.velocity_y + collider.velocity_z * collider.velocity_z) / 10 collider.recent_motion *= 9 collider.recent_motion /= 10 @@ -259,25 +260,25 @@ end function collider_set_orientation(w, i, j, k) define name collider = "collider_$(collider)" - + collider.w = w collider.i = i collider.j = j collider.k = k - + collider_normalize_quaternion() with macros collider_quaternion_to_transform() with macros end function collider_integrate_rotation() define name collider = "collider_$(collider)" - + collider.rotation_x = (collider.rotation_x * 995 + $Half) / $Precision collider.rotation_y = (collider.rotation_y * 995 + $Half) / $Precision collider.rotation_z = (collider.rotation_z * 995 + $Half) / $Precision - + quaternion_multiply(0, collider.rotation_x, collider.rotation_y, collider.rotation_z, collider.w, collider.i, collider.j, collider.k) - + collider.w += new_w / 2 collider.i += new_i / 2 collider.j += new_j / 2 @@ -293,7 +294,7 @@ end function collider_set_transform() define name collider = "collider_$(collider)" - + size = collider.size render_scale = collider.render_scale render_dy = collider.render_dy @@ -311,7 +312,7 @@ function collider_set_transform() dx = 0 dy = 0 dz = 0 - + if render_scale d00 = d00 * render_scale / $Precision d01 = d01 * render_scale / $Precision @@ -323,20 +324,20 @@ function collider_set_transform() d21 = d21 * render_scale / $Precision d22 = d22 * render_scale / $Precision end - + if render_dy dx = d01 * render_dy / $Precision dy = d11 * render_dy / $Precision dz = d21 * render_dy / $Precision end - + for $pair in [[0,"d00"], [1,"d01"], [2,"d02"], [3,"dx"], [4,"d10"], [5,"d11"], [6,"d12"], [7,"dy"], [8,"d20"], [9,"d21"], [10,"d22"], [11,"dz"]] $idx = $pair[0] $var = $pair[1] $downscale = 1.0 / $Precision /execute store result storage $namespace:global transformation[$idx] float $downscale run scoreboard players get Global $var end - + as @PhysicsBlock if @s.collider_id == collider.id @s.x = collider.x @@ -352,7 +353,7 @@ function collider_normalize_quaternion() define name collider = "collider_$(collider)" mag = sqrt(collider.w*collider.w + collider.i*collider.i + collider.j*collider.j + collider.k*collider.k) - + collider.w *= $Precision collider.w += $Half collider.w /= mag @@ -371,7 +372,7 @@ function collider_multiply_quaternion_right(w, i, j, k) define name collider = "collider_$(collider)" quaternion_multiply(collider.w, collider.i, collider.j, collider.k, w, i, j, k) - + collider.w = new_w collider.i = new_i collider.j = new_j @@ -415,7 +416,7 @@ function collider_local_to_world(x, y, z, translation) world_x = (collider.t00 * x + collider.t01 * y + collider.t02 * z) / $Precision world_y = (collider.t10 * x + collider.t11 * y + collider.t12 * z) / $Precision world_z = (collider.t20 * x + collider.t21 * y + collider.t22 * z) / $Precision - + if translation world_x += collider.x world_y += collider.y @@ -431,7 +432,7 @@ function collider_world_to_local(x, y, z, translation) y -= collider.y z -= collider.z end - + local_x = (collider.t00 * x + collider.t10 * y + collider.t20 * z) / $Precision local_y = (collider.t01 * x + collider.t11 * y + collider.t21 * z) / $Precision local_z = (collider.t02 * x + collider.t12 * y + collider.t22 * z) / $Precision @@ -439,7 +440,7 @@ end function collider_apply_impulse(x, y, z, ix, iy, iz) define name collider = "collider_$(collider)" - + collider.velocity_x += (ix * collider.inv_mass + $Half) / $Precision collider.velocity_y += (iy * collider.inv_mass + $Half) / $Precision collider.velocity_z += (iz * collider.inv_mass + $Half) / $Precision @@ -447,15 +448,15 @@ function collider_apply_impulse(x, y, z, ix, iy, iz) dx = x - collider.x dy = y - collider.y dz = z - collider.z - + axis_x = (dy * iz - dz * iy + $Half) / $Precision axis_y = (dz * ix - dx * iz + $Half) / $Precision axis_z = (dx * iy - dy * ix + $Half) / $Precision - + collider.rotation_x += (axis_x * collider.inv_rot_int) / $Precision collider.rotation_y += (axis_y * collider.inv_rot_int) / $Precision collider.rotation_z += (axis_z * collider.inv_rot_int) / $Precision - + if collider.sleeping collider_wake_up() with macros end @@ -465,26 +466,26 @@ function collider_apply_spring_cable(spring_x, spring_y, spring_z, spring_neutra define name collider = "collider_$(collider)" collider_local_to_world(local_att_x, local_att_y, local_att_z, True) with macros - + spring_dx = world_x - spring_x spring_dy = world_y - spring_y spring_dz = world_z - spring_z - + # Current length of the spring spring_mag = sqrt(spring_dx*spring_dx + spring_dy*spring_dy + spring_dz*spring_dz) - + # Spring displacement from neutral spring_disp = spring_mag - spring_neutral - + spring_dir_x = spring_dx * $Precision / spring_mag spring_dir_y = spring_dy * $Precision / spring_mag spring_dir_z = spring_dz * $Precision / spring_mag - + if spring_mag > spring_neutral force_x = -spring_dir_x * spring_disp / $Precision * spring_constant / $Precision force_y = -spring_dir_y * spring_disp / $Precision * spring_constant / $Precision force_z = -spring_dir_z * spring_disp / $Precision * spring_constant / $Precision - + collider_apply_impulse(world_x, world_y, world_z, force_x, force_y, force_z) with macros end end @@ -496,12 +497,12 @@ function collider_ray_intersection(x, y, z, dx, dy, dz) local_origin_x = local_x local_origin_y = local_y local_origin_z = local_z - + collider_world_to_local(dx, dy, dz, False) with macros local_dx = local_x local_dy = local_y local_dz = local_z - + if local_dx == 0 local_dx = 1 end @@ -511,9 +512,9 @@ function collider_ray_intersection(x, y, z, dx, dy, dz) if local_dz == 0 local_dz = 1 end - + halfsize = collider.size / 2 - + # Calculate the times of entry/exit along each axis txn = (-halfsize - local_origin_x) * $Precision / local_dx txp = (halfsize - local_origin_x) * $Precision / local_dx @@ -521,7 +522,7 @@ function collider_ray_intersection(x, y, z, dx, dy, dz) typ = (halfsize - local_origin_y) * $Precision / local_dy tzn = (-halfsize - local_origin_z) * $Precision / local_dz tzp = (halfsize - local_origin_z) * $Precision / local_dz - + # Figure out the minimum and maximum time along the x axis if txn > txp min_tx = txp @@ -532,7 +533,7 @@ function collider_ray_intersection(x, y, z, dx, dy, dz) max_tx = txp x_normal = -$Precision end - + # Figure out the minimum and maximum time along the y axis if tyn > typ min_ty = typ @@ -543,7 +544,7 @@ function collider_ray_intersection(x, y, z, dx, dy, dz) max_ty = typ y_normal = -$Precision end - + # Figure out the minimum and maximum time along the z axis if tzn > tzp min_tz = tzp @@ -554,7 +555,7 @@ function collider_ray_intersection(x, y, z, dx, dy, dz) max_tz = tzp z_normal = -$Precision end - + # Figure out which axis we enter the cube last. Once the ray # has entered the cube along all 3 axes, it can collide. if min_tx > min_ty and min_tx > min_tz @@ -583,32 +584,32 @@ function collider_ray_intersection(x, y, z, dx, dy, dz) else max_t = max_tz end - + # If the ray entered the cube along all three axes before it # exited along any axis, and it exited in front of us and not # behind us, then the ray intersections the cube, first hitting # it at t=min_t. if min_t < max_t and max_t > 0 t = min_t - + if t < 0 t = 0 end - + local_cx = local_origin_x + t * local_dx / $Precision local_cy = local_origin_y + t * local_dy / $Precision local_cz = local_origin_z + t * local_dz / $Precision - + collider_local_to_world(local_cx, local_cy, local_cz, True) with macros collision_x = world_x collision_y = world_y collision_z = world_z - + collider_local_to_world(local_cnx, local_cny, local_cnz, False) with macros collision_nx = world_x collision_ny = world_y collision_nz = world_z - + return True else return False @@ -653,7 +654,7 @@ function collider_calculate_vertex_world_positions() define name collider = "collider_$(collider)" shape = collider.shape - + if shape == $Sphere sphere_calculate_bounds() with macros else @@ -668,7 +669,7 @@ function sphere_calculate_bounds() y = collider.y z = collider.z halfsize = collider.halfsize - + collider.min_x = collider.x - halfsize collider.max_x = collider.x + halfsize collider.min_y = collider.y - halfsize @@ -679,9 +680,9 @@ end function cube_calculate_vertex_world_positions() define name collider = "collider_$(collider)" - + halfsize = collider.size / 2 - + # Initialized AABB collider.min_x = collider.x collider.min_y = collider.y @@ -699,39 +700,39 @@ function cube_calculate_vertex_world_positions() define name v5 = "collider_$(collider)_v5" define name v6 = "collider_$(collider)_v6" define name v7 = "collider_$(collider)_v7" - + v0.x = collider.x v0.y = collider.y v0.z = collider.z - + v1.x = collider.x v1.y = collider.y v1.z = collider.z - + v2.x = collider.x v2.y = collider.y v2.z = collider.z - + v3.x = collider.x v3.y = collider.y v3.z = collider.z - + v4.x = collider.x v4.y = collider.y v4.z = collider.z - + v5.x = collider.x v5.y = collider.y v5.z = collider.z - + v6.x = collider.x v6.y = collider.y v6.z = collider.z - + v7.x = collider.x v7.y = collider.y v7.z = collider.z - + collider_local_to_world($Precision, 0, 0, False) with macros define name axis = "collider_$(collider)_a0" @@ -739,26 +740,26 @@ function cube_calculate_vertex_world_positions() axis.x = world_x axis.y = world_y axis.z = world_z - + world_x *= collider.halfsize world_x /= $Precision world_y *= collider.halfsize world_y /= $Precision world_z *= collider.halfsize world_z /= $Precision - + v0.x += world_x v0.y += world_y v0.z += world_z - + v1.x -= world_x v1.y -= world_y v1.z -= world_z - + v2.x += world_x v2.y += world_y v2.z += world_z - + v3.x -= world_x v3.y -= world_y v3.z -= world_z @@ -766,45 +767,45 @@ function cube_calculate_vertex_world_positions() v4.x += world_x v4.y += world_y v4.z += world_z - + v5.x -= world_x v5.y -= world_y v5.z -= world_z - + v6.x += world_x v6.y += world_y v6.z += world_z - + v7.x -= world_x v7.y -= world_y v7.z -= world_z - + collider_local_to_world(0, $Precision, 0, False) with macros define name axis = "collider_$(collider)_a1" axis.x = world_x axis.y = world_y axis.z = world_z - + world_x *= collider.halfsize world_x /= $Precision world_y *= collider.halfsize world_y /= $Precision world_z *= collider.halfsize world_z /= $Precision - + v0.x += world_x v0.y += world_y v0.z += world_z - + v1.x -= world_x v1.y -= world_y v1.z -= world_z - + v2.x -= world_x v2.y -= world_y v2.z -= world_z - + v3.x += world_x v3.y += world_y v3.z += world_z @@ -812,45 +813,45 @@ function cube_calculate_vertex_world_positions() v4.x += world_x v4.y += world_y v4.z += world_z - + v5.x -= world_x v5.y -= world_y v5.z -= world_z - + v6.x -= world_x v6.y -= world_y v6.z -= world_z - + v7.x += world_x v7.y += world_y v7.z += world_z - + collider_local_to_world(0, 0, $Precision, False) with macros define name axis = "collider_$(collider)_a2" axis.x = world_x axis.y = world_y axis.z = world_z - + world_x *= collider.halfsize world_x /= $Precision world_y *= collider.halfsize world_y /= $Precision world_z *= collider.halfsize world_z /= $Precision - + v0.x += world_x v0.y += world_y v0.z += world_z - + v1.x -= world_x v1.y -= world_y v1.z -= world_z - + v2.x += world_x v2.y += world_y v2.z += world_z - + v3.x -= world_x v3.y -= world_y v3.z -= world_z @@ -858,19 +859,19 @@ function cube_calculate_vertex_world_positions() v4.x -= world_x v4.y -= world_y v4.z -= world_z - + v5.x += world_x v5.y += world_y v5.z += world_z - + v6.x -= world_x v6.y -= world_y v6.z -= world_z - + v7.x += world_x v7.y += world_y v7.z += world_z - + for vertex = 0 to 7 with $(vertex) = vertex @@ -890,7 +891,7 @@ function cube_calculate_vertex_world_positions() end if vertex.y > collider.max_y collider.max_y = vertex.y - collider.max_y_vertex = vertex + collider.max_y_vertex = vertex end if vertex.z < collider.min_z collider.min_z = vertex.z @@ -1109,14 +1110,14 @@ function get_cube_world_collisions() define name collider_a0 = "collider_$(collider)_a0" define name collider_a1 = "collider_$(collider)_a1" define name collider_a2 = "collider_$(collider)_a2" - + # Initialize block axes - + # 1,0,0 separating_axis_3.x = $Precision separating_axis_3.y = 0 separating_axis_3.z = 0 - + hs_x = collider_a0.x if hs_x < 0 hs_x *= -1 @@ -1129,14 +1130,14 @@ function get_cube_world_collisions() if hs_z < 0 hs_z *= -1 end - + separating_axis_3.halfsize = (hs_x + hs_y + hs_z) * collider.halfsize / $Precision + $Half # 0,1,0 separating_axis_4.x = 0 separating_axis_4.y = $Precision separating_axis_4.z = 0 - + hs_x = collider_a0.y if hs_x < 0 hs_x *= -1 @@ -1149,14 +1150,14 @@ function get_cube_world_collisions() if hs_z < 0 hs_z *= -1 end - + separating_axis_4.halfsize = (hs_x + hs_y + hs_z) * collider.halfsize / $Precision + $Half - + # 0,0,1 separating_axis_5.x = 0 separating_axis_5.y = 0 separating_axis_5.z = $Precision - + hs_x = collider_a0.z if hs_x < 0 hs_x *= -1 @@ -1169,23 +1170,23 @@ function get_cube_world_collisions() if hs_z < 0 hs_z *= -1 end - + separating_axis_5.halfsize = (hs_x + hs_y + hs_z) * collider.halfsize / $Precision + $Half - + # Initialize the cube face and edge-edge separating axes edge_axis = 6 - + for axis = 0 to 2 with $(axis) = axis do define name collider_axis = "collider_$(collider)_a$(axis)" define name separating_axis = "separating_axis_$(axis)" - + separating_axis.x = collider_axis.x separating_axis.y = collider_axis.y separating_axis.z = collider_axis.z - + hs_x = separating_axis.x if hs_x < 0 hs_x *= -1 @@ -1198,9 +1199,9 @@ function get_cube_world_collisions() if hs_z < 0 hs_z *= -1 end - + separating_axis.halfsize = collider.halfsize + (hs_x + hs_y + hs_z) / 2 - + with $(edge_0) = edge_axis $(edge_1) = edge_axis+1 @@ -1209,8 +1210,8 @@ function get_cube_world_collisions() define name edge0 = "separating_axis_$(edge_0)" define name edge1 = "separating_axis_$(edge_1)" define name edge2 = "separating_axis_$(edge_2)" - - + + # Cross with 1,0,0 mag = sqrt(collider_axis.y*collider_axis.y + collider_axis.z*collider_axis.z) edge0.x = 0 @@ -1228,26 +1229,26 @@ function get_cube_world_collisions() edge2.x = collider_axis.y * $Precision / mag edge2.y = -collider_axis.x * $Precision / mag edge2.z = 0 - + for edge_iter = 0 to 2 with $(edge_axis) = edge_axis do define name edge = "separating_axis_$(edge_axis)" - + edge.halfsize = 0 - + for cube_axis = 0 to 2 with $(cube_axis) = cube_axis do define name cube_axis = "collider_$(collider)_a$(cube_axis)" # Cube Halfsize - unless axis == cube_axis + unless axis == cube_axis cube_hs = cube_axis.x * edge.x cube_hs += cube_axis.y * edge.y cube_hs += cube_axis.z * edge.z - + cube_hs /= $Precision if cube_hs < 0 @@ -1257,10 +1258,10 @@ function get_cube_world_collisions() end end end - + edge.halfsize *= collider.halfsize edge.halfsize /= $Precision - + hs_x = edge.x if hs_x < 0 hs_x *= -1 @@ -1276,7 +1277,7 @@ function get_cube_world_collisions() edge.halfsize += (hs_x + hs_y + hs_z) / 2 end - + edge_axis++ end end @@ -1289,51 +1290,51 @@ function get_cube_world_collisions() block_end_x = ((collider.max_x - collider.max_pen) / $Precision + 1) * $Precision block_end_y = ((collider.max_y - collider.max_pen) / $Precision + 1) * $Precision block_end_z = ((collider.max_z - collider.max_pen) / $Precision + 1) * $Precision - + for block_x = block_start_x to block_end_x by $Precision test_x = block_x / $Precision center_to_center.x = block_x - collider.x - + for block_y = block_start_y to block_end_y by $Precision test_y = block_y / $Precision center_to_center.y = block_y - collider.y - + for block_z = block_start_z to block_end_z by $Precision test_z = block_z / $Precision - + with $(x) = test_x $(y) = test_y $(z) = test_z is_air() - + unless air center_to_center.z = block_z - collider.z continue = True min_pen = $Billion - + for axis = 0 to 14 if continue with $(axis) = axis do define name separating_axis = "separating_axis_$(axis)" - + unless separating_axis.halfsize == 0 pen = center_to_center.x * separating_axis.x pen += center_to_center.y * separating_axis.y pen += center_to_center.z * separating_axis.z pen /= $Precision axis_sign = 1 - + if pen > 0 pen *= -1 axis_sign = -1 end - + pen += separating_axis.halfsize - + if pen <= collider.max_pen if DebugCollisions tell @a "(test_x),(test_y),(test_z): Penetration (pen) less than (collider.max_pen) on axis (axis)" @@ -1354,14 +1355,14 @@ function get_cube_world_collisions() end end end - + if continue if DebugCollisions tell @a "(test_x),(test_y),(test_z): World penetration (min_pen) on axis (min_axis)" end id = get_unused_collision_id() - + # This collision surpasses the previous maximium penetration collider.max_pen = min_pen collider.max_pen_col = id @@ -1372,41 +1373,41 @@ function get_cube_world_collisions() do define name axis = "separating_axis_$(axis)" define name collision = "collision_$(collision)" - + collision.id = id collision.pen = min_pen - + collision.collider1 = collider.id - + collision.nx = axis.x * min_axis_sign collision.ny = axis.y * min_axis_sign collision.nz = axis.z * min_axis_sign - + if min_axis < 3 collision.type = $CollisionCubeFaceWorldPoint - + if collision.nx > 0 collision.x = block_x + $Half end if collision.nx <= 0 collision.x = block_x - $Half end - + if collision.ny > 0 collision.y = block_y + $Half end if collision.ny <= 0 collision.y = block_y - $Half end - + if collision.nz > 0 collision.z = block_z + $Half end if collision.nz <= 0 collision.z = block_z - $Half end - - + + if min_axis == 0 collision.lnx = min_axis_sign * $Precision collision.lny = 0 @@ -1424,11 +1425,11 @@ function get_cube_world_collisions() end else if min_axis < 6 collision.type = $CollisionCubePointWorldFace - + collision.block_x = block_x - $Half collision.block_y = block_y - $Half collision.block_z = block_z - $Half - + if min_axis == 3 sign0 = -collider_a0.x * collision.nx sign1 = -collider_a1.x * collision.nx @@ -1444,9 +1445,9 @@ function get_cube_world_collisions() sign1 = -collider_a1.z * collision.nz sign2 = -collider_a2.z * collision.nz end - + get_vertex_from_axis_signs() - + collision.vertex = vertex with $(vertex) = vertex @@ -1458,20 +1459,20 @@ function get_cube_world_collisions() end else collision.type = $CollisionCubeEdgeWorldEdge - + min_axis -= 6 collision.block_x = block_x - $Half collision.block_y = block_y - $Half collision.block_z = block_z - $Half - + block_axis = min_axis % 3 if block_axis == 0 collision.ox = collision.block_x collision.ex = $Precision collision.ey = 0 collision.ez = 0 - + if collision.ny > 0 collision.oy = collision.block_y + $Precision end @@ -1490,7 +1491,7 @@ function get_cube_world_collisions() collision.ex = 0 collision.ey = $Precision collision.ez = 0 - + if collision.nx > 0 collision.ox = collision.block_x + $Precision end @@ -1503,13 +1504,13 @@ function get_cube_world_collisions() if collision.nz <= 0 collision.oz = collision.block_z end - end + end if block_axis == 2 collision.oz = collision.block_z collision.ex = 0 collision.ey = 0 collision.ez = $Precision - + if collision.ny > 0 collision.oy = collision.block_y + $Precision end @@ -1523,7 +1524,7 @@ function get_cube_world_collisions() collision.ox = collision.block_x end end - + axis = min_axis / 3 unless axis == 0 sign0 = collision.nx * collider_a0.x + collision.ny * collider_a0.y + collision.nz * collider_a0.z @@ -1534,15 +1535,15 @@ function get_cube_world_collisions() unless axis == 2 sign2 = collision.nx * collider_a2.x + collision.ny * collider_a2.y + collision.nz * collider_a2.z end - + sign0 *= -1 sign1 *= -1 sign2 *= -1 - + get_edge_from_signs() collision.vertex1 = vertex collision.vertex2 = nvert - + with $(vertex) = vertex $(nvert) = nvert @@ -1551,7 +1552,7 @@ function get_cube_world_collisions() define name nvert = "collider_$(collider)_v$(nvert)" get_closest_points_on_edges(vertex.x, vertex.y, vertex.z, nvert.x - vertex.x, nvert.y - vertex.y, nvert.z - vertex.z, collision.ox, collision.oy, collision.oz, collision.ex, collision.ey, collision.ez) end - + collision.x = p1x collision.y = p1y collision.z = p1z @@ -1568,9 +1569,9 @@ end # called with $(collider) function project_halfsize_onto_separating_axis() define name collider = "collider_$(collider)" - + projected = 0 - + for axis_iter = 0 to 2 with $(axis) = axis_iter @@ -1580,11 +1581,11 @@ function project_halfsize_onto_separating_axis() if dot < 0 dot *= -1 end - + projected += dot end end - + projected *= collider.halfsize projected /= $Precision end @@ -1595,11 +1596,11 @@ end function test_axis_penetration() define name collider1 = "collider_$(collider1)" define name collider2 = "collider_$(collider2)" - + # Initialize the separation to be the distance between centers along the axis pen = (center_to_center.x * separating_axis.x + center_to_center.y * separating_axis.y + center_to_center.z * separating_axis.z) / $Precision axis_sign = 1 - + if pen > 0 pen *= -1 axis_sign = -1 @@ -1610,13 +1611,13 @@ function test_axis_penetration() $(collider) = collider1.id project_halfsize_onto_separating_axis() with macros pen += projected - + # Subtract collider2's halfsize along the axis from the separation with $(collider) = collider2.id project_halfsize_onto_separating_axis() with macros pen += projected - + if pen <= pen_threshold # This collision will be smaller than both of the colliders' existing # max collisions. @@ -1634,61 +1635,61 @@ end function get_min_separating_axis() define name collider1 = "collider_$(collider1)" define name collider2 = "collider_$(collider2)" - + if collider1.max_pen < collider2.max_pen pen_threshold = collider1.pen else pen_threshold = collider2.pen end - + min_pen = $Billion - + center_to_center.x = collider2.x - collider1.x center_to_center.y = collider2.y - collider1.y center_to_center.z = collider2.z - collider1.z - + dist_sq = center_to_center.x * center_to_center.x + center_to_center.y * center_to_center.y + center_to_center.z * center_to_center.z halfsize = collider1.halfsize + collider2.halfsize bsphere_sq = halfsize * halfsize / $Precision * 1732 - + if dist_sq > bsphere_sq continue = False end - + for axis1 = 0 to 2 if continue with $(axis) = axis1 do define name axis = "collider_$(collider1)_a$(axis)" - + axis_idx = axis1 separating_axis.x = axis.x separating_axis.y = axis.y separating_axis.z = axis.z - + test_axis_penetration() with macros end end end - + for axis2 = 0 to 2 if continue with $(axis) = axis2 do define name axis = "collider_$(collider2)_a$(axis)" - + axis_idx++ separating_axis.x = axis.x separating_axis.y = axis.y separating_axis.z = axis.z - + test_axis_penetration() with macros end end end - + for axis1 = 0 to 2 with $(axis1) = axis1 @@ -1701,15 +1702,15 @@ function get_min_separating_axis() axis_idx++ define name axis1 = "collider_$(collider1)_a$(axis1)" define name axis2 = "collider_$(collider2)_a$(axis2)" - + separating_axis.x = (axis1.y * axis2.z - axis1.z * axis2.y) / $Precision separating_axis.y = (axis1.z * axis2.x - axis1.x * axis2.z) / $Precision separating_axis.z = (axis1.x * axis2.y - axis1.y * axis2.x) / $Precision - + magsq = separating_axis.x*separating_axis.x magsq += separating_axis.y*separating_axis.y magsq += separating_axis.z*separating_axis.z - + if magsq > 10 # The axes aren't parallel mag = sqrt(magsq) @@ -1719,7 +1720,7 @@ function get_min_separating_axis() separating_axis.y /= mag separating_axis.z *= $Precision separating_axis.z /= mag - + test_axis_penetration() with macros end end @@ -1727,7 +1728,7 @@ function get_min_separating_axis() end end end - + if DebugCollisions if continue tell @a "Penetration of (min_pen) between (collider1.id) and (collider2.id) on axis #(min_axis_idx)" @@ -1765,7 +1766,7 @@ function get_vertex_from_axis_signs() else vertex = 1 end - end + end end end @@ -1787,7 +1788,7 @@ function get_edge_from_signs() vertex = 1 nvert = 6 end - end + end else if axis == 1 if sign0 > 0 if sign2 > 0 @@ -1805,7 +1806,7 @@ function get_edge_from_signs() vertex = 1 nvert = 3 end - end + end else # axis == 2 if sign0 > 0 @@ -1824,40 +1825,40 @@ function get_edge_from_signs() vertex = 1 nvert = 5 end - end + end end end - + function get_collider_collider_collision() define name collider1 = "collider_$(collider1)" define name collider2 = "collider_$(collider2)" define name collision = "collision_$(collision)" continue = True - + if collider1.sleeping and collider2.sleeping continue = False end - + if continue get_min_separating_axis() with macros end - + if continue # Create the collision id = get_unused_collision_id() with $(collision) = id - do + do collision.id = id collision.pen = min_pen - + if min_pen > collider1.max_pen collider1.max_pen = min_pen collider1.max_pen_col = id end - + if min_pen > collider2.max_pen collider2.max_pen = min_pen collider2.max_pen_col = id @@ -1865,7 +1866,7 @@ function get_collider_collider_collision() if min_axis_idx < 3 # collider1 face, collider2 point - # Get the collider1 face + # Get the collider1 face if min_axis_idx == 0 lnx = min_axis_sign * $Precision lny = 0 @@ -1881,26 +1882,26 @@ function get_collider_collider_collision() lny = 0 lnz = min_axis_sign * $Precision end - + define name axis0 = "collider_$(collider2)_a0" define name axis1 = "collider_$(collider2)_a1" define name axis2 = "collider_$(collider2)_a2" - + # Make the axis point toward collider1 min_axis_x *= min_axis_sign min_axis_y *= min_axis_sign min_axis_z *= min_axis_sign - + # Get the collider2 point sign0 = min_axis_x * axis0.x + min_axis_y * axis0.y + min_axis_z * axis0.z sign1 = min_axis_x * axis1.x + min_axis_y * axis1.y + min_axis_z * axis1.z sign2 = min_axis_x * axis2.x + min_axis_y * axis2.y + min_axis_z * axis2.z - + get_vertex_from_axis_signs() - + collision.collider1 = collider1.id collision.collider2 = collider2.id - + with $(vertex) = vertex do @@ -1910,7 +1911,7 @@ function get_collider_collider_collision() collision.y = vertex.y collision.z = vertex.z end - + if DebugCollisions tell @a "Creating collision with (collider1.id) face and (collider2.id) vertex" end @@ -1926,9 +1927,9 @@ function get_collider_collider_collision() collision.vertex = vertex else if min_axis_idx < 6 # collider1 point, collider2 face - # Get the collider2 face + # Get the collider2 face min_axis_sign *= -1 - + if min_axis_idx == 3 lnx = min_axis_sign * $Precision lny = 0 @@ -1944,7 +1945,7 @@ function get_collider_collider_collision() lny = 0 lnz = min_axis_sign * $Precision end - + define name axis0 = "collider_$(collider1)_a0" define name axis1 = "collider_$(collider1)_a1" define name axis2 = "collider_$(collider1)_a2" @@ -1958,12 +1959,12 @@ function get_collider_collider_collision() sign0 = min_axis_x * axis0.x + min_axis_y * axis0.y + min_axis_z * axis0.z sign1 = min_axis_x * axis1.x + min_axis_y * axis1.y + min_axis_z * axis1.z sign2 = min_axis_x * axis2.x + min_axis_y * axis2.y + min_axis_z * axis2.z - + get_vertex_from_axis_signs() - + collision.collider1 = collider2.id collision.collider2 = collider1.id - + with $(vertex) = vertex do @@ -1991,12 +1992,12 @@ function get_collider_collider_collision() else # edge, edge min_axis_idx -= 6 - + # Get the collider1 edge define name axis0 = "collider_$(collider1)_a0" define name axis1 = "collider_$(collider1)_a1" define name axis2 = "collider_$(collider1)_a2" - + # Make the axis point toward collider1 min_axis_x *= min_axis_sign min_axis_y *= min_axis_sign @@ -2012,11 +2013,11 @@ function get_collider_collider_collision() unless axis == 2 sign2 = min_axis_x * axis2.x + min_axis_y * axis2.y + min_axis_z * axis2.z end - + get_edge_from_signs() vertex1 = vertex nvert1 = nvert - + # Get the collider2 edge define name axis0 = "collider_$(collider2)_a0" define name axis1 = "collider_$(collider2)_a1" @@ -2032,11 +2033,11 @@ function get_collider_collider_collision() unless axis == 2 sign2 = min_axis_x * axis2.x + min_axis_y * axis2.y + min_axis_z * axis2.z end - + get_edge_from_signs() vertex2 = vertex nvert2 = nvert - + # Get the nearest points on the edges with $(vertex1) = vertex1 @@ -2048,10 +2049,10 @@ function get_collider_collider_collision() define name nvert1 = "collider_$(collider1)_v$(nvert1)" define name vertex2 = "collider_$(collider2)_v$(vertex2)" define name nvert2 = "collider_$(collider2)_v$(nvert2)" - + get_closest_points_on_edges(vertex1.x, vertex1.y, vertex1.z, nvert1.x - vertex1.x, nvert1.y - vertex1.y, nvert1.z - vertex1.z, vertex2.x, vertex2.y, vertex2.z, nvert2.x - vertex2.x, nvert2.y - vertex2.y, nvert2.z - vertex2.z) end - + if DebugCollisions dx = p2x-p1x dy = p2y-p1y @@ -2064,15 +2065,15 @@ function get_collider_collider_collision() collision.collider1 = collider1.id collision.collider2 = collider2.id - + collision.x = p1x collision.y = p1y collision.z = p1z - + collision.nx = min_axis_x collision.ny = min_axis_y collision.nz = min_axis_z - + collision.type = $CollisionCubeEdgeCubeEdge collision.vertex1 = vertex1 collision.nvert1 = nvert1 @@ -2085,26 +2086,26 @@ end function collider_physics_tick() define name collider = "collider_$(collider)" - + # Apply Gravity collider.velocity_y -= Gravity - + collider_integrate() with macros collider_quaternion_to_transform() with macros end function resolve_collision_velocity() collision_frame++ - + for vel_iter = 1 to 20 max_closing = 0 - + for collision = 1 to max_collision with $(collision) = collision do define name collision = "collision_$(collision)" - + if collision.active and collision.pen >= 0 with $(collider1) = collision.collider1 @@ -2112,19 +2113,19 @@ function resolve_collision_velocity() do define name collider1 = "collider_$(collider1)" define name collider2 = "collider_$(collider2)" - + sleeping = True unless collider1.sleeping sleeping = False end - + if collision.collider2 unless collider2.sleeping sleeping = False end - - if not sleeping + + if not sleeping update_closing_velocity() with macros - + if closing > max_closing max_closing = closing max_closing_id = collision.id @@ -2136,7 +2137,7 @@ function resolve_collision_velocity() end end end - + if max_closing <= 5 vel_iter = 1000000 else @@ -2153,17 +2154,17 @@ function update_closing_velocity() define name collision = "collision_$(collision)" define name collider1 = "collider_$(collider1)" define name collider2 = "collider_$(collider2)" - + /scoreboard players set Global twobody $(collider2) - + collision_x = collision.x collision_y = collision.y collision_z = collision.z - + dx = collision_x - collider1.x dy = collision_y - collider1.y dz = collision_z - collider1.z - + rotation_x = collider1.rotation_x rotation_y = collider1.rotation_y rotation_z = collider1.rotation_z @@ -2171,7 +2172,7 @@ function update_closing_velocity() rot_lin_vel_x = (rotation_y * dz - rotation_z * dy + $Half) / $Precision rot_lin_vel_y = (rotation_z * dx - rotation_x * dz + $Half) / $Precision rot_lin_vel_z = (rotation_x * dy - rotation_y * dx + $Half) / $Precision - + vel_x = collider1.velocity_x + rot_lin_vel_x vel_y = collider1.velocity_y + rot_lin_vel_y vel_z = collider1.velocity_z + rot_lin_vel_z @@ -2188,24 +2189,24 @@ function update_closing_velocity() rot_lin_vel_x = (rotation_y * dz - rotation_z * dy + $Half) / $Precision rot_lin_vel_y = (rotation_z * dx - rotation_x * dz + $Half) / $Precision rot_lin_vel_z = (rotation_x * dy - rotation_y * dx + $Half) / $Precision - + vel_x -= collider2.velocity_x + rot_lin_vel_x vel_y -= collider2.velocity_y + rot_lin_vel_y vel_z -= collider2.velocity_z + rot_lin_vel_z end - + collision.vel_x = vel_x collision.vel_y = vel_y collision.vel_z = vel_z - + closing = -(vel_x * collision.nx + vel_y * collision.ny + vel_z * collision.nz + $Half) / $Precision end function resolve_collision_penetration() for pen_iter = 1 to 10 max_pen = 0 - + for collision = 1 to max_collision with $(collision) = collision @@ -2219,16 +2220,16 @@ function resolve_collision_penetration() do define name collider1 = "collider_$(collider1)" define name collider2 = "collider_$(collider2)" - + sleeping = True unless collider1.sleeping sleeping = False end - + if collision.collider2 unless collider2.sleeping sleeping = False end - + if not sleeping and collision.pen > max_pen max_pen = collision.pen max_id = collision.id @@ -2242,30 +2243,30 @@ function resolve_collision_penetration() end end end - + if max_pen <= 20 pen_iter = $Billion else mx = (max_pen_nx * max_pen) / $Precision my = (max_pen_ny * max_pen) / $Precision mz = (max_pen_nz * max_pen) / $Precision - + #tell @a "Resolving (max_pen_col1) and (max_pen_col2) with pen (max_pen), moving (mx), (my), (mz)" - + if not max_pen_col2 with $(collider) = max_pen_col1 do define name collider = "collider_$(collider)" - + if DebugCollisions tell @a "#(pen_iter): Separating (collider.id)/world (mx), (my), (mz) from collision #(max_id)" end - + collider.x += mx collider.y += my collider.z += mz - + move_collisions(mx, my, mz, collider.id) end else @@ -2275,7 +2276,7 @@ function resolve_collision_penetration() do define name collider1 = "collider_$(collider1)" define name collider2 = "collider_$(collider2)" - + if DebugCollisions tell @a "#(pen_iter): Separating (collider1.id)/(collider2.id) (mx), (my), (mz) from collision #(max_id)" end @@ -2283,12 +2284,12 @@ function resolve_collision_penetration() inv_mass = collider1.inv_mass + collider2.inv_mass p1 = collider1.inv_mass * $Precision / inv_mass - + m1x = p1 * mx / $Precision m1y = p1 * my / $Precision m1z = p1 * mz / $Precision - - collider1.x += m1x + + collider1.x += m1x collider1.y += m1y collider1.z += m1z if collider1.sleeping @@ -2296,16 +2297,16 @@ function resolve_collision_penetration() $(collider) = collider1.id collider_wake_up() end - + move_collisions(m1x, m1y, m1z, collider1.id) - + p2 = -collider2.inv_mass * $Precision / inv_mass - + m2x = p2 * mx / $Precision m2y = p2 * my / $Precision m2z = p2 * mz / $Precision - - collider2.x += m2x + + collider2.x += m2x collider2.y += m2y collider2.z += m2z if collider2.sleeping @@ -2313,7 +2314,7 @@ function resolve_collision_penetration() $(collider) = collider2.id collider_wake_up() end - + move_collisions(m2x, m2y, m2z, collider2.id) end end @@ -2327,7 +2328,7 @@ function move_collisions(dx, dy, dz, collider) $(collision) = collision do define name collision = "collision_$(collision)" - + do_move = False if collision.collider1 == collider do_move = True @@ -2337,7 +2338,7 @@ function move_collisions(dx, dy, dz, collider) do_move = True sign = -1 end - + if do_move collision.pen -= sign * (dx*collision.nx + dy*collision.ny + dz*collision.nz) / $Precision end @@ -2362,7 +2363,7 @@ function update_active_collisions() end end end - + # Update each active collision for collision_iter = max_collision to 1 by -1 with @@ -2396,7 +2397,7 @@ function update_collision() vy = vertex.y vz = vertex.z end - + keep = False with @@ -2404,14 +2405,14 @@ function update_collision() $(y) = collision.block_y / $Precision $(z) = collision.block_z / $Precision is_air() - + if air collider_wake_up() with macros else nx = collision.nx ny = collision.ny nz = collision.nz - + block_x = collision.block_x block_y = collision.block_y block_z = collision.block_z @@ -2436,13 +2437,13 @@ function update_collision() collision.pen = (block_z + $Precision) - vz keep = True end - + if nz == -$Precision and vy >= block_y and vy <= block_y+$Precision and vx >= block_x and vx <= block_x+$Precision collision.pen = vz - block_z keep = True end end - + if keep collision.x = vx collision.y = vy @@ -2456,23 +2457,23 @@ function update_collision() $(collider) = collision.collider1 do # TODO: Check if the point is outside the bounds of the cube - + collider_world_to_local(collision.block_x, collision.block_y, collision.block_z, True) with macros - + lnx = collision.lnx lny = collision.lny lnz = collision.lnz - + halfsize = collider.halfsize - + keep = False - + with $(x) = collision.block_x / $Precision $(y) = collision.block_y / $Precision $(z) = collision.block_z / $Precision is_air() - + if air collider_wake_up() with macros else @@ -2523,7 +2524,7 @@ function update_collision() oy = vertex.y oz = vertex.z end - + with $(vertex) = collision.vertex2 do @@ -2532,13 +2533,13 @@ function update_collision() ey = vertex.y - oy ez = vertex.z - oz end - + get_closest_points_on_edges(ox, oy, oz, ex, ey, ez, collision.ox, collision.oy, collision.oz, collision.ex, collision.ey, collision.ez) - + if t1 >= 0 and t1 <= $Precision and t2 >= 0 and t2 <= $Precision # The collision falls along the collider edges is_collision = False - + block_min_x = collision.block_x block_min_y = collision.block_y block_min_z = collision.block_z @@ -2547,13 +2548,13 @@ function update_collision() block_max_z = block_min_z + $Precision if p1x >= block_x and p1y >= block_y and p1z >= block_z and p1x <= block_max_x and p1y <= block_max_y and p1z <= block_max_z collider_world_to_local(p2x, p2y, p2z, True) with macros - + halfsize = collider.halfsize if local_x >= -halfsize and local_x <= halfsize and local_y >= -halfsize and local_y <= halfsize and local_z >= -halfsize and local_z <= halfsize is_collision = True end end - + if is_collision dx = p2x - p1x dy = p2y - p1y @@ -2564,13 +2565,13 @@ function update_collision() collision.x = p1x collision.y = p1y collision.z = p1z - + collision.pen = pen - + dx = dx * $Precision / pen dy = dy * $Precision / pen dz = dz * $Precision / pen - + collision.nx = dx collision.ny = dy collision.nz = dz @@ -2586,35 +2587,35 @@ function update_collision() $(collider2) = collision.collider2 $(vertex) = collision.vertex do - define name v = "collider_$(collider2)_v$(vertex)" + define name v = "collider_$(collider2)_v$(vertex)" vx = v.x vy = v.y vz = v.z end - + with $(collider) = collision.collider1 - do + do define name collider1 = "collider_$(collider)" - + lnx = collision.lnx lny = collision.lny lnz = collision.lnz - + collider_local_to_world(lnx, lny, lnz, False) with macros - + collision.nx = world_x collision.ny = world_y collision.nz = world_z - + collider_world_to_local(vx, vy, vz, True) with macros - + # TODO: Check if local_xyz lies within the bounds of the cube halfsize = collider1.halfsize - + keep = False - + if lnx == -$Precision and local_y >= -halfsize and local_y <= halfsize and local_z >= -halfsize and local_z <= halfsize collision.pen = halfsize - local_x keep = True @@ -2639,7 +2640,7 @@ function update_collision() collision.pen = local_z + halfsize keep = True end - + if keep collision.x = vx collision.y = vy @@ -2669,7 +2670,7 @@ function update_collision() e1y = v.y - o1y e1z = v.z - o1z end - + with $(v) = collision.vertex2 do @@ -2686,27 +2687,27 @@ function update_collision() e2y = v.y - o2y e2z = v.z - o2z end - + get_closest_points_on_edges(o1x, o1y, o1z, e1x, e1y, e1z, o2x, o2y, o2z, e2x, e2y, e2z) - + if t1 >= 0 and t1 <= $Precision and t2 >= 0 and t2 <= $Precision with $(collider) = collider2.id collider_world_to_local(p1x, p1y, p1z, True) - + is_collision = False if local_x >= -collider2.halfsize and local_x <= collider2.halfsize and local_y >= -collider2.halfsize and local_y <= collider2.halfsize and local_z >= -collider2.halfsize and local_z <= collider2.halfsize # The collision point falls within collider2 with $(collider) = collider1.id collider_world_to_local(p2x, p2y, p2z) - + if local_x >= -collider1.halfsize and local_x <= collider1.halfsize and local_y >= -collider1.halfsize and local_y <= collider1.halfsize and local_z >= -collider1.halfsize and local_z <= collider1.halfsize # The collision point falls within collider1 is_collision = True end end - + if is_collision # The collision falls along the collider edges dx = p2x - p1x @@ -2714,13 +2715,13 @@ function update_collision() dz = p2z - p1z pen = sqrt(dx*dx + dy*dy + dz*dz) - + collision.pen = pen - + collision.x = p1x collision.y = p1y collision.z = p1z - + collision.nx = dx * $Precision / pen collision.ny = dy * $Precision / pen collision.nz = dz * $Precision / pen @@ -2859,7 +2860,7 @@ function update_collision() # No type specified delete_collision() with macros end - + if collision.pen < -100 delete_collision() with macros else @@ -2870,7 +2871,7 @@ function update_collision() collider.max_pen = collision.pen end end - + if collision.collider2 with $(collider) = collision.collider2 @@ -2896,7 +2897,7 @@ function cull_collisions() do if collision.id unless collision.active already_exists = False - + for collision2_iter = 1 to max_collision with $(collision2) = collision2_iter @@ -2941,14 +2942,14 @@ function cull_collisions() end end end - + if already_exists delete_collision() with macros end end end end - + # Set the highest penetration collision to active for collider_iter = 1 to max_collider with @@ -2966,7 +2967,7 @@ function cull_collisions() end end end - + # Delete any inactive collisions for collision_iter = max_collision to 1 by -1 with @@ -2983,7 +2984,7 @@ end function merge_collisions_down() free_collision = 0 get_next_free_collision() - + for collision_iter = max_collision to 1 by -1 with $(collision) = collision_iter @@ -2997,21 +2998,21 @@ function merge_collisions_down() $(free_collision) = free_collision do define name free_collision = "collision_$(free_collision)" - + free_collision.id = free_collision free_collision.active = True free_collision.pen = collision.pen - + free_collision.x = collision.x free_collision.y = collision.y free_collision.z = collision.z - + free_collision.nx = collision.nx free_collision.ny = collision.ny free_collision.nz = collision.nz - + free_collision.restitution = collision.restitution - + free_collision.type = collision.type free_collision.collider1 = collision.collider1 free_collision.collider2 = collision.collider2 @@ -3032,15 +3033,15 @@ function merge_collisions_down() free_collision.ex = collision.ex free_collision.ey = collision.ey free_collision.ez = collision.ez - + /scoreboard players reset collision_$(collision) - + get_next_free_collision() end end end end - + max_collision = free_collision - 1 end @@ -3048,7 +3049,7 @@ function get_next_free_collision() continue = True while continue free_collision++ - + with $(free_collision) = free_collision do @@ -3082,7 +3083,7 @@ function get_unused_collision_id() end end end - + return unused_id end @@ -3092,7 +3093,7 @@ function delete_collisions() $(collision) = collision delete_collision() end - + max_collision = 0 end @@ -3112,7 +3113,7 @@ function initialize_collision_matrices() define name collider1 = "collider_$(collider1)" define name collider2 = "collider_$(collider2)" define name collision = "collision_$(collision)" - + if collision.initialized == collision_frame ct_00 = collision.ct_00 ct_01 = collision.ct_01 @@ -3123,7 +3124,7 @@ function initialize_collision_matrices() ct_20 = collision.ct_20 ct_21 = collision.ct_21 ct_22 = collision.ct_22 - + v_to_i_00 = collision.v_to_i_00 v_to_i_01 = collision.v_to_i_01 v_to_i_02 = collision.v_to_i_02 @@ -3133,7 +3134,7 @@ function initialize_collision_matrices() v_to_i_20 = collision.v_to_i_20 v_to_i_21 = collision.v_to_i_21 v_to_i_22 = collision.v_to_i_22 - + c_i_to_v_10 = collision.c_i_to_v_10 c_i_to_v_11 = collision.c_i_to_v_11 c_i_to_v_12 = collision.c_i_to_v_12 @@ -3146,10 +3147,10 @@ function initialize_collision_matrices() ct_01 = nx ct_11 = ny ct_21 = nz - + absx = abs(nx) absz = abs(nz) - + if absx < absz # The norm isn't pointing toward x, so # cross the norm with 1,0,0 @@ -3175,7 +3176,7 @@ function initialize_collision_matrices() ct_12 = (ct_00*ct_21) / $Precision ct_22 = (ct_00*ct_11 - ct_10*ct_01) / $Precision end - + collision.ct_00 = ct_00 collision.ct_01 = ct_01 collision.ct_02 = ct_02 @@ -3193,9 +3194,9 @@ function initialize_collision_matrices() dx = collision_x - collider1.x dy = collision_y - collider1.y dz = collision_z - collider1.z - + inv_rot_int = collider1.inv_rot_int - + # Impulse to velocity transform # Formula: -(i_to_t^2) * InverseRotationalIntertia i_to_v_00 = ((dz * dz + dy * dy) / $Precision * inv_rot_int) / $Precision @@ -3209,10 +3210,10 @@ function initialize_collision_matrices() i_to_v_20 = ((-dx * dz) / $Precision * inv_rot_int) / $Precision i_to_v_21 = ((-dy * dz) / $Precision * inv_rot_int) / $Precision i_to_v_22 = ((dy * dy + dx * dx) / $Precision * inv_rot_int) / $Precision - + # Transform i_to_v into contact coordinates before inverting, # using change of basis formula - + # First, ct^transpose * i_to_v with $(m1) = "Global ct" @@ -3226,14 +3227,14 @@ function initialize_collision_matrices() $(m2) = "Global ct" $(out) = "Global c_i_to_v" matrix_multiply() - + inv_mass = collider1.inv_mass - + if twobody dx = collision_x - collider2.x dy = collision_y - collider2.y dz = collision_z - collider2.z - + inv_rot_int = collider2.inv_rot_int # Impulse to velocity transform @@ -3249,10 +3250,10 @@ function initialize_collision_matrices() i_to_v_20 = ((-dx * dz) / $Precision * inv_rot_int) / $Precision i_to_v_21 = ((-dy * dz) / $Precision * inv_rot_int) / $Precision i_to_v_22 = ((dy * dy + dx * dx) / $Precision * inv_rot_int) / $Precision - + # Transform i_to_v into contact coordinates before inverting, # using change of basis formula - + # First, ct^transpose * i_to_v with $(m1) = "Global ct" @@ -3266,7 +3267,7 @@ function initialize_collision_matrices() $(m2) = "Global ct" $(out) = "Global c_i_to_v_2" matrix_multiply() - + c_i_to_v_00 += c_i_to_v_2_00 c_i_to_v_01 += c_i_to_v_2_01 c_i_to_v_02 += c_i_to_v_2_02 @@ -3276,10 +3277,10 @@ function initialize_collision_matrices() c_i_to_v_20 += c_i_to_v_2_20 c_i_to_v_21 += c_i_to_v_2_21 c_i_to_v_22 += c_i_to_v_2_22 - + inv_mass += collider2.inv_mass end - + # In contact space, add the inverse mass to the diagonal c_i_to_v_00 += inv_mass c_i_to_v_11 += inv_mass @@ -3300,7 +3301,7 @@ function initialize_collision_matrices() g = c_i_to_v_20 h = c_i_to_v_21 i = c_i_to_v_22 - + # Inverse impulse to velocity det = (a * e) / $Precision * i det += (d * h) / $Precision * c @@ -3309,7 +3310,7 @@ function initialize_collision_matrices() det -= (g * e) / $Precision * c det -= (d * b) / $Precision * i det /= $Precision - + v_to_i_00 = (e * i - f * h) / det v_to_i_01 = (c * h - b * i) / det v_to_i_02 = (b * f - c * e) / det @@ -3321,7 +3322,7 @@ function initialize_collision_matrices() v_to_i_20 = (d * h - e * g) / det v_to_i_21 = (b * g - a * h) / det v_to_i_22 = (a * e - b * d) / det - + collision.v_to_i_00 = v_to_i_00 collision.v_to_i_01 = v_to_i_01 collision.v_to_i_02 = v_to_i_02 @@ -3333,7 +3334,7 @@ function initialize_collision_matrices() collision.v_to_i_20 = v_to_i_20 collision.v_to_i_21 = v_to_i_21 collision.v_to_i_22 = v_to_i_22 - + collision.initialized = collision_frame end end @@ -3342,29 +3343,29 @@ function handle_collision_impulse() define name collider1 = "collider_$(collider1)" define name collider2 = "collider_$(collider2)" define name collision = "collision_$(collision)" - + /scoreboard players set Global twobody $(collider2) - + initialize_collision_matrices() with macros - + vel_x = collision.vel_x vel_y = collision.vel_y vel_z = collision.vel_z - + # Transform by the ct transpose matrix to get the closing velocity in contact coordinates c_vel_x = (ct_00 * vel_x + ct_10 * vel_y + ct_20 * vel_z + $Half) / $Precision c_vel_y = (ct_01 * vel_x + ct_11 * vel_y + ct_21 * vel_z + $Half) / $Precision c_vel_z = (ct_02 * vel_x + ct_12 * vel_y + ct_22 * vel_z + $Half) / $Precision - + restitution = Restitution if collision.restitution restitution = collision.restitution end - + if c_vel_y > $CancelRestitution restitution = 0 end - + if transforms.impact_sounds if c_vel_y < -500 as @PhysicsBlock if @s.collider_id == collider_1.id at @s @@ -3376,7 +3377,7 @@ function handle_collision_impulse() end end end - + desired_vx = 0 # TODO: Add gravity in the positive Y world direction desired_vy = (-(c_vel_y) * restitution) / $Precision @@ -3385,44 +3386,44 @@ function handle_collision_impulse() desired_dvx = desired_vx - c_vel_x desired_dvy = desired_vy - c_vel_y desired_dvz = desired_vz - c_vel_z - + cix = (v_to_i_00 * desired_dvx + v_to_i_01 * desired_dvy + v_to_i_02 * desired_dvz + $Half) / $Precision ciy = (v_to_i_10 * desired_dvx + v_to_i_11 * desired_dvy + v_to_i_12 * desired_dvz + $Half) / $Precision ciz = (v_to_i_20 * desired_dvx + v_to_i_21 * desired_dvy + v_to_i_22 * desired_dvz + $Half) / $Precision - + planar_impulse = sqrt(cix*cix + ciz*ciz) - + max_fric_impulse = (ciy * Friction + $Half) / $Precision - + if planar_impulse > max_fric_impulse dir_ix = cix * $Precision / planar_impulse dir_iz = ciz * $Precision / planar_impulse - + v_per_i_y = c_i_to_v_11 + ((c_i_to_v_10 * dir_ix + c_i_to_v_12 * dir_iz + $Half) / $Precision * Friction + $Half) / $Precision - + ciy = desired_dvy * $Precision / v_per_i_y - + cix = ((dir_ix * Friction + $Half) / $Precision * ciy + $Half) / $Precision ciz = ((dir_iz * Friction + $Half) / $Precision * ciy + $Half) / $Precision end - + # Transform impulse vector out of contact coordinates ix = (ct_00 * cix + ct_01 * ciy + ct_02 * ciz + $Half) / $Precision iy = (ct_10 * cix + ct_11 * ciy + ct_12 * ciz + $Half) / $Precision iz = (ct_20 * cix + ct_21 * ciy + ct_22 * ciz + $Half) / $Precision - + # collider1.id isn't using define name with $(collider) = collider1.id collider_apply_impulse(collision.x, collision.y, collision.z, ix, iy, iz) - + if twobody ix *= -1 iy *= -1 iz *= -1 - + with $(collider) = collider2.id collider_apply_impulse(collision.x, collision.y, collision.z, ix, iy, iz) end -end \ No newline at end of file +end diff --git a/block_types/advancement_definition_block.py b/block_types/advancement_definition_block.py index 5a23d4b..3a6abb8 100644 --- a/block_types/advancement_definition_block.py +++ b/block_types/advancement_definition_block.py @@ -1,12 +1,13 @@ from .block_base import block_base + class advancement_definition_block(block_base): - def __init__(self, line, name, json): - self.line = line - self.name = name - self.json = json - - def compile(self, func): - json = func.apply_replacements(self.json) - - func.add_advancement(self.name, json) + def __init__(self, line, name, json): + self.line = line + self.name = name + self.json = json + + def compile(self, func): + json = func.apply_replacements(self.json) + + func.add_advancement(self.name, json) diff --git a/block_types/array_definition_block.py b/block_types/array_definition_block.py index 8cb05f9..816c786 100644 --- a/block_types/array_definition_block.py +++ b/block_types/array_definition_block.py @@ -3,47 +3,86 @@ from variable_types.scoreboard_var import scoreboard_var from CompileError import CompileError + class array_definition_block(block_base): - def __init__(self, line, name, from_val, to_val, selector_based): - self.line = line - self.name = name - self.from_val = from_val - self.to_val = to_val - self.selector_based = selector_based - - def compile(self, func): - try: - from_val = int(self.from_val.get_value(func)) - to_val = int(self.to_val.get_value(func)) - except Exception: - raise CompileError(f'Unable to get array range for "{self.name}" at line {self.line}') - - name = self.name - - vals = list(range(from_val, to_val)) - - for i in vals: - func.register_objective(f'{name}{i}') - - valvar = f'{name}Val' - func.register_objective(valvar) - - selector = '@s' if self.selector_based else 'Global' - - indexvar = scoreboard_var(selector, f'{name}Idx') - - get_func = func.create_child_function() - get_func_name = f'array_{name.lower()}_get' - func.register_function(get_func_name, get_func) - cases = [(i, i, [command_block(self.line, f'/scoreboard players operation {selector} {valvar} = {selector} {name}{i}')], self.line, None) for i in vals] - if not get_func.switch_cases(indexvar, cases, 'arrayget', 'arraygetidx'): - raise Exception(f'Error creating getter for array at line {self.line}') - - set_func = func.create_child_function() - set_func_name = f'array_{name.lower()}_set' - func.register_function(set_func_name, set_func) - cases = [(i, i, [command_block(self.line, f'/scoreboard players operation {selector} {name}{i} = {selector} {valvar}')], self.line, None) for i in vals] - if not set_func.switch_cases(indexvar, cases, 'arrayset', 'arraysetidx'): - raise Exception(f'Error creating setter for array at line {self.line}') - - func.register_array(name, from_val, to_val, self.selector_based) + def __init__(self, line, name, from_val, to_val, selector_based): + self.line = line + self.name = name + self.from_val = from_val + self.to_val = to_val + self.selector_based = selector_based + + def compile(self, func): + try: + from_val = int(self.from_val.get_value(func)) + to_val = int(self.to_val.get_value(func)) + except Exception: + raise CompileError( + f'Unable to get array range for "{self.name}" at line {self.line}' + ) + + name = self.name + + vals = list(range(from_val, to_val)) + + for i in vals: + func.register_objective(f"{name}{i}") + + valvar = f"{name}Val" + func.register_objective(valvar) + + selector = "@s" if self.selector_based else "Global" + + indexvar = scoreboard_var(selector, f"{name}Idx") + + get_func = func.create_child_function() + get_func_name = f"array_{name.lower()}_get" + func.register_function(get_func_name, get_func) + cases = [ + ( + i, + i, + [ + command_block( + self.line, + f"/scoreboard players operation {selector} {valvar} = {selector} {name}{i}", + ) + ], + self.line, + None, + ) + for i in vals + ] + if not get_func.switch_cases( + indexvar, cases, "arrayget", "arraygetidx" + ): + raise Exception( + f"Error creating getter for array at line {self.line}" + ) + + set_func = func.create_child_function() + set_func_name = f"array_{name.lower()}_set" + func.register_function(set_func_name, set_func) + cases = [ + ( + i, + i, + [ + command_block( + self.line, + f"/scoreboard players operation {selector} {name}{i} = {selector} {valvar}", + ) + ], + self.line, + None, + ) + for i in vals + ] + if not set_func.switch_cases( + indexvar, cases, "arrayset", "arraysetidx" + ): + raise Exception( + f"Error creating setter for array at line {self.line}" + ) + + func.register_array(name, from_val, to_val, self.selector_based) diff --git a/block_types/block_base.py b/block_types/block_base.py index 55e78dd..ee8cb49 100644 --- a/block_types/block_base.py +++ b/block_types/block_base.py @@ -1,23 +1,28 @@ from CompileError import CompileError import traceback + class block_base(object): - def compile(self, func): - raise NotImplementedError('Section does not implement compile()') - - def register(self, global_context): - None - - def compile_lines(self, func, lines): - try: - func.compile_blocks(lines) - except CompileError as e: - print(e) - raise CompileError(f'Unable to compile {self.block_name} at line {self.line}') - except e: - print(traceback.format_exc()) - raise CompileError(f'Error compiling {self.block_name} at line {self.line}') - - @property - def block_name(self): - return 'block' + def compile(self, func): + raise NotImplementedError("Section does not implement compile()") + + def register(self, global_context): + None + + def compile_lines(self, func, lines): + try: + func.compile_blocks(lines) + except CompileError as e: + print(e) + raise CompileError( + f"Unable to compile {self.block_name} at line {self.line}" + ) + except e: + print(traceback.format_exc()) + raise CompileError( + f"Error compiling {self.block_name} at line {self.line}" + ) + + @property + def block_name(self): + return "block" diff --git a/block_types/block_definition_block.py b/block_types/block_definition_block.py index a3b6488..49c65ae 100644 --- a/block_types/block_definition_block.py +++ b/block_types/block_definition_block.py @@ -1,44 +1,50 @@ from .block_base import block_base -from data_types.relcoords import relcoords from CompileError import CompileError + class block_definition_block(block_base): - def __init__(self, line, block_id, items, coords): - self.line = line - self.block_id = block_id - self.items = items - self.coords = coords - self.paths = {} - - def compile(self, func): - func.add_block_definition(self.block_id, self) - - for item in self.items: - self.paths[item.get_name()] = item - - def copy_to_objective(self, func, path, coords, macro_args, objective): - if coords == None: - coords = self.coords - - if path not in self.paths: - raise CompileError(f'No path "{path}" defined for [{self.block_id}].') - - self.paths[id].copy_to_objective(func, coords, macro_args, objective) - - def copy_from(self, func, path, coords, macro_args, var): - if coords == None: - coords = self.coords - - if path not in self.paths: - raise CompileError(f'No path "{path}" defined for [{self.block_id}].') - - self.paths[path].copy_from(func, coords, macro_args, var) - - def get_command(self, func, path, coords, macro_args): - if coords == None: - coords = self.coords - - if path not in self.paths: - raise CompileError(f'No path "{path}" defined for [{self.block_id}].') - - return self.paths[path].get_command(func, coords, macro_args) + def __init__(self, line, block_id, items, coords): + self.line = line + self.block_id = block_id + self.items = items + self.coords = coords + self.paths = {} + + def compile(self, func): + func.add_block_definition(self.block_id, self) + + for item in self.items: + self.paths[item.get_name()] = item + + def copy_to_objective(self, func, path, coords, macro_args, objective): + if coords == None: + coords = self.coords + + if path not in self.paths: + raise CompileError( + f'No path "{path}" defined for [{self.block_id}].' + ) + + self.paths[id].copy_to_objective(func, coords, macro_args, objective) + + def copy_from(self, func, path, coords, macro_args, var): + if coords == None: + coords = self.coords + + if path not in self.paths: + raise CompileError( + f'No path "{path}" defined for [{self.block_id}].' + ) + + self.paths[path].copy_from(func, coords, macro_args, var) + + def get_command(self, func, path, coords, macro_args): + if coords == None: + coords = self.coords + + if path not in self.paths: + raise CompileError( + f'No path "{path}" defined for [{self.block_id}].' + ) + + return self.paths[path].get_command(func, coords, macro_args) diff --git a/block_types/block_id_switch_block.py b/block_types/block_id_switch_block.py index c7ddbc1..62392fc 100644 --- a/block_types/block_id_switch_block.py +++ b/block_types/block_id_switch_block.py @@ -1,52 +1,57 @@ from .block_switch_base import block_switch_base from CompileError import CompileError + class block_id_switch_block(block_switch_base): - def __init__(self, line, expr, cases, include_block_states): - self.line = line - self.expr = expr - self.cases = cases - self.include_block_states = include_block_states - - super(block_id_switch_block, self).__init__() - - def compile_initialization(self, func): - try: - var = self.expr.compile(func) - self.condition_var = var.get_scoreboard_var(func) - except CompileError as e: - print(e) - raise CompileError(f'Unable to compile switch expression at line {self.line}.') - - def case_condition(self, block_id): - return f'score {self.condition_var.selector} {self.condition_var.objective} matches {block_id}' - - def compile_block_case(self, func, id): - case_func = func.create_child_function() - block_state = self.id_block_states[id] - - if block_state not in self.block_state_list: - return - - case = self.block_state_list[block_state] - falling_block_nbt = self.falling_block_nbt[block_state] - - block = block_state.split('[')[0].replace('minecraft:', '') - - try: - case.compile(block, block_state, id, case_func, falling_block_nbt) - except CompileError as e: - print(e) - raise CompileError(f'Unable to compile block switch at line {self.line}') - - func.call_function( - case_func, - f'line{self.line:03}/case{id}', - f'execute if {self.case_condition(id)} run ' - ) - - def get_range_condition(self, func, ids): - return f'score {self.condition_var.selector} {self.condition_var.objective} matches {ids[0]}..{ids[-1]}' - - def get_case_ids(self): - return sorted(self.id_block_states.keys()) + def __init__(self, line, expr, cases, include_block_states): + self.line = line + self.expr = expr + self.cases = cases + self.include_block_states = include_block_states + + super(block_id_switch_block, self).__init__() + + def compile_initialization(self, func): + try: + var = self.expr.compile(func) + self.condition_var = var.get_scoreboard_var(func) + except CompileError as e: + print(e) + raise CompileError( + f"Unable to compile switch expression at line {self.line}." + ) + + def case_condition(self, block_id): + return f"score {self.condition_var.selector} {self.condition_var.objective} matches {block_id}" + + def compile_block_case(self, func, id): + case_func = func.create_child_function() + block_state = self.id_block_states[id] + + if block_state not in self.block_state_list: + return + + case = self.block_state_list[block_state] + falling_block_nbt = self.falling_block_nbt[block_state] + + block = block_state.split("[")[0].replace("minecraft:", "") + + try: + case.compile(block, block_state, id, case_func, falling_block_nbt) + except CompileError as e: + print(e) + raise CompileError( + f"Unable to compile block switch at line {self.line}" + ) + + func.call_function( + case_func, + f"line{self.line:03}/case{id}", + f"execute if {self.case_condition(id)} run ", + ) + + def get_range_condition(self, func, ids): + return f"score {self.condition_var.selector} {self.condition_var.objective} matches {ids[0]}..{ids[-1]}" + + def get_case_ids(self): + return sorted(self.id_block_states.keys()) diff --git a/block_types/block_switch_base.py b/block_types/block_switch_base.py index 1f69024..71683f9 100644 --- a/block_types/block_switch_base.py +++ b/block_types/block_switch_base.py @@ -1,126 +1,141 @@ from .block_base import block_base from CompileError import CompileError + class block_switch_base(block_base): - def __init__(self): - self.default_case = None - for case in self.cases: - if case.is_default: - if self.default_case: - raise CompileError(f'Block switch at line {self.line} has multiple default cases.') - else: - self.default_case = case - - self.block_state_list = {} - self.block_list = {} - self.block_state_ids = {} - self.id_block_states = {} - self.falling_block_nbt = {} - - # In child classes, can be used to initialize switch variables - def compile_initialization(self, func): - None - - # Create and call all required switch/case functions - def compile(self, func): - self.compile_initialization(func) - self.blocks = func.get_block_state_list(include_block_states=self.include_block_states) - self.get_block_state_list(func, self.blocks) - case_ids = self.get_case_ids() - - if self.default_case: - # If there is a default case, launch right into switch branches - self.compile_block_cases(func, case_ids) - else: - # If there isn't a default case, do initial check on all case ids - switch_func = func.create_child_function() - self.compile_block_cases(switch_func, case_ids) - func.call_function( - switch_func, - f'line{self.line:03}/switch_block', - f'execute if {self.get_range_condition(func, case_ids)} run ' - ) - - # Splits a list into four quartiles - def get_quartiles(self, list): - size = len(list) - return [ - list[:size//4], - list[size//4:size//2], - list[size//2:size*3//4], - list[size*3//4:]] - - # Creates switch and case function tree - def compile_block_cases(self, func, block_cases): - quartiles = self.get_quartiles(block_cases) - - for quartile in quartiles: - if len(quartile) == 0: - continue - - if len(quartile) == 1: - block_case = quartile[0] - - self.compile_block_case(func, block_case) - else: - range_func = func.create_child_function() - self.compile_block_cases(range_func, quartile) - - func.call_function( - range_func, - f'line{self.line:03}/switch_{str(quartile[0]).replace("minecraft:", "")}-{str(quartile[-1]).replace("minecraft:", "")}', - f'execute if {self.get_range_condition(func, quartile)} run ' - ) - - # Gets a block state name in command format from a json block state object - def get_block_state_name(self, block, state): - if 'properties' in state: - props = state['properties'] - - return f'{block}[{",".join(f"{p}={props[p]}" for p in props)}]' - else: - return block - - # Gets BlockProperties nbt from a json block state object - def get_falling_block_nbt(self, block, state): - if 'properties' in state: - props = state['properties'] - - return 'Name:"{}",Properties:{{{}}}'.format( - block, - ','.join('{}:"{}"'.format(p, props[p]) for p in props) - ) - - else: - return f'Name:"{block}"' - - # Gets a list of all block states matching some case (including the default case) - def get_block_state_list(self, func, blocks): - self.block_state_list = {} - self.block_list = {} - - for block in blocks: - for state in blocks[block]["states"]: - block_state = self.get_block_state_name(block, state) - - case = self.get_matching_case(func, block, state) - if case != None: - self.block_state_list[block_state] = case - if block not in self.block_list: - self.block_list[block] = [] - self.block_list[block].append(block_state) - self.block_state_ids[block_state] = state["id"] - self.falling_block_nbt[block_state] = self.get_falling_block_nbt(block, state) - - self.id_block_states = {self.block_state_ids[block_state]:block_state for block_state in self.block_state_ids} - - # Finds a case matching a block state in command format - def get_matching_case(self, func, block, state): - for case in self.cases: - if not case.is_default and case.matches(block, state): - return case - - if not case.is_default and case.block_name in func.block_tags and block.replace('minecraft:','') in func.block_tags[case.block_name]: - return case - - return self.default_case \ No newline at end of file + def __init__(self): + self.default_case = None + for case in self.cases: + if case.is_default: + if self.default_case: + raise CompileError( + f"Block switch at line {self.line} has multiple default cases." + ) + else: + self.default_case = case + + self.block_state_list = {} + self.block_list = {} + self.block_state_ids = {} + self.id_block_states = {} + self.falling_block_nbt = {} + + # In child classes, can be used to initialize switch variables + def compile_initialization(self, func): + None + + # Create and call all required switch/case functions + def compile(self, func): + self.compile_initialization(func) + self.blocks = func.get_block_state_list( + include_block_states=self.include_block_states + ) + self.get_block_state_list(func, self.blocks) + case_ids = self.get_case_ids() + + if self.default_case: + # If there is a default case, launch right into switch branches + self.compile_block_cases(func, case_ids) + else: + # If there isn't a default case, do initial check on all case ids + switch_func = func.create_child_function() + self.compile_block_cases(switch_func, case_ids) + func.call_function( + switch_func, + f"line{self.line:03}/switch_block", + f"execute if {self.get_range_condition(func, case_ids)} run ", + ) + + # Splits a list into four quartiles + def get_quartiles(self, list): + size = len(list) + return [ + list[: size // 4], + list[size // 4 : size // 2], + list[size // 2 : size * 3 // 4], + list[size * 3 // 4 :], + ] + + # Creates switch and case function tree + def compile_block_cases(self, func, block_cases): + quartiles = self.get_quartiles(block_cases) + + for quartile in quartiles: + if len(quartile) == 0: + continue + + if len(quartile) == 1: + block_case = quartile[0] + + self.compile_block_case(func, block_case) + else: + range_func = func.create_child_function() + self.compile_block_cases(range_func, quartile) + + func.call_function( + range_func, + f'line{self.line:03}/switch_{str(quartile[0]).replace("minecraft:", "")}-{str(quartile[-1]).replace("minecraft:", "")}', + f"execute if {self.get_range_condition(func, quartile)} run ", + ) + + # Gets a block state name in command format from a json block state object + def get_block_state_name(self, block, state): + if "properties" in state: + props = state["properties"] + + return f'{block}[{",".join(f"{p}={props[p]}" for p in props)}]' + else: + return block + + # Gets BlockProperties nbt from a json block state object + def get_falling_block_nbt(self, block, state): + if "properties" in state: + props = state["properties"] + + return 'Name:"{}",Properties:{{{}}}'.format( + block, ",".join('{}:"{}"'.format(p, props[p]) for p in props) + ) + + else: + return f'Name:"{block}"' + + # Gets a list of all block states matching some case (including the default case) + def get_block_state_list(self, func, blocks): + self.block_state_list = {} + self.block_list = {} + + for block in blocks: + for state in blocks[block]["states"]: + block_state = self.get_block_state_name(block, state) + + case = self.get_matching_case(func, block, state) + if case != None: + self.block_state_list[block_state] = case + if block not in self.block_list: + self.block_list[block] = [] + self.block_list[block].append(block_state) + self.block_state_ids[block_state] = state["id"] + self.falling_block_nbt[block_state] = ( + self.get_falling_block_nbt(block, state) + ) + + self.id_block_states = { + self.block_state_ids[block_state]: block_state + for block_state in self.block_state_ids + } + + # Finds a case matching a block state in command format + def get_matching_case(self, func, block, state): + for case in self.cases: + if not case.is_default and case.matches(block, state): + return case + + if ( + not case.is_default + and case.block_name in func.block_tags + and block.replace("minecraft:", "") + in func.block_tags[case.block_name] + ): + return case + + return self.default_case diff --git a/block_types/block_switch_block.py b/block_types/block_switch_block.py index caee58c..1e4e1b9 100644 --- a/block_types/block_switch_block.py +++ b/block_types/block_switch_block.py @@ -1,118 +1,136 @@ from .block_switch_base import block_switch_base from CompileError import CompileError + class block_switch_block(block_switch_base): - def __init__(self, line, coords, cases, include_block_states): - self.line = line - self.coords = coords - self.cases = cases - self.include_block_states = include_block_states - - super(block_switch_block, self).__init__() - - def case_condition(self, func, block_state): - return f'block {self.coords.get_value(func)} {block_state}' - - def compile_block_case(self, func, block): - single_case = self.get_matching_case(func, block, {}) - - if single_case and not single_case.is_default: - block_state = block - if 'properties' in self.blocks[block]: - first = True - block_state += '[' - - props = self.blocks[block]['properties'] - for prop in props: - if first: - first = False - else: - block_state += ',' - - block_state += f'{prop}={props[prop][0]}' - - block_state += ']' - - self.compile_single_case( - func, - block, - block, - block_state, - f'line{self.line:03}/case_{block.replace("minecraft:", "")}' - ) - elif 'properties' in self.blocks[block]: - case_func = func.create_child_function() - - props = self.blocks[block]['properties'] - self.compile_property_case(case_func, block, props.keys(), props, f'{block}[') - func.call_function( - case_func, - f'line{self.line:03}/switch_{block.replace("minecraft:", "")}/{block.replace("minecraft:", "")}', - f'execute if block {self.coords.get_value(func)} {block} run ' - ) - elif self.default_case: - self.compile_single_case( - func, - block, - block, - block, - f'line{self.line:03}/case_{block.replace("minecraft:", "")}' - ) - - def compile_property_case(self, func, block, prop_names, props, partial_block_state): - cur_prop_name = prop_names[0] - cur_prop = props[cur_prop_name] - - if len(prop_names) == 1: - for value in cur_prop: - block_state = f'{partial_block_state}{cur_prop_name}={value}]' - if block_state in self.block_state_list: - self.compile_single_case( - func, - block, - block_state, - block_state, - f'line{self.line:03}/switch_{block.replace("minecraft:", "")}/{cur_prop_name}_{value}' - ) - else: - for value in cur_prop: - block_state = f'{partial_block_state}{cur_prop_name}={value},' - - case_func = func.create_child_function() - - self.compile_property_case(case_func, block, prop_names[1:], props, block_state) - func.call_function( - case_func, - f'line{self.line:03}/switch_{block.replace("minecraft:", "")}/{cur_prop_name}_{value}', - f'execute if block {self.coords.get_value(func)} {block}[{cur_prop_name}={value}] run ' - ) - - - def compile_single_case(self, func, block, block_test, block_state, case_func_name): - id = self.block_state_ids[block_state] - case = self.block_state_list[block_state] - falling_block_nbt = self.falling_block_nbt[block_state] - - case_func = func.create_child_function() - try: - case.compile(block.replace('minecraft:', ''), block_state, id, case_func, falling_block_nbt) - except CompileError as e: - print(e) - raise CompileError(f'Unable to compile block switch case "{block_state}" at line {self.line}') - - func.call_function( - case_func, - case_func_name, - f'execute if {self.case_condition(func, block_test)} run ' - - ) - - def get_range_condition(self, func, blocks): - unique = func.get_unique_id() - block_tag_name = f'switch_{unique}' - func.register_block_tag(block_tag_name, [block.replace('minecraft:', '') for block in blocks]) - - return f'block {self.coords.get_value(func)} #{func.namespace}:{block_tag_name}' - - def get_case_ids(self): - return sorted(self.block_list.keys()) \ No newline at end of file + def __init__(self, line, coords, cases, include_block_states): + self.line = line + self.coords = coords + self.cases = cases + self.include_block_states = include_block_states + + super(block_switch_block, self).__init__() + + def case_condition(self, func, block_state): + return f"block {self.coords.get_value(func)} {block_state}" + + def compile_block_case(self, func, block): + single_case = self.get_matching_case(func, block, {}) + + if single_case and not single_case.is_default: + block_state = block + if "properties" in self.blocks[block]: + first = True + block_state += "[" + + props = self.blocks[block]["properties"] + for prop in props: + if first: + first = False + else: + block_state += "," + + block_state += f"{prop}={props[prop][0]}" + + block_state += "]" + + self.compile_single_case( + func, + block, + block, + block_state, + f'line{self.line:03}/case_{block.replace("minecraft:", "")}', + ) + elif "properties" in self.blocks[block]: + case_func = func.create_child_function() + + props = self.blocks[block]["properties"] + self.compile_property_case( + case_func, block, props.keys(), props, f"{block}[" + ) + func.call_function( + case_func, + f'line{self.line:03}/switch_{block.replace("minecraft:", "")}/{block.replace("minecraft:", "")}', + f"execute if block {self.coords.get_value(func)} {block} run ", + ) + elif self.default_case: + self.compile_single_case( + func, + block, + block, + block, + f'line{self.line:03}/case_{block.replace("minecraft:", "")}', + ) + + def compile_property_case( + self, func, block, prop_names, props, partial_block_state + ): + cur_prop_name = prop_names[0] + cur_prop = props[cur_prop_name] + + if len(prop_names) == 1: + for value in cur_prop: + block_state = f"{partial_block_state}{cur_prop_name}={value}]" + if block_state in self.block_state_list: + self.compile_single_case( + func, + block, + block_state, + block_state, + f'line{self.line:03}/switch_{block.replace("minecraft:", "")}/{cur_prop_name}_{value}', + ) + else: + for value in cur_prop: + block_state = f"{partial_block_state}{cur_prop_name}={value}," + + case_func = func.create_child_function() + + self.compile_property_case( + case_func, block, prop_names[1:], props, block_state + ) + func.call_function( + case_func, + f'line{self.line:03}/switch_{block.replace("minecraft:", "")}/{cur_prop_name}_{value}', + f"execute if block {self.coords.get_value(func)} {block}[{cur_prop_name}={value}] run ", + ) + + def compile_single_case( + self, func, block, block_test, block_state, case_func_name + ): + id = self.block_state_ids[block_state] + case = self.block_state_list[block_state] + falling_block_nbt = self.falling_block_nbt[block_state] + + case_func = func.create_child_function() + try: + case.compile( + block.replace("minecraft:", ""), + block_state, + id, + case_func, + falling_block_nbt, + ) + except CompileError as e: + print(e) + raise CompileError( + f'Unable to compile block switch case "{block_state}" at line {self.line}' + ) + + func.call_function( + case_func, + case_func_name, + f"execute if {self.case_condition(func, block_test)} run ", + ) + + def get_range_condition(self, func, blocks): + unique = func.get_unique_id() + block_tag_name = f"switch_{unique}" + func.register_block_tag( + block_tag_name, + [block.replace("minecraft:", "") for block in blocks], + ) + + return f"block {self.coords.get_value(func)} #{func.namespace}:{block_tag_name}" + + def get_case_ids(self): + return sorted(self.block_list.keys()) diff --git a/block_types/block_tag_block.py b/block_types/block_tag_block.py index 00e65a0..97b7b5e 100644 --- a/block_types/block_tag_block.py +++ b/block_types/block_tag_block.py @@ -1,10 +1,11 @@ from .block_base import block_base + class block_tag_block(block_base): - def __init__(self, line, name, blocks): - self.line = line - self.name = name - self.blocks = blocks - - def compile(self, func): - func.register_block_tag(self.name, self.blocks) \ No newline at end of file + def __init__(self, line, name, blocks): + self.line = line + self.name = name + self.blocks = blocks + + def compile(self, func): + func.register_block_tag(self.name, self.blocks) diff --git a/block_types/call_block_base.py b/block_types/call_block_base.py index 76f2265..8faa422 100644 --- a/block_types/call_block_base.py +++ b/block_types/call_block_base.py @@ -1,8 +1,9 @@ from .block_base import block_base + class call_block_base(block_base): def compile_with_macro_items(self, func): if self.with_macro_items == None: return - - self.with_macro_items.compile(func) \ No newline at end of file + + self.with_macro_items.compile(func) diff --git a/block_types/clock_section.py b/block_types/clock_section.py index 7ea9009..8c49bb1 100644 --- a/block_types/clock_section.py +++ b/block_types/clock_section.py @@ -1,17 +1,18 @@ from .block_base import block_base + class clock_section(block_base): - def __init__(self, line, id, lines): - self.line = line - self.id = id - self.lines = lines - - def compile(self, func): - clock_func = func.create_child_function(new_function_name = self.id) - func.register_clock(self.id) - func.register_function(self.id, clock_func) - self.compile_lines(clock_func, self.lines) - - @property - def block_name(self): - return f'clock "{self.id}"' + def __init__(self, line, id, lines): + self.line = line + self.id = id + self.lines = lines + + def compile(self, func): + clock_func = func.create_child_function(new_function_name=self.id) + func.register_clock(self.id) + func.register_function(self.id, clock_func) + self.compile_lines(clock_func, self.lines) + + @property + def block_name(self): + return f'clock "{self.id}"' diff --git a/block_types/command_block.py b/block_types/command_block.py index 58d2719..c2bd295 100644 --- a/block_types/command_block.py +++ b/block_types/command_block.py @@ -1,9 +1,10 @@ from .block_base import block_base + class command_block(block_base): - def __init__(self, line, text): - self.line = line - self.text = text - - def compile(self, func): - func.add_command(self.text) \ No newline at end of file + def __init__(self, line, text): + self.line = line + self.text = text + + def compile(self, func): + func.add_command(self.text) diff --git a/block_types/comment_block.py b/block_types/comment_block.py index 4999426..d7873b2 100644 --- a/block_types/comment_block.py +++ b/block_types/comment_block.py @@ -1,11 +1,12 @@ from .block_base import block_base + class comment_block(block_base): - def __init__(self, line, text): - self.line = line - self.text = text - if text[0] != '#': - raise Exception('Comment does not begin with "#"') - - def compile(self, func): - func.add_command(self.text) \ No newline at end of file + def __init__(self, line, text): + self.line = line + self.text = text + if text[0] != "#": + raise Exception('Comment does not begin with "#"') + + def compile(self, func): + func.add_command(self.text) diff --git a/block_types/create_block.py b/block_types/create_block.py index 9c82d9d..3e557ca 100644 --- a/block_types/create_block.py +++ b/block_types/create_block.py @@ -1,12 +1,13 @@ from .block_base import block_base + class create_block(block_base): - def __init__(self, line, atid, relcoords, index): - self.line = line - self.atid = atid - self.relcoords = relcoords - self.index = index - - def compile(self, func): - if not func.run_create(self.atid, self.relcoords, self.index): - raise Exception(f'Error creating entity at line {self.line}') + def __init__(self, line, atid, relcoords, index): + self.line = line + self.atid = atid + self.relcoords = relcoords + self.index = index + + def compile(self, func): + if not func.run_create(self.atid, self.relcoords, self.index): + raise Exception(f"Error creating entity at line {self.line}") diff --git a/block_types/define_name_block.py b/block_types/define_name_block.py index 85547f9..31ac715 100644 --- a/block_types/define_name_block.py +++ b/block_types/define_name_block.py @@ -1,5 +1,6 @@ from .block_base import block_base + class define_name_block(block_base): def __init__(self, line, id, str): self.line = line @@ -7,4 +8,4 @@ def __init__(self, line, id, str): self.str = str[1:-1] def compile(self, func): - func.register_name_definition(self.id, self.str) \ No newline at end of file + func.register_name_definition(self.id, self.str) diff --git a/block_types/entity_tag_block.py b/block_types/entity_tag_block.py index 30b08d1..19264de 100644 --- a/block_types/entity_tag_block.py +++ b/block_types/entity_tag_block.py @@ -1,10 +1,11 @@ from .block_base import block_base + class entity_tag_block(block_base): - def __init__(self, line, name, entities): - self.line = line - self.name = name - self.entities = entities - - def compile(self, func): - func.register_entity_tag(self.name, self.entities) \ No newline at end of file + def __init__(self, line, name, entities): + self.line = line + self.name = name + self.entities = entities + + def compile(self, func): + func.register_entity_tag(self.name, self.entities) diff --git a/block_types/execute_base.py b/block_types/execute_base.py index 5b76318..cd9581e 100644 --- a/block_types/execute_base.py +++ b/block_types/execute_base.py @@ -2,64 +2,71 @@ import traceback from CompileError import CompileError + class execute_base(block_base): - # Override to force the creation of a sub function, even for a single command - def force_sub_function(self): - return False - - # By default, no continuation is added to the end of the sub function - def add_continuation_command(self, func, exec_func): - None - - def prepare_scratch(self, func): - None - - def perform_execute(self, func): - self.prepare_scratch(func) - exec_func = func.create_child_function() - - cmd = 'execute ' + func.get_execute_items(self.exec_items, exec_func) - if cmd == None: - raise CompileError(f'Unable to compile {self.display_name()} block at line {self.line}') - - try: - exec_func.compile_blocks(self.sub) - except CompileError as e: - print(e) - raise CompileError(f'Unable to compile {self.display_name()} block contents at line {self.line}') - except Exception as e: - print(traceback.format_exc()) - raise CompileError(f'Unable to compile {self.display_name()} block contents at line {self.line}') - - single = exec_func.single_command() - if single == None or self.force_sub_function(): - unique = func.get_unique_id() - func_name = f'line{self.line:03}/{self.display_name()}{unique}' - func.register_function(func_name, exec_func) - - self.add_continuation_command(func, exec_func) - - func.add_command(f'{cmd}run {exec_func.get_call()}') - else: - if single.startswith('/'): - single = single[1:] - - macro = False - if single.startswith('$'): - single = single[1:] - macro = True - - if single.startswith('execute '): - cmd = cmd + single[len('execute '):] - else: - cmd = cmd + 'run ' + single - - if macro: - cmd = '$' + cmd - - func.add_command(cmd) - - self.compile_else(func) - - def compile_else(self, func): - None \ No newline at end of file + # Override to force the creation of a sub function, even for a single command + def force_sub_function(self): + return False + + # By default, no continuation is added to the end of the sub function + def add_continuation_command(self, func, exec_func): + None + + def prepare_scratch(self, func): + None + + def perform_execute(self, func): + self.prepare_scratch(func) + exec_func = func.create_child_function() + + cmd = "execute " + func.get_execute_items(self.exec_items, exec_func) + if cmd == None: + raise CompileError( + f"Unable to compile {self.display_name()} block at line {self.line}" + ) + + try: + exec_func.compile_blocks(self.sub) + except CompileError as e: + print(e) + raise CompileError( + f"Unable to compile {self.display_name()} block contents at line {self.line}" + ) + except Exception as e: + print(traceback.format_exc()) + raise CompileError( + f"Unable to compile {self.display_name()} block contents at line {self.line}" + ) + + single = exec_func.single_command() + if single == None or self.force_sub_function(): + unique = func.get_unique_id() + func_name = f"line{self.line:03}/{self.display_name()}{unique}" + func.register_function(func_name, exec_func) + + self.add_continuation_command(func, exec_func) + + func.add_command(f"{cmd}run {exec_func.get_call()}") + else: + if single.startswith("/"): + single = single[1:] + + macro = False + if single.startswith("$"): + single = single[1:] + macro = True + + if single.startswith("execute "): + cmd = cmd + single[len("execute ") :] + else: + cmd = cmd + "run " + single + + if macro: + cmd = "$" + cmd + + func.add_command(cmd) + + self.compile_else(func) + + def compile_else(self, func): + None diff --git a/block_types/execute_block.py b/block_types/execute_block.py index fe6c766..badea04 100644 --- a/block_types/execute_block.py +++ b/block_types/execute_block.py @@ -2,79 +2,88 @@ from CompileError import CompileError import traceback + class execute_block(execute_base): - def __init__(self, line, exec_items, sub, else_list = []): - self.line = line - self.exec_items = exec_items - self.sub = sub - self.else_list = else_list - - def compile(self, func): - self.perform_execute(func) - - def display_name(self): - return 'execute' - - def add_continuation_command(self, func, exec_func): - if len(self.else_list) > 0: - func.add_command(f'scoreboard players set Global {self.scratch} 1') - exec_func.add_command(f'scoreboard players set Global {self.scratch} 0') - - def force_sub_function(self): - return len(self.else_list) > 0 - - def prepare_scratch(self, func): - if len(self.else_list) > 0: - self.scratch = func.get_scratch() - - def compile_else(self, func): - if len(self.else_list) == 0: - return - - for idx in range(len(self.else_list)): - execute_items, else_sub = self.else_list[idx] - exec_func = func.create_child_function() - - try: - exec_func.compile_blocks(else_sub) - except CompileError as e: - print(e) - raise CompileError(f'Unable to compile else block contents at line {self.display_name()}') - except Exception as e: - print(traceback.format_exc()) - raise CompileError(f'Unable to compile else block contents at line {self.display_name()}') - - if execute_items == None: - exec_text = '' - else: - exec_text = func.get_execute_items(execute_items, exec_func) - prefix = f'execute if score Global {self.scratch} matches 1.. {exec_text}' - if idx < len(self.else_list) - 1: - # There are more else items, so make sure we don't run them - exec_func.add_command(f'scoreboard players set Global {self.scratch} 0') - - single = exec_func.single_command() - if single == None: - unique = func.get_unique_id() - func_name = f'line{self.line:03}/else{unique}' - func.register_function(func_name, exec_func) - - func.add_command(f'{prefix}run {exec_func.get_call()}') - else: - if single.startswith('/'): - single = single[1:] - - cmd = "" - - if single.startswith('$'): - single = single[1:] - cmd = "$" - - if single.startswith('execute '): - cmd = cmd + prefix + single[len('execute '):] - else: - cmd = cmd + prefix + 'run ' + single - - func.add_command(cmd) - - func.free_scratch(self.scratch) \ No newline at end of file + def __init__(self, line, exec_items, sub, else_list=[]): + self.line = line + self.exec_items = exec_items + self.sub = sub + self.else_list = else_list + + def compile(self, func): + self.perform_execute(func) + + def display_name(self): + return "execute" + + def add_continuation_command(self, func, exec_func): + if len(self.else_list) > 0: + func.add_command(f"scoreboard players set Global {self.scratch} 1") + exec_func.add_command( + f"scoreboard players set Global {self.scratch} 0" + ) + + def force_sub_function(self): + return len(self.else_list) > 0 + + def prepare_scratch(self, func): + if len(self.else_list) > 0: + self.scratch = func.get_scratch() + + def compile_else(self, func): + if len(self.else_list) == 0: + return + + for idx in range(len(self.else_list)): + execute_items, else_sub = self.else_list[idx] + exec_func = func.create_child_function() + + try: + exec_func.compile_blocks(else_sub) + except CompileError as e: + print(e) + raise CompileError( + f"Unable to compile else block contents at line {self.display_name()}" + ) + except Exception as e: + print(traceback.format_exc()) + raise CompileError( + f"Unable to compile else block contents at line {self.display_name()}" + ) + + if execute_items == None: + exec_text = "" + else: + exec_text = func.get_execute_items(execute_items, exec_func) + prefix = f"execute if score Global {self.scratch} matches 1.. {exec_text}" + if idx < len(self.else_list) - 1: + # There are more else items, so make sure we don't run them + exec_func.add_command( + f"scoreboard players set Global {self.scratch} 0" + ) + + single = exec_func.single_command() + if single == None: + unique = func.get_unique_id() + func_name = f"line{self.line:03}/else{unique}" + func.register_function(func_name, exec_func) + + func.add_command(f"{prefix}run {exec_func.get_call()}") + else: + if single.startswith("/"): + single = single[1:] + + cmd = "" + + if single.startswith("$"): + single = single[1:] + cmd = "$" + + if single.startswith("execute "): + cmd = cmd + prefix + single[len("execute ") :] + else: + cmd = cmd + prefix + "run " + single + + func.add_command(cmd) + + func.free_scratch(self.scratch) diff --git a/block_types/for_index_block.py b/block_types/for_index_block.py index 86ae5c8..7baad70 100644 --- a/block_types/for_index_block.py +++ b/block_types/for_index_block.py @@ -2,93 +2,104 @@ import traceback from CompileError import CompileError + class for_index_block(block_base): - def __init__(self, line, var, fr, to, by, sub): - self.line = line - self.var = var - self.fr = fr - self.to = to - self.by = by - self.sub = sub - - def compile(self, func): - var, fr, to, by, sub = self.var, self.fr, self.to, self.by, self.sub - - from_var = fr.compile(func, var.get_assignto(func)) - var.copy_from(func, from_var) - - to_var = to.compile(func).get_scoreboard_var(func) - - if by != None: - by_var = by.compile(func) - by_const = by_var.get_const_value(func) - - if by_const == None: - by_var = by_var.get_scoreboard_var(func) - else: - by_const = int(by_const) - - unique = func.get_unique_id() - loop_func_name = f'line{self.line:03}/for{unique:03}' - - loop_func = func.create_child_function() - func.register_function(loop_func_name, loop_func) - - if var.uses_macro(func): - loop_func.has_macros = True - - if to_var.uses_macro(func): - loop_func.has_macros = True - - if by != None and by_const == None and by_var.uses_macro(func): - loop_func.has_macros = True - - try: - loop_func.compile_blocks(sub) - except CompileError as e: - print(e) - raise CompileError(f'Unable to compile for block contents at line {self.line}') - except Exception as e: - print(traceback.print_exc()) - raise CompileError(f'Unable to compile for block contents at line {self.line}') - - if by == None: - # Use a temporary version of the counting var to work with the scoreboard - temp_var = var.get_scoreboard_var(func) - continue_command = f'execute if score {temp_var.get_selvar(func)} <= {to_var.get_selvar(func)} run {loop_func.get_call()}' - func.add_command(continue_command) - - # Add 1 to the counter variable - loop_func.add_command(f'scoreboard players add {temp_var.get_selvar(func)} 1') - var.copy_from(func, temp_var) - - loop_func.add_command(continue_command) - else: - # Use a temporary version of the counting var to work with the scoreboard - temp_var = var.get_scoreboard_var(func) - - if by_const: - continue_command = f'execute if score {temp_var.get_selvar(func)} {"<=" if by_const >= 0 else ">="} {to_var.get_selvar(func)} run {loop_func.get_call()}' - func.add_command(continue_command) - - loop_func.add_command(f'scoreboard players {"add" if by_const > 0 else "remove"} {temp_var.get_selvar(func)} {abs(by_const)}') - else: - continue_negative_command = f'execute if score {by_var.get_selvar(func)} matches ..-1 if score {temp_var.get_selvar(func)} >= {to_var.get_selvar(func)} run {loop_func.get_call()}' - continue_positive_command = f'execute if score {by_var.get_selvar(func)} matches 1.. if score {temp_var.get_selvar(func)} <= {to_var.get_selvar(func)} run {loop_func.get_call()}' - func.add_command(continue_negative_command) - func.add_command(continue_positive_command) - - loop_func.add_command(f'scoreboard players operation {temp_var.get_selvar(func)} += {by_var.get_selvar(func)}') - - var.copy_from(func, temp_var) - - if by_const: - loop_func.add_command(continue_command) - else: - loop_func.add_command(continue_negative_command) - loop_func.add_command(continue_positive_command) - - to_var.free_scratch(func) - from_var.free_scratch(func) - if by != None: - by_var.free_scratch(func) + def __init__(self, line, var, fr, to, by, sub): + self.line = line + self.var = var + self.fr = fr + self.to = to + self.by = by + self.sub = sub + + def compile(self, func): + var, fr, to, by, sub = self.var, self.fr, self.to, self.by, self.sub + + from_var = fr.compile(func, var.get_assignto(func)) + var.copy_from(func, from_var) + + to_var = to.compile(func).get_scoreboard_var(func) + + if by != None: + by_var = by.compile(func) + by_const = by_var.get_const_value(func) + + if by_const == None: + by_var = by_var.get_scoreboard_var(func) + else: + by_const = int(by_const) + + unique = func.get_unique_id() + loop_func_name = f"line{self.line:03}/for{unique:03}" + + loop_func = func.create_child_function() + func.register_function(loop_func_name, loop_func) + + if var.uses_macro(func): + loop_func.has_macros = True + + if to_var.uses_macro(func): + loop_func.has_macros = True + + if by != None and by_const == None and by_var.uses_macro(func): + loop_func.has_macros = True + + try: + loop_func.compile_blocks(sub) + except CompileError as e: + print(e) + raise CompileError( + f"Unable to compile for block contents at line {self.line}" + ) + except Exception as e: + print(traceback.print_exc()) + raise CompileError( + f"Unable to compile for block contents at line {self.line}" + ) + + if by == None: + # Use a temporary version of the counting var to work with the scoreboard + temp_var = var.get_scoreboard_var(func) + continue_command = f"execute if score {temp_var.get_selvar(func)} <= {to_var.get_selvar(func)} run {loop_func.get_call()}" + func.add_command(continue_command) + + # Add 1 to the counter variable + loop_func.add_command( + f"scoreboard players add {temp_var.get_selvar(func)} 1" + ) + var.copy_from(func, temp_var) + + loop_func.add_command(continue_command) + else: + # Use a temporary version of the counting var to work with the scoreboard + temp_var = var.get_scoreboard_var(func) + + if by_const: + continue_command = f'execute if score {temp_var.get_selvar(func)} {"<=" if by_const >= 0 else ">="} {to_var.get_selvar(func)} run {loop_func.get_call()}' + func.add_command(continue_command) + + loop_func.add_command( + f'scoreboard players {"add" if by_const > 0 else "remove"} {temp_var.get_selvar(func)} {abs(by_const)}' + ) + else: + continue_negative_command = f"execute if score {by_var.get_selvar(func)} matches ..-1 if score {temp_var.get_selvar(func)} >= {to_var.get_selvar(func)} run {loop_func.get_call()}" + continue_positive_command = f"execute if score {by_var.get_selvar(func)} matches 1.. if score {temp_var.get_selvar(func)} <= {to_var.get_selvar(func)} run {loop_func.get_call()}" + func.add_command(continue_negative_command) + func.add_command(continue_positive_command) + + loop_func.add_command( + f"scoreboard players operation {temp_var.get_selvar(func)} += {by_var.get_selvar(func)}" + ) + + var.copy_from(func, temp_var) + + if by_const: + loop_func.add_command(continue_command) + else: + loop_func.add_command(continue_negative_command) + loop_func.add_command(continue_positive_command) + + to_var.free_scratch(func) + from_var.free_scratch(func) + if by != None: + by_var.free_scratch(func) diff --git a/block_types/for_selector_block.py b/block_types/for_selector_block.py index a11c862..866a580 100644 --- a/block_types/for_selector_block.py +++ b/block_types/for_selector_block.py @@ -2,42 +2,51 @@ from CompileError import CompileError import traceback + class for_selector_block(block_base): - def __init__(self, line, id, selector, sub): - self.line = line - self.id = id - self.selector = selector - self.sub = sub - - def compile(self, func): - scratch_id = func.get_scratch() - - exec_func = func.create_child_function() - - combined_selector = func.get_combined_selector(self.selector) - combined_selector.scores_min[scratch_id] = 1 - combined_selector.set_part('limit', '1') - exec_func.selectors[self.id] = combined_selector - exec_func.update_self_selector(self.selector) - - func.add_command(f'scoreboard players set {self.selector} {scratch_id} 0') - exec_func.add_command(f'scoreboard players set @s {scratch_id} 1') - - try: - exec_func.compile_blocks(self.sub) - except CompileError as e: - print(e) - raise CompileError(f'Unable to compile for block contents at line {self.line}') - except: - print(traceback.format_exc()) - raise CompileError(f'Unable to compile for block contents at line {self.line}') - - exec_func.add_command(f'scoreboard players set @s {scratch_id} 0') - - func.free_scratch(scratch_id) - - unique = func.get_unique_id() - exec_name = f'for{unique}_ln{self.line}' - func.register_function(exec_name, exec_func) - - func.add_command(f'execute as {self.selector} run {exec_func.get_call()}') + def __init__(self, line, id, selector, sub): + self.line = line + self.id = id + self.selector = selector + self.sub = sub + + def compile(self, func): + scratch_id = func.get_scratch() + + exec_func = func.create_child_function() + + combined_selector = func.get_combined_selector(self.selector) + combined_selector.scores_min[scratch_id] = 1 + combined_selector.set_part("limit", "1") + exec_func.selectors[self.id] = combined_selector + exec_func.update_self_selector(self.selector) + + func.add_command( + f"scoreboard players set {self.selector} {scratch_id} 0" + ) + exec_func.add_command(f"scoreboard players set @s {scratch_id} 1") + + try: + exec_func.compile_blocks(self.sub) + except CompileError as e: + print(e) + raise CompileError( + f"Unable to compile for block contents at line {self.line}" + ) + except: + print(traceback.format_exc()) + raise CompileError( + f"Unable to compile for block contents at line {self.line}" + ) + + exec_func.add_command(f"scoreboard players set @s {scratch_id} 0") + + func.free_scratch(scratch_id) + + unique = func.get_unique_id() + exec_name = f"for{unique}_ln{self.line}" + func.register_function(exec_name, exec_func) + + func.add_command( + f"execute as {self.selector} run {exec_func.get_call()}" + ) diff --git a/block_types/function_call_block.py b/block_types/function_call_block.py index 4edae6b..c0d96df 100644 --- a/block_types/function_call_block.py +++ b/block_types/function_call_block.py @@ -1,33 +1,40 @@ from .call_block_base import call_block_base + class function_call_block(call_block_base): - def __init__(self, line, dest, args, with_macro_items): - self.line = line - self.dest, self.args, self.with_macro_items = dest, args, with_macro_items - - def compile(self, func): - if self.dest == func.name: - locals = func.get_local_variables() - func.push_locals(locals) - - self.compile_with_macro_items(func) - - if not func.evaluate_params(self.args): - raise Exception(f'Unable to evaluate function call parameters at line {self.line}') - - cmd = "" - - if ':' in self.dest: - cmd = f'function {self.dest}' - else: - # Default to this datapack's namespace - cmd = f'function {func.namespace}:{self.dest}' - - if self.with_macro_items != None: - cmd += f' with storage {func.namespace}:global args' - func.has_macros = True - - func.add_command(cmd) - - if self.dest == func.name: - func.pop_locals(locals) + def __init__(self, line, dest, args, with_macro_items): + self.line = line + self.dest, self.args, self.with_macro_items = ( + dest, + args, + with_macro_items, + ) + + def compile(self, func): + if self.dest == func.name: + locals = func.get_local_variables() + func.push_locals(locals) + + self.compile_with_macro_items(func) + + if not func.evaluate_params(self.args): + raise Exception( + f"Unable to evaluate function call parameters at line {self.line}" + ) + + cmd = "" + + if ":" in self.dest: + cmd = f"function {self.dest}" + else: + # Default to this datapack's namespace + cmd = f"function {func.namespace}:{self.dest}" + + if self.with_macro_items != None: + cmd += f" with storage {func.namespace}:global args" + func.has_macros = True + + func.add_command(cmd) + + if self.dest == func.name: + func.pop_locals(locals) diff --git a/block_types/function_section.py b/block_types/function_section.py index 4aaf6c4..99f415d 100644 --- a/block_types/function_section.py +++ b/block_types/function_section.py @@ -1,28 +1,27 @@ from .block_base import block_base + class function_section(block_base): - def __init__(self, line, name, params, lines): - self.line = line - self.name = name - self.params = params - self.lines = lines - self.self_selector = None - - def compile(self, func): - func_func = func.create_child_function( - new_function_name = self.name, - callable = True, - params = self.params - ) - func.register_function(self.name, func_func) - - if self.self_selector: - func_func.update_self_selector(self.self_selector) - self.compile_lines(func_func, self.lines) - - def register(self, global_context): - global_context.register_function_params(self.name, self.params) - - @property - def block_name(self): - return f'function "{self.name}"' + def __init__(self, line, name, params, lines): + self.line = line + self.name = name + self.params = params + self.lines = lines + self.self_selector = None + + def compile(self, func): + func_func = func.create_child_function( + new_function_name=self.name, callable=True, params=self.params + ) + func.register_function(self.name, func_func) + + if self.self_selector: + func_func.update_self_selector(self.self_selector) + self.compile_lines(func_func, self.lines) + + def register(self, global_context): + global_context.register_function_params(self.name, self.params) + + @property + def block_name(self): + return f'function "{self.name}"' diff --git a/block_types/import_block.py b/block_types/import_block.py index 2f1e88b..510d576 100644 --- a/block_types/import_block.py +++ b/block_types/import_block.py @@ -2,20 +2,27 @@ import traceback from CompileError import CompileError + class import_block(block_base): - def __init__(self, line, filename): - self.line = line - self.filename = filename - - def compile(self, func): - try: - func.import_file(self.filename + '.cblib') - except SyntaxError as e: - print(e) - raise CompileError(f'Importing file "{self.filename}" failed at line {self.line}:\n{e}') - except CompileError as e: - print(e) - raise CompileError(f'Importing file "{self.filename}" failed at line {self.line}:\n{e}') - except Exception as e: - print(traceback.format_exc()) - raise CompileError(f'Importing file "{self.filename}" failed at line {self.line}:\n{e}') + def __init__(self, line, filename): + self.line = line + self.filename = filename + + def compile(self, func): + try: + func.import_file(self.filename + ".cblib") + except SyntaxError as e: + print(e) + raise CompileError( + f'Importing file "{self.filename}" failed at line {self.line}:\n{e}' + ) + except CompileError as e: + print(e) + raise CompileError( + f'Importing file "{self.filename}" failed at line {self.line}:\n{e}' + ) + except Exception as e: + print(traceback.format_exc()) + raise CompileError( + f'Importing file "{self.filename}" failed at line {self.line}:\n{e}' + ) diff --git a/block_types/item_modifier_definition_block.py b/block_types/item_modifier_definition_block.py index 1cc3a3e..605b8bc 100644 --- a/block_types/item_modifier_definition_block.py +++ b/block_types/item_modifier_definition_block.py @@ -1,10 +1,11 @@ from .block_base import block_base + class item_modifier_definition_block(block_base): - def __init__(self, line, name, json): - self.line = line - self.name = name - self.json = json - - def compile(self, func): - func.add_item_modifier(self.name, self.json) \ No newline at end of file + def __init__(self, line, name, json): + self.line = line + self.name = name + self.json = json + + def compile(self, func): + func.add_item_modifier(self.name, self.json) diff --git a/block_types/item_tag_block.py b/block_types/item_tag_block.py index 9b9b14b..b6e0e7d 100644 --- a/block_types/item_tag_block.py +++ b/block_types/item_tag_block.py @@ -1,10 +1,11 @@ from .block_base import block_base + class item_tag_block(block_base): - def __init__(self, line, name, items): - self.line = line - self.name = name - self.items = items - - def compile(self, func): - func.register_item_tag(self.name, self.items) \ No newline at end of file + def __init__(self, line, name, items): + self.line = line + self.name = name + self.items = items + + def compile(self, func): + func.register_item_tag(self.name, self.items) diff --git a/block_types/loot_table_definition_block.py b/block_types/loot_table_definition_block.py index b4c2b72..be9d3af 100644 --- a/block_types/loot_table_definition_block.py +++ b/block_types/loot_table_definition_block.py @@ -1,11 +1,12 @@ from .block_base import block_base + class loot_table_definition_block(block_base): - def __init__(self, line, type, name, json): - self.line = line - self.type = type - self.name = name - self.json = json - - def compile(self, func): - func.add_loot_table(self.name, (self.type, self.json)) \ No newline at end of file + def __init__(self, line, type, name, json): + self.line = line + self.type = type + self.name = name + self.json = json + + def compile(self, func): + func.add_loot_table(self.name, (self.type, self.json)) diff --git a/block_types/macro_call_block.py b/block_types/macro_call_block.py index f4edeb5..36103bf 100644 --- a/block_types/macro_call_block.py +++ b/block_types/macro_call_block.py @@ -1,36 +1,44 @@ from .block_base import block_base -from mcfunction import isNumber from CompileError import CompileError import traceback + class macro_call_block(block_base): - def __init__(self, line, macro, args): - self.line = line - self.macro, self.args = macro, args - - def compile(self, func): - if self.macro not in func.macros: - raise CompileError(f'Line {self.line}: macro "{self.macro}" does not exist') - - params, sub = func.macros[self.macro] - - if len(self.args) != len(params): - raise CompileError(f'Tried to call Macro "{macro}" with {len(args)} arguments at line {get_line(line)}, but it requires {len(params)}') - - new_env = func.clone_environment() - - for p in range(len(params)): - new_env.set_dollarid(params[p], self.args[p].get_value(func)) - - func.push_environment(new_env) - - try: - func.compile_blocks(sub) - except CompileError as e: - print(e) - raise CompileError(f'Unable to compile macro contents at line {self.line}') - except Exception as e: - print(traceback.format_exc()) - raise CompileError(f'Unable to compile macro contents at line {self.line}') - - func.pop_environment() + def __init__(self, line, macro, args): + self.line = line + self.macro, self.args = macro, args + + def compile(self, func): + if self.macro not in func.macros: + raise CompileError( + f'Line {self.line}: macro "{self.macro}" does not exist' + ) + + params, sub = func.macros[self.macro] + + if len(self.args) != len(params): + raise CompileError( + f'Tried to call Macro "{macro}" with {len(args)} arguments at line {get_line(line)}, but it requires {len(params)}' + ) + + new_env = func.clone_environment() + + for p in range(len(params)): + new_env.set_dollarid(params[p], self.args[p].get_value(func)) + + func.push_environment(new_env) + + try: + func.compile_blocks(sub) + except CompileError as e: + print(e) + raise CompileError( + f"Unable to compile macro contents at line {self.line}" + ) + except Exception as e: + print(traceback.format_exc()) + raise CompileError( + f"Unable to compile macro contents at line {self.line}" + ) + + func.pop_environment() diff --git a/block_types/macro_section.py b/block_types/macro_section.py index 3e308c8..a530483 100644 --- a/block_types/macro_section.py +++ b/block_types/macro_section.py @@ -1,18 +1,19 @@ from .block_base import block_base + class macro_section(block_base): - def __init__(self, line, name, params, lines): - self.line = line - self.name = name - self.params = params - self.lines = lines + def __init__(self, line, name, params, lines): + self.line = line + self.name = name + self.params = params + self.lines = lines + + def compile(self, func): + None + + def register(self, global_context): + global_context.macros[self.name] = (self.params, self.lines) - def compile(self, func): - None - - def register(self, global_context): - global_context.macros[self.name] = (self.params, self.lines) - - @property - def block_name(self): - return f'macro "${self.name}"' + @property + def block_name(self): + return f'macro "${self.name}"' diff --git a/block_types/method_call_block.py b/block_types/method_call_block.py index d299a01..f001249 100644 --- a/block_types/method_call_block.py +++ b/block_types/method_call_block.py @@ -1,25 +1,33 @@ from .call_block_base import call_block_base + class method_call_block(call_block_base): - def __init__(self, line, selector, dest, params, with_macro_items): - self.line = line - self.selector, self.dest, self.params, self.with_macro_items = selector, dest, params, with_macro_items - - def compile(self, func): - self.compile_with_macro_items(func) - - if not func.evaluate_params(self.params): - raise Exception(f'Unable to evaluate method call parameters at line {self.line}') - - cmd = "" - - if self.selector == '@s' or self.selector == '@s[]': - cmd = f'function {func.namespace}:{self.dest}' - else: - cmd = f'execute as {self.selector} run function {func.namespace}:{self.dest}' - - if self.with_macro_items != None: - cmd += f' with storage {func.namespace}:global args' - self.has_macros = True - - func.add_command(cmd) + def __init__(self, line, selector, dest, params, with_macro_items): + self.line = line + self.selector, self.dest, self.params, self.with_macro_items = ( + selector, + dest, + params, + with_macro_items, + ) + + def compile(self, func): + self.compile_with_macro_items(func) + + if not func.evaluate_params(self.params): + raise Exception( + f"Unable to evaluate method call parameters at line {self.line}" + ) + + cmd = "" + + if self.selector == "@s" or self.selector == "@s[]": + cmd = f"function {func.namespace}:{self.dest}" + else: + cmd = f"execute as {self.selector} run function {func.namespace}:{self.dest}" + + if self.with_macro_items != None: + cmd += f" with storage {func.namespace}:global args" + self.has_macros = True + + func.add_command(cmd) diff --git a/block_types/move_block.py b/block_types/move_block.py index 176d950..1a6489f 100644 --- a/block_types/move_block.py +++ b/block_types/move_block.py @@ -1,15 +1,16 @@ from .block_base import block_base + class move_block(block_base): - def __init__(self, line, selector, coords): - self.line = line - self.selector = selector - self.coords = coords - - def compile(self, func): - if self.selector == '@s' or self.selector == '@s[]': - cmd = f'execute at @s run tp @s {self.coords.get_value(func)}' - else: - cmd = f'execute as {self.selector} at @s run tp @s {self.coords.get_value(func)}' - - func.add_command(cmd) + def __init__(self, line, selector, coords): + self.line = line + self.selector = selector + self.coords = coords + + def compile(self, func): + if self.selector == "@s" or self.selector == "@s[]": + cmd = f"execute at @s run tp @s {self.coords.get_value(func)}" + else: + cmd = f"execute as {self.selector} at @s run tp @s {self.coords.get_value(func)}" + + func.add_command(cmd) diff --git a/block_types/nbt_data_block.py b/block_types/nbt_data_block.py index a61b563..570b9a4 100644 --- a/block_types/nbt_data_block.py +++ b/block_types/nbt_data_block.py @@ -1,11 +1,14 @@ from .block_base import block_base + class nbt_data_block(block_base): - def __init__(self, line, dest, op, source): - self.line = line - self.dest = dest - self.op = op - self.source = source + def __init__(self, line, dest, op, source): + self.line = line + self.dest = dest + self.op = op + self.source = source - def compile(self, func): - func.add_command(f'data modify {self.dest.get_dest_path(func)} {self.op} {self.source.get_source_path(func)}') + def compile(self, func): + func.add_command( + f"data modify {self.dest.get_dest_path(func)} {self.op} {self.source.get_source_path(func)}" + ) diff --git a/block_types/nbt_remove_block.py b/block_types/nbt_remove_block.py index 709d18b..3367371 100644 --- a/block_types/nbt_remove_block.py +++ b/block_types/nbt_remove_block.py @@ -1,9 +1,10 @@ from .block_base import block_base + class nbt_remove_block(block_base): - def __init__(self, line, path): - self.line = line - self.path = path + def __init__(self, line, path): + self.line = line + self.path = path - def compile(self, func): - func.add_command(f'data remove {self.path.get_dest_path(func)}') + def compile(self, func): + func.add_command(f"data remove {self.path.get_dest_path(func)}") diff --git a/block_types/pointer_decl_block.py b/block_types/pointer_decl_block.py index ffe37f8..124a23d 100644 --- a/block_types/pointer_decl_block.py +++ b/block_types/pointer_decl_block.py @@ -1,10 +1,11 @@ from .block_base import block_base + class pointer_decl_block(block_base): - def __init__(self, line, id, selector): - self.line = line - self.id = id - self.selector = selector - - def compile(self, func): - func.add_pointer(self.id, self.selector) \ No newline at end of file + def __init__(self, line, id, selector): + self.line = line + self.id = id + self.selector = selector + + def compile(self, func): + func.add_pointer(self.id, self.selector) diff --git a/block_types/pop_block.py b/block_types/pop_block.py index 29dd9c1..64df634 100644 --- a/block_types/pop_block.py +++ b/block_types/pop_block.py @@ -1,17 +1,18 @@ from .block_base import block_base from variable_types.storage_path_var import storage_path_var + class pop_block(block_base): - def __init__(self, line, var_list): - self.var_list = var_list - self.line = line - - def compile(self, func): - idx = 0 - for var in self.var_list: - data_var = storage_path_var(None, f'stack[-1].v{idx}') - var.copy_from(func, data_var) - - idx += 1 - - func.add_command(f'data remove storage {func.namespace} stack[-1]') + def __init__(self, line, var_list): + self.var_list = var_list + self.line = line + + def compile(self, func): + idx = 0 + for var in self.var_list: + data_var = storage_path_var(None, f"stack[-1].v{idx}") + var.copy_from(func, data_var) + + idx += 1 + + func.add_command(f"data remove storage {func.namespace} stack[-1]") diff --git a/block_types/predicate_definition_block.py b/block_types/predicate_definition_block.py index ae4008b..1a74406 100644 --- a/block_types/predicate_definition_block.py +++ b/block_types/predicate_definition_block.py @@ -1,10 +1,11 @@ from .block_base import block_base + class predicate_definition_block(block_base): - def __init__(self, line, name, json): - self.line = line - self.name = name - self.json = json - - def compile(self, func): - func.add_predicate(self.name, self.json) \ No newline at end of file + def __init__(self, line, name, json): + self.line = line + self.name = name + self.json = json + + def compile(self, func): + func.add_predicate(self.name, self.json) diff --git a/block_types/print_block.py b/block_types/print_block.py index f6b2447..cc401d2 100644 --- a/block_types/print_block.py +++ b/block_types/print_block.py @@ -1,12 +1,15 @@ from .block_base import block_base + class print_block(block_base): - def __init__(self, line, val): - self.line = line - self.val = val - - def compile(self, func): - try: - print(self.val.get_value(func)) - except Exception as e: - raise Exception(f'Unable to get print value at line {self.line}. Exception: "{e}"') + def __init__(self, line, val): + self.line = line + self.val = val + + def compile(self, func): + try: + print(self.val.get_value(func)) + except Exception as e: + raise Exception( + f'Unable to get print value at line {self.line}. Exception: "{e}"' + ) diff --git a/block_types/push_block.py b/block_types/push_block.py index ee7f8c2..8c12d2d 100644 --- a/block_types/push_block.py +++ b/block_types/push_block.py @@ -1,18 +1,21 @@ from .block_base import block_base from variable_types.storage_path_var import storage_path_var + class push_block(block_base): - def __init__(self, line, expr_list): - self.expr_list = expr_list - self.line = line - - def compile(self, func): - func.add_command(f'data modify storage {func.namespace} stack append value {{}}') - - idx = 0 - for expr in self.expr_list: - expr_var = expr.compile(func) - data_var = storage_path_var(None, f'stack[-1].v{idx}') - data_var.copy_from(func, expr_var) - - idx += 1 + def __init__(self, line, expr_list): + self.expr_list = expr_list + self.line = line + + def compile(self, func): + func.add_command( + f"data modify storage {func.namespace} stack append value {{}}" + ) + + idx = 0 + for expr in self.expr_list: + expr_var = expr.compile(func) + data_var = storage_path_var(None, f"stack[-1].v{idx}") + data_var.copy_from(func, expr_var) + + idx += 1 diff --git a/block_types/python_assignment_block.py b/block_types/python_assignment_block.py index 8aef4aa..8f64575 100644 --- a/block_types/python_assignment_block.py +++ b/block_types/python_assignment_block.py @@ -1,10 +1,10 @@ from .block_base import block_base -import math + class python_assignment_block(block_base): - def __init__(self, line, id, val): - self.line = line - self.id, self.val = id, val - - def compile(self, func): - func.set_dollarid(self.id, self.val.get_value(func)) \ No newline at end of file + def __init__(self, line, id, val): + self.line = line + self.id, self.val = id, val + + def compile(self, func): + func.set_dollarid(self.id, self.val.get_value(func)) diff --git a/block_types/python_for_block.py b/block_types/python_for_block.py index a3abeca..65b4ee6 100644 --- a/block_types/python_for_block.py +++ b/block_types/python_for_block.py @@ -1,40 +1,50 @@ from .block_base import block_base -import math from CompileError import CompileError + class python_for_block(block_base): - def __init__(self, line, ids, val, sub): - self.line = line - self.ids = ids - self.val = val - self.sub = sub - - def compile(self, func): - set = self.val.get_value(func) - - try: - iter(set) - except: - raise CompileError(f'"{set}" in "for" block at line {self.line} is not an iterable set.') + def __init__(self, line, ids, val, sub): + self.line = line + self.ids = ids + self.val = val + self.sub = sub + + def compile(self, func): + set = self.val.get_value(func) + + try: + iter(set) + except: + raise CompileError( + f'"{set}" in "for" block at line {self.line} is not an iterable set.' + ) - for v in set: - if len(self.ids) == 1: - func.set_dollarid(self.ids[0], v) - else: - try: - v_len = len(v) - except Exception as e: - print(e) - raise CompileError(f'Set is not a tuple at line {self.line}') - if v_len != len(self.ids): - raise CompileError(f'Expected {len(self.ids)} tuple items at line {self.line}, got {v_len}.') - for idx in range(v_len): - func.set_dollarid(self.ids[idx], v[idx]) - try: - func.compile_blocks(self.sub) - except CompileError as e: - print(e) - raise CompileError(f'Unable to compile python for block contents at line {self.line}') - except: - print(traceback.format_exc()) - raise CompileError(f'Unable to compile python for block contents at line {self.line}') + for v in set: + if len(self.ids) == 1: + func.set_dollarid(self.ids[0], v) + else: + try: + v_len = len(v) + except Exception as e: + print(e) + raise CompileError( + f"Set is not a tuple at line {self.line}" + ) + if v_len != len(self.ids): + raise CompileError( + f"Expected {len(self.ids)} tuple items at line {self.line}, got {v_len}." + ) + for idx in range(v_len): + func.set_dollarid(self.ids[idx], v[idx]) + try: + func.compile_blocks(self.sub) + except CompileError as e: + print(e) + raise CompileError( + f"Unable to compile python for block contents at line {self.line}" + ) + except: + print(traceback.format_exc()) + raise CompileError( + f"Unable to compile python for block contents at line {self.line}" + ) diff --git a/block_types/python_if_block.py b/block_types/python_if_block.py index ffc0b3f..1bd666b 100644 --- a/block_types/python_if_block.py +++ b/block_types/python_if_block.py @@ -1,25 +1,29 @@ from .block_base import block_base -import math + class python_if_block(block_base): - def __init__(self, line, val, sub, else_sub): - self.line = line - self.val = val - self.sub = sub - self.else_sub = else_sub - - def compile(self, func): - condition = self.val.get_value(func) - - if condition: - try: - func.compile_blocks(self.sub) - except Exception as e: - print(e.message) - raise Exception(f'Unable to compile true block for python if block at line {self.line}') - elif self.else_sub != None: - try: - func.compile_blocks(self.else_sub) - except Exception as e: - print(e.message) - raise Exception(f'Unable to compile false block for python if block at line {self.line}') + def __init__(self, line, val, sub, else_sub): + self.line = line + self.val = val + self.sub = sub + self.else_sub = else_sub + + def compile(self, func): + condition = self.val.get_value(func) + + if condition: + try: + func.compile_blocks(self.sub) + except Exception as e: + print(e.message) + raise Exception( + f"Unable to compile true block for python if block at line {self.line}" + ) + elif self.else_sub != None: + try: + func.compile_blocks(self.else_sub) + except Exception as e: + print(e.message) + raise Exception( + f"Unable to compile false block for python if block at line {self.line}" + ) diff --git a/block_types/python_import_block.py b/block_types/python_import_block.py index f284755..8399ee4 100644 --- a/block_types/python_import_block.py +++ b/block_types/python_import_block.py @@ -2,20 +2,27 @@ import traceback from CompileError import CompileError + class python_import_block(block_base): - def __init__(self, line, filename): - self.line = line - self.filename = filename - - def compile(self, func): - try: - func.import_python_file(self.filename + '.py') - except SyntaxError as e: - print(e) - raise CompileError(f'Importing file "{self.filename}" failed at line {self.line}:\n{e}') - except CompileError as e: - print(e) - raise CompileError(f'Importing file "{self.filename}" failed at line {self.line}:\n{e}') - except Exception as e: - print(traceback.format_exc()) - raise CompileError(f'Importing file "{self.filename}" failed at line {self.line}:\n{e}') + def __init__(self, line, filename): + self.line = line + self.filename = filename + + def compile(self, func): + try: + func.import_python_file(self.filename + ".py") + except SyntaxError as e: + print(e) + raise CompileError( + f'Importing file "{self.filename}" failed at line {self.line}:\n{e}' + ) + except CompileError as e: + print(e) + raise CompileError( + f'Importing file "{self.filename}" failed at line {self.line}:\n{e}' + ) + except Exception as e: + print(traceback.format_exc()) + raise CompileError( + f'Importing file "{self.filename}" failed at line {self.line}:\n{e}' + ) diff --git a/block_types/python_tuple_assignment_block.py b/block_types/python_tuple_assignment_block.py index b326dc1..025d6ac 100644 --- a/block_types/python_tuple_assignment_block.py +++ b/block_types/python_tuple_assignment_block.py @@ -1,22 +1,26 @@ from .block_base import block_base -import math from CompileError import CompileError + class python_tuple_assignment_block(block_base): - def __init__(self, line, ids, val): - self.line = line - self.ids, self.val = ids, val - - def compile(self, func): - val = self.val.get_value(func) - try: - val_len = len(val) - except Exception as e: - print(e) - raise CompileError(f'Expression at line {self.line} is not a tuple.') - - if val_len != len(self.ids): - raise CompileError(f'Expected {len(self.ids)} values for tuple expression at line {self.line}, got {len(val)}') - - for idx in range(val_len): - func.set_dollarid(self.ids[idx], val[idx]) + def __init__(self, line, ids, val): + self.line = line + self.ids, self.val = ids, val + + def compile(self, func): + val = self.val.get_value(func) + try: + val_len = len(val) + except Exception as e: + print(e) + raise CompileError( + f"Expression at line {self.line} is not a tuple." + ) + + if val_len != len(self.ids): + raise CompileError( + f"Expected {len(self.ids)} values for tuple expression at line {self.line}, got {len(val)}" + ) + + for idx in range(val_len): + func.set_dollarid(self.ids[idx], val[idx]) diff --git a/block_types/reset_section.py b/block_types/reset_section.py index 46f0023..2c65f19 100644 --- a/block_types/reset_section.py +++ b/block_types/reset_section.py @@ -1,20 +1,21 @@ from .block_base import block_base + class reset_section(block_base): - def __init__(self, line, lines): - self.line = line - self.lines = lines - - def compile(self, func): - reset_func = func.get_reset_function() - if reset_func == None: - reset_func = func.create_child_function() - func.register_function('reset', reset_func) - - reset_func.copy_environment_from(func) - - self.compile_lines(reset_func, self.lines) - - @property - def block_name(self): - return 'reset section' \ No newline at end of file + def __init__(self, line, lines): + self.line = line + self.lines = lines + + def compile(self, func): + reset_func = func.get_reset_function() + if reset_func == None: + reset_func = func.create_child_function() + func.register_function("reset", reset_func) + + reset_func.copy_environment_from(func) + + self.compile_lines(reset_func, self.lines) + + @property + def block_name(self): + return "reset section" diff --git a/block_types/scoreboard_assignment_block.py b/block_types/scoreboard_assignment_block.py index 261f200..eb412c4 100644 --- a/block_types/scoreboard_assignment_block.py +++ b/block_types/scoreboard_assignment_block.py @@ -1,41 +1,50 @@ from .block_base import block_base -from mcfunction import isNumber + class scoreboard_assignment_block(block_base): - def __init__(self, line, var, op, expr): - self.var, self.op, self.expr = var, op, expr - self.line = line - - def compile(self, func): - op = self.op - - if op == '=': - assignto = self.var.get_assignto(func) - else: - assignto = None - - expr_var = self.expr.compile(func, assignto) - - if op == '=': - self.var.copy_from(func, expr_var) - else: - temp_var = self.var.get_scoreboard_var(func) - expr_const = expr_var.get_const_value(func) - - if expr_const != None and op in ['+=', '-=']: - if expr_const < 0: - expr_const = -expr_const - op = {'+=':'-=', '-=':'+='}[op] - - func.add_command('scoreboard players {} {} {} {}'.format({'+=': 'add', '-=':'remove'}[op], temp_var.selector, temp_var.objective, expr_const)) - else: - expr_scoreboard_var = expr_var.get_scoreboard_var(func) - func.add_command(f'scoreboard players operation {temp_var.selector} {temp_var.objective} {self.op} {expr_scoreboard_var.selector} {expr_scoreboard_var.objective}') - - expr_scoreboard_var.free_scratch(func) - - self.var.copy_from(func, temp_var) - - temp_var.free_scratch(func) - - expr_var.free_scratch(func) \ No newline at end of file + def __init__(self, line, var, op, expr): + self.var, self.op, self.expr = var, op, expr + self.line = line + + def compile(self, func): + op = self.op + + if op == "=": + assignto = self.var.get_assignto(func) + else: + assignto = None + + expr_var = self.expr.compile(func, assignto) + + if op == "=": + self.var.copy_from(func, expr_var) + else: + temp_var = self.var.get_scoreboard_var(func) + expr_const = expr_var.get_const_value(func) + + if expr_const != None and op in ["+=", "-="]: + if expr_const < 0: + expr_const = -expr_const + op = {"+=": "-=", "-=": "+="}[op] + + func.add_command( + "scoreboard players {} {} {} {}".format( + {"+=": "add", "-=": "remove"}[op], + temp_var.selector, + temp_var.objective, + expr_const, + ) + ) + else: + expr_scoreboard_var = expr_var.get_scoreboard_var(func) + func.add_command( + f"scoreboard players operation {temp_var.selector} {temp_var.objective} {self.op} {expr_scoreboard_var.selector} {expr_scoreboard_var.objective}" + ) + + expr_scoreboard_var.free_scratch(func) + + self.var.copy_from(func, temp_var) + + temp_var.free_scratch(func) + + expr_var.free_scratch(func) diff --git a/block_types/selector_assignment_block.py b/block_types/selector_assignment_block.py index 98e039d..3688973 100644 --- a/block_types/selector_assignment_block.py +++ b/block_types/selector_assignment_block.py @@ -1,10 +1,11 @@ from .block_base import block_base + class selector_assignment_block(block_base): - def __init__(self, line, id, fullselector): - self.line = line - self.id = id - self.fullselector = fullselector - - def compile(self, func): - func.set_atid(self.id, self.fullselector) \ No newline at end of file + def __init__(self, line, id, fullselector): + self.line = line + self.id = id + self.fullselector = fullselector + + def compile(self, func): + func.set_atid(self.id, self.fullselector) diff --git a/block_types/selector_definition_block.py b/block_types/selector_definition_block.py index 1820f89..7ed6d9f 100644 --- a/block_types/selector_definition_block.py +++ b/block_types/selector_definition_block.py @@ -1,48 +1,50 @@ from .block_base import block_base -from mcfunction import compile_section + class selector_definition_block(block_base): - def __init__(self, line, id, fullselector, uuid, items): - self.line = line - self.id = id - self.uuid = uuid - self.fullselector = fullselector - self.items = items - - def compile(self, func): - selector = func.set_atid(self.id, self.fullselector) - selector.uuid = self.uuid - - for type, val in self.items: - if type == 'Tag': - selector.tag = val - elif type == 'Path': - path_id, path, data_type, scale = val - if scale == None: - scale = func.scale - else: - scale = scale.get_value(func) - selector.paths[path_id] = (path, data_type, scale) - elif type == 'VectorPath': - vector_id, path, data_type, scale = val - if scale == None: - scale = func.scale - else: - scale = scale.get_value(func) - selector.vector_paths[vector_id] = (path, data_type, scale) - elif type == 'Method': - func_section = val - func_section.self_selector = '@'+self.id - func_section.compile(func) - elif type == 'Pointer': - pointer_id, pointer_selector = val - selector.pointers[pointer_id] = pointer_selector - elif type == 'Array': - def_block = val - def_block.compile(func) - elif type == 'Predicate': - def_block = val - def_block.compile(func) - selector.predicates[def_block.name] = True - else: - raise ValueError(f'Unknown selector item type "{type}" in selector definition at line {get_line(line)}') + def __init__(self, line, id, fullselector, uuid, items): + self.line = line + self.id = id + self.uuid = uuid + self.fullselector = fullselector + self.items = items + + def compile(self, func): + selector = func.set_atid(self.id, self.fullselector) + selector.uuid = self.uuid + + for type, val in self.items: + if type == "Tag": + selector.tag = val + elif type == "Path": + path_id, path, data_type, scale = val + if scale == None: + scale = func.scale + else: + scale = scale.get_value(func) + selector.paths[path_id] = (path, data_type, scale) + elif type == "VectorPath": + vector_id, path, data_type, scale = val + if scale == None: + scale = func.scale + else: + scale = scale.get_value(func) + selector.vector_paths[vector_id] = (path, data_type, scale) + elif type == "Method": + func_section = val + func_section.self_selector = "@" + self.id + func_section.compile(func) + elif type == "Pointer": + pointer_id, pointer_selector = val + selector.pointers[pointer_id] = pointer_selector + elif type == "Array": + def_block = val + def_block.compile(func) + elif type == "Predicate": + def_block = val + def_block.compile(func) + selector.predicates[def_block.name] = True + else: + raise ValueError( + f'Unknown selector item type "{type}" in selector definition at line {get_line(line)}' + ) diff --git a/block_types/shaped_recipe_block.py b/block_types/shaped_recipe_block.py index 3937517..f2cc70c 100644 --- a/block_types/shaped_recipe_block.py +++ b/block_types/shaped_recipe_block.py @@ -1,33 +1,34 @@ from .block_base import block_base from data_types.shaped_recipe import shaped_recipe + class shaped_recipe_block(block_base): - def __init__(self, line, recipe_lines, keys, count, item): - self.line = line - self.recipe_lines = recipe_lines - self.keys = keys - self.count = count - self.item = item - - def compile(self, func): - count = self.count.get_value(func) - - recipe = shaped_recipe( - self.recipe_lines, - self.get_keys_with_namespace(func), - count, - self.item, - func.namespace - ) - - func.add_recipe(recipe) - - def get_keys_with_namespace(self, func): - keys = [] - for key, type, value in self.keys: - if type == 'tag' and value in func.item_tags: - keys.append((key, type, f'{func.namespace}:{value}')) - else: - keys.append((key, type, f'minecraft:{value}')) - - return keys + def __init__(self, line, recipe_lines, keys, count, item): + self.line = line + self.recipe_lines = recipe_lines + self.keys = keys + self.count = count + self.item = item + + def compile(self, func): + count = self.count.get_value(func) + + recipe = shaped_recipe( + self.recipe_lines, + self.get_keys_with_namespace(func), + count, + self.item, + func.namespace, + ) + + func.add_recipe(recipe) + + def get_keys_with_namespace(self, func): + keys = [] + for key, type, value in self.keys: + if type == "tag" and value in func.item_tags: + keys.append((key, type, f"{func.namespace}:{value}")) + else: + keys.append((key, type, f"minecraft:{value}")) + + return keys diff --git a/block_types/switch_block.py b/block_types/switch_block.py index d820448..193effb 100644 --- a/block_types/switch_block.py +++ b/block_types/switch_block.py @@ -2,71 +2,86 @@ import collections from CompileError import CompileError + class switch_block(block_base): - def __init__(self, line, expr, cases_raw): - self.line = line - self.expr = expr - self.cases_raw = cases_raw - - def compile(self, func): - if len(self.cases_raw) == 0: - return - - result = self.expr.compile(func, None).get_scoreboard_var(func) - if result == None: - raise Exception(f'Unable to compute switch expression at line {self.line}') + def __init__(self, line, expr, cases_raw): + self.line = line + self.expr = expr + self.cases_raw = cases_raw + + def compile(self, func): + if len(self.cases_raw) == 0: + return + + result = self.expr.compile(func, None).get_scoreboard_var(func) + if result == None: + raise Exception( + f"Unable to compute switch expression at line {self.line}" + ) + + cases = [] + for case in self.cases_raw: + type, content, line = case + if type == "range": + vmin, vmax, sub = content + try: + vmin = int(vmin.get_value(func)) + vmax = int(vmax.get_value(func)) + except Exception as e: + print(e) + raise Exception( + f"Unable to get values of range for case at line {line}" + ) + + cases.append((vmin, vmax, sub, line, None)) + elif type == "python": + dollarid, python, sub = content + try: + vals = python.get_value(func) + except: + raise Exception( + f"Could not evaluate case value at line {line}" + ) + + if not isinstance(vals, collections.Iterable): + raise Exception( + f'Python "{python}" is not iterable at line {line}' + ) + + for val in vals: + try: + ival = int(val) + except: + print( + f'Value "{val}" is not an integer at line {line}' + ) + return False + cases.append((ival, ival, sub, line, dollarid)) + else: + raise CompileError(f'Unknown switch case type "{type}"') + + cases = sorted(cases, key=lambda case: case[0]) + + # Check that none of the cases overlap + prevmax = cases[0][0] - 1 + for vmin, vmax, sub, line, dollarid in cases: + if vmin > vmax: + raise ValueError( + f'"case {vmin}-{vmax}" has invalid range at line {line}' + ) + + if vmin <= prevmax: + if vmin == vmax: + rangestr = f"{vmin}" + else: + rangestr = f"{vmin}-{vmax}" + raise CompileError( + f'"case {rangestr}" overlaps another case at line {line}' + ) + + prevmax = vmax - cases = [] - for case in self.cases_raw: - type, content, line = case - if type == 'range': - vmin, vmax, sub = content - try: - vmin = int(vmin.get_value(func)) - vmax = int(vmax.get_value(func)) - except Exception as e: - print(e) - raise Exception(f'Unable to get values of range for case at line {line}') - - cases.append((vmin, vmax, sub, line, None)) - elif type == 'python': - dollarid, python, sub = content - try: - vals = python.get_value(func) - except: - raise Exception(f'Could not evaluate case value at line {line}') - - if not isinstance(vals, collections.Iterable): - raise Exception(f'Python "{python}" is not iterable at line {line}') + if not func.switch_cases(result, cases): + raise Exception(f"Unable to compile switch block at line {line}") - for val in vals: - try: - ival = int(val) - except: - print(f'Value "{val}" is not an integer at line {line}') - return False - cases.append((ival, ival, sub, line, dollarid)) - else: - raise CompileError(f'Unknown switch case type "{type}"') - - cases = sorted(cases, key=lambda case: case[0]) - - # Check that none of the cases overlap - prevmax = cases[0][0]-1 - for vmin, vmax, sub, line, dollarid in cases: - if vmin > vmax: - raise ValueError(f'"case {vmin}-{vmax}" has invalid range at line {line}') - - if vmin <= prevmax: - if vmin == vmax: - rangestr = f'{vmin}' - else: - rangestr = f'{vmin}-{vmax}' - raise CompileError(f'"case {rangestr}" overlaps another case at line {line}') - - prevmax = vmax - - if not func.switch_cases(result, cases): - raise Exception(f'Unable to compile switch block at line {line}') - - result.free_scratch(func) + result.free_scratch(func) diff --git a/block_types/tell_block.py b/block_types/tell_block.py index 60f16c8..c42416e 100644 --- a/block_types/tell_block.py +++ b/block_types/tell_block.py @@ -1,13 +1,16 @@ from .block_base import block_base import tellraw + class tell_block(block_base): - def __init__(self, line, selector, unformatted): - self.line = line - self.selector = selector - self.unformatted = unformatted - - def compile(self, func): - text = tellraw.formatJsonText(func, func.apply_replacements(self.unformatted)) - command = f'/tellraw {self.selector} {text}' - func.add_command(command) + def __init__(self, line, selector, unformatted): + self.line = line + self.selector = selector + self.unformatted = unformatted + + def compile(self, func): + text = tellraw.formatJsonText( + func, func.apply_replacements(self.unformatted) + ) + command = f"/tellraw {self.selector} {text}" + func.add_command(command) diff --git a/block_types/template_function_call_block.py b/block_types/template_function_call_block.py index 198e604..badc0bb 100644 --- a/block_types/template_function_call_block.py +++ b/block_types/template_function_call_block.py @@ -1,81 +1,95 @@ from .call_block_base import call_block_base from mcfunction import mcfunction -from environment import isNumber, isInt from variable_types.scoreboard_var import scoreboard_var + class template_function_call_block(call_block_base): - def __init__(self, line, function, template_args, args, with_macro_items): - self.line = line - self.function = function - self.template_args = template_args - self.args = args - self.with_macro_items = with_macro_items - - def compile(self, func): - function, template_args, args = self.function, self.template_args, self.args - - if function not in func.template_functions: - raise ValueError(f'Tried to call non-existant template function "{function}" at line {self.line}') - - template_params, params, sub = func.template_functions[function] - - if len(template_args) != len(template_params): - raise ValueError(f'Tried to call template function "{function}" with {len(template_args)} template arguments ({len(template_params)} expected) at line {self.line}') - - if len(args) != len(params): - raise ValueError(f'Tried to call template function "{function}" with {len(args)} function arguments ({len(params)} expected) at line {self.line}') - - # Get textual function name - func_name = function - for template_arg in template_args: - template_arg_val = template_arg.get_value(func) - # TODO: Replace all invalid function characters with _ - template_arg_val = str(template_arg_val).replace(' ', '_') - func_name = func_name + f'_{template_arg_val}' - - if func_name == func.name: - locals = func.get_all_locals() - func.push_locals(locals) - - # Compile macro items if there are any - self.compile_with_macro_items(func) - - # Calculate function arguments - for i in range(len(args)): - assignto = scoreboard_var(f'Global', 'Param{i}') - arg_var = args[i].compile(func, assignto) - - assignto.copy_from(func, arg_var) - - arg_var.free_scratch(func) - - # Compile the function if it doens't exist yet - if func_name not in func.functions: - func.functions[func_name] = None - new_env = func.clone_environment() - - # Bind template paramters in the function's environment - for p in range(len(template_args)): - new_env.set_dollarid(template_params[p], template_args[p].get_value(func)) - - # Compile the new function - new_func = mcfunction(new_env, True, params) - try: - new_func.compile_blocks(sub) - except Exception as e: - print(e.message) - raise Exception(f'Unable to compile template function contents at line {self.line}') - - # Register the new function - func.register_function(func_name, new_func) - - cmd = f'function {func.namespace}:{func_name}' - - if self.with_macro_items != None: - cmd = cmd + f'with storage {func.namespace}:global args' - self.has_macros = True - - func.add_command(cmd) - - if func_name == func.name: - func.pop_locals(locals) + def __init__(self, line, function, template_args, args, with_macro_items): + self.line = line + self.function = function + self.template_args = template_args + self.args = args + self.with_macro_items = with_macro_items + + def compile(self, func): + function, template_args, args = ( + self.function, + self.template_args, + self.args, + ) + + if function not in func.template_functions: + raise ValueError( + f'Tried to call non-existant template function "{function}" at line {self.line}' + ) + + template_params, params, sub = func.template_functions[function] + + if len(template_args) != len(template_params): + raise ValueError( + f'Tried to call template function "{function}" with {len(template_args)} template arguments ({len(template_params)} expected) at line {self.line}' + ) + + if len(args) != len(params): + raise ValueError( + f'Tried to call template function "{function}" with {len(args)} function arguments ({len(params)} expected) at line {self.line}' + ) + + # Get textual function name + func_name = function + for template_arg in template_args: + template_arg_val = template_arg.get_value(func) + # TODO: Replace all invalid function characters with _ + template_arg_val = str(template_arg_val).replace(" ", "_") + func_name = func_name + f"_{template_arg_val}" + + if func_name == func.name: + locals = func.get_all_locals() + func.push_locals(locals) + + # Compile macro items if there are any + self.compile_with_macro_items(func) + + # Calculate function arguments + for i in range(len(args)): + assignto = scoreboard_var(f"Global", "Param{i}") + arg_var = args[i].compile(func, assignto) + + assignto.copy_from(func, arg_var) + + arg_var.free_scratch(func) + + # Compile the function if it doens't exist yet + if func_name not in func.functions: + func.functions[func_name] = None + new_env = func.clone_environment() + + # Bind template paramters in the function's environment + for p in range(len(template_args)): + new_env.set_dollarid( + template_params[p], template_args[p].get_value(func) + ) + + # Compile the new function + new_func = mcfunction(new_env, True, params) + try: + new_func.compile_blocks(sub) + except Exception as e: + print(e.message) + raise Exception( + f"Unable to compile template function contents at line {self.line}" + ) + + # Register the new function + func.register_function(func_name, new_func) + + cmd = f"function {func.namespace}:{func_name}" + + if self.with_macro_items != None: + cmd = cmd + f"with storage {func.namespace}:global args" + self.has_macros = True + + func.add_command(cmd) + + if func_name == func.name: + func.pop_locals(locals) diff --git a/block_types/template_function_section.py b/block_types/template_function_section.py index 8be1514..871dbf0 100644 --- a/block_types/template_function_section.py +++ b/block_types/template_function_section.py @@ -1,20 +1,25 @@ from .block_base import block_base + class template_function_section(block_base): - def __init__(self, line, name, macro_params, params, lines): - self.line = line - self.name = name - self.macro_params = macro_params - self.params = params - self.lines = lines + def __init__(self, line, name, macro_params, params, lines): + self.line = line + self.name = name + self.macro_params = macro_params + self.params = params + self.lines = lines + + def compile(self, func): + None + + def register(self, global_context): + global_context.template_functions[self.name] = ( + self.macro_params, + self.params, + self.lines, + ) + global_context.register_function_params(self.name, self.params) - def compile(self, func): - None - - def register(self, global_context): - global_context.template_functions[self.name] = (self.macro_params, self.params, self.lines) - global_context.register_function_params(self.name, self.params) - - @property - def block_name(self): - return f'template function "{self.name}"' + @property + def block_name(self): + return f'template function "{self.name}"' diff --git a/block_types/title_block.py b/block_types/title_block.py index f7bd0b1..0fb03fa 100644 --- a/block_types/title_block.py +++ b/block_types/title_block.py @@ -1,18 +1,21 @@ from .block_base import block_base import tellraw + class title_block(block_base): - def __init__(self, line, subtype, selector, times, unformatted): - self.line = line - self.subtype = subtype - self.selector = selector - self.times = times - self.unformatted = unformatted - - def compile(self, func): - if self.times != None: - func.add_command(f'/title {self.selector} times {" ".join(str(t.get_value(func)) for t in self.times)}') - - text = tellraw.formatJsonText(func, self.unformatted) - command = f'/title {self.selector} {self.subtype} {text}' - func.add_command(command) + def __init__(self, line, subtype, selector, times, unformatted): + self.line = line + self.subtype = subtype + self.selector = selector + self.times = times + self.unformatted = unformatted + + def compile(self, func): + if self.times != None: + func.add_command( + f'/title {self.selector} times {" ".join(str(t.get_value(func)) for t in self.times)}' + ) + + text = tellraw.formatJsonText(func, self.unformatted) + command = f"/title {self.selector} {self.subtype} {text}" + func.add_command(command) diff --git a/block_types/vector_assignment_base.py b/block_types/vector_assignment_base.py index 3621186..336c0f8 100644 --- a/block_types/vector_assignment_base.py +++ b/block_types/vector_assignment_base.py @@ -2,53 +2,62 @@ from variable_types.scoreboard_var import scoreboard_var from CompileError import CompileError + class vector_assignment_base(block_base): - def perform_vector_assignment(self, func): - var, op, expr = self.var, self.op, self.expr - - var_type, var_content = var - - if var_type == 'VAR_COMPONENTS': - components = var_content - elif var_type == 'VAR_ID': - id = var_content - components = [scoreboard_var('Global', f'_{id}_{i}') for i in range(3)] - elif var_type == 'SEL_VAR_ID': - selector, id = var_content - components = [scoreboard_var(selector, f'_{id}_{i}') for i in range(3)] - elif var_type == 'VAR_CONST': - raise CompileError(f'Cannot assign to vector constant at line {self.line}.') - - if op == '=': - assignto = [] - for var in components: - component_assignto = var.get_assignto(func) - if component_assignto == None: - assignto = None - break - else: - assignto.append(component_assignto) - - component_val_vars = self.compute_assignment(func, expr, assignto) - - for i in range(3): - components[i].copy_from(func, component_val_vars[i]) - component_val_vars[i].free_scratch(func) - else: - component_val_vars = self.compute_assignment(func, expr, None) - - if var_type == 'SEL_VAR_ID': - selector, id = var_content - func.get_vector_path(selector, id) - - for i in range(3): - temp_var = components[i].get_scoreboard_var(func) - rvar = component_val_vars[i].get_scoreboard_var(func) - func.add_command(f'scoreboard players operation {temp_var.selector} {temp_var.objective} {op} {rvar.selector} {rvar.objective}') - components[i].copy_from(func, temp_var) - temp_var.free_scratch(func) - rvar.free_scratch(func) - - if var_type == 'SEL_VAR_ID': - selector, id = var_content - func.set_vector_path(selector, id, components) + def perform_vector_assignment(self, func): + var, op, expr = self.var, self.op, self.expr + + var_type, var_content = var + + if var_type == "VAR_COMPONENTS": + components = var_content + elif var_type == "VAR_ID": + id = var_content + components = [ + scoreboard_var("Global", f"_{id}_{i}") for i in range(3) + ] + elif var_type == "SEL_VAR_ID": + selector, id = var_content + components = [ + scoreboard_var(selector, f"_{id}_{i}") for i in range(3) + ] + elif var_type == "VAR_CONST": + raise CompileError( + f"Cannot assign to vector constant at line {self.line}." + ) + + if op == "=": + assignto = [] + for var in components: + component_assignto = var.get_assignto(func) + if component_assignto == None: + assignto = None + break + else: + assignto.append(component_assignto) + + component_val_vars = self.compute_assignment(func, expr, assignto) + + for i in range(3): + components[i].copy_from(func, component_val_vars[i]) + component_val_vars[i].free_scratch(func) + else: + component_val_vars = self.compute_assignment(func, expr, None) + + if var_type == "SEL_VAR_ID": + selector, id = var_content + func.get_vector_path(selector, id) + + for i in range(3): + temp_var = components[i].get_scoreboard_var(func) + rvar = component_val_vars[i].get_scoreboard_var(func) + func.add_command( + f"scoreboard players operation {temp_var.selector} {temp_var.objective} {op} {rvar.selector} {rvar.objective}" + ) + components[i].copy_from(func, temp_var) + temp_var.free_scratch(func) + rvar.free_scratch(func) + + if var_type == "SEL_VAR_ID": + selector, id = var_content + func.set_vector_path(selector, id, components) diff --git a/block_types/vector_assignment_block.py b/block_types/vector_assignment_block.py index da7549c..7672ecc 100644 --- a/block_types/vector_assignment_block.py +++ b/block_types/vector_assignment_block.py @@ -1,18 +1,21 @@ from .vector_assignment_base import vector_assignment_base + class vector_assignment_block(vector_assignment_base): - def __init__(self, line, var, op, expr): - self.line = line - self.var = var - self.op = op - self.expr = expr - - def compile(self, func): - self.perform_vector_assignment(func) - - def compute_assignment(self, func, expr, assignto): - component_val_vars = expr.compile(func, assignto) - if component_val_vars == None: - raise Exception(f'Unable to compute vector assignment at line {self.line}') - - return component_val_vars + def __init__(self, line, var, op, expr): + self.line = line + self.var = var + self.op = op + self.expr = expr + + def compile(self, func): + self.perform_vector_assignment(func) + + def compute_assignment(self, func, expr, assignto): + component_val_vars = expr.compile(func, assignto) + if component_val_vars == None: + raise Exception( + f"Unable to compute vector assignment at line {self.line}" + ) + + return component_val_vars diff --git a/block_types/vector_assignment_scalar_block.py b/block_types/vector_assignment_scalar_block.py index e38c2c8..923fb68 100644 --- a/block_types/vector_assignment_scalar_block.py +++ b/block_types/vector_assignment_scalar_block.py @@ -1,17 +1,18 @@ from .vector_assignment_base import vector_assignment_base + class vector_assignment_scalar_block(vector_assignment_base): - def __init__(self, line, var, op, expr): - self.line = line - self.var = var - self.op = op - self.expr = expr - - def compile(self, func): - self.perform_vector_assignment(func) - - def compute_assignment(self, func, expr, assignto): - val_var = expr.compile(func, None) - component_val_vars = [val_var for i in range(3)] - - return component_val_vars + def __init__(self, line, var, op, expr): + self.line = line + self.var = var + self.op = op + self.expr = expr + + def compile(self, func): + self.perform_vector_assignment(func) + + def compute_assignment(self, func, expr, assignto): + val_var = expr.compile(func, None) + component_val_vars = [val_var for i in range(3)] + + return component_val_vars diff --git a/block_types/while_block.py b/block_types/while_block.py index f1541a9..f413883 100644 --- a/block_types/while_block.py +++ b/block_types/while_block.py @@ -1,30 +1,35 @@ from .execute_base import execute_base + class while_block(execute_base): - def __init__(self, line, exec_items, sub): - self.line = line - self.exec_items = exec_items - self.sub = sub - - def compile(self, func): - self.perform_execute(func) - - # Force a sub-function for the continuation commands - def force_sub_function(self): - return True - - # Adds the recursive continuation execute command to the end of the sub function - def add_continuation_command(self, func, exec_func): - dummy_func = exec_func.create_child_function() - sub_cmd = 'execute ' + exec_func.get_execute_items(self.exec_items, dummy_func) - - if "$(" in sub_cmd: - exec_func.has_macros = True - - if sub_cmd == None: - raise Exception(f'Unable to compile continuation command for while block at line {self.line}') - - exec_func.add_command(f'{sub_cmd}run {exec_func.get_call()}') - - def display_name(self): - return 'while' + def __init__(self, line, exec_items, sub): + self.line = line + self.exec_items = exec_items + self.sub = sub + + def compile(self, func): + self.perform_execute(func) + + # Force a sub-function for the continuation commands + def force_sub_function(self): + return True + + # Adds the recursive continuation execute command to the end of the sub function + def add_continuation_command(self, func, exec_func): + dummy_func = exec_func.create_child_function() + sub_cmd = "execute " + exec_func.get_execute_items( + self.exec_items, dummy_func + ) + + if "$(" in sub_cmd: + exec_func.has_macros = True + + if sub_cmd == None: + raise Exception( + f"Unable to compile continuation command for while block at line {self.line}" + ) + + exec_func.add_command(f"{sub_cmd}run {exec_func.get_call()}") + + def display_name(self): + return "while" diff --git a/block_types/with_anonymous_block.py b/block_types/with_anonymous_block.py index 0d960e7..85aca0a 100644 --- a/block_types/with_anonymous_block.py +++ b/block_types/with_anonymous_block.py @@ -2,12 +2,13 @@ from CompileError import CompileError from .block_base import block_base + class with_anonymous_block(block_base): def __init__(self, line, with_items, sub): self.line = line self.with_items = with_items self.sub = sub - + def compile(self, func): if self.with_items != None: self.with_items.compile(func) @@ -18,11 +19,15 @@ def compile(self, func): anon_func.compile_blocks(self.sub) except CompileError as e: print(e) - raise CompileError(f'Unable to compile with block contents at line {self.line}') + raise CompileError( + f"Unable to compile with block contents at line {self.line}" + ) except Exception as e: print(traceback.format_exc()) - raise CompileError(f'Unable to compile with block contents at line {self.line}') - + raise CompileError( + f"Unable to compile with block contents at line {self.line}" + ) + unique = func.get_unique_id() func_name = f'line{self.line:03}/{"with"}{unique:03}' func.register_function(func_name, anon_func) diff --git a/block_types/with_items.py b/block_types/with_items.py index ccb6d05..7a25a69 100644 --- a/block_types/with_items.py +++ b/block_types/with_items.py @@ -5,21 +5,27 @@ def __init__(self, line, items): def compile(self, func): for item in self.items: - if item[0] == 'expr': + if item[0] == "expr": id = item[1] expr = item[2] expr_value_var = expr.compile(func) const_value = expr_value_var.get_const_value(func) - + if const_value != None: - func.add_command(f'data modify storage {func.namespace}:global args.{id} set value {const_value}') - else: - func.add_command(f'execute store result storage {func.namespace}:global args.{id} int 1 run scoreboard players get {expr_value_var.selector} {expr_value_var.objective}') + func.add_command( + f"data modify storage {func.namespace}:global args.{id} set value {const_value}" + ) + else: + func.add_command( + f"execute store result storage {func.namespace}:global args.{id} int 1 run scoreboard players get {expr_value_var.selector} {expr_value_var.objective}" + ) - elif item[0] == 'string': + elif item[0] == "string": id = item[1] str = item[2] - func.add_command(f'data modify storage {func.namespace}:global args.{id} set value {str}') + func.add_command( + f"data modify storage {func.namespace}:global args.{id} set value {str}" + ) diff --git a/cbscript.py b/cbscript.py index d7d4507..ec7a64d 100644 --- a/cbscript.py +++ b/cbscript.py @@ -1,201 +1,227 @@ import global_context import mcworld from environment import environment -from mcfunction import mcfunction, compile_section -from selector_definition import selector_definition +from mcfunction import mcfunction from source_file import source_file from CompileError import CompileError -import tellraw import traceback -import math -import collections import time import os + class cbscript(object): - def __init__(self, source_file, parse_func): - self.source_file = source_file - self.parse = parse_func - self.namespace = self.source_file.get_base_name().split('.')[0].lower() - self.dependencies = [] - self.latest_log_file = None - - def log(self, text): - print(text) - - def log_traceback(self): - traceback.print_exc() - - def check_for_update(self): - recompile = False - # It's important to go through all the files, to make sure that if multiple were updated - # we don't try to compile multiple times - for file in [self.source_file] + self.dependencies: - if file.was_updated(): - recompile = True - - if recompile: - self.try_to_compile() - - if self.latest_log_file and self.latest_log_file.was_updated(): - log_text = self.latest_log_file.get_text(only_new_text=True) - self.search_log_for_errors(log_text) - - def search_log_for_errors(self, log_text): - lines = log_text.split('\n') - error_text = '' - for line in lines: - if len(error_text) == 0: - # Haven't found an error, keep searching - if self.namespace in line and ('ERROR' in line or 'Exception' in line): - error_text = line - else: - # Append lines to the error message until it's over - if len(line) > 0 and line[0] == '[': - # Error message is over, print and return - print('========= Error detected in Minecraft log file =========') - print(error_text + '\a') - print('========================================================') - return - else: - # Error message continues - if not line.startswith('\t'): - error_text = error_text + '\n \n' + line - - - - def try_to_compile(self): - try: - self.log(f'Compiling {self.namespace}...') - success = self.compile_all() - if success: - self.log(f"Script successfully applied at {time.ctime()}.") - else: - self.log("Script had compile error(s).\a") - except SyntaxError as e: - self.log(str(e) + '\a') - except CompileError as e: - self.log(str(e) + '\a') - except Exception as e: - self.log("Compiler encountered unexpected error during compilation:\a") - self.log_traceback() - - def create_world(self, dir, namespace): - return mcworld.mcworld(dir, namespace) - - def compile_all(self): - text = self.source_file.get_text() - - result = self.parse(text + "\n") - - if result == None: - self.log('Unable to parse script.') - return False - - type, parsed = result - - if type != 'program': - self.log('Script does not contain a full program.') - return False - - self.global_context = global_context.global_context(self.namespace) - global_environment = environment(self.global_context) - global_environment.set_dollarid('namespace', self.namespace) - global_environment.set_dollarid('get_num_blocks', self.global_context.get_num_blocks) - global_environment.set_dollarid('get_num_block_states', self.global_context.get_num_block_states) - - if 'scale' not in parsed: - parsed['scale'] = 10000 - global_environment.set_dollarid('global_scale', parsed['scale']) - global_func = mcfunction(global_environment) - - self.global_context.scale = parsed['scale'] - self.global_context.parser = self.parse - - lines = parsed['lines'] - - # Register macros and template functions - for line in lines: - line.register(self.global_context) - - # Compile all lines - try: - global_func.compile_blocks(lines) - except Exception as e: - print(e) - self.dependencies = [source_file(d) for d in self.global_context.dependencies] - return False - - self.post_processing() - - world = self.create_world(parsed["dir"], self.namespace) - - latest_log_filename = world.get_latest_log_file() - if os.path.exists(latest_log_filename): - self.latest_log_file = source_file(latest_log_filename) - - world.write_functions(self.global_context.functions) - world.write_tags(self.global_context.clocks, self.global_context.block_tags, self.global_context.entity_tags, self.global_context.item_tags) - world.write_mcmeta(parsed['desc']) - world.write_recipes(self.global_context.recipes) - world.write_advancements(self.global_context.advancements) - world.write_loot_tables(self.global_context.loot_tables) - world.write_predicates(self.global_context.predicates) - world.write_item_modifiers(self.global_context.item_modifiers) - world.write_zip() - - self.dependencies = [source_file(d) for d in self.global_context.dependencies] - - return True - - def post_processing(self): - self.global_context.finalize_functions() - self.add_scratch_objectives() - self.add_temp_objectives() - self.add_constants() - self.add_trigger_objectives() - self.add_registered_objectives() - self.add_max_chain_length() - self.initialize_stack() - self.initialize_args() - - def add_max_chain_length(self): - f = self.global_context.get_reset_function() - f.insert_command('/gamerule maxCommandChainLength 1000000000', 0) - - def initialize_stack(self): - f = self.global_context.get_reset_function() - f.insert_command(f'/data modify storage {self.namespace} stack set value []', 0) - - def initialize_args(self): - f = self.global_context.get_reset_function() - f.insert_command(f'/data modify storage {self.namespace}:global args set value {{}}', 0) - - def add_scratch_objectives(self): - f = self.global_context.get_reset_function() - - for prefix in self.global_context.scratch: - for i in range(self.global_context.scratch[prefix]): - f.insert_command(f'/scoreboard objectives add {prefix}_scratch{i} dummy', 0) - - - def add_temp_objectives(self): - f = self.global_context.get_reset_function() - - for t in range(self.global_context.temp): - f.insert_command(f'scoreboard objectives add temp{str(t)} dummy', 0) - - def add_constants(self): - self.global_context.add_constant_definitions() - - def add_trigger_objectives(self): - None - - def add_registered_objectives(self): - reset = self.global_context.get_reset_function() - - defined = reset.defined_objectives() - - for objective in self.global_context.objectives.keys(): - if objective not in defined: - reset.insert_command(f"/scoreboard objectives add {objective} dummy", 0) + def __init__(self, source_file, parse_func): + self.source_file = source_file + self.parse = parse_func + self.namespace = self.source_file.get_base_name().split(".")[0].lower() + self.dependencies = [] + self.latest_log_file = None + + def log(self, text): + print(text) + + def log_traceback(self): + traceback.print_exc() + + def check_for_update(self): + recompile = False + # It's important to go through all the files, to make sure that if multiple were updated + # we don't try to compile multiple times + for file in [self.source_file] + self.dependencies: + if file.was_updated(): + recompile = True + + if recompile: + self.try_to_compile() + + if self.latest_log_file and self.latest_log_file.was_updated(): + log_text = self.latest_log_file.get_text(only_new_text=True) + self.search_log_for_errors(log_text) + + def search_log_for_errors(self, log_text): + lines = log_text.split("\n") + error_text = "" + for line in lines: + if len(error_text) == 0: + # Haven't found an error, keep searching + if self.namespace in line and ( + "ERROR" in line or "Exception" in line + ): + error_text = line + else: + # Append lines to the error message until it's over + if len(line) > 0 and line[0] == "[": + # Error message is over, print and return + print( + "========= Error detected in Minecraft log file =========" + ) + print(error_text + "\a") + print( + "========================================================" + ) + return + else: + # Error message continues + if not line.startswith("\t"): + error_text = error_text + "\n \n" + line + + def try_to_compile(self): + try: + self.log(f"Compiling {self.namespace}...") + success = self.compile_all() + if success: + self.log(f"Script successfully applied at {time.ctime()}.") + else: + self.log("Script had compile error(s).\a") + except SyntaxError as e: + self.log(str(e) + "\a") + except CompileError as e: + self.log(str(e) + "\a") + except Exception as e: + self.log( + "Compiler encountered unexpected error during compilation:\a" + ) + self.log_traceback() + + def create_world(self, dir, namespace): + return mcworld.mcworld(dir, namespace) + + def compile_all(self): + text = self.source_file.get_text() + + result = self.parse(text + "\n") + + if result == None: + self.log("Unable to parse script.") + return False + + type, parsed = result + + if type != "program": + self.log("Script does not contain a full program.") + return False + + self.global_context = global_context.global_context(self.namespace) + global_environment = environment(self.global_context) + global_environment.set_dollarid("namespace", self.namespace) + global_environment.set_dollarid( + "get_num_blocks", self.global_context.get_num_blocks + ) + global_environment.set_dollarid( + "get_num_block_states", self.global_context.get_num_block_states + ) + + if "scale" not in parsed: + parsed["scale"] = 10000 + global_environment.set_dollarid("global_scale", parsed["scale"]) + global_func = mcfunction(global_environment) + + self.global_context.scale = parsed["scale"] + self.global_context.parser = self.parse + + lines = parsed["lines"] + + # Register macros and template functions + for line in lines: + line.register(self.global_context) + + # Compile all lines + try: + global_func.compile_blocks(lines) + except Exception as e: + print(e) + self.dependencies = [ + source_file(d) for d in self.global_context.dependencies + ] + return False + + self.post_processing() + + world = self.create_world(parsed["dir"], self.namespace) + + latest_log_filename = world.get_latest_log_file() + if os.path.exists(latest_log_filename): + self.latest_log_file = source_file(latest_log_filename) + + world.write_functions(self.global_context.functions) + world.write_tags( + self.global_context.clocks, + self.global_context.block_tags, + self.global_context.entity_tags, + self.global_context.item_tags, + ) + world.write_mcmeta(parsed["desc"]) + world.write_recipes(self.global_context.recipes) + world.write_advancements(self.global_context.advancements) + world.write_loot_tables(self.global_context.loot_tables) + world.write_predicates(self.global_context.predicates) + world.write_item_modifiers(self.global_context.item_modifiers) + world.write_zip() + + self.dependencies = [ + source_file(d) for d in self.global_context.dependencies + ] + + return True + + def post_processing(self): + self.global_context.finalize_functions() + self.add_scratch_objectives() + self.add_temp_objectives() + self.add_constants() + self.add_trigger_objectives() + self.add_registered_objectives() + self.add_max_chain_length() + self.initialize_stack() + self.initialize_args() + + def add_max_chain_length(self): + f = self.global_context.get_reset_function() + f.insert_command("/gamerule maxCommandChainLength 1000000000", 0) + + def initialize_stack(self): + f = self.global_context.get_reset_function() + f.insert_command( + f"/data modify storage {self.namespace} stack set value []", 0 + ) + + def initialize_args(self): + f = self.global_context.get_reset_function() + f.insert_command( + f"/data modify storage {self.namespace}:global args set value {{}}", + 0, + ) + + def add_scratch_objectives(self): + f = self.global_context.get_reset_function() + + for prefix in self.global_context.scratch: + for i in range(self.global_context.scratch[prefix]): + f.insert_command( + f"/scoreboard objectives add {prefix}_scratch{i} dummy", 0 + ) + + def add_temp_objectives(self): + f = self.global_context.get_reset_function() + + for t in range(self.global_context.temp): + f.insert_command( + f"scoreboard objectives add temp{str(t)} dummy", 0 + ) + + def add_constants(self): + self.global_context.add_constant_definitions() + + def add_trigger_objectives(self): + None + + def add_registered_objectives(self): + reset = self.global_context.get_reset_function() + + defined = reset.defined_objectives() + + for objective in self.global_context.objectives.keys(): + if objective not in defined: + reset.insert_command( + f"/scoreboard objectives add {objective} dummy", 0 + ) diff --git a/compile.py b/compile.py index 19fd57c..c1de391 100644 --- a/compile.py +++ b/compile.py @@ -10,8 +10,8 @@ import os if len(sys.argv) != 2: - print("You must include a script filename.") - exit() + print("You must include a script filename.") + exit() source = source_file.source_file(sys.argv[1]) @@ -22,9 +22,10 @@ def run(): - while True: - script.check_for_update() - - time.sleep(1) - -run() \ No newline at end of file + while True: + script.check_for_update() + + time.sleep(1) + + +run() diff --git a/data_types/block_case.py b/data_types/block_case.py index 2766091..cf6cf85 100644 --- a/data_types/block_case.py +++ b/data_types/block_case.py @@ -1,37 +1,37 @@ class block_case(object): - def __init__(self, block_name, props, lines, is_default): - self.block_name = block_name - self.lines = lines - self.is_default = is_default - self.props = props - - def matches(self, block, state): - block_name = self.block_name - - if block_name != '*': - if not block_name.startswith('minecraft:'): - block_name = 'minecraft:' + block_name - - if block_name != block: - return False - - if len(self.props) > 0: - if 'properties' not in state: - return False - - block_props = state['properties'] - for name,value in self.props: - if name not in block_props: - return False - if block_props[name] != value: - return False - - return True - - def compile(self, block, block_state, block_id, func, falling_block_nbt): - func.set_dollarid('block_name', block) - func.set_dollarid('block_state', block_state) - func.set_dollarid('block_id', block_id) - func.set_dollarid('falling_block_nbt', falling_block_nbt) - - func.compile_blocks(self.lines) \ No newline at end of file + def __init__(self, block_name, props, lines, is_default): + self.block_name = block_name + self.lines = lines + self.is_default = is_default + self.props = props + + def matches(self, block, state): + block_name = self.block_name + + if block_name != "*": + if not block_name.startswith("minecraft:"): + block_name = "minecraft:" + block_name + + if block_name != block: + return False + + if len(self.props) > 0: + if "properties" not in state: + return False + + block_props = state["properties"] + for name, value in self.props: + if name not in block_props: + return False + if block_props[name] != value: + return False + + return True + + def compile(self, block, block_state, block_id, func, falling_block_nbt): + func.set_dollarid("block_name", block) + func.set_dollarid("block_state", block_state) + func.set_dollarid("block_id", block_id) + func.set_dollarid("falling_block_nbt", falling_block_nbt) + + func.compile_blocks(self.lines) diff --git a/data_types/const_number.py b/data_types/const_number.py index 7d1d3b3..ceb040d 100644 --- a/data_types/const_number.py +++ b/data_types/const_number.py @@ -1,13 +1,14 @@ from environment import isNumber, isInt + class const_number(object): - def __init__(self, val): - if not isNumber(val): - raise Exception(f'Non-numeric value "{val}" for number.') - if isInt(val): - self.val = int(val) - else: - self.val = float(val) - - def get_value(self, func): - return self.val + def __init__(self, val): + if not isNumber(val): + raise Exception(f'Non-numeric value "{val}" for number.') + if isInt(val): + self.val = int(val) + else: + self.val = float(val) + + def get_value(self, func): + return self.val diff --git a/data_types/const_string.py b/data_types/const_string.py index 14459ea..432c262 100644 --- a/data_types/const_string.py +++ b/data_types/const_string.py @@ -1,6 +1,6 @@ class const_string(object): - def __init__(self, val): - self.val = val - - def get_value(self, func): - return self.val \ No newline at end of file + def __init__(self, val): + self.val = val + + def get_value(self, func): + return self.val diff --git a/data_types/interpreted_python.py b/data_types/interpreted_python.py index ca15dc1..0c6d1e4 100644 --- a/data_types/interpreted_python.py +++ b/data_types/interpreted_python.py @@ -1,7 +1,7 @@ class interpreted_python(object): - def __init__(self, expr, line=0): - self.expr = expr - self.line = line - - def get_value(self, func): - return func.eval(self.expr, self.line) \ No newline at end of file + def __init__(self, expr, line=0): + self.expr = expr + self.line = line + + def get_value(self, func): + return func.eval(self.expr, self.line) diff --git a/data_types/number_macro_path.py b/data_types/number_macro_path.py index 4309c4f..aeff699 100644 --- a/data_types/number_macro_path.py +++ b/data_types/number_macro_path.py @@ -1,43 +1,52 @@ from CompileError import CompileError + class number_macro_path(object): - def __init__(self, id, params, path, type, scale=None): - self.id = id - self.params = params - self.path = path - self.type = type - self.scale = scale - - def get_scale(self, func): - if self.scale == None: - scale = func.scale - else: - scale = self.scale.get_value(func) - - return scale - - def get_path(self, func, macro_args): - if len(macro_args) != len(self.params): - raise CompileError(f'"[{self.id}].{self.path}" expects {len(self.params)} macro arguments, received {len(macro_args)}.') - - overrides = {} - for i in range(len(macro_args)): - overrides[self.params[i]] = macro_args[i].get_value(func) - - return func.apply_replacements(self.path, overrides) - - def copy_to_objective(self, func, coords, macro_args, objective): - func.add_command(f'execute store result score Global {objective} run {self.get_command(func, coords, macro_args)}') - - def copy_from(self, func, coords, macro_args, var): - const_val = var.get_const_value(func) - if const_val: - func.add_command(f'data modify block {coords.get_value(func)} {self.get_path(func, macro_args)} set value {float(const_val) / float(self.get_scale(func))}') - else: - func.add_command(f'execute store result block {coords.get_value(func)} {self.get_path(func, macro_args)} {self.type} {1 / float(self.get_scale(func))} run {var.get_command(func)}') - - def get_command(self, func, coords, macro_args): - return f'data get block {coords.get_value(func)} {self.get_path(func, macro_args)} {self.get_scale(func)}' - - def get_name(self): - return self.id + def __init__(self, id, params, path, type, scale=None): + self.id = id + self.params = params + self.path = path + self.type = type + self.scale = scale + + def get_scale(self, func): + if self.scale == None: + scale = func.scale + else: + scale = self.scale.get_value(func) + + return scale + + def get_path(self, func, macro_args): + if len(macro_args) != len(self.params): + raise CompileError( + f'"[{self.id}].{self.path}" expects {len(self.params)} macro arguments, received {len(macro_args)}.' + ) + + overrides = {} + for i in range(len(macro_args)): + overrides[self.params[i]] = macro_args[i].get_value(func) + + return func.apply_replacements(self.path, overrides) + + def copy_to_objective(self, func, coords, macro_args, objective): + func.add_command( + f"execute store result score Global {objective} run {self.get_command(func, coords, macro_args)}" + ) + + def copy_from(self, func, coords, macro_args, var): + const_val = var.get_const_value(func) + if const_val: + func.add_command( + f"data modify block {coords.get_value(func)} {self.get_path(func, macro_args)} set value {float(const_val) / float(self.get_scale(func))}" + ) + else: + func.add_command( + f"execute store result block {coords.get_value(func)} {self.get_path(func, macro_args)} {self.type} {1 / float(self.get_scale(func))} run {var.get_command(func)}" + ) + + def get_command(self, func, coords, macro_args): + return f"data get block {coords.get_value(func)} {self.get_path(func, macro_args)} {self.get_scale(func)}" + + def get_name(self): + return self.id diff --git a/data_types/python_identifier.py b/data_types/python_identifier.py index 99eef36..579550a 100644 --- a/data_types/python_identifier.py +++ b/data_types/python_identifier.py @@ -1,10 +1,10 @@ class python_identifier(object): - def __init__(self, id, negate = False): - self.id = id - self.negate = negate - - def get_value(self, func): - if self.negate: - return -func.get_dollarid(self.id) - else: - return func.get_dollarid(self.id) \ No newline at end of file + def __init__(self, id, negate=False): + self.id = id + self.negate = negate + + def get_value(self, func): + if self.negate: + return -func.get_dollarid(self.id) + else: + return func.get_dollarid(self.id) diff --git a/data_types/relcoord.py b/data_types/relcoord.py index 281ca78..3362265 100644 --- a/data_types/relcoord.py +++ b/data_types/relcoord.py @@ -1,7 +1,7 @@ class relcoord(object): - def __init__(self, type, coord): - self.type = type - self.coord = coord - - def get_value(self, func): - return self.type + str(self.coord.get_value(func)) \ No newline at end of file + def __init__(self, type, coord): + self.type = type + self.coord = coord + + def get_value(self, func): + return self.type + str(self.coord.get_value(func)) diff --git a/data_types/relcoord_vector.py b/data_types/relcoord_vector.py index 2580863..be102da 100644 --- a/data_types/relcoord_vector.py +++ b/data_types/relcoord_vector.py @@ -1,18 +1,21 @@ from CompileError import CompileError + class relcoord_vector(object): - def __init__(self, line, type, value): - self.type = type - self.value = value - self.line = line - - def get_value(self, func): - coords = self.value.get_value(func) - relcoords = [] - try: - for i in range(3): - relcoords.append(f'{self.type}{coords[i]}') - except Exception as e: - raise CompileError(f'Unable to get three coordinates from constant value at line {self.line}.') - - return ' '.join(relcoords) + def __init__(self, line, type, value): + self.type = type + self.value = value + self.line = line + + def get_value(self, func): + coords = self.value.get_value(func) + relcoords = [] + try: + for i in range(3): + relcoords.append(f"{self.type}{coords[i]}") + except Exception as e: + raise CompileError( + f"Unable to get three coordinates from constant value at line {self.line}." + ) + + return " ".join(relcoords) diff --git a/data_types/relcoords.py b/data_types/relcoords.py index 05cdadd..af1fe1f 100644 --- a/data_types/relcoords.py +++ b/data_types/relcoords.py @@ -1,16 +1,17 @@ from .relcoord import relcoord from .const_string import const_string + class relcoords(object): - def __init__(self, coords = None): - if coords == None: - self.coords = ( - relcoord('~', const_string('')), - relcoord('~', const_string('')), - relcoord('~', const_string('')), - ) - else: - self.coords = coords - - def get_value(self, func): - return ' '.join([c.get_value(func) for c in self.coords]) \ No newline at end of file + def __init__(self, coords=None): + if coords == None: + self.coords = ( + relcoord("~", const_string("")), + relcoord("~", const_string("")), + relcoord("~", const_string("")), + ) + else: + self.coords = coords + + def get_value(self, func): + return " ".join([c.get_value(func) for c in self.coords]) diff --git a/data_types/shaped_recipe.py b/data_types/shaped_recipe.py index 06457bf..79df618 100644 --- a/data_types/shaped_recipe.py +++ b/data_types/shaped_recipe.py @@ -1,28 +1,27 @@ class shaped_recipe(object): - def __init__(self, recipe_lines, keys, count, item, group): - self.recipe_lines = recipe_lines - self.keys = keys - self.count = count - self.item = item - self.group = group - - def get_json_struct(self): - recipe_struct = {} - recipe_struct['type'] = 'minecraft:crafting_shaped' - recipe_struct['group'] = self.group - recipe_struct['pattern'] = self.recipe_lines - recipe_struct['key'] = {} - for key, type, value in self.keys: - # TODO: check for custom tags - recipe_struct['key'][key] = {type: value} - - recipe_struct['result'] = { - 'item': 'minecraft:' + self.item, - 'count': self.count - } - - return recipe_struct - - - def get_type(self): - return 'shaped' \ No newline at end of file + def __init__(self, recipe_lines, keys, count, item, group): + self.recipe_lines = recipe_lines + self.keys = keys + self.count = count + self.item = item + self.group = group + + def get_json_struct(self): + recipe_struct = {} + recipe_struct["type"] = "minecraft:crafting_shaped" + recipe_struct["group"] = self.group + recipe_struct["pattern"] = self.recipe_lines + recipe_struct["key"] = {} + for key, type, value in self.keys: + # TODO: check for custom tags + recipe_struct["key"][key] = {type: value} + + recipe_struct["result"] = { + "item": "minecraft:" + self.item, + "count": self.count, + } + + return recipe_struct + + def get_type(self): + return "shaped" diff --git a/environment.py b/environment.py index 26aabd7..7478f4e 100644 --- a/environment.py +++ b/environment.py @@ -1,410 +1,434 @@ -import copy import math from scratch_tracker import scratch_tracker from selector_definition import selector_definition from CompileError import CompileError + def isNumber(s): - try: - val = float(s) - - if math.isinf(val): - return False - - if math.isnan(val): - return False - - return True - except Exception: - return False - + try: + val = float(s) + + if math.isinf(val): + return False + + if math.isnan(val): + return False + + return True + except Exception: + return False + + def isInt(s): - try: - if isinstance(s, str): - if s == str(int(s)): - return True - return False - else: - int(s) - return True - except Exception: - return False - - + try: + if isinstance(s, str): + if s == str(int(s)): + return True + return False + else: + int(s) + return True + except Exception: + return False + + class environment(object): - def __init__(self, global_context): - self.dollarid = {} - self.global_context = global_context - self.scratch = scratch_tracker(global_context) - self.locals = [] - self.selectors = {} - self.self_selector = None - self.name_definitions = {} - self.pointers = {} - self.block_definitions = {} - self.function_name = None - - def clone(self, new_function_name = None): - new_env = environment(self.global_context) - - for id in self.selectors: - new_env.selectors[id] = self.selectors[id] - - for id in self.block_definitions: - new_env.block_definitions[id] = self.block_definitions[id] - - for id in self.pointers: - new_env.pointers[id] = self.pointers[id] - - for id in self.dollarid: - new_env.dollarid[id] = self.dollarid[id] - - for id in self.name_definitions: - new_env.name_definitions[id] = self.name_definitions[id] - - #new_env.dollarid = copy.deepcopy(self.dollarid) - if new_function_name == None: - new_env.scratch = self.scratch - new_env.locals = self.locals - new_env.function_name = self.function_name - else: - new_env.scratch.prefix = self.global_context.get_scratch_prefix(new_function_name) - new_env.function_name = new_function_name - - - new_env.self_selector = self.self_selector - - return new_env - - def register_local(self, local): - if local not in self.locals: - self.locals.append(local) - - def apply(self, text): - text = self.apply_replacements(text) - text = self.compile_selectors(text) - - return text - - def apply_replacements(self, text, overrides = {}): - replacements = {} - for k in self.dollarid: - replacements[k] = self.dollarid[k] - - for k in overrides: - replacements[k] = overrides[k] - - for identifier in reversed(sorted(replacements.keys())): - if isInt(replacements[identifier]): - text = str(text).replace('-$' + identifier, str(-int(replacements[identifier]))) - elif isNumber(replacements[identifier]): - text = str(text).replace('-$' + identifier, str(-float(replacements[identifier]))) - text = str(text).replace('$' + identifier, str(replacements[identifier])) - - if text == None: - raise Exception(f'Applying replacements to "{text}" returned None.') - - return text - - def set_dollarid(self, id, val): - if len(id) == 0: - raise Exception('Dollar ID is empty string.') - - if id[0] == '$': - id = id[1:] - - self.dollarid[id] = val - - def get_dollarid(self, id): - if len(id) == 0: - raise Exception('Dollar ID is empty string.') - - if id[0] == '$': - id = id[1:] - - return self.dollarid[id] - - def copy_dollarid(self, id, copyid): - negate = False - if len(id) == 0: - raise Exception('Dollar ID is empty string.') - - if id[0].startswith('$'): - id = id[1:] - - if copyid.startswith('$'): - copyid = copyid[1:] - - if copyid.startswith('-$'): - copyid = copyid[2:] - negate = True - - self.dollarid[id] = self.dollarid[copyid] - if negate: - if isInt(self.dollarid[id]): - self.dollarid[id] = str(-int(self.dollarid[id])) - elif isNumber(self.dollarid[id]): - self.dollarid[id] = str(-float(self.dollarid[id])) - else: - raise CompileError(f'Unable to negate value of ${copyid} when copying to ${id}, it has non-numeric value "{self.dollarid[id]}"') - - def set_atid(self, id, fullselector): - self.selectors[id] = selector_definition(fullselector, self) - - return self.selectors[id] - - def register_name_definition(self, id, str): - self.name_definitions[id] = str - - def get_name_definition(self, id): - if id in self.name_definitions: - return self.name_definitions[id] - else: - return None - - def compile_selectors(self, command): - ret = "" - for fragment in self.split_selectors(command): - if fragment[0] == "@": - ret = ret + self.compile_selector(fragment) - else: - ret = ret + fragment - - return ret - - def get_selector_parts(self, selector): - if len(selector) == 2: - selector += "[]" - - start = selector[0:3] - end = selector[-1] - middle = selector[3:-1] - - parts = middle.split(',') - - return start, [part.strip() for part in parts], end - - def compile_selector(self, selector): - sel = selector_definition(selector, self) - interpreted = sel.compile() - - if len(interpreted) == 4: - # We have @a[] or similar, so truncate - interpreted = interpreted[:2] - - return interpreted - - def get_python_env(self): - return self.dollarid - - def register_objective(self, objective): - if len(objective) > 16: - raise CompileError(f'Objective name "{objective}" is {len(objective)} characters long, max is 16.') - self.global_context.register_objective(objective) - - def split_selectors(self, line): - fragments = [] - - remaining = str(line) - while '@' in remaining: - parts = remaining.split('@', 1) - if len(parts[0]) > 0: - fragments.append(parts[0]) - - end = 0 - for i in range(len(parts[1])): - if parts[1][i].isalnum() or parts[1][i] == '_': - end += 1 - elif parts[1][i] == '[': - brack_count = 1 - for j in range(i+1, len(parts[1])): - if parts[1][j] == '[': - brack_count += 1 - if parts[1][j] == ']': - brack_count -= 1 - if brack_count == 0: - end = j+1 - break - break - else: - break - - fragments.append('@' + parts[1][:end]) - remaining = parts[1][end:] - - if len(remaining) > 0: - fragments.append(remaining) - - #print(line, fragments) - - return fragments - - def update_self_selector(self, selector): - if selector[0] != '@': - return - - id = selector[1:] - if '[' in id: - id = id.split('[',1)[0] - - if id in self.selectors: - self.self_selector = self.selectors[id] - - def register_objective(self, objective): - self.global_context.register_objective(objective) - - def register_array(self, name, from_val, to_val, selector_based): - self.global_context.register_array(name, from_val, to_val, selector_based) - - def register_block_tag(self, name, blocks): - self.global_context.register_block_tag(name, blocks) - - def register_entity_tag(self, name, entities): - self.global_context.register_entity_tag(name, entities) - - def register_item_tag(self, name, items): - self.global_context.register_item_tag(name, items) - - def get_scale(self): - return self.global_context.scale - - def set_scale(self, scale): - self.global_context.scale = scale - - scale = property(get_scale, set_scale) - - @property - def arrays(self): - return self.global_context.arrays - - @property - def block_tags(self): - return self.global_context.block_tags - - @property - def item_tags(self): - return self.global_context.item_tags - - @property - def entity_tags(self): - return self.global_context.entity_tags - - @property - def namespace(self): - return self.global_context.namespace - - @property - def macros(self): - return self.global_context.macros - - @property - def template_functions(self): - return self.global_context.template_functions - - @property - def functions(self): - return self.global_context.functions - - def get_scratch(self): - return self.scratch.get_scratch() - - def get_scratch_vector(self): - return self.scratch.get_scratch_vector() - - def is_scratch(self, var): - return self.scratch.is_scratch(var) - - def free_scratch(self, id): - self.scratch.free_scratch(id) - - def get_temp_var(self): - return self.scratch.get_temp_var() - - def free_temp_var(self): - self.scratch.free_temp_var() - - def add_constant(self, val): - return self.global_context.add_constant(val) - - def get_friendly_name(self): - return self.global_context.get_friendly_name() - - def get_random_objective(self): - return self.global_context.get_random_objective() - - def register_function(self, name, func): - self.global_context.register_function(name, func) - - def get_unique_id(self): - return self.global_context.get_unique_id() - - def register_clock(self, name): - self.global_context.register_clock(name) - - def get_selector_definition(self, selector_text): - if selector_text.startswith('@'): - return selector_definition(selector_text, self) - else: - return None - - @property - def parser(self): - return self.global_context.parser - - def register_dependency(self, filename): - self.global_context.register_dependency(filename) - - def add_pointer(self, block_id, selector): - self.pointers[block_id] = selector - - def add_block_definition(self, block_id, definition): - self.block_definitions[block_id] = definition - - def get_block_definition(self, block_id): - if block_id not in self.block_definitions: - raise CompileError(f'[{block_id}] is not defined.') - - return self.block_definitions[block_id] - - def get_block_path(self, func, block_id, path_id, coords, macro_args, initialize): - if block_id not in self.block_definitions: - raise CompileError(f'[{block_id}] is not defined.') - - if initialize: - self.block_definitions[block_id].get_path(func, path_id, coords, macro_args) - - return 'Global', path_id - - def set_block_path(self, func, block_id, path_id, coords, macro_args, initialize): - if block_id not in self.block_definitions: - raise CompileError(f'[{block_id}] is not defined.') - - self.block_definitions[block_id].set_path(func, path_id, coords, macro_args) - - def add_recipe(self, recipe): - self.global_context.add_recipe(recipe) - - def add_advancement(self, name, advancement): - self.global_context.add_advancement(name, advancement) - - def add_loot_table(self, name, loot_table): - self.global_context.add_loot_table(name, loot_table) - - def add_predicate(self, name, predicate): - self.global_context.add_predicate(name, predicate) - - def add_item_modifier(self, name, item_modifier): - self.global_context.add_item_modifier(name, item_modifier) - - def get_block_state_list(self, include_block_states): - return self.global_context.get_block_state_list(include_block_states) - - def get_reset_function(self): - return self.global_context.get_reset_function() - - def get_all_locals(self): - return self.locals + self.scratch.get_active_objectives() - - @property - def predicates(self): - return self.global_context.predicates \ No newline at end of file + def __init__(self, global_context): + self.dollarid = {} + self.global_context = global_context + self.scratch = scratch_tracker(global_context) + self.locals = [] + self.selectors = {} + self.self_selector = None + self.name_definitions = {} + self.pointers = {} + self.block_definitions = {} + self.function_name = None + + def clone(self, new_function_name=None): + new_env = environment(self.global_context) + + for id in self.selectors: + new_env.selectors[id] = self.selectors[id] + + for id in self.block_definitions: + new_env.block_definitions[id] = self.block_definitions[id] + + for id in self.pointers: + new_env.pointers[id] = self.pointers[id] + + for id in self.dollarid: + new_env.dollarid[id] = self.dollarid[id] + + for id in self.name_definitions: + new_env.name_definitions[id] = self.name_definitions[id] + + # new_env.dollarid = copy.deepcopy(self.dollarid) + if new_function_name == None: + new_env.scratch = self.scratch + new_env.locals = self.locals + new_env.function_name = self.function_name + else: + new_env.scratch.prefix = self.global_context.get_scratch_prefix( + new_function_name + ) + new_env.function_name = new_function_name + + new_env.self_selector = self.self_selector + + return new_env + + def register_local(self, local): + if local not in self.locals: + self.locals.append(local) + + def apply(self, text): + text = self.apply_replacements(text) + text = self.compile_selectors(text) + + return text + + def apply_replacements(self, text, overrides={}): + replacements = {} + for k in self.dollarid: + replacements[k] = self.dollarid[k] + + for k in overrides: + replacements[k] = overrides[k] + + for identifier in reversed(sorted(replacements.keys())): + if isInt(replacements[identifier]): + text = str(text).replace( + "-$" + identifier, str(-int(replacements[identifier])) + ) + elif isNumber(replacements[identifier]): + text = str(text).replace( + "-$" + identifier, str(-float(replacements[identifier])) + ) + text = str(text).replace( + "$" + identifier, str(replacements[identifier]) + ) + + if text == None: + raise Exception( + f'Applying replacements to "{text}" returned None.' + ) + + return text + + def set_dollarid(self, id, val): + if len(id) == 0: + raise Exception("Dollar ID is empty string.") + + if id[0] == "$": + id = id[1:] + + self.dollarid[id] = val + + def get_dollarid(self, id): + if len(id) == 0: + raise Exception("Dollar ID is empty string.") + + if id[0] == "$": + id = id[1:] + + return self.dollarid[id] + + def copy_dollarid(self, id, copyid): + negate = False + if len(id) == 0: + raise Exception("Dollar ID is empty string.") + + if id[0].startswith("$"): + id = id[1:] + + if copyid.startswith("$"): + copyid = copyid[1:] + + if copyid.startswith("-$"): + copyid = copyid[2:] + negate = True + + self.dollarid[id] = self.dollarid[copyid] + if negate: + if isInt(self.dollarid[id]): + self.dollarid[id] = str(-int(self.dollarid[id])) + elif isNumber(self.dollarid[id]): + self.dollarid[id] = str(-float(self.dollarid[id])) + else: + raise CompileError( + f'Unable to negate value of ${copyid} when copying to ${id}, it has non-numeric value "{self.dollarid[id]}"' + ) + + def set_atid(self, id, fullselector): + self.selectors[id] = selector_definition(fullselector, self) + + return self.selectors[id] + + def register_name_definition(self, id, str): + self.name_definitions[id] = str + + def get_name_definition(self, id): + if id in self.name_definitions: + return self.name_definitions[id] + else: + return None + + def compile_selectors(self, command): + ret = "" + for fragment in self.split_selectors(command): + if fragment[0] == "@": + ret = ret + self.compile_selector(fragment) + else: + ret = ret + fragment + + return ret + + def get_selector_parts(self, selector): + if len(selector) == 2: + selector += "[]" + + start = selector[0:3] + end = selector[-1] + middle = selector[3:-1] + + parts = middle.split(",") + + return start, [part.strip() for part in parts], end + + def compile_selector(self, selector): + sel = selector_definition(selector, self) + interpreted = sel.compile() + + if len(interpreted) == 4: + # We have @a[] or similar, so truncate + interpreted = interpreted[:2] + + return interpreted + + def get_python_env(self): + return self.dollarid + + def register_objective(self, objective): + if len(objective) > 16: + raise CompileError( + f'Objective name "{objective}" is {len(objective)} characters long, max is 16.' + ) + self.global_context.register_objective(objective) + + def split_selectors(self, line): + fragments = [] + + remaining = str(line) + while "@" in remaining: + parts = remaining.split("@", 1) + if len(parts[0]) > 0: + fragments.append(parts[0]) + + end = 0 + for i in range(len(parts[1])): + if parts[1][i].isalnum() or parts[1][i] == "_": + end += 1 + elif parts[1][i] == "[": + brack_count = 1 + for j in range(i + 1, len(parts[1])): + if parts[1][j] == "[": + brack_count += 1 + if parts[1][j] == "]": + brack_count -= 1 + if brack_count == 0: + end = j + 1 + break + break + else: + break + + fragments.append("@" + parts[1][:end]) + remaining = parts[1][end:] + + if len(remaining) > 0: + fragments.append(remaining) + + # print(line, fragments) + + return fragments + + def update_self_selector(self, selector): + if selector[0] != "@": + return + + id = selector[1:] + if "[" in id: + id = id.split("[", 1)[0] + + if id in self.selectors: + self.self_selector = self.selectors[id] + + def register_objective(self, objective): + self.global_context.register_objective(objective) + + def register_array(self, name, from_val, to_val, selector_based): + self.global_context.register_array( + name, from_val, to_val, selector_based + ) + + def register_block_tag(self, name, blocks): + self.global_context.register_block_tag(name, blocks) + + def register_entity_tag(self, name, entities): + self.global_context.register_entity_tag(name, entities) + + def register_item_tag(self, name, items): + self.global_context.register_item_tag(name, items) + + def get_scale(self): + return self.global_context.scale + + def set_scale(self, scale): + self.global_context.scale = scale + + scale = property(get_scale, set_scale) + + @property + def arrays(self): + return self.global_context.arrays + + @property + def block_tags(self): + return self.global_context.block_tags + + @property + def item_tags(self): + return self.global_context.item_tags + + @property + def entity_tags(self): + return self.global_context.entity_tags + + @property + def namespace(self): + return self.global_context.namespace + + @property + def macros(self): + return self.global_context.macros + + @property + def template_functions(self): + return self.global_context.template_functions + + @property + def functions(self): + return self.global_context.functions + + def get_scratch(self): + return self.scratch.get_scratch() + + def get_scratch_vector(self): + return self.scratch.get_scratch_vector() + + def is_scratch(self, var): + return self.scratch.is_scratch(var) + + def free_scratch(self, id): + self.scratch.free_scratch(id) + + def get_temp_var(self): + return self.scratch.get_temp_var() + + def free_temp_var(self): + self.scratch.free_temp_var() + + def add_constant(self, val): + return self.global_context.add_constant(val) + + def get_friendly_name(self): + return self.global_context.get_friendly_name() + + def get_random_objective(self): + return self.global_context.get_random_objective() + + def register_function(self, name, func): + self.global_context.register_function(name, func) + + def get_unique_id(self): + return self.global_context.get_unique_id() + + def register_clock(self, name): + self.global_context.register_clock(name) + + def get_selector_definition(self, selector_text): + if selector_text.startswith("@"): + return selector_definition(selector_text, self) + else: + return None + + @property + def parser(self): + return self.global_context.parser + + def register_dependency(self, filename): + self.global_context.register_dependency(filename) + + def add_pointer(self, block_id, selector): + self.pointers[block_id] = selector + + def add_block_definition(self, block_id, definition): + self.block_definitions[block_id] = definition + + def get_block_definition(self, block_id): + if block_id not in self.block_definitions: + raise CompileError(f"[{block_id}] is not defined.") + + return self.block_definitions[block_id] + + def get_block_path( + self, func, block_id, path_id, coords, macro_args, initialize + ): + if block_id not in self.block_definitions: + raise CompileError(f"[{block_id}] is not defined.") + + if initialize: + self.block_definitions[block_id].get_path( + func, path_id, coords, macro_args + ) + + return "Global", path_id + + def set_block_path( + self, func, block_id, path_id, coords, macro_args, initialize + ): + if block_id not in self.block_definitions: + raise CompileError(f"[{block_id}] is not defined.") + + self.block_definitions[block_id].set_path( + func, path_id, coords, macro_args + ) + + def add_recipe(self, recipe): + self.global_context.add_recipe(recipe) + + def add_advancement(self, name, advancement): + self.global_context.add_advancement(name, advancement) + + def add_loot_table(self, name, loot_table): + self.global_context.add_loot_table(name, loot_table) + + def add_predicate(self, name, predicate): + self.global_context.add_predicate(name, predicate) + + def add_item_modifier(self, name, item_modifier): + self.global_context.add_item_modifier(name, item_modifier) + + def get_block_state_list(self, include_block_states): + return self.global_context.get_block_state_list(include_block_states) + + def get_reset_function(self): + return self.global_context.get_reset_function() + + def get_all_locals(self): + return self.locals + self.scratch.get_active_objectives() + + @property + def predicates(self): + return self.global_context.predicates diff --git a/global_context.py b/global_context.py index 74544ad..5a8654d 100644 --- a/global_context.py +++ b/global_context.py @@ -1,201 +1,214 @@ -from mcfunction import mcfunction from CompileError import CompileError import json + def get_friendly_name(namespace): - name = "CB" + namespace[:14] - name = name.replace(' ', '_') - name = name.replace('.', '_') - name = name.replace(',', '_') - name = name.replace(':', '_') - name = name.replace('{', '_') - name = name.replace('}', '_') - name = name.replace('=', '_') - - return name + name = "CB" + namespace[:14] + name = name.replace(" ", "_") + name = name.replace(".", "_") + name = name.replace(",", "_") + name = name.replace(":", "_") + name = name.replace("{", "_") + name = name.replace("}", "_") + name = name.replace("=", "_") + + return name + def get_constant_name(c): - if c == -1: - return 'minus' - elif c >= 0: - return f'c{c}' - else: - return f'cm{-c}' - + if c == -1: + return "minus" + elif c >= 0: + return f"c{c}" + else: + return f"cm{-c}" + + class global_context(object): - def __init__(self, namespace): - self.clocks = [] - self.functions = {} - self.function_params = {} - self.macros = {} - self.template_functions = {} - self.reset = None - self.objectives = {} - self.constants = [] - self.arrays = {} - self.scratch = {} - self.temp = 0 - self.unique = 0 - self.friendly_name = get_friendly_name(namespace) - self.block_tags = {} - self.entity_tags = {} - self.item_tags = {} - self.scratch_prefixes = {} - self.namespace = namespace - self.parser = None - self.dependencies = [] - self.recipes = [] - self.advancements = {} - self.loot_tables = {} - self.predicates = {} - self.item_modifiers = {} - self.block_state_list = None - self.block_list = None - - def register_block_tag(self, name, blocks): - self.block_tags[name] = blocks - - def register_entity_tag(self, name, entities): - self.entity_tags[name] = entities - - def register_item_tag(self, name, items): - self.item_tags[name] = items - - def get_unique_id(self): - self.unique += 1 - return self.unique - - def register_clock(self, name): - self.clocks.append(name) - - def register_function(self, name, func): - self.functions[name] = func - func.set_filename(name) - - def register_function_params(self, name, params): - self.function_params[name] = params - - def register_array(self, name, from_val, to_val, selector_based): - if name in self.arrays: - raise CompileError(f'Array "{name}" is defined multiple times.') - self.arrays[name] = (from_val, to_val, selector_based) - - def register_objective(self, objective): - if len(objective) > 16: - raise CompileError(f'Cannot create objective "{objective}", name is {len(objective)} characters (max is 16)') - self.objectives[objective] = True - - def get_reset_function(self): - if 'reset' in self.functions: - return self.functions['reset'] - else: - return None - - def add_constant(self, c): - try: - c = int(c) - except: - print(e) - raise Exception(f'Unable to create constant integer value for "{c}"') - - if c not in self.constants: - self.constants.append(c) - - return get_constant_name(c) - - def add_constant_definitions(self): - f = self.get_reset_function() - - if len(self.constants) > 0: - f.insert_command('/scoreboard objectives add Constant dummy', 0) - for c in self.constants: - f.insert_command(f'/scoreboard players set {get_constant_name(c)} Constant {c}', 1) - - def allocate_scratch(self, prefix, n): - if prefix not in self.scratch: - self.scratch[prefix] = 0 - - if n > self.scratch[prefix]: - self.scratch[prefix] = n - - def allocate_temp(self, temp): - if temp > self.temp: - self.temp = temp - - def finalize_functions(self): - for func in self.functions.values(): - func.finalize() - - def get_scratch_prefix(self, name): - name = name[:3] - if name in self.scratch_prefixes: - i = 2 - while f"{name}{i}" in self.scratch_prefixes: - i += 1 - - name = f"{name}{i}" - self.scratch_prefixes[name] = True - return name - else: - self.scratch_prefixes[name] = True - return name - - def get_random_objective(self): - return "RV" + self.friendly_name[2:] - - def register_dependency(self, filename): - self.dependencies.append(filename) - - def add_recipe(self, recipe): - self.recipes.append(recipe) - - def add_advancement(self, name, advancement): - self.advancements[name] = advancement - - def add_loot_table(self, name, loot_table): - self.loot_tables[name] = loot_table - - def add_predicate(self, name, predicate): - self.predicates[name] = predicate - - def add_item_modifier(self, name, item_modifier): - self.item_modifiers[name] = item_modifier - - def get_block_state_list(self, include_block_states): - if include_block_states: - if self.block_state_list: - blocks = self.block_state_list - else: - with open('blocks.json', 'r') as f: - blocks = json.load(f) - - self.block_state_list = blocks - - else: - if self.block_list: - blocks = self.block_list - else: - with open('blocks.json', 'r') as f: - blocks = json.load(f) - - id = 0 - for block in blocks: - blocks[block]['states'] = [state for state in blocks[block]['states'] if 'default' in state] - if 'properties' in blocks[block]['states'][0]: - del blocks[block]['states'][0]['properties'] - if 'properties' in blocks[block]: - del blocks[block]['properties'] - blocks[block]['states'][0]['id'] = id - id += 1 - - self.block_list = blocks - - return blocks - - def get_num_blocks(self): - blocks = self.get_block_state_list(False) - return len(blocks) - - def get_num_block_states(self): - blocks = self.get_block_state_list(True) - return len(blocks) \ No newline at end of file + def __init__(self, namespace): + self.clocks = [] + self.functions = {} + self.function_params = {} + self.macros = {} + self.template_functions = {} + self.reset = None + self.objectives = {} + self.constants = [] + self.arrays = {} + self.scratch = {} + self.temp = 0 + self.unique = 0 + self.friendly_name = get_friendly_name(namespace) + self.block_tags = {} + self.entity_tags = {} + self.item_tags = {} + self.scratch_prefixes = {} + self.namespace = namespace + self.parser = None + self.dependencies = [] + self.recipes = [] + self.advancements = {} + self.loot_tables = {} + self.predicates = {} + self.item_modifiers = {} + self.block_state_list = None + self.block_list = None + + def register_block_tag(self, name, blocks): + self.block_tags[name] = blocks + + def register_entity_tag(self, name, entities): + self.entity_tags[name] = entities + + def register_item_tag(self, name, items): + self.item_tags[name] = items + + def get_unique_id(self): + self.unique += 1 + return self.unique + + def register_clock(self, name): + self.clocks.append(name) + + def register_function(self, name, func): + self.functions[name] = func + func.set_filename(name) + + def register_function_params(self, name, params): + self.function_params[name] = params + + def register_array(self, name, from_val, to_val, selector_based): + if name in self.arrays: + raise CompileError(f'Array "{name}" is defined multiple times.') + self.arrays[name] = (from_val, to_val, selector_based) + + def register_objective(self, objective): + if len(objective) > 16: + raise CompileError( + f'Cannot create objective "{objective}", name is {len(objective)} characters (max is 16)' + ) + self.objectives[objective] = True + + def get_reset_function(self): + if "reset" in self.functions: + return self.functions["reset"] + else: + return None + + def add_constant(self, c): + try: + c = int(c) + except: + print(e) + raise Exception( + f'Unable to create constant integer value for "{c}"' + ) + + if c not in self.constants: + self.constants.append(c) + + return get_constant_name(c) + + def add_constant_definitions(self): + f = self.get_reset_function() + + if len(self.constants) > 0: + f.insert_command("/scoreboard objectives add Constant dummy", 0) + for c in self.constants: + f.insert_command( + f"/scoreboard players set {get_constant_name(c)} Constant {c}", + 1, + ) + + def allocate_scratch(self, prefix, n): + if prefix not in self.scratch: + self.scratch[prefix] = 0 + + if n > self.scratch[prefix]: + self.scratch[prefix] = n + + def allocate_temp(self, temp): + if temp > self.temp: + self.temp = temp + + def finalize_functions(self): + for func in self.functions.values(): + func.finalize() + + def get_scratch_prefix(self, name): + name = name[:3] + if name in self.scratch_prefixes: + i = 2 + while f"{name}{i}" in self.scratch_prefixes: + i += 1 + + name = f"{name}{i}" + self.scratch_prefixes[name] = True + return name + else: + self.scratch_prefixes[name] = True + return name + + def get_random_objective(self): + return "RV" + self.friendly_name[2:] + + def register_dependency(self, filename): + self.dependencies.append(filename) + + def add_recipe(self, recipe): + self.recipes.append(recipe) + + def add_advancement(self, name, advancement): + self.advancements[name] = advancement + + def add_loot_table(self, name, loot_table): + self.loot_tables[name] = loot_table + + def add_predicate(self, name, predicate): + self.predicates[name] = predicate + + def add_item_modifier(self, name, item_modifier): + self.item_modifiers[name] = item_modifier + + def get_block_state_list(self, include_block_states): + if include_block_states: + if self.block_state_list: + blocks = self.block_state_list + else: + with open("blocks.json", "r") as f: + blocks = json.load(f) + + self.block_state_list = blocks + + else: + if self.block_list: + blocks = self.block_list + else: + with open("blocks.json", "r") as f: + blocks = json.load(f) + + id = 0 + for block in blocks: + blocks[block]["states"] = [ + state + for state in blocks[block]["states"] + if "default" in state + ] + if "properties" in blocks[block]["states"][0]: + del blocks[block]["states"][0]["properties"] + if "properties" in blocks[block]: + del blocks[block]["properties"] + blocks[block]["states"][0]["id"] = id + id += 1 + + self.block_list = blocks + + return blocks + + def get_num_blocks(self): + blocks = self.get_block_state_list(False) + return len(blocks) + + def get_num_block_states(self): + blocks = self.get_block_state_list(True) + return len(blocks) diff --git a/mcfunction.py b/mcfunction.py index 977808c..9567509 100644 --- a/mcfunction.py +++ b/mcfunction.py @@ -1,906 +1,1000 @@ from selector_definition import selector_definition -from environment import isNumber from source_file import source_file from variable_types.scoreboard_var import scoreboard_var from block_types.push_block import push_block from block_types.pop_block import pop_block from CompileError import CompileError -import math import traceback import json + def get_undecorated_selector_name(selector): - if selector.startswith('@'): - selector = selector[1:] - selector = selector.split('[')[0] - - return selector + if selector.startswith("@"): + selector = selector[1:] + selector = selector.split("[")[0] + + return selector + def compile_section(section, environment): - type, name, template_params, params, lines = section - - if type == 'function': - f = mcfunction(environment.clone(new_function_name = name), True, params) - elif type == 'reset': - f = environment.get_reset_function() - if f == None: - f = mcfunction(environment.clone(new_function_name = name)) - else: - f = mcfunction(environment.clone(new_function_name = name)) - - environment.register_function(name, f) - - if type == 'clock': - environment.register_clock(name) - - f.compile_blocks(lines) + type, name, template_params, params, lines = section + + if type == "function": + f = mcfunction(environment.clone(new_function_name=name), True, params) + elif type == "reset": + f = environment.get_reset_function() + if f == None: + f = mcfunction(environment.clone(new_function_name=name)) + else: + f = mcfunction(environment.clone(new_function_name=name)) + + environment.register_function(name, f) + + if type == "clock": + environment.register_clock(name) + + f.compile_blocks(lines) + def real_command(cmd): - return not cmd.startswith('#') and len(cmd) > 0 - + return not cmd.startswith("#") and len(cmd) > 0 + + class mcfunction(object): - def __init__(self, environment, callable = False, params = []): - self.commands = [] - self.environment = environment - self.params = params - self.callable = callable - self.environment_stack = [] - self.has_macros = False - self.filename = None - - for param in params: - self.register_local(param) - - def set_filename(self, filename): - self.filename = filename - - # Returns the command to call this function - def get_call(self): - if self.filename == None: - raise CompileError('Tried to call function with no registered filename.') - - if self.has_macros: - return f'function {self.namespace}:{self.filename} with storage {self.namespace}:global args' - else: - return f'function {self.namespace}:{self.filename}' - - def evaluate_params(self, params): - results = [] - for p in range(len(params)): - param_name = f'Param{p}' - param_var = scoreboard_var('Global', param_name) - try: - var = params[p].compile(self, None) - except Exception as e: - print(e) - print(f'Unable to compile parameter {p}.') - return False - - param_var.copy_from(self, var) - - return True - - def get_arrayconst_var(self, name, idxval): - return self.environment.get_arrayconst_var(name, idxval) - - def get_if_chain(self, conditions, iftype='if'): - test = '' - for type, val in conditions: - if type == 'selector': - test += f'{iftype} entity {val} ' - elif type == 'predicate': - if ':' in val: - test += f'{iftype} predicate {val} ' - elif val in self.predicates: - test += f'{iftype} predicate {self.namespace}:{val} ' - else: - raise CompileError(f'Predicate "{val}" does not exist') - elif type == 'score': - lexpr, op, rexpr = val - - lvar = lexpr.compile(self) - rvar = rexpr.compile(self) - - lconst = lvar.get_const_value(self) - rconst = rvar.get_const_value(self) - - if lconst != None and rconst != None: - result = False - # Perform comparison, terminate if-chain if false - if op == '=' and lconst == rconst: - result = True - elif op == '>' and lconst > rconst: - result = True - elif op == '<' and lconst < rconst: - result = True - elif op == '>=' and lconst >= rconst: - result = True - elif op == '<=' and lconst <= rconst: - result = True - - if iftype == 'if' and not result or iftype == 'unless' and result: - # Clobber entire if chain - return 'if score Global unique matches -1 ' - else: - # No modification to the test string is necessary - continue - - elif lconst != None or rconst != None: - # Continue if chain comparing the scoreboard value with numeric range - if lconst != None: - sbvar = rvar.get_scoreboard_var(self) - const = lconst - elif rconst != None: - sbvar = lvar.get_scoreboard_var(self) - const = rconst - - if op == '>': - test += f'{iftype} score {sbvar.selector} {sbvar.objective} matches {int(const)+1}.. ' - if op == '>=': - test += f'{iftype} score {sbvar.selector} {sbvar.objective} matches {const}.. ' - if op == '<': - test += f'{iftype} score {sbvar.selector} {sbvar.objective} matches ..{int(const)-1} ' - if op == '<=': - test += f'{iftype} score {sbvar.selector} {sbvar.objective} matches ..{const} ' - if op == '=': - test += f'{iftype} score {sbvar.selector} {sbvar.objective} matches {const} ' - - else: - # Continue if chain comparing two score values - lsbvar = lvar.get_scoreboard_var(self) - rsbvar = rvar.get_scoreboard_var(self) - - test += f'{iftype} score {lsbvar.selector} {lsbvar.objective} {op} {rsbvar.selector} {rsbvar.objective} ' - - elif type == 'vector_equality': - if iftype == 'unless': - raise CompileError('Vector equality may not be used with "unless"') - - (type1, var1), (type2, var2) = val - - if type1 == 'VAR_CONST' and type2 == 'VAR_CONST': - val1 = var1.get_value(self) - val2 = var2.get_value(self) - if val1 != val2: - # Test fails, clobber entire chain - return 'if score Global unique matches -1 ' - else: - # Test succeeds, continue with the chain - continue - else: - if type1 == 'VAR_CONST': - # Swap vars so that the constant var is always second - temp_type = type1 - temp_var = var1 - type1 = type2 - var1 = var2 - type2 = temp_type - var2 = temp_var - - const_vals = [] - if type2 == 'VAR_CONST': - components = var2.get_value(self) - try: - const_vals = [int(components[i]) for i in range(3)] - except Exception as e: - print(e) - raise CompileError('Unable to get three components for constant vector.') - - for i in range(3): - if type1 == 'VAR_ID': - lvar = scoreboard_var('Global', f'_{var1}_{i}') - elif type1 == 'SEL_VAR_ID': - sel1, selvar1 = var1 - lvar = scoreboard_var(sel1, f'_{selvar1}_{i}') - elif type1 == 'VAR_COMPONENTS': - lvar = var1[i].get_scoreboard_var(self) - - if type2 == 'VAR_CONST': - test += f'if score {sel1} {sco1} matches {const_vals[i]} ' - else: - if type2 == 'VAR_ID': - rvar = scoreboard_var('Global', f'_{var2}_{i}') - elif type2 == 'SEL_VAR_ID': - sel2, selvar2 = var2 - rvar = scoreboard_var(sel2, f'_{selvar2}_{i}') - elif type2 == 'VAR_COMPONENTS': - rvar = var2[i].get_scoreboard_var(self) - - test += f'if score {lvar.selvar} = {rvar.selvar} ' - - elif type == 'block': - relcoords, block = val - block = self.apply_environment(block) - - if block in self.block_tags: - block = f'#{self.namespace}:{block}' - else: - block = f'minecraft:{block}' - - test += f'{iftype} block {relcoords.get_value(self)} {block} ' - elif type == 'nbt_path': - test += f'{iftype} data {val.get_dest_path(self)} ' - else: - raise ValueError(f'Unknown "if" type: {type}') - - return test - - def get_execute_items(self, exec_items, exec_func): - cmd = '' - as_count = 0 - for type, _ in exec_items: - if type[:2] == 'As': - as_count += 1 - - if as_count >= 2: - print('Execute chain may only contain a single "as" clause.') - return None - - at_vector_count = 0 - - for type, val in exec_items: - if type == 'If': - cmd += self.get_if_chain(val) - if type == 'Unless': - cmd += self.get_if_chain(val, 'unless') - elif type == 'As': - cmd += f'as {val} ' - exec_func.update_self_selector(val) - elif type == 'On': - cmd += f'on {val} ' - exec_func.update_self_selector("@s") - elif type == 'AsId': - var, attype = val - - sbvar = var.get_scoreboard_var(self) - selector, id = sbvar.selector, sbvar.objective - - if attype == None: - psel = '@e' - else: - psel = f'@{attype}' - if selector[0] == '@': - seldef = selector_definition(selector, self.environment) - if seldef.base_name == 's' and self.environment.self_selector != None and id in self.environment.self_selector.pointers: - psel = self.environment.self_selector.pointers[id] - elif id in seldef.pointers: - psel = seldef.pointers[id] - elif selector == 'Global': - if id in self.environment.pointers: - psel = self.environment.pointers[id] - - self.register_objective('_id') - self.register_objective(id) - - self.add_command(f'scoreboard players operation Global _id = {selector} {id}') - - cmd += f'as {psel} if score @s _id = Global _id ' - - if attype != None: - exec_func.update_self_selector('@' + attype) - elif psel != '@e': - exec_func.update_self_selector('@' + get_undecorated_selector_name(psel)) - else: - exec_func.update_self_selector('@s') - elif type == 'AsCreate': - if len(exec_items) > 1: - print('"as create" may not be paired with other execute commands.') - return None - create_operation = val - - self.register_objective('_age') - self.add_command(f'scoreboard players set @{create_operation.atid} _age 1') - - create_operation.compile(self) - - self.add_command(f'scoreboard players add @{create_operation.atid} _age 1') - cmd += f'as @{create_operation.atid}[_age==1,limit=1] ' - - exec_func.update_self_selector('@'+create_operation.atid) - elif type == 'Rotated': - cmd += f'rotated as {val} ' - elif type == 'FacingCoords': - cmd += f'facing {val.get_value(self)} ' - elif type == 'FacingEntity': - cmd += f'facing entity {val} feet ' - elif type == 'Align': - cmd += f'align {val} ' - elif type == 'At': - selector, relcoords, anchor = val - if selector != None: - cmd += f'at {selector} ' - if anchor != None: - cmd += f'anchored {anchor} ' - if relcoords != None: - cmd += f'positioned {relcoords.get_value(self)} ' - elif type == 'AtVector': - at_vector_count += 1 - if at_vector_count >= 2: - print('Tried to execute at multiple vector locations.') - return None - - scale, expr = val - if scale == None: - scale = self.scale - else: - scale = scale.get_value(self) - - vec_vals = expr.compile(self, None) - self.add_command('scoreboard players add @e _age 1') - self.add_command('summon area_effect_cloud') - self.add_command('scoreboard players add @e _age 1') - for i in range(3): - var = vec_vals[i].get_scoreboard_var(self) - self.add_command(f'execute store result entity @e[_age==1,limit=1] Pos[{i}] double {1/float(scale)} run scoreboard players get {var.selector} {var.objective}') - cmd += 'at @e[_age == 1] ' - exec_func.add_command('/kill @e[_age == 1]') - elif type == 'In': - dimension = val - cmd += f'in {dimension} ' - - return cmd - - def switch_cases(self, var, cases, switch_func_name = 'switch', case_func_name = 'case'): - for q in range(4): - imin = q * len(cases) // 4 - imax = (q+1) * len(cases) // 4 - if imin == imax: - continue - - vmin = cases[imin][0] - vmax = cases[imax-1][1] - line = cases[imin][3] - - sub_cases = cases[imin:imax] - case_func = self.create_child_function() - - if len(sub_cases) == 1: - vmin, vmax, sub, line, dollarid = sub_cases[0] - if dollarid != None: - case_func.set_dollarid(dollarid, vmin) - try: - case_func.compile_blocks(sub) - except CompileError as e: - print(e) - raise CompileError(f'Unable to compile case at line {line}') - except Exception as e: - print(traceback.format_exc()) - raise CompileError(f'Unable to compile case at line {line}') - - single_command = case_func.single_command() - if single_command != None: - if vmin == vmax: - vrange = str(vmin) - else: - vrange = f'{vmin}..{vmax}' - - if len(single_command) >= 1 and single_command[0] == '$': - self.add_command(f'$execute if score {var.selector} {var.objective} matches {vrange} run {single_command[1:]}') - else: - self.add_command(f'execute if score {var.selector} {var.objective} matches {vrange} run {single_command}') - else: - unique = self.get_unique_id() - - if vmin == vmax: - case_name = f'line{line}/{case_func_name}{vmin}_{unique}' - else: - case_name = f'line{line}/{case_func_name}{vmin}-{vmax}_{unique}' - - self.register_function(case_name, case_func) - self.add_command(f'execute if score {var.selector} {var.objective} matches {vmin}..{vmax} run {case_func.get_call()}') - else: - unique = self.get_unique_id() - case_name = f'line{line}/{switch_func_name}{vmin}-{vmax}_{unique}' - self.register_function(case_name, case_func) - self.add_command(f'execute if score {var.selector} {var.objective} matches {vmin}..{vmax} run {case_func.get_call()}') - - if not case_func.switch_cases(var, sub_cases): - return False - - return True - - - def add_operation(self, selector, id1, operation, id2): - selector = self.environment.apply(selector) - - self.add_command(f"scoreboard players operation {selector} {id1} {operation} {selector} {id2}") - - if self.is_scratch(id2): - self.free_scratch(id2) - - def add_command(self, command): - self.insert_command(command, len(self.commands)) - - def insert_command(self, command, index): - if len(command) == 0: - return - - if command[0] != '#': - if command[0] == '/': - command = command[1:] - - command = self.environment.apply(command) - - if '$(' in command: - if command[0] != '$': - command = '$' + command - - self.has_macros = True - - - self.commands.insert(index, command) - - def get_utf8_text(self): - return "\n".join([(cmd if cmd[0] != '/' else cmd[1:]) for cmd in self.commands]).encode('utf-8') - - def defined_objectives(self): - existing = {} - defineStr = "scoreboard objectives add " - for cmd in self.commands: - if cmd[0] == '/': - cmd = cmd[1:] - if cmd[:len(defineStr)] == defineStr: - existing[cmd[len(defineStr):].split(' ')[0]] = True - - return existing - - def register_local(self, id): - self.environment.register_local(id) - - def finalize(self): - comments = [] - while len(self.commands) > 0 and len(self.commands[0]) >= 2 and self.commands[0][0:2] == '##': - comments.append(self.commands[0]) - del self.commands[0] - - if self.callable: - for v in self.environment.scratch.get_allocated_variables(): - self.register_local(v) - - for p in range(len(self.params)): - self.insert_command(f'scoreboard players operation Global {self.params[p]} = Global Param{p}', 0) - self.register_objective(f"Param{p}") - - self.commands = comments + self.commands - - def single_command(self): - ret = None - count = 0 - for cmd in self.commands: - if real_command(cmd): - ret = cmd - count += 1 - - if count >= 2: - return None - - return ret - - def is_empty(self): - for cmd in self.commands: - if real_command(cmd): - return False - - return True - - def check_single_entity(self, selector): - if selector[0] != '@': - return True - - parsed = self.environment.get_selector_definition(selector) - return parsed.single_entity() - - def get_path(self, selector, var): - if selector[0] != '@': - return - id = selector[1:] - if '[' in id: - id = id.split('[',1)[0] - - if id in self.environment.selectors: - sel_def = self.environment.selectors[id] - elif id == 's' and self.environment.self_selector != None: - sel_def = self.environment.self_selector - else: - return - - if var in sel_def.paths: - path, data_type, scale = sel_def.paths[var] - if scale == None: - scale = self.scale - - if not self.check_single_entity(selector): - raise CompileError(f'Tried to get data "{var}" from selector "{selector}" which is not limited to a single entity.') - - self.add_command(f'execute store result score {selector} {var} run data get entity {selector} {path} {scale}') - - def set_path(self, selector, var): - if selector[0] != '@': - return - id = selector[1:] - if '[' in id: - id = id.split('[',1)[0] - - if id in self.environment.selectors: - sel_def = self.environment.selectors[id] - elif id == 's' and self.environment.self_selector != None: - sel_def = self.environment.self_selector - else: - return - - if var in sel_def.paths: - path, data_type, scale = sel_def.paths[var] - if scale == None: - scale = self.scale - - if not self.check_single_entity(selector): - raise CompileError(f'Tried to set data "{var}" for selector "{selector}" which is not limited to a single entity.') - - self.add_command(f'execute store result entity {selector} {path} {data_type} {1/float(scale)} run scoreboard players get {selector} {var}') - - def get_vector_path(self, selector, var): - if selector[0] != '@': - return False - id = selector[1:] - if '[' in id: - id = id.split('[',1)[0] - - if id in self.environment.selectors: - sel_def = self.environment.selectors[id] - elif id == 's' and self.environment.self_selector != None: - sel_def = self.environment.self_selector - else: - return False - - if var in sel_def.vector_paths: - path, data_type, scale = sel_def.vector_paths[var] - if scale == None: - scale = self.scale - - if not self.check_single_entity(selector): - raise CompileError(f'Tried to get vector data "{var}" from selector "{selector}" which is not limited to a single entity.') - - for i in range(3): - self.add_command(f'execute store result score {selector} _{var}_{i} run data get entity {selector} {path}[{i}] {scale}') - - return True - else: - return False - - def set_vector_path(self, selector, var, values): - if selector[0] != '@': - return False - id = selector[1:] - if '[' in id: - id = id.split('[',1)[0] - - if id in self.environment.selectors: - sel_def = self.environment.selectors[id] - elif id == 's' and self.environment.self_selector != None: - sel_def = self.environment.self_selector - else: - return False - - if var in sel_def.vector_paths: - path, data_type, scale = sel_def.vector_paths[var] - if scale == None: - scale = self.scale - - if not self.check_single_entity(selector): - raise CompileError(f'Tried to set vector data "{var}" for selector "{selector}" which is not limited to a single entity.') - - for i in range(3): - val_var = values[i].get_scoreboard_var(self) - self.add_command(f'execute store result entity {selector} {path}[{i}] {data_type} {1/float(scale)} run scoreboard players get {val_var.selector} {val_var.objective}') - - return True - else: - return False - - def register_objective(self, objective): - self.environment.register_objective(objective) - - def register_array(self, name, from_val, to_val, selector_based): - self.environment.register_array(name, from_val, to_val, selector_based) - - def apply_replacements(self, text, overrides = {}): - return self.environment.apply_replacements(text, overrides) - - def register_block_tag(self, name, blocks): - self.environment.register_block_tag(name, blocks) - - def register_entity_tag(self, name, entities): - self.environment.register_entity_tag(name, entities) - - def register_item_tag(self, name, items): - self.environment.register_item_tag(name, items) - - def get_scale(self): - return self.environment.scale - - def set_scale(self, scale): - self.environment.scale = scale - - scale = property(get_scale, set_scale) - - @property - def arrays(self): - return self.environment.arrays - - @property - def block_tags(self): - return self.environment.block_tags - - @property - def item_tags(self): - return self.environment.item_tags - - @property - def namespace(self): - return self.environment.namespace - - @property - def macros(self): - return self.environment.macros - - @property - def template_functions(self): - return self.environment.template_functions - - @property - def functions(self): - return self.environment.functions - - @property - def selectors(self): - return self.environment.selectors - - def get_scratch(self): - return self.environment.get_scratch() - - def get_scratch_vector(self): - return self.environment.get_scratch_vector() - - def is_scratch(self, var): - return self.environment.is_scratch(var) - - def free_scratch(self, id): - self.environment.free_scratch(id) - - def get_temp_var(self): - return self.environment.get_temp_var() - - def free_temp_var(self): - self.environment.free_temp_var() - - def apply_environment(self, text): - return self.environment.apply(text) - - def add_constant(self, val): - return self.environment.add_constant(val) - - def get_friendly_name(self): - return self.environment.get_friendly_name() - - def get_random_objective(self): - return self.environment.get_random_objective() - - def register_function(self, name, func): - self.environment.register_function(name, func) - - def get_unique_id(self): - return self.environment.get_unique_id() - - def update_self_selector(self, selector): - self.environment.update_self_selector(selector) - - def get_self_selector_definition(self): - return self.environment.self_selector - - def get_python_env(self): - return self.environment.get_python_env() - - def clone_environment(self, new_function_name = None): - return self.environment.clone(new_function_name = new_function_name) - - # Combines a selector with an existing selector definition in the environment - def get_combined_selector(self, selector): - return selector_definition(selector, self.environment) - - def set_dollarid(self, id, val): - self.environment.set_dollarid(id, val) - - def get_dollarid(self, id): - return self.environment.get_dollarid(id) - - def set_atid(self, id, fullselector): - return self.environment.set_atid(id, fullselector) - - def push_environment(self, new_env): - self.environment_stack.append(self.environment) - self.environment = new_env - - def pop_environment(self): - self.environment = self.environment_stack.pop() - - def run_create(self, atid, relcoords, idx=None): - if atid not in self.selectors: - print(f'Unable to create unknown entity: @{atid}') - return False - - selector = self.selectors[atid] - - entity_type = selector.get_type() - - if entity_type == None: - print(f'Unable to create @{atid}, no entity type is defined.') - return False - - if selector.tag == None: - if idx: - self.add_command(f'summon {entity_type} {relcoords.get_value(self)} {idx.get_value(self) + hash(atid) % (2 ** 32)}}}') - else: - self.add_command(f'summon {entity_type} {relcoords.get_value(self)}') - else: - if idx: - parsed = json.loads(selector.tag) - parsed['UUIDMost'] = 0 - parsed['UUIDLeast'] = idx.get_value(self) + hash(atid) % (2 ** 32) - tag = json.dumps(parsed) - else: - tag = selector.tag - - self.add_command(f'summon {entity_type} {relcoords.get_value(self)} {tag}') - - return True - - def register_name_definition(self, id, str): - self.environment.register_name_definition(id, str) - - def get_name_definition(self, id): - return self.environment.get_name_definition(id) - - # Creates an empty function with a copy of the current environment - def create_child_function(self, new_function_name = None, callable = False, params = []): - return mcfunction(self.clone_environment(new_function_name = new_function_name), - callable = callable, - params = params - ) - - def compile_blocks(self, lines): - for block in lines: - try: - block.compile(self) - except CompileError as e: - print(e) - raise CompileError(f'Error compiling block at line {block.line}') - except: - print(traceback.format_exc()) - raise CompileError(f'Error compiling block at line {block.line}') - - @property - def parser(self): - return self.environment.parser - - def import_file(self, filename): - self.environment.register_dependency(filename) - - file = source_file(filename) - - result = self.parser('import ' + file.get_text() + '\n') - if result == None: - raise CompileError(f'Unable to parse file "{filename}"') - - type, parsed = result - if type != 'lib': - raise CompileError(f'Unable to import non-lib-file "{filename}"') - - for line in parsed['lines']: - line.register(self.global_context) - - self.compile_blocks(parsed['lines']) - - def import_python_file(self, filename): - self.environment.register_dependency(filename) - - try: - with open(filename) as file: - text = file.read() - except Exception as e: - print(e) - raise CompileError(f'Unable to open "{filename}"') - - try: - exec(text, globals(), self.get_python_env()) - except Exception as e: - print(e) - raise CompileError(f'Unable to execute "{filename}"') - - def eval(self, expr, line): - try: - return eval(expr, globals(), self.get_python_env()) - except Exception as e: - print(e) - raise CompileError(f'Could not evaluate python expression "{expr}" at line {line}') - - def add_pointer(self, id, selector): - self.environment.add_pointer(id, selector) - - def add_block_definition(self, id, definition): - self.environment.add_block_definition(id, definition) - - def get_block_definition(self, block_id): - return self.environment.get_block_definition(block_id) - - def get_selector_definition(self, selector): - return self.environment.get_selector_definition(selector) - - def add_recipe(self, recipe): - self.environment.add_recipe(recipe) - - def add_advancement(self, name, advancement): - self.environment.add_advancement(name, advancement) - - def add_loot_table(self, name, loot_table): - self.environment.add_loot_table(name, loot_table) - - def add_predicate(self, name, predicate): - self.environment.add_predicate(name, predicate) - - def add_item_modifier(self, name, item_modifier): - self.environment.add_item_modifier(name, item_modifier) - - def get_block_state_list(self, include_block_states): - return self.environment.get_block_state_list(include_block_states) - - def call_function(self, sub_func, sub_name, prefix = ''): - if sub_func.is_empty(): - return - - single_command = sub_func.single_command() - - if single_command: - if single_command.startswith('$'): - self.add_command(f'${prefix}{single_command[1:]}') - else: - self.add_command(f'{prefix}{single_command}') - else: - unique = self.get_unique_id() - sub_name = f'{sub_name}_{unique}' - - self.register_function(sub_name, sub_func) - cmd = prefix + sub_func.get_call() - - self.add_command(cmd) - - def get_reset_function(self): - return self.environment.get_reset_function() - - def register_clock(self, id): - self.environment.register_clock(id) - - @property - def global_context(self): - return self.environment.global_context - - def copy_environment_from(self, func): - self.environment = func.environment.clone() - - @property - def name(self): - return self.environment.function_name - - def get_local_variables(self): - return [scoreboard_var('Global', l) for l in self.environment.get_all_locals()] - - def push_locals(self, locals): - block = push_block(0, locals) - block.compile(self) - - def pop_locals(self, locals): - block = pop_block(0, locals) - block.compile(self) - - @property - def predicates(self): - return self.environment.predicates \ No newline at end of file + def __init__(self, environment, callable=False, params=[]): + self.commands = [] + self.environment = environment + self.params = params + self.callable = callable + self.environment_stack = [] + self.has_macros = False + self.filename = None + + for param in params: + self.register_local(param) + + def set_filename(self, filename): + self.filename = filename + + # Returns the command to call this function + def get_call(self): + if self.filename == None: + raise CompileError( + "Tried to call function with no registered filename." + ) + + if self.has_macros: + return f"function {self.namespace}:{self.filename} with storage {self.namespace}:global args" + else: + return f"function {self.namespace}:{self.filename}" + + def evaluate_params(self, params): + results = [] + for p in range(len(params)): + param_name = f"Param{p}" + param_var = scoreboard_var("Global", param_name) + try: + var = params[p].compile(self, None) + except Exception as e: + print(e) + print(f"Unable to compile parameter {p}.") + return False + + param_var.copy_from(self, var) + + return True + + def get_arrayconst_var(self, name, idxval): + return self.environment.get_arrayconst_var(name, idxval) + + def get_if_chain(self, conditions, iftype="if"): + test = "" + for type, val in conditions: + if type == "selector": + test += f"{iftype} entity {val} " + elif type == "predicate": + if ":" in val: + test += f"{iftype} predicate {val} " + elif val in self.predicates: + test += f"{iftype} predicate {self.namespace}:{val} " + else: + raise CompileError(f'Predicate "{val}" does not exist') + elif type == "score": + lexpr, op, rexpr = val + + lvar = lexpr.compile(self) + rvar = rexpr.compile(self) + + lconst = lvar.get_const_value(self) + rconst = rvar.get_const_value(self) + + if lconst != None and rconst != None: + result = False + # Perform comparison, terminate if-chain if false + if op == "=" and lconst == rconst: + result = True + elif op == ">" and lconst > rconst: + result = True + elif op == "<" and lconst < rconst: + result = True + elif op == ">=" and lconst >= rconst: + result = True + elif op == "<=" and lconst <= rconst: + result = True + + if ( + iftype == "if" + and not result + or iftype == "unless" + and result + ): + # Clobber entire if chain + return "if score Global unique matches -1 " + else: + # No modification to the test string is necessary + continue + + elif lconst != None or rconst != None: + # Continue if chain comparing the scoreboard value with numeric range + if lconst != None: + sbvar = rvar.get_scoreboard_var(self) + const = lconst + elif rconst != None: + sbvar = lvar.get_scoreboard_var(self) + const = rconst + + if op == ">": + test += f"{iftype} score {sbvar.selector} {sbvar.objective} matches {int(const)+1}.. " + if op == ">=": + test += f"{iftype} score {sbvar.selector} {sbvar.objective} matches {const}.. " + if op == "<": + test += f"{iftype} score {sbvar.selector} {sbvar.objective} matches ..{int(const)-1} " + if op == "<=": + test += f"{iftype} score {sbvar.selector} {sbvar.objective} matches ..{const} " + if op == "=": + test += f"{iftype} score {sbvar.selector} {sbvar.objective} matches {const} " + + else: + # Continue if chain comparing two score values + lsbvar = lvar.get_scoreboard_var(self) + rsbvar = rvar.get_scoreboard_var(self) + + test += f"{iftype} score {lsbvar.selector} {lsbvar.objective} {op} {rsbvar.selector} {rsbvar.objective} " + + elif type == "vector_equality": + if iftype == "unless": + raise CompileError( + 'Vector equality may not be used with "unless"' + ) + + (type1, var1), (type2, var2) = val + + if type1 == "VAR_CONST" and type2 == "VAR_CONST": + val1 = var1.get_value(self) + val2 = var2.get_value(self) + if val1 != val2: + # Test fails, clobber entire chain + return "if score Global unique matches -1 " + else: + # Test succeeds, continue with the chain + continue + else: + if type1 == "VAR_CONST": + # Swap vars so that the constant var is always second + temp_type = type1 + temp_var = var1 + type1 = type2 + var1 = var2 + type2 = temp_type + var2 = temp_var + + const_vals = [] + if type2 == "VAR_CONST": + components = var2.get_value(self) + try: + const_vals = [int(components[i]) for i in range(3)] + except Exception as e: + print(e) + raise CompileError( + "Unable to get three components for constant vector." + ) + + for i in range(3): + if type1 == "VAR_ID": + lvar = scoreboard_var("Global", f"_{var1}_{i}") + elif type1 == "SEL_VAR_ID": + sel1, selvar1 = var1 + lvar = scoreboard_var(sel1, f"_{selvar1}_{i}") + elif type1 == "VAR_COMPONENTS": + lvar = var1[i].get_scoreboard_var(self) + + if type2 == "VAR_CONST": + test += f"if score {sel1} {sco1} matches {const_vals[i]} " + else: + if type2 == "VAR_ID": + rvar = scoreboard_var("Global", f"_{var2}_{i}") + elif type2 == "SEL_VAR_ID": + sel2, selvar2 = var2 + rvar = scoreboard_var(sel2, f"_{selvar2}_{i}") + elif type2 == "VAR_COMPONENTS": + rvar = var2[i].get_scoreboard_var(self) + + test += f"if score {lvar.selvar} = {rvar.selvar} " + + elif type == "block": + relcoords, block = val + block = self.apply_environment(block) + + if block in self.block_tags: + block = f"#{self.namespace}:{block}" + else: + block = f"minecraft:{block}" + + test += f"{iftype} block {relcoords.get_value(self)} {block} " + elif type == "nbt_path": + test += f"{iftype} data {val.get_dest_path(self)} " + else: + raise ValueError(f'Unknown "if" type: {type}') + + return test + + def get_execute_items(self, exec_items, exec_func): + cmd = "" + as_count = 0 + for type, _ in exec_items: + if type[:2] == "As": + as_count += 1 + + if as_count >= 2: + print( + 'Execute chain may only contain a single "as" clause.' + ) + return None + + at_vector_count = 0 + + for type, val in exec_items: + if type == "If": + cmd += self.get_if_chain(val) + if type == "Unless": + cmd += self.get_if_chain(val, "unless") + elif type == "As": + cmd += f"as {val} " + exec_func.update_self_selector(val) + elif type == "On": + cmd += f"on {val} " + exec_func.update_self_selector("@s") + elif type == "AsId": + var, attype = val + + sbvar = var.get_scoreboard_var(self) + selector, id = sbvar.selector, sbvar.objective + + if attype == None: + psel = "@e" + else: + psel = f"@{attype}" + if selector[0] == "@": + seldef = selector_definition(selector, self.environment) + if ( + seldef.base_name == "s" + and self.environment.self_selector != None + and id in self.environment.self_selector.pointers + ): + psel = self.environment.self_selector.pointers[id] + elif id in seldef.pointers: + psel = seldef.pointers[id] + elif selector == "Global": + if id in self.environment.pointers: + psel = self.environment.pointers[id] + + self.register_objective("_id") + self.register_objective(id) + + self.add_command( + f"scoreboard players operation Global _id = {selector} {id}" + ) + + cmd += f"as {psel} if score @s _id = Global _id " + + if attype != None: + exec_func.update_self_selector("@" + attype) + elif psel != "@e": + exec_func.update_self_selector( + "@" + get_undecorated_selector_name(psel) + ) + else: + exec_func.update_self_selector("@s") + elif type == "AsCreate": + if len(exec_items) > 1: + print( + '"as create" may not be paired with other execute commands.' + ) + return None + create_operation = val + + self.register_objective("_age") + self.add_command( + f"scoreboard players set @{create_operation.atid} _age 1" + ) + + create_operation.compile(self) + + self.add_command( + f"scoreboard players add @{create_operation.atid} _age 1" + ) + cmd += f"as @{create_operation.atid}[_age==1,limit=1] " + + exec_func.update_self_selector("@" + create_operation.atid) + elif type == "Rotated": + cmd += f"rotated as {val} " + elif type == "FacingCoords": + cmd += f"facing {val.get_value(self)} " + elif type == "FacingEntity": + cmd += f"facing entity {val} feet " + elif type == "Align": + cmd += f"align {val} " + elif type == "At": + selector, relcoords, anchor = val + if selector != None: + cmd += f"at {selector} " + if anchor != None: + cmd += f"anchored {anchor} " + if relcoords != None: + cmd += f"positioned {relcoords.get_value(self)} " + elif type == "AtVector": + at_vector_count += 1 + if at_vector_count >= 2: + print("Tried to execute at multiple vector locations.") + return None + + scale, expr = val + if scale == None: + scale = self.scale + else: + scale = scale.get_value(self) + + vec_vals = expr.compile(self, None) + self.add_command("scoreboard players add @e _age 1") + self.add_command("summon area_effect_cloud") + self.add_command("scoreboard players add @e _age 1") + for i in range(3): + var = vec_vals[i].get_scoreboard_var(self) + self.add_command( + f"execute store result entity @e[_age==1,limit=1] Pos[{i}] double {1/float(scale)} run scoreboard players get {var.selector} {var.objective}" + ) + cmd += "at @e[_age == 1] " + exec_func.add_command("/kill @e[_age == 1]") + elif type == "In": + dimension = val + cmd += f"in {dimension} " + + return cmd + + def switch_cases( + self, var, cases, switch_func_name="switch", case_func_name="case" + ): + for q in range(4): + imin = q * len(cases) // 4 + imax = (q + 1) * len(cases) // 4 + if imin == imax: + continue + + vmin = cases[imin][0] + vmax = cases[imax - 1][1] + line = cases[imin][3] + + sub_cases = cases[imin:imax] + case_func = self.create_child_function() + + if len(sub_cases) == 1: + vmin, vmax, sub, line, dollarid = sub_cases[0] + if dollarid != None: + case_func.set_dollarid(dollarid, vmin) + try: + case_func.compile_blocks(sub) + except CompileError as e: + print(e) + raise CompileError( + f"Unable to compile case at line {line}" + ) + except Exception as e: + print(traceback.format_exc()) + raise CompileError( + f"Unable to compile case at line {line}" + ) + + single_command = case_func.single_command() + if single_command != None: + if vmin == vmax: + vrange = str(vmin) + else: + vrange = f"{vmin}..{vmax}" + + if len(single_command) >= 1 and single_command[0] == "$": + self.add_command( + f"$execute if score {var.selector} {var.objective} matches {vrange} run {single_command[1:]}" + ) + else: + self.add_command( + f"execute if score {var.selector} {var.objective} matches {vrange} run {single_command}" + ) + else: + unique = self.get_unique_id() + + if vmin == vmax: + case_name = ( + f"line{line}/{case_func_name}{vmin}_{unique}" + ) + else: + case_name = f"line{line}/{case_func_name}{vmin}-{vmax}_{unique}" + + self.register_function(case_name, case_func) + self.add_command( + f"execute if score {var.selector} {var.objective} matches {vmin}..{vmax} run {case_func.get_call()}" + ) + else: + unique = self.get_unique_id() + case_name = ( + f"line{line}/{switch_func_name}{vmin}-{vmax}_{unique}" + ) + self.register_function(case_name, case_func) + self.add_command( + f"execute if score {var.selector} {var.objective} matches {vmin}..{vmax} run {case_func.get_call()}" + ) + + if not case_func.switch_cases(var, sub_cases): + return False + + return True + + def add_operation(self, selector, id1, operation, id2): + selector = self.environment.apply(selector) + + self.add_command( + f"scoreboard players operation {selector} {id1} {operation} {selector} {id2}" + ) + + if self.is_scratch(id2): + self.free_scratch(id2) + + def add_command(self, command): + self.insert_command(command, len(self.commands)) + + def insert_command(self, command, index): + if len(command) == 0: + return + + if command[0] != "#": + if command[0] == "/": + command = command[1:] + + command = self.environment.apply(command) + + if "$(" in command: + if command[0] != "$": + command = "$" + command + + self.has_macros = True + + self.commands.insert(index, command) + + def get_utf8_text(self): + return "\n".join( + [(cmd if cmd[0] != "/" else cmd[1:]) for cmd in self.commands] + ).encode("utf-8") + + def defined_objectives(self): + existing = {} + defineStr = "scoreboard objectives add " + for cmd in self.commands: + if cmd[0] == "/": + cmd = cmd[1:] + if cmd[: len(defineStr)] == defineStr: + existing[cmd[len(defineStr) :].split(" ")[0]] = True + + return existing + + def register_local(self, id): + self.environment.register_local(id) + + def finalize(self): + comments = [] + while ( + len(self.commands) > 0 + and len(self.commands[0]) >= 2 + and self.commands[0][0:2] == "##" + ): + comments.append(self.commands[0]) + del self.commands[0] + + if self.callable: + for v in self.environment.scratch.get_allocated_variables(): + self.register_local(v) + + for p in range(len(self.params)): + self.insert_command( + f"scoreboard players operation Global {self.params[p]} = Global Param{p}", + 0, + ) + self.register_objective(f"Param{p}") + + self.commands = comments + self.commands + + def single_command(self): + ret = None + count = 0 + for cmd in self.commands: + if real_command(cmd): + ret = cmd + count += 1 + + if count >= 2: + return None + + return ret + + def is_empty(self): + for cmd in self.commands: + if real_command(cmd): + return False + + return True + + def check_single_entity(self, selector): + if selector[0] != "@": + return True + + parsed = self.environment.get_selector_definition(selector) + return parsed.single_entity() + + def get_path(self, selector, var): + if selector[0] != "@": + return + id = selector[1:] + if "[" in id: + id = id.split("[", 1)[0] + + if id in self.environment.selectors: + sel_def = self.environment.selectors[id] + elif id == "s" and self.environment.self_selector != None: + sel_def = self.environment.self_selector + else: + return + + if var in sel_def.paths: + path, data_type, scale = sel_def.paths[var] + if scale == None: + scale = self.scale + + if not self.check_single_entity(selector): + raise CompileError( + f'Tried to get data "{var}" from selector "{selector}" which is not limited to a single entity.' + ) + + self.add_command( + f"execute store result score {selector} {var} run data get entity {selector} {path} {scale}" + ) + + def set_path(self, selector, var): + if selector[0] != "@": + return + id = selector[1:] + if "[" in id: + id = id.split("[", 1)[0] + + if id in self.environment.selectors: + sel_def = self.environment.selectors[id] + elif id == "s" and self.environment.self_selector != None: + sel_def = self.environment.self_selector + else: + return + + if var in sel_def.paths: + path, data_type, scale = sel_def.paths[var] + if scale == None: + scale = self.scale + + if not self.check_single_entity(selector): + raise CompileError( + f'Tried to set data "{var}" for selector "{selector}" which is not limited to a single entity.' + ) + + self.add_command( + f"execute store result entity {selector} {path} {data_type} {1/float(scale)} run scoreboard players get {selector} {var}" + ) + + def get_vector_path(self, selector, var): + if selector[0] != "@": + return False + id = selector[1:] + if "[" in id: + id = id.split("[", 1)[0] + + if id in self.environment.selectors: + sel_def = self.environment.selectors[id] + elif id == "s" and self.environment.self_selector != None: + sel_def = self.environment.self_selector + else: + return False + + if var in sel_def.vector_paths: + path, data_type, scale = sel_def.vector_paths[var] + if scale == None: + scale = self.scale + + if not self.check_single_entity(selector): + raise CompileError( + f'Tried to get vector data "{var}" from selector "{selector}" which is not limited to a single entity.' + ) + + for i in range(3): + self.add_command( + f"execute store result score {selector} _{var}_{i} run data get entity {selector} {path}[{i}] {scale}" + ) + + return True + else: + return False + + def set_vector_path(self, selector, var, values): + if selector[0] != "@": + return False + id = selector[1:] + if "[" in id: + id = id.split("[", 1)[0] + + if id in self.environment.selectors: + sel_def = self.environment.selectors[id] + elif id == "s" and self.environment.self_selector != None: + sel_def = self.environment.self_selector + else: + return False + + if var in sel_def.vector_paths: + path, data_type, scale = sel_def.vector_paths[var] + if scale == None: + scale = self.scale + + if not self.check_single_entity(selector): + raise CompileError( + f'Tried to set vector data "{var}" for selector "{selector}" which is not limited to a single entity.' + ) + + for i in range(3): + val_var = values[i].get_scoreboard_var(self) + self.add_command( + f"execute store result entity {selector} {path}[{i}] {data_type} {1/float(scale)} run scoreboard players get {val_var.selector} {val_var.objective}" + ) + + return True + else: + return False + + def register_objective(self, objective): + self.environment.register_objective(objective) + + def register_array(self, name, from_val, to_val, selector_based): + self.environment.register_array(name, from_val, to_val, selector_based) + + def apply_replacements(self, text, overrides={}): + return self.environment.apply_replacements(text, overrides) + + def register_block_tag(self, name, blocks): + self.environment.register_block_tag(name, blocks) + + def register_entity_tag(self, name, entities): + self.environment.register_entity_tag(name, entities) + + def register_item_tag(self, name, items): + self.environment.register_item_tag(name, items) + + def get_scale(self): + return self.environment.scale + + def set_scale(self, scale): + self.environment.scale = scale + + scale = property(get_scale, set_scale) + + @property + def arrays(self): + return self.environment.arrays + + @property + def block_tags(self): + return self.environment.block_tags + + @property + def item_tags(self): + return self.environment.item_tags + + @property + def namespace(self): + return self.environment.namespace + + @property + def macros(self): + return self.environment.macros + + @property + def template_functions(self): + return self.environment.template_functions + + @property + def functions(self): + return self.environment.functions + + @property + def selectors(self): + return self.environment.selectors + + def get_scratch(self): + return self.environment.get_scratch() + + def get_scratch_vector(self): + return self.environment.get_scratch_vector() + + def is_scratch(self, var): + return self.environment.is_scratch(var) + + def free_scratch(self, id): + self.environment.free_scratch(id) + + def get_temp_var(self): + return self.environment.get_temp_var() + + def free_temp_var(self): + self.environment.free_temp_var() + + def apply_environment(self, text): + return self.environment.apply(text) + + def add_constant(self, val): + return self.environment.add_constant(val) + + def get_friendly_name(self): + return self.environment.get_friendly_name() + + def get_random_objective(self): + return self.environment.get_random_objective() + + def register_function(self, name, func): + self.environment.register_function(name, func) + + def get_unique_id(self): + return self.environment.get_unique_id() + + def update_self_selector(self, selector): + self.environment.update_self_selector(selector) + + def get_self_selector_definition(self): + return self.environment.self_selector + + def get_python_env(self): + return self.environment.get_python_env() + + def clone_environment(self, new_function_name=None): + return self.environment.clone(new_function_name=new_function_name) + + # Combines a selector with an existing selector definition in the environment + def get_combined_selector(self, selector): + return selector_definition(selector, self.environment) + + def set_dollarid(self, id, val): + self.environment.set_dollarid(id, val) + + def get_dollarid(self, id): + return self.environment.get_dollarid(id) + + def set_atid(self, id, fullselector): + return self.environment.set_atid(id, fullselector) + + def push_environment(self, new_env): + self.environment_stack.append(self.environment) + self.environment = new_env + + def pop_environment(self): + self.environment = self.environment_stack.pop() + + def run_create(self, atid, relcoords, idx=None): + if atid not in self.selectors: + print(f"Unable to create unknown entity: @{atid}") + return False + + selector = self.selectors[atid] + + entity_type = selector.get_type() + + if entity_type == None: + print(f"Unable to create @{atid}, no entity type is defined.") + return False + + if selector.tag == None: + if idx: + self.add_command( + f"summon {entity_type} {relcoords.get_value(self)} {idx.get_value(self) + hash(atid) % (2 ** 32)}}}" + ) + else: + self.add_command( + f"summon {entity_type} {relcoords.get_value(self)}" + ) + else: + if idx: + parsed = json.loads(selector.tag) + parsed["UUIDMost"] = 0 + parsed["UUIDLeast"] = idx.get_value(self) + hash(atid) % ( + 2**32 + ) + tag = json.dumps(parsed) + else: + tag = selector.tag + + self.add_command( + f"summon {entity_type} {relcoords.get_value(self)} {tag}" + ) + + return True + + def register_name_definition(self, id, str): + self.environment.register_name_definition(id, str) + + def get_name_definition(self, id): + return self.environment.get_name_definition(id) + + # Creates an empty function with a copy of the current environment + def create_child_function( + self, new_function_name=None, callable=False, params=[] + ): + return mcfunction( + self.clone_environment(new_function_name=new_function_name), + callable=callable, + params=params, + ) + + def compile_blocks(self, lines): + for block in lines: + try: + block.compile(self) + except CompileError as e: + print(e) + raise CompileError( + f"Error compiling block at line {block.line}" + ) + except: + print(traceback.format_exc()) + raise CompileError( + f"Error compiling block at line {block.line}" + ) + + @property + def parser(self): + return self.environment.parser + + def import_file(self, filename): + self.environment.register_dependency(filename) + + file = source_file(filename) + + result = self.parser("import " + file.get_text() + "\n") + if result == None: + raise CompileError(f'Unable to parse file "{filename}"') + + type, parsed = result + if type != "lib": + raise CompileError(f'Unable to import non-lib-file "{filename}"') + + for line in parsed["lines"]: + line.register(self.global_context) + + self.compile_blocks(parsed["lines"]) + + def import_python_file(self, filename): + self.environment.register_dependency(filename) + + try: + with open(filename) as file: + text = file.read() + except Exception as e: + print(e) + raise CompileError(f'Unable to open "{filename}"') + + try: + exec(text, globals(), self.get_python_env()) + except Exception as e: + print(e) + raise CompileError(f'Unable to execute "{filename}"') + + def eval(self, expr, line): + try: + return eval(expr, globals(), self.get_python_env()) + except Exception as e: + print(e) + raise CompileError( + f'Could not evaluate python expression "{expr}" at line {line}' + ) + + def add_pointer(self, id, selector): + self.environment.add_pointer(id, selector) + + def add_block_definition(self, id, definition): + self.environment.add_block_definition(id, definition) + + def get_block_definition(self, block_id): + return self.environment.get_block_definition(block_id) + + def get_selector_definition(self, selector): + return self.environment.get_selector_definition(selector) + + def add_recipe(self, recipe): + self.environment.add_recipe(recipe) + + def add_advancement(self, name, advancement): + self.environment.add_advancement(name, advancement) + + def add_loot_table(self, name, loot_table): + self.environment.add_loot_table(name, loot_table) + + def add_predicate(self, name, predicate): + self.environment.add_predicate(name, predicate) + + def add_item_modifier(self, name, item_modifier): + self.environment.add_item_modifier(name, item_modifier) + + def get_block_state_list(self, include_block_states): + return self.environment.get_block_state_list(include_block_states) + + def call_function(self, sub_func, sub_name, prefix=""): + if sub_func.is_empty(): + return + + single_command = sub_func.single_command() + + if single_command: + if single_command.startswith("$"): + self.add_command(f"${prefix}{single_command[1:]}") + else: + self.add_command(f"{prefix}{single_command}") + else: + unique = self.get_unique_id() + sub_name = f"{sub_name}_{unique}" + + self.register_function(sub_name, sub_func) + cmd = prefix + sub_func.get_call() + + self.add_command(cmd) + + def get_reset_function(self): + return self.environment.get_reset_function() + + def register_clock(self, id): + self.environment.register_clock(id) + + @property + def global_context(self): + return self.environment.global_context + + def copy_environment_from(self, func): + self.environment = func.environment.clone() + + @property + def name(self): + return self.environment.function_name + + def get_local_variables(self): + return [ + scoreboard_var("Global", l) + for l in self.environment.get_all_locals() + ] + + def push_locals(self, locals): + block = push_block(0, locals) + block.compile(self) + + def pop_locals(self, locals): + block = pop_block(0, locals) + block.compile(self) + + @property + def predicates(self): + return self.environment.predicates diff --git a/mcworld.py b/mcworld.py index 6b0bef8..8196243 100644 --- a/mcworld.py +++ b/mcworld.py @@ -1,121 +1,160 @@ -import sys import os -import codecs -import shutil -import time import json import io import zipfile from CompileError import CompileError + class mcworld(object): - def __init__(self, leveldir, namespace): - self.dir = leveldir - self.zipbytes = io.BytesIO() - self.zip = zipfile.ZipFile(self.zipbytes, 'w', zipfile.ZIP_DEFLATED, False) - self.namespace = namespace - - def get_latest_log_file(self): - savesdir = os.path.split(self.dir)[0] - versiondir = os.path.split(savesdir)[0] - logsdir = os.path.join(versiondir, 'logs') - logfile = os.path.join(logsdir, 'latest.log') - - return logfile - - def write_functions(self, functions): - function_dir = f'data/{self.namespace}/functions/' - - for name in functions: - filename = os.path.join(function_dir, f"{name}.mcfunction") - - func = functions[name] - text = func.get_utf8_text() - self.zip.writestr(filename, text) - - def write_tags(self, clocks, block_tags, entity_tags, item_tags): - tag_dir = 'data/minecraft/tags/functions/' - - tick_tag_file = os.path.join(tag_dir, 'tick.json') - self.zip.writestr(tick_tag_file, json.dumps({'values':[f'{self.namespace}:{name}'for name in clocks]}, indent=4)) - - load_tag_file = os.path.join(tag_dir, 'load.json') - self.zip.writestr(load_tag_file, json.dumps({'values':[f'{self.namespace}:reset']}, indent=4)) - - for name, list in [ - ('blocks', block_tags), - ('items', item_tags), - ('entity_types', entity_tags) - ]: - if len(list) > 0: - tag_dir = f'data/{self.namespace}/tags/{name}/' - - for tag in list: - items = list[tag] - - tag_filename = os.path.join(tag_dir, f'{tag}.json') - self.zip.writestr(tag_filename, json.dumps({'values':[f'minecraft:{item}'for item in items]}, indent=4)) - - def write_recipes(self, recipes): - if len(recipes) > 0: - recipe_dir = f'data/{self.namespace}/recipes/' - - id = 0 - for recipe in recipes: - id += 1 - recipe_file = os.path.join(recipe_dir, f'{recipe.get_type()}{id}.json') - recipe_struct = recipe.get_json_struct() - - self.zip.writestr(recipe_file, json.dumps(recipe_struct, indent=4)) - - def write_advancements(self, advancements): - if len(advancements) > 0: - advancement_dir = f'data/{self.namespace}/advancements/' - - for name in advancements: - advancement_file = os.path.join(advancement_dir, f'{name}.json') - self.zip.writestr(advancement_file, advancements[name]) - - def write_loot_tables(self, loot_tables): - if len(loot_tables) > 0: - for name in loot_tables: - (type, contents) = loot_tables[name] - if ':' in name: - parts = name.split(':') - if len(parts) != 2: - raise CompileError(f'Invalid loot tables name "{name}"') - loot_table_dir = f'data/{parts[0]}/loot_tables/{type}/' - filename = parts[1] - else: - loot_table_dir = f'data/{self.namespace}/loot_tables/{type}/' - filename = name - loot_table_file = os.path.join(loot_table_dir, f'{filename}.json') - self.zip.writestr(loot_table_file, contents) - - def write_predicates(self, predicates): - if len(predicates) > 0: - predicate_dir = f'data/{self.namespace}/predicates/' - - for name in predicates: - predicate_file = os.path.join(predicate_dir, f'{name}.json') - self.zip.writestr(predicate_file, predicates[name]) - - def write_item_modifiers(self, item_modifiers): - if len(item_modifiers) > 0: - item_modifier_dir = f'data/{self.namespace}/item_modifiers/' - - for name in item_modifiers: - item_modifier_file = os.path.join(item_modifier_dir, f'{name}.json') - self.zip.writestr(item_modifier_file, item_modifiers[name]) - - def write_mcmeta(self, desc): - mcmeta_file = 'pack.mcmeta' - - self.zip.writestr(mcmeta_file, json.dumps({'pack':{'pack_format':1, 'description':desc}}, indent=4)) - - def write_zip(self): - self.zip.close() - - zip_filename = os.path.join(self.dir, f'datapacks/{self.namespace}.zip') - with open(zip_filename, 'wb') as file: - file.write(self.zipbytes.getvalue()) + def __init__(self, leveldir, namespace): + self.dir = leveldir + self.zipbytes = io.BytesIO() + self.zip = zipfile.ZipFile( + self.zipbytes, "w", zipfile.ZIP_DEFLATED, False + ) + self.namespace = namespace + + def get_latest_log_file(self): + savesdir = os.path.split(self.dir)[0] + versiondir = os.path.split(savesdir)[0] + logsdir = os.path.join(versiondir, "logs") + logfile = os.path.join(logsdir, "latest.log") + + return logfile + + def write_functions(self, functions): + function_dir = f"data/{self.namespace}/functions/" + + for name in functions: + filename = os.path.join(function_dir, f"{name}.mcfunction") + + func = functions[name] + text = func.get_utf8_text() + self.zip.writestr(filename, text) + + def write_tags(self, clocks, block_tags, entity_tags, item_tags): + tag_dir = "data/minecraft/tags/functions/" + + tick_tag_file = os.path.join(tag_dir, "tick.json") + self.zip.writestr( + tick_tag_file, + json.dumps( + {"values": [f"{self.namespace}:{name}" for name in clocks]}, + indent=4, + ), + ) + + load_tag_file = os.path.join(tag_dir, "load.json") + self.zip.writestr( + load_tag_file, + json.dumps({"values": [f"{self.namespace}:reset"]}, indent=4), + ) + + for name, list in [ + ("blocks", block_tags), + ("items", item_tags), + ("entity_types", entity_tags), + ]: + if len(list) > 0: + tag_dir = f"data/{self.namespace}/tags/{name}/" + + for tag in list: + items = list[tag] + + tag_filename = os.path.join(tag_dir, f"{tag}.json") + self.zip.writestr( + tag_filename, + json.dumps( + { + "values": [ + f"minecraft:{item}" for item in items + ] + }, + indent=4, + ), + ) + + def write_recipes(self, recipes): + if len(recipes) > 0: + recipe_dir = f"data/{self.namespace}/recipes/" + + id = 0 + for recipe in recipes: + id += 1 + recipe_file = os.path.join( + recipe_dir, f"{recipe.get_type()}{id}.json" + ) + recipe_struct = recipe.get_json_struct() + + self.zip.writestr( + recipe_file, json.dumps(recipe_struct, indent=4) + ) + + def write_advancements(self, advancements): + if len(advancements) > 0: + advancement_dir = f"data/{self.namespace}/advancements/" + + for name in advancements: + advancement_file = os.path.join( + advancement_dir, f"{name}.json" + ) + self.zip.writestr(advancement_file, advancements[name]) + + def write_loot_tables(self, loot_tables): + if len(loot_tables) > 0: + for name in loot_tables: + (type, contents) = loot_tables[name] + if ":" in name: + parts = name.split(":") + if len(parts) != 2: + raise CompileError( + f'Invalid loot tables name "{name}"' + ) + loot_table_dir = f"data/{parts[0]}/loot_tables/{type}/" + filename = parts[1] + else: + loot_table_dir = ( + f"data/{self.namespace}/loot_tables/{type}/" + ) + filename = name + loot_table_file = os.path.join( + loot_table_dir, f"{filename}.json" + ) + self.zip.writestr(loot_table_file, contents) + + def write_predicates(self, predicates): + if len(predicates) > 0: + predicate_dir = f"data/{self.namespace}/predicates/" + + for name in predicates: + predicate_file = os.path.join(predicate_dir, f"{name}.json") + self.zip.writestr(predicate_file, predicates[name]) + + def write_item_modifiers(self, item_modifiers): + if len(item_modifiers) > 0: + item_modifier_dir = f"data/{self.namespace}/item_modifiers/" + + for name in item_modifiers: + item_modifier_file = os.path.join( + item_modifier_dir, f"{name}.json" + ) + self.zip.writestr(item_modifier_file, item_modifiers[name]) + + def write_mcmeta(self, desc): + mcmeta_file = "pack.mcmeta" + + self.zip.writestr( + mcmeta_file, + json.dumps( + {"pack": {"pack_format": 1, "description": desc}}, indent=4 + ), + ) + + def write_zip(self): + self.zip.close() + + zip_filename = os.path.join( + self.dir, f"datapacks/{self.namespace}.zip" + ) + with open(zip_filename, "wb") as file: + file.write(self.zipbytes.getvalue()) diff --git a/nbt_types/block_nbt_path.py b/nbt_types/block_nbt_path.py index 76b7491..f73c9e8 100644 --- a/nbt_types/block_nbt_path.py +++ b/nbt_types/block_nbt_path.py @@ -1,10 +1,10 @@ class block_nbt_path(object): - def __init__(self, coords, path): - self.coords = coords - self.path = path - - def get_dest_path(self, func): - return f'block {self.coords.get_value(func)} {self.path}' - - def get_source_path(self, func): - return 'from ' + self.get_dest_path(func) + def __init__(self, coords, path): + self.coords = coords + self.path = path + + def get_dest_path(self, func): + return f"block {self.coords.get_value(func)} {self.path}" + + def get_source_path(self, func): + return "from " + self.get_dest_path(func) diff --git a/nbt_types/entity_nbt_path.py b/nbt_types/entity_nbt_path.py index 9c8554d..c6ccd51 100644 --- a/nbt_types/entity_nbt_path.py +++ b/nbt_types/entity_nbt_path.py @@ -1,10 +1,10 @@ class entity_nbt_path(object): - def __init__(self, selector, path): - self.selector = selector - self.path = path - - def get_dest_path(self, func): - return f'entity {self.selector} {self.path}' - - def get_source_path(self, func): - return 'from ' + self.get_dest_path(func) + def __init__(self, selector, path): + self.selector = selector + self.path = path + + def get_dest_path(self, func): + return f"entity {self.selector} {self.path}" + + def get_source_path(self, func): + return "from " + self.get_dest_path(func) diff --git a/nbt_types/nbt_json.py b/nbt_types/nbt_json.py index 0b99ca3..e4f8300 100644 --- a/nbt_types/nbt_json.py +++ b/nbt_types/nbt_json.py @@ -1,6 +1,6 @@ class nbt_json(object): - def __init__(self, json): - self.json = json - - def get_source_path(self, func): - return f'value {self.json}' + def __init__(self, json): + self.json = json + + def get_source_path(self, func): + return f"value {self.json}" diff --git a/nbt_types/storage_nbt_path.py b/nbt_types/storage_nbt_path.py index 0403cce..f1bebeb 100644 --- a/nbt_types/storage_nbt_path.py +++ b/nbt_types/storage_nbt_path.py @@ -1,16 +1,16 @@ class storage_nbt_path(object): - def __init__(self, target, path): - self.target = target - self.path = path - - def get_target(self, func): - if self.target == None: - return func.namespace - else: - return self.target - - def get_dest_path(self, func): - return f'storage {self.get_target(func)} {self.path}' - - def get_source_path(self, func): - return 'from ' + self.get_dest_path(func) + def __init__(self, target, path): + self.target = target + self.path = path + + def get_target(self, func): + if self.target == None: + return func.namespace + else: + return self.target + + def get_dest_path(self, func): + return f"storage {self.get_target(func)} {self.path}" + + def get_source_path(self, func): + return "from " + self.get_dest_path(func) diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..3c67015 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,7 @@ +[tool.pycln] +all = true +disable_all_dunder_policy = true + +[tool.black] +line-length = 79 +target-version = ['py311'] diff --git a/requirements.txt b/requirements.txt index 7e4b483..ce240e5 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,2 @@ ply -pyyaml \ No newline at end of file +pyyaml diff --git a/run.cmd b/run.cmd index 58f245a..36b10e2 100644 --- a/run.cmd +++ b/run.cmd @@ -9,4 +9,4 @@ @title %~nx1 @cd "%~dp0" py -3 compile.py %1 -@pause \ No newline at end of file +@pause diff --git a/scalar_expressions/binop_expr.py b/scalar_expressions/binop_expr.py index 1f1939b..3515eb4 100644 --- a/scalar_expressions/binop_expr.py +++ b/scalar_expressions/binop_expr.py @@ -1,90 +1,111 @@ from .scalar_expression_base import scalar_expression_base + + class binop_expr(scalar_expression_base): - def __init__(self, lhs, op, rhs): - self.lhs = lhs - self.op = op - self.rhs = rhs - - # Returns true if this varariable/expression references the specified scoreboard variable - def references_scoreboard_var(self, func, var): - return self.lhs.references_scoreboard_var(func, var) or self.rhs.references_scoreboard_var(func, var) - - - def compile(self, func, assignto=None): - # TODO: Handle case where both variables are constant, and return constant - - if len(self.op) == 1 and self.op in ['+', '-', '*', '/', '%']: - left_var = self.lhs.compile(func, assignto) - left_const = left_var.get_const_value(func) - - right_var = self.rhs.compile(func, None) - right_const = right_var.get_const_value(func) - - if self.op in ['+', '*'] and left_const != None and right_const == None: - # Swap the operands so that the constant is on the right - old_left_var = left_var - old_left_const = left_const - - left_var = right_var - left_const = right_const - - right_var = old_left_var - right_const = old_left_const - - if assignto != None and not self.rhs.references_scoreboard_var(func, assignto): - assignto.copy_from(func, left_var) - temp_var = assignto - else: - temp_var = left_var.get_modifiable_var(func, assignto) - - # TODO: handle case where both variables have constant values, return constant result - - if right_const and self.op in ['+','-']: - op = self.op - - if right_const < 0: - right_const = -right_const - op = {'+':'-', '-':'+'}[self.op] - - func.add_command('scoreboard players {} {} {}'.format({'+':'add', '-':'remove'}[op], temp_var.get_selvar(func), right_const)) - else: - right_var = right_var.get_scoreboard_var(func) - func.add_command(f'scoreboard players operation {temp_var.get_selvar(func)} {self.op}= {right_var.get_selvar(func)}') - - right_var.free_scratch(func) - - return temp_var - - if self.op == "^": - left_var = self.lhs.compile(func, assignto) - temp_var = left_var.get_modifiable_var(func, assignto) - - right_var = self.rhs.compile(func) - power = right_var.get_const_value(func) - - if power == None: - print('Exponentiation must have constant operand.') - return None - - power = int(power) - - if power < 1: - print("Powers less than 1 are not supported") - return None - - if power == 1: - return target - - multiplier_obj = func.get_scratch() - func.add_command(f'scoreboard players operation Global {multiplier_obj} = {temp_var.selector} {temp_var.objective}') - - for i in range(power-1): - func.add_command(f'scoreboard players operation {temp_var.selector} {temp_var.objective} *= Global {multiplier_obj}') - - func.free_scratch(multiplier_obj) - - return temp_var - - else: - print(f"Binary operation '{self.op}' isn't implemented") - return None \ No newline at end of file + def __init__(self, lhs, op, rhs): + self.lhs = lhs + self.op = op + self.rhs = rhs + + # Returns true if this varariable/expression references the specified scoreboard variable + def references_scoreboard_var(self, func, var): + return self.lhs.references_scoreboard_var( + func, var + ) or self.rhs.references_scoreboard_var(func, var) + + def compile(self, func, assignto=None): + # TODO: Handle case where both variables are constant, and return constant + + if len(self.op) == 1 and self.op in ["+", "-", "*", "/", "%"]: + left_var = self.lhs.compile(func, assignto) + left_const = left_var.get_const_value(func) + + right_var = self.rhs.compile(func, None) + right_const = right_var.get_const_value(func) + + if ( + self.op in ["+", "*"] + and left_const != None + and right_const == None + ): + # Swap the operands so that the constant is on the right + old_left_var = left_var + old_left_const = left_const + + left_var = right_var + left_const = right_const + + right_var = old_left_var + right_const = old_left_const + + if assignto != None and not self.rhs.references_scoreboard_var( + func, assignto + ): + assignto.copy_from(func, left_var) + temp_var = assignto + else: + temp_var = left_var.get_modifiable_var(func, assignto) + + # TODO: handle case where both variables have constant values, return constant result + + if right_const and self.op in ["+", "-"]: + op = self.op + + if right_const < 0: + right_const = -right_const + op = {"+": "-", "-": "+"}[self.op] + + func.add_command( + "scoreboard players {} {} {}".format( + {"+": "add", "-": "remove"}[op], + temp_var.get_selvar(func), + right_const, + ) + ) + else: + right_var = right_var.get_scoreboard_var(func) + func.add_command( + f"scoreboard players operation {temp_var.get_selvar(func)} {self.op}= {right_var.get_selvar(func)}" + ) + + right_var.free_scratch(func) + + return temp_var + + if self.op == "^": + left_var = self.lhs.compile(func, assignto) + temp_var = left_var.get_modifiable_var(func, assignto) + + right_var = self.rhs.compile(func) + power = right_var.get_const_value(func) + + if power == None: + print("Exponentiation must have constant operand.") + return None + + power = int(power) + + if power < 1: + print("Powers less than 1 are not supported") + return None + + if power == 1: + return target + + multiplier_obj = func.get_scratch() + func.add_command( + f"scoreboard players operation Global {multiplier_obj} = {temp_var.selector} {temp_var.objective}" + ) + + for i in range(power - 1): + func.add_command( + f"scoreboard players operation {temp_var.selector} {temp_var.objective} *= Global {multiplier_obj}" + ) + + func.free_scratch(multiplier_obj) + + return temp_var + + else: + print(f"Binary operation '{self.op}' isn't implemented") + return None diff --git a/scalar_expressions/create_expr.py b/scalar_expressions/create_expr.py index a3f04d8..f718a7b 100644 --- a/scalar_expressions/create_expr.py +++ b/scalar_expressions/create_expr.py @@ -1,23 +1,28 @@ from .scalar_expression_base import scalar_expression_base from variable_types.selector_id_var import selector_id_var + class create_expr(scalar_expression_base): - def __init__(self, create_block): - self.create_block = create_block - - def compile(self, func, assignto=None): - func.register_objective('_age') - func.register_objective('_unique') - func.register_objective('_id') - - func.add_command(f'scoreboard players set @{self.create_block.atid} _age 1') - - try: - self.create_block.compile(func) - except Exception as e: - print(e) - raise Exception('Could not run create operation.') - - func.add_command(f'scoreboard players add @{self.create_block.atid} _age 1') - - return selector_id_var(f'@{self.create_block.atid}[_age==1,limit=1]') + def __init__(self, create_block): + self.create_block = create_block + + def compile(self, func, assignto=None): + func.register_objective("_age") + func.register_objective("_unique") + func.register_objective("_id") + + func.add_command( + f"scoreboard players set @{self.create_block.atid} _age 1" + ) + + try: + self.create_block.compile(func) + except Exception as e: + print(e) + raise Exception("Could not run create operation.") + + func.add_command( + f"scoreboard players add @{self.create_block.atid} _age 1" + ) + + return selector_id_var(f"@{self.create_block.atid}[_age==1,limit=1]") diff --git a/scalar_expressions/dot_expr.py b/scalar_expressions/dot_expr.py index f6408db..e853feb 100644 --- a/scalar_expressions/dot_expr.py +++ b/scalar_expressions/dot_expr.py @@ -1,31 +1,37 @@ from .scalar_expression_base import scalar_expression_base -from variable_types.scoreboard_var import scoreboard_var + class dot_expr(scalar_expression_base): - def __init__(self, lhs, rhs): - self.lhs = lhs - self.rhs = rhs - - def compile(self, func, assignto=None): - lhs = self.lhs.compile(func, None) - rhs = self.rhs.compile(func, None) - - prods = [] - for i in range(3): - prod = lhs[i].get_modifiable_var(func, assignto) - assignto = None - multiplicand = rhs[i].get_scoreboard_var(func) - - func.add_command(f'scoreboard players operation {prod.selvar} *= {multiplicand.selvar}') - - prods.append(prod) - - func.add_command(f'scoreboard players operation {prods[0].selvar} += {prods[1].selvar}') - func.add_command(f'scoreboard players operation {prods[0].selvar} += {prods[2].selvar}') - - for i in range(3): - for var in [lhs[i], rhs[i], prods[i]]: - if var != prods[0]: - var.free_scratch(func) - - return prods[0] + def __init__(self, lhs, rhs): + self.lhs = lhs + self.rhs = rhs + + def compile(self, func, assignto=None): + lhs = self.lhs.compile(func, None) + rhs = self.rhs.compile(func, None) + + prods = [] + for i in range(3): + prod = lhs[i].get_modifiable_var(func, assignto) + assignto = None + multiplicand = rhs[i].get_scoreboard_var(func) + + func.add_command( + f"scoreboard players operation {prod.selvar} *= {multiplicand.selvar}" + ) + + prods.append(prod) + + func.add_command( + f"scoreboard players operation {prods[0].selvar} += {prods[1].selvar}" + ) + func.add_command( + f"scoreboard players operation {prods[0].selvar} += {prods[2].selvar}" + ) + + for i in range(3): + for var in [lhs[i], rhs[i], prods[i]]: + if var != prods[0]: + var.free_scratch(func) + + return prods[0] diff --git a/scalar_expressions/func_expr.py b/scalar_expressions/func_expr.py index 6314366..fe2e73e 100644 --- a/scalar_expressions/func_expr.py +++ b/scalar_expressions/func_expr.py @@ -1,8 +1,8 @@ from .scalar_expression_base import scalar_expression_base from variable_types.scoreboard_var import scoreboard_var -from environment import isInt import math + def factor(n): i = 2 limit = math.sqrt(n) @@ -16,11 +16,12 @@ def factor(n): if n > 1: yield n + class func_expr(scalar_expression_base): - def __init__(self, function_call): - self.function_call = function_call - - def compile(self, func, assignto=None): - self.function_call.compile(func) - - return scoreboard_var('Global', 'ReturnValue') \ No newline at end of file + def __init__(self, function_call): + self.function_call = function_call + + def compile(self, func, assignto=None): + self.function_call.compile(func) + + return scoreboard_var("Global", "ReturnValue") diff --git a/scalar_expressions/method_expr.py b/scalar_expressions/method_expr.py index 6a2bcca..4677222 100644 --- a/scalar_expressions/method_expr.py +++ b/scalar_expressions/method_expr.py @@ -1,13 +1,12 @@ from .scalar_expression_base import scalar_expression_base from variable_types.scoreboard_var import scoreboard_var -from environment import isInt -import math + class method_expr(scalar_expression_base): - def __init__(self, method_call): - self.method_call = method_call - - def compile(self, func, assignto=None): - self.method_call.compile(func) - - return scoreboard_var('Global', 'ReturnValue') \ No newline at end of file + def __init__(self, method_call): + self.method_call = method_call + + def compile(self, func, assignto=None): + self.method_call.compile(func) + + return scoreboard_var("Global", "ReturnValue") diff --git a/scalar_expressions/scalar_expression_base.py b/scalar_expressions/scalar_expression_base.py index 08231bb..5d53a76 100644 --- a/scalar_expressions/scalar_expression_base.py +++ b/scalar_expressions/scalar_expression_base.py @@ -1,7 +1,7 @@ class scalar_expression_base(object): - def const_value(self, func=None): - return None - - # Returns true if this varariable/expression references the specified scoreboard variable - def references_scoreboard_var(self, func, var): - return False + def const_value(self, func=None): + return None + + # Returns true if this varariable/expression references the specified scoreboard variable + def references_scoreboard_var(self, func, var): + return False diff --git a/scalar_expressions/unary_expr.py b/scalar_expressions/unary_expr.py index 061a5d9..e574f9c 100644 --- a/scalar_expressions/unary_expr.py +++ b/scalar_expressions/unary_expr.py @@ -1,37 +1,41 @@ from .scalar_expression_base import scalar_expression_base from variable_types.virtualint_var import virtualint_var -from variable_types.scoreboard_var import scoreboard_var + class unary_expr(scalar_expression_base): - def __init__(self, type, expr): - self.type = type - self.expr = expr - - # Returns true if this varariable/expression references the specified scoreboard variable - def references_scoreboard_var(self, func, var): - return self.expr.references_scoreboard_var(func, var) - - def compile(self, func, assignto=None): - if self.type == '-': - var = self.expr.compile(func, assignto) - - if var == None: - return None - - const_val = var.get_const_value(func) - if const_val: - return virtualint_var(-int(const_val)) - - if assignto != None and not self.references_scoreboard_var(func, assignto): - assignto.copy_from(func, var) - temp_var = assignto - else: - temp_var = var.get_modifiable_var(func, assignto) - - minus = func.add_constant(-1) - func.add_command(f'scoreboard players operation {temp_var.get_selvar(func)} *= {minus} Constant') - - return temp_var - - print(f"Unary operation '{self.type}' isn't implemented.") - return None + def __init__(self, type, expr): + self.type = type + self.expr = expr + + # Returns true if this varariable/expression references the specified scoreboard variable + def references_scoreboard_var(self, func, var): + return self.expr.references_scoreboard_var(func, var) + + def compile(self, func, assignto=None): + if self.type == "-": + var = self.expr.compile(func, assignto) + + if var == None: + return None + + const_val = var.get_const_value(func) + if const_val: + return virtualint_var(-int(const_val)) + + if assignto != None and not self.references_scoreboard_var( + func, assignto + ): + assignto.copy_from(func, var) + temp_var = assignto + else: + temp_var = var.get_modifiable_var(func, assignto) + + minus = func.add_constant(-1) + func.add_command( + f"scoreboard players operation {temp_var.get_selvar(func)} *= {minus} Constant" + ) + + return temp_var + + print(f"Unary operation '{self.type}' isn't implemented.") + return None diff --git a/scratch_tracker.py b/scratch_tracker.py index aec40de..eb43aff 100644 --- a/scratch_tracker.py +++ b/scratch_tracker.py @@ -1,84 +1,85 @@ class scratch_tracker(object): - def __init__(self, global_context): - self.scratch = {} - self.temp = {} - self.global_context = global_context - self.scratch_allocation = 0 - self.temp_allocation = 0 - self.prefix = '' - - def get_temp_var(self): - for key in self.temp.keys(): - if self.temp[key] == False: - self.temp[key] = True - return "temp" + str(key) - - newScratch = len(self.temp.keys()) - self.temp[newScratch] = True - - new_length = len(self.temp.keys()) - if new_length > self.temp_allocation: - self.temp_allocation = new_length - self.global_context.allocate_temp(new_length) - - return f'temp{newScratch}' - - def free_temp_var(self, id): - num = int(id[len('temp'):]) - - self.temp[num] = False - - - def get_scratch(self): - for key in self.scratch.keys(): - if self.scratch[key] == False: - self.scratch[key] = True - return f'{self.prefix}_scratch{key}' - - newScratch = len(self.scratch.keys()) - self.scratch[newScratch] = True - - new_length = len(self.scratch.keys()) - if new_length > self.scratch_allocation: - self.scratch_allocation = new_length - self.global_context.allocate_scratch(self.prefix, new_length) - - return f'{self.prefix}_scratch{newScratch}' - - def get_scratch_vector(self): - return [self.get_scratch() for i in range(3)] - - def get_prefix(self): - return f'{self.prefix}_scratch' - - def is_scratch(self, id): - scratch_prefix = self.get_prefix() - - return id.startswith(scratch_prefix) - - def free_scratch(self, id): - if not self.is_scratch(id): - return - - scratch_prefix = self.get_prefix() - num = int(id[len(scratch_prefix):]) - - self.scratch[num] = False - - def get_allocated_variables(self): - ret = [f'{self.prefix}_scratch{i}'for i in range(self.scratch_allocation)] - ret += [f'temp{i}' for i in range(self.temp_allocation)] - - return ret - - def get_active_objectives(self): - all_objectives = [] - for num in self.scratch: - if self.scratch[num]: - all_objectives.append(f'{self.prefix}_scratch{num}') - - for num in self.temp: - if self.temp[num]: - all_objectives.append(f'temp{num}') - - return all_objectives + def __init__(self, global_context): + self.scratch = {} + self.temp = {} + self.global_context = global_context + self.scratch_allocation = 0 + self.temp_allocation = 0 + self.prefix = "" + + def get_temp_var(self): + for key in self.temp.keys(): + if self.temp[key] == False: + self.temp[key] = True + return "temp" + str(key) + + newScratch = len(self.temp.keys()) + self.temp[newScratch] = True + + new_length = len(self.temp.keys()) + if new_length > self.temp_allocation: + self.temp_allocation = new_length + self.global_context.allocate_temp(new_length) + + return f"temp{newScratch}" + + def free_temp_var(self, id): + num = int(id[len("temp") :]) + + self.temp[num] = False + + def get_scratch(self): + for key in self.scratch.keys(): + if self.scratch[key] == False: + self.scratch[key] = True + return f"{self.prefix}_scratch{key}" + + newScratch = len(self.scratch.keys()) + self.scratch[newScratch] = True + + new_length = len(self.scratch.keys()) + if new_length > self.scratch_allocation: + self.scratch_allocation = new_length + self.global_context.allocate_scratch(self.prefix, new_length) + + return f"{self.prefix}_scratch{newScratch}" + + def get_scratch_vector(self): + return [self.get_scratch() for i in range(3)] + + def get_prefix(self): + return f"{self.prefix}_scratch" + + def is_scratch(self, id): + scratch_prefix = self.get_prefix() + + return id.startswith(scratch_prefix) + + def free_scratch(self, id): + if not self.is_scratch(id): + return + + scratch_prefix = self.get_prefix() + num = int(id[len(scratch_prefix) :]) + + self.scratch[num] = False + + def get_allocated_variables(self): + ret = [ + f"{self.prefix}_scratch{i}" for i in range(self.scratch_allocation) + ] + ret += [f"temp{i}" for i in range(self.temp_allocation)] + + return ret + + def get_active_objectives(self): + all_objectives = [] + for num in self.scratch: + if self.scratch[num]: + all_objectives.append(f"{self.prefix}_scratch{num}") + + for num in self.temp: + if self.temp[num]: + all_objectives.append(f"temp{num}") + + return all_objectives diff --git a/scriptlex.py b/scriptlex.py index d918408..fec4997 100644 --- a/scriptlex.py +++ b/scriptlex.py @@ -1,162 +1,284 @@ -from ply import * +from ply import lex keywords = ( - 'for', 'dir', 'desc', 'in', 'end', 'not', 'and', 'or', 'to', 'by', 'import', - 'name', 'with', 'macros', - 'at', 'as', 'on', 'facing', 'rotated', 'align', 'here', 'the_end', 'the_nether', 'overworld', - 'move', 'create', 'tell', 'title', 'subtitle', 'actionbar', - 'reset', 'clock', 'function', 'if', 'unless', 'then', 'do', 'else', 'switch', 'case', 'default', - 'return', 'while', 'macro', 'block', 'block_data', 'block_tag', 'entity_tag', 'item_tag', 'define', 'array', 'remove', 'success', 'result', - 'shaped', 'recipe', 'keys', 'eyes', 'feet', 'advancement', 'loot_table', 'predicate', "item_modifier", - 'push', 'pop', 'true', 'false', + "for", + "dir", + "desc", + "in", + "end", + "not", + "and", + "or", + "to", + "by", + "import", + "name", + "with", + "macros", + "at", + "as", + "on", + "facing", + "rotated", + "align", + "here", + "the_end", + "the_nether", + "overworld", + "move", + "create", + "tell", + "title", + "subtitle", + "actionbar", + "reset", + "clock", + "function", + "if", + "unless", + "then", + "do", + "else", + "switch", + "case", + "default", + "return", + "while", + "macro", + "block", + "block_data", + "block_tag", + "entity_tag", + "item_tag", + "define", + "array", + "remove", + "success", + "result", + "shaped", + "recipe", + "keys", + "eyes", + "feet", + "advancement", + "loot_table", + "predicate", + "item_modifier", + "push", + "pop", + "true", + "false", ) tokens = keywords + ( - 'COMMAND', - 'LEQ','GEQ','GT','LT','EQUALEQUAL','DOLLAR','DOT','COLON','SEMICOLON', - 'PLUSEQUALS','MINUSEQUALS','TIMESEQUALS','DIVIDEEQUALS','MODEQUALS','PLUSPLUS','MINUSMINUS', - 'EQUALS','PLUS','MINUS','TIMES','DIVIDE','MOD','REF', - #'POWEREMPTY', - 'POWER', - 'LPAREN','RPAREN','COMMA','DECIMAL','FLOAT','HEX','BINARY','FUNCTIONID','ID','NEWLINE','LBRACK','RBRACK','LCURLY','RCURLY', - 'ATID', 'NOT', 'TILDEEMPTY', 'TILDE', - 'NORMSTRING', 'COMMENT', 'PRINT' + "COMMAND", + "LEQ", + "GEQ", + "GT", + "LT", + "EQUALEQUAL", + "DOLLAR", + "DOT", + "COLON", + "SEMICOLON", + "PLUSEQUALS", + "MINUSEQUALS", + "TIMESEQUALS", + "DIVIDEEQUALS", + "MODEQUALS", + "PLUSPLUS", + "MINUSMINUS", + "EQUALS", + "PLUS", + "MINUS", + "TIMES", + "DIVIDE", + "MOD", + "REF", + #'POWEREMPTY', + "POWER", + "LPAREN", + "RPAREN", + "COMMA", + "DECIMAL", + "FLOAT", + "HEX", + "BINARY", + "FUNCTIONID", + "ID", + "NEWLINE", + "LBRACK", + "RBRACK", + "LCURLY", + "RCURLY", + "ATID", + "NOT", + "TILDEEMPTY", + "TILDE", + "NORMSTRING", + "COMMENT", + "PRINT", ) + def t_None(t): - r'None' + r"None" t.value = "0" t.type = "DECIMAL" - + return t + def t_False(t): - r'False' + r"False" t.value = "0" t.type = "DECIMAL" - + return t + def t_True(t): - r'True' + r"True" t.value = "1" t.type = "DECIMAL" - + return t + def t_FUNCTIONID(t): - r'[A-Za-z_][A-Za-z0-9_]*\(' - t.value = t.value[:-1] - return t - + r"[A-Za-z_][A-Za-z0-9_]*\(" + t.value = t.value[:-1] + return t + + def t_ID(t): - r'[A-Za-z_][A-Za-z0-9_]*' + r"[A-Za-z_][A-Za-z0-9_]*" if t.value in keywords: t.type = t.value return t - + + def t_COMMAND(t): - r'(?m:^\s*\/.+)' - t.lexer.lineno += t.value.count('\n') + r"(?m:^\s*\/.+)" + t.lexer.lineno += t.value.count("\n") t.value = t.value.strip() return t + def t_WHITESPACE(t): - r'[ \t]' + r"[ \t]" + def t_ATID(t): - r'@[A-Za-z_][A-Za-z0-9_]*' + r"@[A-Za-z_][A-Za-z0-9_]*" t.value = t.value[1:] return t -t_PRINT = r'\$print\(' -t_EQUALEQUAL = r'==' -t_LEQ = r'<=' -t_GEQ = r'>=' -t_LT = r'<' -t_GT = r'>' -t_DOLLAR = r'\$' -t_COMMA = r'\,' -t_PLUSEQUALS = r'\+=' -t_MINUSEQUALS = r'-=' -t_TIMESEQUALS = r'\*=' -t_MODEQUALS = r'\%=' -t_EQUALS = r'=' -t_PLUS = r'\+' -t_MINUS = r'-' -t_TIMES = r'\*' -t_PLUSPLUS = r'\+\+' -t_MINUSMINUS = r'--' -t_DOT = r'\.' -t_COLON = r'\:' -t_NOT = r'!' -t_REF = r'&' -t_SEMICOLON = r';' - -#def t_POWEREMPTY(t): + +t_PRINT = r"\$print\(" +t_EQUALEQUAL = r"==" +t_LEQ = r"<=" +t_GEQ = r">=" +t_LT = r"<" +t_GT = r">" +t_DOLLAR = r"\$" +t_COMMA = r"\," +t_PLUSEQUALS = r"\+=" +t_MINUSEQUALS = r"-=" +t_TIMESEQUALS = r"\*=" +t_MODEQUALS = r"\%=" +t_EQUALS = r"=" +t_PLUS = r"\+" +t_MINUS = r"-" +t_TIMES = r"\*" +t_PLUSPLUS = r"\+\+" +t_MINUSMINUS = r"--" +t_DOT = r"\." +t_COLON = r"\:" +t_NOT = r"!" +t_REF = r"&" +t_SEMICOLON = r";" + +# def t_POWEREMPTY(t): # r'\^[ \t]' # t.value = "^" # return t -t_POWER = r'\^' +t_POWER = r"\^" + def t_TILDEEMPTY(t): - r'~[ \t]' + r"~[ \t]" t.value = "~" return t -t_TILDE = r'~' -t_FLOAT = r'\d+\.\d+' -t_DECIMAL = r'\d+' + + +t_TILDE = r"~" +t_FLOAT = r"\d+\.\d+" +t_DECIMAL = r"\d+" + def t_HEX(t): - r'0x[0-9A-Fa-f]+' - t.value = str(int(t.value, 16)) - return t - + r"0x[0-9A-Fa-f]+" + t.value = str(int(t.value, 16)) + return t + + def t_BINARY(t): - r'0b[01]+' - t.value = str(int(t.value, 2)) - return t + r"0b[01]+" + t.value = str(int(t.value, 2)) + return t + def t_DIVIDEEQUALS(t): - r'/=' + r"/=" return t + def t_DIVIDE(t): - r'/' + r"/" return t - -t_MOD = r'\%' -t_LPAREN = r'\(' -t_RPAREN = r'\)' -t_LBRACK = r'\[' -t_RBRACK = r'\]' -t_LCURLY = r'\{' -t_RCURLY = r'\}' -t_ignore = '\r' + +t_MOD = r"\%" +t_LPAREN = r"\(" +t_RPAREN = r"\)" +t_LBRACK = r"\[" +t_RBRACK = r"\]" +t_LCURLY = r"\{" +t_RCURLY = r"\}" + +t_ignore = "\r" + def t_NEWLINE(t): - r'\n' + r"\n" t.lexer.lineno += 1 return t - + + def t_NORMSTRING(t): r'("((\\.)|[^"\n])*")|(\'((\\.)|[^\'\n])*\')' return t + def t_COMMENT(t): - r'\#.+' + r"\#.+" return t + def t_error(t): - print(f'Illegal character "{t.value[0]}" was skipped at line {t.lexer.lineno}') + print( + f'Illegal character "{t.value[0]}" was skipped at line {t.lexer.lineno}' + ) t.lexer.skip(1) - + + # Compute column. # input is the input text string # token is a token instance def find_column(input, token): - line_start = input.rfind('\n', 0, token.lexpos) + 1 + line_start = input.rfind("\n", 0, token.lexpos) + 1 return (token.lexpos - line_start) + 1 -lexer = lex.lex(debug=0) \ No newline at end of file + +lexer = lex.lex(debug=0) diff --git a/scriptparse.py b/scriptparse.py index 9f7a414..4637eb2 100644 --- a/scriptparse.py +++ b/scriptparse.py @@ -1,7 +1,9 @@ -from ply import * +from ply import yacc import traceback import scriptlex -from block_types.advancement_definition_block import advancement_definition_block +from block_types.advancement_definition_block import ( + advancement_definition_block, +) from block_types.array_definition_block import array_definition_block from block_types.block_definition_block import block_definition_block from block_types.block_switch_block import block_switch_block @@ -30,14 +32,18 @@ from block_types.pop_block import pop_block from block_types.pointer_decl_block import pointer_decl_block from block_types.predicate_definition_block import predicate_definition_block -from block_types.item_modifier_definition_block import item_modifier_definition_block +from block_types.item_modifier_definition_block import ( + item_modifier_definition_block, +) from block_types.print_block import print_block from block_types.push_block import push_block from block_types.python_assignment_block import python_assignment_block from block_types.python_for_block import python_for_block from block_types.python_if_block import python_if_block from block_types.python_import_block import python_import_block -from block_types.python_tuple_assignment_block import python_tuple_assignment_block +from block_types.python_tuple_assignment_block import ( + python_tuple_assignment_block, +) from block_types.reset_section import reset_section from block_types.scoreboard_assignment_block import scoreboard_assignment_block from block_types.selector_assignment_block import selector_assignment_block @@ -45,11 +51,15 @@ from block_types.shaped_recipe_block import shaped_recipe_block from block_types.switch_block import switch_block from block_types.tell_block import tell_block -from block_types.template_function_call_block import template_function_call_block +from block_types.template_function_call_block import ( + template_function_call_block, +) from block_types.template_function_section import template_function_section from block_types.title_block import title_block from block_types.vector_assignment_block import vector_assignment_block -from block_types.vector_assignment_scalar_block import vector_assignment_scalar_block +from block_types.vector_assignment_scalar_block import ( + vector_assignment_scalar_block, +) from block_types.while_block import while_block from block_types.with_anonymous_block import with_anonymous_block from block_types.with_items import with_items @@ -57,7 +67,6 @@ from data_types.const_number import const_number from data_types.const_string import const_string from data_types.number_macro_path import number_macro_path -from data_types.python_identifier import python_identifier from data_types.interpreted_python import interpreted_python from data_types.relcoord_vector import relcoord_vector from data_types.relcoord import relcoord @@ -82,1789 +91,2181 @@ from variable_types.storage_path_var import storage_path_var from variable_types.virtualint_var import virtualint_var from vector_expressions.sel_vector_var_expr import sel_vector_var_expr -from vector_expressions.vector_binop_scalar_expr import vector_binop_scalar_expr -from vector_expressions.vector_binop_vector_expr import vector_binop_vector_expr +from vector_expressions.vector_binop_scalar_expr import ( + vector_binop_scalar_expr, +) +from vector_expressions.vector_binop_vector_expr import ( + vector_binop_vector_expr, +) from vector_expressions.vector_expr import vector_expr from vector_expressions.vector_here_expr import vector_here_expr from vector_expressions.vector_var_const_vector import vector_var_const_vector from vector_expressions.vector_var_expr import vector_var_expr -import mcfunction tokens = scriptlex.tokens precedence = ( - ('left', 'PLUS','MINUS'), - ('left', 'TIMES','DIVIDE','MOD'), - ('left', 'POWER'), - ('right','UMINUS'), - ('left', 'VECTOR'), - ('left', 'COMP'), + ("left", "PLUS", "MINUS"), + ("left", "TIMES", "DIVIDE", "MOD"), + ("left", "POWER"), + ("right", "UMINUS"), + ("left", "VECTOR"), + ("left", "COMP"), ) + #### Parsed def p_parsed_assignment(p): - '''parsed : program''' - p[0] = ('program', p[1]) + """parsed : program""" + p[0] = ("program", p[1]) + def p_parsed_lib(p): - '''parsed : import lib''' - p[0] = ('lib', p[2]) - + """parsed : import lib""" + p[0] = ("lib", p[2]) + + def p_parsed_expr(p): - '''parsed : expr''' - p[0] = ('expr', p[1]) - + """parsed : expr""" + p[0] = ("expr", p[1]) + + #### Program def p_program(p): - '''program : optcomments dir string newlines optdesc file_params top_level_blocks''' - p[0] = {} - p[0]['dir'] = p[3] - p[0]['desc'] = p[5] - - for param_name in p[6]: - p[0][param_name] = p[6][param_name] - - p[0]['lines'] = p[7] - + """program : optcomments dir string newlines optdesc file_params top_level_blocks""" + p[0] = {} + p[0]["dir"] = p[3] + p[0]["desc"] = p[5] + + for param_name in p[6]: + p[0][param_name] = p[6][param_name] + + p[0]["lines"] = p[7] + + ### Lib def p_lib(p): - '''lib : top_level_blocks''' - p[0] = {} - p[0]['lines'] = p[1] + """lib : top_level_blocks""" + p[0] = {} + p[0]["lines"] = p[1] + #### Optdesc def p_optdesc(p): - '''optdesc : desc string newlines - | empty''' - if len(p) < 4: - p[0] = 'No Description' - else: - p[0] = p[2] + """optdesc : desc string newlines + | empty""" + if len(p) < 4: + p[0] = "No Description" + else: + p[0] = p[2] + #### File Params def p_file_params(p): - '''file_params : file_param file_params''' - param_name, param_value = p[1] + """file_params : file_param file_params""" + param_name, param_value = p[1] + + p[2][param_name] = param_value - p[2][param_name] = param_value + p[0] = p[2] - p[0] = p[2] def p_file_params_none(p): - '''file_params : empty''' - p[0] = {} + """file_params : empty""" + p[0] = {} + #### File Param def p_file_param(p): - '''file_param : ID integer newlines''' + """file_param : ID integer newlines""" + + if p[1] not in ["scale"]: + raise SyntaxError( + f'Unknown file parameter: "{p[1]}" at line {p.lineno(1)}' + ) + + p[0] = (p[1], int(p[2])) + - if p[1] not in ['scale']: - raise SyntaxError(f'Unknown file parameter: "{p[1]}" at line {p.lineno(1)}') - - p[0] = (p[1], int(p[2])) - #### Sections def p_section_commented(p): - '''section_commented : optcomments section''' - - # TODO: Put the comments into the sections - p[0] = p[2] - + """section_commented : optcomments section""" + + # TODO: Put the comments into the sections + p[0] = p[2] + def p_optcomments(p): - '''optcomments : COMMENT optnewlines optcomments''' - p[0] = [p[1]] + p[3] - + """optcomments : COMMENT optnewlines optcomments""" + p[0] = [p[1]] + p[3] + + def p_optcomments_empty(p): - '''optcomments : empty''' - p[0] = [] - + """optcomments : empty""" + p[0] = [] + + def p_section(p): - '''section : clocksection - | functionsection - | resetsection - | macrosection - | template_function_section''' - p[0] = p[1] - -#### Reset Section + """section : clocksection + | functionsection + | resetsection + | macrosection + | template_function_section""" + p[0] = p[1] + + +#### Reset Section def p_resetsection(p): - '''resetsection : reset newlines blocklist end''' - p[0] = reset_section(p.lineno(1), p[3]) - - + """resetsection : reset newlines blocklist end""" + p[0] = reset_section(p.lineno(1), p[3]) + + def validate_mcfunction_name(str): - for ch in str: - if ch.isupper(): - print(f'"{str}" is not a valid mcfunction name.') - raise SyntaxError() - + for ch in str: + if ch.isupper(): + print(f'"{str}" is not a valid mcfunction name.') + raise SyntaxError() + + #### Clock Section def p_clocksection(p): - '''clocksection : clock ID newlines blocklist end''' - validate_mcfunction_name(p[2]) - - p[0] = clock_section(p.lineno(1), p[2], p[4]) - + """clocksection : clock ID newlines blocklist end""" + validate_mcfunction_name(p[2]) + + p[0] = clock_section(p.lineno(1), p[2], p[4]) + + #### Function Section def p_functionsection(p): - '''functionsection : function FUNCTIONID id_list RPAREN newlines blocklist end''' - validate_mcfunction_name(p[2]) + """functionsection : function FUNCTIONID id_list RPAREN newlines blocklist end""" + validate_mcfunction_name(p[2]) + + p[0] = function_section(p.lineno(1), p[2], p[3], p[6]) - p[0] = function_section(p.lineno(1), p[2], p[3], p[6]) #### Template Function Section def p_template_function_section(p): - '''template_function_section : function ID LCURLY macro_params RCURLY LPAREN id_list RPAREN newlines blocklist end''' - validate_mcfunction_name(p[2]) - - p[0] = template_function_section(p.lineno(1), p[2], p[4], p[7], p[10]) + """template_function_section : function ID LCURLY macro_params RCURLY LPAREN id_list RPAREN newlines blocklist end""" + validate_mcfunction_name(p[2]) + + p[0] = template_function_section(p.lineno(1), p[2], p[4], p[7], p[10]) + #### Macro section def p_macrosection(p): - '''macrosection : macro DOLLAR FUNCTIONID macro_args newlines blocklist end''' - - p[0] = macro_section(p.lineno(1), p[3], p[4], p[6]) + """macrosection : macro DOLLAR FUNCTIONID macro_args newlines blocklist end""" + + p[0] = macro_section(p.lineno(1), p[3], p[4], p[6]) + def p_macro_args(p): - '''macro_args : macro_params RPAREN''' - p[0] = p[1] - + """macro_args : macro_params RPAREN""" + p[0] = p[1] + + def p_macro_args_empty(p): - '''macro_args : empty''' - p[0] = [] + """macro_args : empty""" + p[0] = [] + def p_macro_params(p): - '''macro_params : DOLLAR ID COMMA macro_params''' - p[0] = [p[2]] + p[4] + """macro_params : DOLLAR ID COMMA macro_params""" + p[0] = [p[2]] + p[4] + def p_macro_params_one(p): - '''macro_params : DOLLAR ID''' - p[0] = [p[2]] - + """macro_params : DOLLAR ID""" + p[0] = [p[2]] + + def p_macro_params_empty(p): - '''macro_params : empty''' - p[0] = [] + """macro_params : empty""" + p[0] = [] + #### Macro decorators #### With macro items list def p_with_macro_item_expr(p): - '''with_macro_item : DOLLAR LPAREN ID RPAREN EQUALS expr newlines''' - p[0] = ('expr', p[3], p[6]) + """with_macro_item : DOLLAR LPAREN ID RPAREN EQUALS expr newlines""" + p[0] = ("expr", p[3], p[6]) + def p_with_macro_item_str(p): - '''with_macro_item : DOLLAR LPAREN ID RPAREN EQUALS NORMSTRING newlines''' - p[0] = ('string', p[3], p[6]) + """with_macro_item : DOLLAR LPAREN ID RPAREN EQUALS NORMSTRING newlines""" + p[0] = ("string", p[3], p[6]) + def p_with_macro_items_one(p): - '''with_macro_items : with_macro_item''' - p[0] = [p[1]] + """with_macro_items : with_macro_item""" + p[0] = [p[1]] + def p_with_macro_items(p): - '''with_macro_items : with_macro_item with_macro_items''' - p[0] = [p[1]] + p[2] + """with_macro_items : with_macro_item with_macro_items""" + p[0] = [p[1]] + p[2] + def p_with_macro_items_prefix(p): - '''with_macro_items_prefix : with newlines with_macro_items''' - p[0] = with_items(p.lineno(1), p[3]) + """with_macro_items_prefix : with newlines with_macro_items""" + p[0] = with_items(p.lineno(1), p[3]) + #### With macros suffix decorator def p_opt_with_macros_true(p): - '''opt_with_macros : with macros''' - p[0] = with_items(p.lineno(1), []) + """opt_with_macros : with macros""" + p[0] = with_items(p.lineno(1), []) + def p_opt_with_macros_false(p): - '''opt_with_macros : empty''' - p[0] = None + """opt_with_macros : empty""" + p[0] = None + #### Expression list def p_exprlist_multiple(p): - '''exprlist : exprlist COMMA expr''' - p[0] = p[1] - p[0].append(p[3]) - + """exprlist : exprlist COMMA expr""" + p[0] = p[1] + p[0].append(p[3]) + + def p_exprlist_single(p): - '''exprlist : expr''' - p[0] = [p[1]] + """exprlist : expr""" + p[0] = [p[1]] + def p_exprlist_empty(p): - '''exprlist : empty''' - p[0] = [] + """exprlist : empty""" + p[0] = [] + #### With Anonymouse def p_with_anonymous_block(p): - '''with_anonymous_block : with_macro_items_prefix do newlines blocklist end''' - p[0] = with_anonymous_block(p.lineno(1), p[1], p[4]) + """with_anonymous_block : with_macro_items_prefix do newlines blocklist end""" + p[0] = with_anonymous_block(p.lineno(1), p[1], p[4]) + #### Function call def p_function_call_namespace(p): - '''function_call : ID COLON FUNCTIONID exprlist RPAREN opt_with_macros''' - p[0] = function_call_block(p.lineno(1), p[1]+p[2]+p[3], p[4], p[6]) + """function_call : ID COLON FUNCTIONID exprlist RPAREN opt_with_macros""" + p[0] = function_call_block(p.lineno(1), p[1] + p[2] + p[3], p[4], p[6]) + def p_function_call(p): - '''function_call : FUNCTIONID exprlist RPAREN opt_with_macros''' - p[0] = function_call_block(p.lineno(1), p[1], p[2], p[4]) + """function_call : FUNCTIONID exprlist RPAREN opt_with_macros""" + p[0] = function_call_block(p.lineno(1), p[1], p[2], p[4]) + def p_function_call_block(p): - '''function_call_block : function_call''' - p[0] = p[1] + """function_call_block : function_call""" + p[0] = p[1] + def p_function_call_block_with_macro_items(p): - '''function_call_block : with_macro_items_prefix function_call''' - p[2].with_macro_items = p[1] - p[0] = p[2] + """function_call_block : with_macro_items_prefix function_call""" + p[2].with_macro_items = p[1] + p[0] = p[2] -#### Method call + +#### Method call def p_method_call(p): - '''method_call : fullselector DOT FUNCTIONID exprlist RPAREN opt_with_macros''' - p[0] = method_call_block(p.lineno(1), p[1], p[3], p[4], p[6]) + """method_call : fullselector DOT FUNCTIONID exprlist RPAREN opt_with_macros""" + p[0] = method_call_block(p.lineno(1), p[1], p[3], p[4], p[6]) + def p_method_call_block(p): - '''method_call_block : method_call''' - p[0] = p[1] + """method_call_block : method_call""" + p[0] = p[1] + def p_method_call_block_with_macro_items(p): - '''method_call_block : with_macro_items_prefix method_call''' - p[2].with_macro_items = p[1] - p[0] = p[2] + """method_call_block : with_macro_items_prefix method_call""" + p[2].with_macro_items = p[1] + p[0] = p[2] + #### Template Function Call def p_template_function_call(p): - '''template_function_call : ID LCURLY macro_call_params RCURLY LPAREN exprlist RPAREN opt_with_macros''' - p[0] = template_function_call_block(p.lineno(1), p[1], p[3], p[6], p[8]) + """template_function_call : ID LCURLY macro_call_params RCURLY LPAREN exprlist RPAREN opt_with_macros""" + p[0] = template_function_call_block(p.lineno(1), p[1], p[3], p[6], p[8]) + def p_template_function_call_block(p): - '''template_function_call_block : template_function_call''' - p[0] = p[1] + """template_function_call_block : template_function_call""" + p[0] = p[1] + def p_template_function_call_block_with_macro_items(p): - '''template_function_call_block : with_macro_items_prefix template_function_call''' - p[2].with_macro_items = p[1] - p[0] = p[2] + """template_function_call_block : with_macro_items_prefix template_function_call""" + p[2].with_macro_items = p[1] + p[0] = p[2] -#### Macro call + +#### Macro call def p_macro_call(p): - '''macro_call : DOLLAR FUNCTIONID macro_call_args''' - p[0] = macro_call_block(p.lineno(1), p[2], p[3]) - + """macro_call : DOLLAR FUNCTIONID macro_call_args""" + p[0] = macro_call_block(p.lineno(1), p[2], p[3]) + + def p_macro_call_args(p): - '''macro_call_args : macro_call_params RPAREN''' - p[0] = p[1] - + """macro_call_args : macro_call_params RPAREN""" + p[0] = p[1] + + def p_macro_call_args_empty(p): - '''macro_call_args : empty''' - p[0] = [] - + """macro_call_args : empty""" + p[0] = [] + + def p_macro_call_params(p): - '''macro_call_params : macro_call_param COMMA macro_call_params''' - p[0] = [p[1]] + p[3] + """macro_call_params : macro_call_param COMMA macro_call_params""" + p[0] = [p[1]] + p[3] + def p_macro_call_params_one(p): - '''macro_call_params : macro_call_param''' - p[0] = [p[1]] - + """macro_call_params : macro_call_param""" + p[0] = [p[1]] + + def p_macro_call_params_empty(p): - '''macro_call_params : empty''' - p[0] = [] - + """macro_call_params : empty""" + p[0] = [] + + def p_macro_call_param_number(p): - '''macro_call_param : const_value''' - p[0] = p[1] - + """macro_call_param : const_value""" + p[0] = p[1] + + #### Newlines def p_newlines(p): - '''newlines : NEWLINE newlines - | NEWLINE''' - p[0] = None - + """newlines : NEWLINE newlines + | NEWLINE""" + p[0] = None + + def p_optnewlines(p): - '''optnewlines : newlines - | empty''' - + """optnewlines : newlines + | empty""" + + #### Identifier List def p_id_list(p): - '''id_list : ID COMMA id_list''' - p[0] = [p[1]] + p[3] + """id_list : ID COMMA id_list""" + p[0] = [p[1]] + p[3] + def p_id_list_one(p): - '''id_list : ID''' - p[0] = [p[1]] + """id_list : ID""" + p[0] = [p[1]] + def p_id_list_empty(p): - '''id_list : empty''' - p[0] = [] - + """id_list : empty""" + p[0] = [] + + #### Top Level Blocks def p_top_level_blocks(p): - '''top_level_blocks : pythonassignment newlines top_level_blocks - | python_tuple_assignment newlines top_level_blocks - | selector_assignment newlines top_level_blocks - | selector_define_block newlines top_level_blocks - | block_define_block newlines top_level_blocks - | blocktag newlines top_level_blocks - | entitytag newlines top_level_blocks - | itemtag newlines top_level_blocks - | array_definition newlines top_level_blocks - | import_statement newlines top_level_blocks - | python_import_statement newlines top_level_blocks - | print_block newlines top_level_blocks - | pointer_decl newlines top_level_blocks - | shaped_recipe newlines top_level_blocks - | advancement_definition newlines top_level_blocks - | loot_table_definition newlines top_level_blocks - | predicate_definition newlines top_level_blocks - | item_modifier_definition newlines top_level_blocks - | section_commented newlines top_level_blocks''' - p[0] = [p[1]] + p[3] - + """top_level_blocks : pythonassignment newlines top_level_blocks + | python_tuple_assignment newlines top_level_blocks + | selector_assignment newlines top_level_blocks + | selector_define_block newlines top_level_blocks + | block_define_block newlines top_level_blocks + | blocktag newlines top_level_blocks + | entitytag newlines top_level_blocks + | itemtag newlines top_level_blocks + | array_definition newlines top_level_blocks + | import_statement newlines top_level_blocks + | python_import_statement newlines top_level_blocks + | print_block newlines top_level_blocks + | pointer_decl newlines top_level_blocks + | shaped_recipe newlines top_level_blocks + | advancement_definition newlines top_level_blocks + | loot_table_definition newlines top_level_blocks + | predicate_definition newlines top_level_blocks + | item_modifier_definition newlines top_level_blocks + | section_commented newlines top_level_blocks""" + p[0] = [p[1]] + p[3] + + def p_top_level_blocks_comment(p): - '''top_level_blocks : COMMENT newlines top_level_blocks''' - p[0] = p[3] + """top_level_blocks : COMMENT newlines top_level_blocks""" + p[0] = p[3] + def p_top_level_blocks_empty(p): - '''top_level_blocks : empty''' - p[0] = [] + """top_level_blocks : empty""" + p[0] = [] + -#### Import +#### Import def p_import_statement(p): - '''import_statement : import ID''' - p[0] = import_block(p.lineno(1), p[2]) + """import_statement : import ID""" + p[0] = import_block(p.lineno(1), p[2]) -#### Import + +#### Import def p_python_import_statement(p): - '''python_import_statement : import ID DOT ID''' - if p[4] == 'py': - p[0] = python_import_block(p.lineno(1), p[2]) - elif p[4] == 'cblib': - p[0] = import_block(p.lineno(1), p[2]) - else: - raise SyntaxError(f'Unknown import file type: "{p[2]}.{p[4]}"') - + """python_import_statement : import ID DOT ID""" + if p[4] == "py": + p[0] = python_import_block(p.lineno(1), p[2]) + elif p[4] == "cblib": + p[0] = import_block(p.lineno(1), p[2]) + else: + raise SyntaxError(f'Unknown import file type: "{p[2]}.{p[4]}"') + + #### Variable def p_variable_selector(p): - '''variable : fullselector DOT ID - | ID DOT ID''' - p[0] = scoreboard_var(p[1], p[3]) - + """variable : fullselector DOT ID + | ID DOT ID""" + p[0] = scoreboard_var(p[1], p[3]) + + def p_variable_global(p): - '''variable : ID''' - if p[1] == 'scale': - p[0] = scale_var() - else: - p[0] = scoreboard_var('Global', p[1]) - + """variable : ID""" + if p[1] == "scale": + p[0] = scale_var() + else: + p[0] = scoreboard_var("Global", p[1]) + + def p_variable_array_const(p): - '''variable : ID LBRACK virtualinteger RBRACK''' - p[0] = array_const_var('Global', p[1], p[3]) + """variable : ID LBRACK virtualinteger RBRACK""" + p[0] = array_const_var("Global", p[1], p[3]) + def p_variable_array_expr(p): - '''variable : ID LBRACK expr RBRACK''' - p[0] = array_expr_var('Global', p[1], p[3]) + """variable : ID LBRACK expr RBRACK""" + p[0] = array_expr_var("Global", p[1], p[3]) + def p_variable_array_const_selector(p): - '''variable : fullselector DOT ID LBRACK virtualinteger RBRACK''' - p[0] = array_const_var(p[1], p[3], p[5]) - + """variable : fullselector DOT ID LBRACK virtualinteger RBRACK""" + p[0] = array_const_var(p[1], p[3], p[5]) + + def p_variable_array_expr_selector(p): - '''variable : fullselector DOT ID LBRACK expr RBRACK''' - p[0] = array_expr_var(p[1], p[3], p[5]) - + """variable : fullselector DOT ID LBRACK expr RBRACK""" + p[0] = array_expr_var(p[1], p[3], p[5]) + + def p_variable_block_path_nocoords(p): - '''variable : LBRACK ID RBRACK DOT ID''' - p[0] = block_path_var(p[2], p[5], None, []) + """variable : LBRACK ID RBRACK DOT ID""" + p[0] = block_path_var(p[2], p[5], None, []) + def p_variable_block_path_coords(p): - '''variable : LBRACK ID at relcoords RBRACK DOT ID''' - p[0] = block_path_var(p[2], p[7], p[4], []) + """variable : LBRACK ID at relcoords RBRACK DOT ID""" + p[0] = block_path_var(p[2], p[7], p[4], []) + def p_variable_block_macro_path_nocoords(p): - '''variable : LBRACK ID RBRACK DOT ID LBRACK macro_call_params RBRACK''' - p[0] = block_path_var(p[2], p[5], None, p[7]) + """variable : LBRACK ID RBRACK DOT ID LBRACK macro_call_params RBRACK""" + p[0] = block_path_var(p[2], p[5], None, p[7]) + def p_variable_block_macro_path_coords(p): - '''variable : LBRACK ID at relcoords RBRACK DOT ID LBRACK macro_call_params RBRACK''' - p[0] = block_path_var(p[2], p[7], p[4], p[9]) - + """variable : LBRACK ID at relcoords RBRACK DOT ID LBRACK macro_call_params RBRACK""" + p[0] = block_path_var(p[2], p[7], p[4], p[9]) + + def p_variable_virtualint(p): - '''variable : virtualinteger''' - p[0] = virtualint_var(p[1]) - + """variable : virtualinteger""" + p[0] = virtualint_var(p[1]) + + def p_variable_selector_ref(p): - '''variable : REF fullselector''' - p[0] = selector_id_var(p[2]) - + """variable : REF fullselector""" + p[0] = selector_id_var(p[2]) + + def p_variable_command(p): - '''variable : success NEWLINE COMMAND - | result NEWLINE COMMAND''' - p[0] = command_var(p[1], p[3]) - + """variable : success NEWLINE COMMAND + | result NEWLINE COMMAND""" + p[0] = command_var(p[1], p[3]) + + def p_variable_storage(p): - '''variable : COLON data_path''' - p[0] = storage_path_var(None, p[2]) - + """variable : COLON data_path""" + p[0] = storage_path_var(None, p[2]) + + def p_variable_storage_target(p): - '''variable : ID COLON data_path''' - p[0] = storage_path_var(p[1], p[3]) - + """variable : ID COLON data_path""" + p[0] = storage_path_var(p[1], p[3]) + + #### Blocklist def p_optcomment(p): - '''optcomment : COMMENT''' - p[0] = [comment_block(p.lineno(1), p[1])] - + """optcomment : COMMENT""" + p[0] = [comment_block(p.lineno(1), p[1])] + + def p_optcomment_empty(p): - '''optcomment : empty''' - p[0] = [] + """optcomment : empty""" + p[0] = [] + def p_blocklist_multiple(p): - '''blocklist : codeblock optcomment newlines blocklist''' - p[0] = p[2] + [p[1]] + p[4] + """blocklist : codeblock optcomment newlines blocklist""" + p[0] = p[2] + [p[1]] + p[4] + def p_blocklist_empty(p): - '''blocklist : empty''' - p[0] = [] + """blocklist : empty""" + p[0] = [] + #### Block def p_block_comment(p): - '''codeblock : COMMENT''' - p[0] = comment_block(p.lineno(1), p[1]) + """codeblock : COMMENT""" + p[0] = comment_block(p.lineno(1), p[1]) + def p_block_command(p): - '''codeblock : COMMAND''' - p[0] = command_block(p.lineno(1), p[1]) + """codeblock : COMMAND""" + p[0] = command_block(p.lineno(1), p[1]) + def p_block_move(p): - '''codeblock : move fullselector relcoords''' - p[0] = move_block(p.lineno(1), p[2], p[3]) + """codeblock : move fullselector relcoords""" + p[0] = move_block(p.lineno(1), p[2], p[3]) + def p_block_for(p): - '''codeblock : for DOLLAR ID in const_value newlines blocklist end''' - p[0] = python_for_block(p.lineno(1), [p[3]], p[5], p[7]) - + """codeblock : for DOLLAR ID in const_value newlines blocklist end""" + p[0] = python_for_block(p.lineno(1), [p[3]], p[5], p[7]) + + def p_block_for_tuple(p): - '''codeblock : for python_tuple in const_value newlines blocklist end''' - p[0] = python_for_block(p.lineno(1), p[2], p[4], p[6]) - + """codeblock : for python_tuple in const_value newlines blocklist end""" + p[0] = python_for_block(p.lineno(1), p[2], p[4], p[6]) + + def p_block_print(p): - '''codeblock : print_block''' - p[0] = p[1] - + """codeblock : print_block""" + p[0] = p[1] + + def p_print_block(p): - '''print_block : PRINT const_value RPAREN''' - p[0] = print_block(p.lineno(1), p[2]) - + """print_block : PRINT const_value RPAREN""" + p[0] = print_block(p.lineno(1), p[2]) + + #### Execute def p_else_list_empty(p): - '''else_list : empty''' - p[0] = [] + """else_list : empty""" + p[0] = [] + def p_else_list(p): - '''else_list : else_item else_list''' - p[0] = [p[1]] + p[2] + """else_list : else_item else_list""" + p[0] = [p[1]] + p[2] + def p_else_item_execute(p): - '''else_item : else execute_items newlines blocklist''' - p[0] = (p[2], p[4]) - + """else_item : else execute_items newlines blocklist""" + p[0] = (p[2], p[4]) + + def p_else_item_empty(p): - '''else_item : else newlines blocklist''' - p[0] = (None, p[3]) + """else_item : else newlines blocklist""" + p[0] = (None, p[3]) + def p_block_if_command(p): - '''codeblock : if const_value newlines blocklist else_list end''' - p[0] = python_if_block(p.lineno(1), p[2], p[4], p[5]) + """codeblock : if const_value newlines blocklist else_list end""" + p[0] = python_if_block(p.lineno(1), p[2], p[4], p[5]) + def p_execute_as_id_global(p): - '''codeblock : as variable newlines blocklist else_list end''' - p[0] = execute_block(p.lineno(1), [('AsId', (p[2], None))], p[4], p[5]) + """codeblock : as variable newlines blocklist else_list end""" + p[0] = execute_block(p.lineno(1), [("AsId", (p[2], None))], p[4], p[5]) + def p_execute_as_id_type_global(p): - '''codeblock : as variable LPAREN ATID RPAREN newlines blocklist else_list end''' - p[0] = execute_block(p.lineno(1), [('AsId', (p[2], p[4]))], p[7], p[8]) + """codeblock : as variable LPAREN ATID RPAREN newlines blocklist else_list end""" + p[0] = execute_block(p.lineno(1), [("AsId", (p[2], p[4]))], p[7], p[8]) + def p_execute_as_id_do_global(p): - '''codeblock : as variable do codeblock else_list''' - p[0] = execute_block(p.lineno(1), [('AsId', (p[2], None))], [p[4]]) + """codeblock : as variable do codeblock else_list""" + p[0] = execute_block(p.lineno(1), [("AsId", (p[2], None))], [p[4]]) + def p_execute_as_id_do_type_global(p): - '''codeblock : as variable LPAREN ATID RPAREN do codeblock''' - p[0] = execute_block(p.lineno(1), [('AsId', (p[2], p[4]))], [p[7]]) + """codeblock : as variable LPAREN ATID RPAREN do codeblock""" + p[0] = execute_block(p.lineno(1), [("AsId", (p[2], p[4]))], [p[7]]) + def p_execute_as_create(p): - '''codeblock : as create_block newlines blocklist else_list end''' - p[0] = execute_block(p.lineno(1), [('AsCreate', p[2])], p[4]) + """codeblock : as create_block newlines blocklist else_list end""" + p[0] = execute_block(p.lineno(1), [("AsCreate", p[2])], p[4]) + def p_execute_as_create_do(p): - '''codeblock : as create_block do codeblock''' - p[0] = execute_block(p.lineno(1), [('AsCreate', p[2])], [p[4]]) - + """codeblock : as create_block do codeblock""" + p[0] = execute_block(p.lineno(1), [("AsCreate", p[2])], [p[4]]) + + def p_execute_chain(p): - '''codeblock : execute_items newlines blocklist else_list end''' - p[0] = execute_block(p.lineno(1), p[1], p[3], p[4]) - + """codeblock : execute_items newlines blocklist else_list end""" + p[0] = execute_block(p.lineno(1), p[1], p[3], p[4]) + + def p_execute_chain_inline(p): - '''codeblock : execute_items do codeblock - | execute_items then codeblock''' - p[0] = execute_block(p.lineno(1), p[1], [p[3]]) + """codeblock : execute_items do codeblock + | execute_items then codeblock""" + p[0] = execute_block(p.lineno(1), p[1], [p[3]]) + -#### Execute Items +#### Execute Items def p_execute_items_one(p): - '''execute_items : execute_item''' - p[0] = [p[1]] - + """execute_items : execute_item""" + p[0] = [p[1]] + + def p_execute_items(p): - '''execute_items : execute_item execute_items''' - p[0] = [p[1]] + p[2] - + """execute_items : execute_item execute_items""" + p[0] = [p[1]] + p[2] + + def p_execute_if_condition(p): - '''execute_item : if conditions''' - p[0] = ('If', p[2]) + """execute_item : if conditions""" + p[0] = ("If", p[2]) + def p_execute_unless_condition(p): - '''execute_item : unless conditions''' - p[0] = ('Unless', p[2]) - + """execute_item : unless conditions""" + p[0] = ("Unless", p[2]) + + def p_execute_as(p): - '''execute_item : as fullselector''' - p[0] = ('As', p[2]) + """execute_item : as fullselector""" + p[0] = ("As", p[2]) + def p_execute_on(p): - '''execute_item : on ID''' - - if p[2] not in [ - 'attacker', - 'controller', - 'leasher', - 'origin', - 'owner', - 'passengers', - 'target', - 'vehicle', - ]: - print(f'Warning: Unknown argument for execute on: "{p[2]}" at line {p.lineno(2)}') - - p[0] = ('On', p[2]) + """execute_item : on ID""" + + if p[2] not in [ + "attacker", + "controller", + "leasher", + "origin", + "owner", + "passengers", + "target", + "vehicle", + ]: + print( + f'Warning: Unknown argument for execute on: "{p[2]}" at line {p.lineno(2)}' + ) + + p[0] = ("On", p[2]) + def p_execute_rotated(p): - '''execute_item : rotated fullselector''' - p[0] = ('Rotated', p[2]) - + """execute_item : rotated fullselector""" + p[0] = ("Rotated", p[2]) + + def p_execute_facing_coords(p): - '''execute_item : facing relcoords''' - p[0] = ('FacingCoords', p[2]) - + """execute_item : facing relcoords""" + p[0] = ("FacingCoords", p[2]) + + def p_execute_facing_entity(p): - '''execute_item : facing fullselector''' - p[0] = ('FacingEntity', p[2]) + """execute_item : facing fullselector""" + p[0] = ("FacingEntity", p[2]) + def p_execute_align(p): - '''execute_item : align ID''' - if p[2] not in ['x','y','z','xy','xz','yz','xyz']: - raise SyntaxError(f'Must align to a combination of x, y, and z axes, not "{p[2]}", at line {p.lineno(2)}') - p[0] = ('Align', p[2]) - + """execute_item : align ID""" + if p[2] not in ["x", "y", "z", "xy", "xz", "yz", "xyz"]: + raise SyntaxError( + f'Must align to a combination of x, y, and z axes, not "{p[2]}", at line {p.lineno(2)}' + ) + p[0] = ("Align", p[2]) + + def p_opt_anchor(p): - '''opt_anchor : eyes - | feet''' - p[0] = p[1] - + """opt_anchor : eyes + | feet""" + p[0] = p[1] + + def p_opt_anchor_empty(p): - '''opt_anchor : empty''' - p[0] = None - + """opt_anchor : empty""" + p[0] = None + + def p_execute_at_selector(p): - '''execute_item : at fullselector opt_anchor''' - p[0] = ('At', (p[2], None, p[3])) - + """execute_item : at fullselector opt_anchor""" + p[0] = ("At", (p[2], None, p[3])) + + def p_execute_at_relcoords(p): - '''execute_item : at opt_anchor relcoords''' - p[0] = ('At', (None, p[3], p[2])) - + """execute_item : at opt_anchor relcoords""" + p[0] = ("At", (None, p[3], p[2])) + + def p_execute_at_selector_relcoords(p): - '''execute_item : at fullselector opt_anchor relcoords''' - p[0] = ('At', (p[2], p[4], p[3])) - + """execute_item : at fullselector opt_anchor relcoords""" + p[0] = ("At", (p[2], p[4], p[3])) + + def p_execute_at_vector(p): - '''execute_item : at vector_expr''' - p[0] = ('AtVector', (None, p[2])) + """execute_item : at vector_expr""" + p[0] = ("AtVector", (None, p[2])) + def p_execute_at_vector_scale(p): - '''execute_item : at LPAREN const_value RPAREN vector_expr''' - p[0] = ('AtVector', (p[3], p[5])) + """execute_item : at LPAREN const_value RPAREN vector_expr""" + p[0] = ("AtVector", (p[3], p[5])) + def p_execute_in_dimension(p): - '''execute_item : in overworld - | in the_end - | in the_nether''' - p[0] = ('In', p[2]) + """execute_item : in overworld + | in the_end + | in the_nether""" + p[0] = ("In", p[2]) -#### For selector + +#### For selector def p_for_selector(p): - '''codeblock : for ATID in fullselector newlines blocklist end''' - p[0] = for_selector_block(p.lineno(1), p[2], p[4], p[6]) + """codeblock : for ATID in fullselector newlines blocklist end""" + p[0] = for_selector_block(p.lineno(1), p[2], p[4], p[6]) + #### Conditions def p_conditions_one(p): - '''conditions : condition''' - p[0] = [p[1]] - + """conditions : condition""" + p[0] = [p[1]] + + def p_conditions(p): - '''conditions : condition and conditions''' - p[0] = [p[1]] + p[3] + """conditions : condition and conditions""" + p[0] = [p[1]] + p[3] + def p_condition_bool_predicate(p): - '''condition : predicate ID''' - p[0] = ('predicate', p[2]) - + """condition : predicate ID""" + p[0] = ("predicate", p[2]) + + def p_condition_fullselector(p): - '''condition : fullselector''' - p[0] = ('selector', p[1]) - + """condition : fullselector""" + p[0] = ("selector", p[1]) + + def p_condition_score(p): - '''condition : expr LT expr - | expr LEQ expr - | expr EQUALEQUAL expr - | expr GT expr - | expr GEQ expr''' - op = p[2] - if op == '==': - op = '=' - p[0] = ('score', (p[1], op, p[3])) + """condition : expr LT expr + | expr LEQ expr + | expr EQUALEQUAL expr + | expr GT expr + | expr GEQ expr""" + op = p[2] + if op == "==": + op = "=" + p[0] = ("score", (p[1], op, p[3])) + def p_condition_vector_equality(p): - '''condition : vector_var EQUALEQUAL vector_var''' - p[0] = ('vector_equality', (p[1], p[3])) + """condition : vector_var EQUALEQUAL vector_var""" + p[0] = ("vector_equality", (p[1], p[3])) + def p_condition_bool(p): - '''condition : expr''' - p[0] = ('score', (p[1], '>', virtualint_var('0'))) + """condition : expr""" + p[0] = ("score", (p[1], ">", virtualint_var("0"))) + def p_condition_not_bool(p): - '''condition : not expr''' - p[0] = ('score', (p[2], '<=', virtualint_var(0))) - + """condition : not expr""" + p[0] = ("score", (p[2], "<=", virtualint_var(0))) + + def p_opt_block_state(p): - '''opt_block_state : LBRACK block_states RBRACK''' - p[0] = p[1] + p[2] + p[3] - + """opt_block_state : LBRACK block_states RBRACK""" + p[0] = p[1] + p[2] + p[3] + + def p_opt_block_state_none(p): - '''opt_block_state : empty''' - p[0] = '' - + """opt_block_state : empty""" + p[0] = "" + + def p_block_states_one(p): - '''block_states : ID EQUALS ID - | ID EQUALS virtualinteger - | facing EQUALS ID - | facing EQUALS virtualinteger''' - p[0] = p[1] + p[2] + p[3] - + """block_states : ID EQUALS ID + | ID EQUALS virtualinteger + | facing EQUALS ID + | facing EQUALS virtualinteger""" + p[0] = p[1] + p[2] + p[3] + + def p_block_states_list(p): - '''block_states : ID EQUALS ID COMMA block_states - | ID EQUALS virtualinteger COMMA block_states - | facing EQUALS ID COMMA block_states - | facing EQUALS virtualinteger COMMA block_states''' - p[0] = p[1] + p[2] + p[3] + p[4] + p[5] - + """block_states : ID EQUALS ID COMMA block_states + | ID EQUALS virtualinteger COMMA block_states + | facing EQUALS ID COMMA block_states + | facing EQUALS virtualinteger COMMA block_states""" + p[0] = p[1] + p[2] + p[3] + p[4] + p[5] + + def p_opt_tile_data(p): - '''opt_tile_data : json_object''' - p[0] = p[1] + """opt_tile_data : json_object""" + p[0] = p[1] + def p_opt_tile_data_empty(p): - '''opt_tile_data : empty''' - p[0] = '' - + """opt_tile_data : empty""" + p[0] = "" + + def p_condition_block(p): - '''condition : block relcoords ID opt_block_state opt_tile_data''' - p[0] = ('block', (p[2], p[3] + p[4] + p[5])) + """condition : block relcoords ID opt_block_state opt_tile_data""" + p[0] = ("block", (p[2], p[3] + p[4] + p[5])) + def p_condition_block_virtual(p): - '''condition : block relcoords DOLLAR ID opt_block_state opt_tile_data''' - p[0] = ('block', (p[2], p[3]+p[4]+p[5]+p[6])) + """condition : block relcoords DOLLAR ID opt_block_state opt_tile_data""" + p[0] = ("block", (p[2], p[3] + p[4] + p[5] + p[6])) + def p_condition_block_nocoords(p): - '''condition : block ID opt_block_state opt_tile_data''' - p[0] = ('block', (relcoords(), p[2] + p[3] + p[4])) + """condition : block ID opt_block_state opt_tile_data""" + p[0] = ("block", (relcoords(), p[2] + p[3] + p[4])) + def p_condition_block_virtual_nocoords(p): - '''condition : block DOLLAR ID opt_block_state opt_tile_data''' - p[0] = ('block', (relcoords(), p[2]+p[3]+p[4]+p[5])) + """condition : block DOLLAR ID opt_block_state opt_tile_data""" + p[0] = ("block", (relcoords(), p[2] + p[3] + p[4] + p[5])) + - def p_condition_nbt_path(p): - '''condition : nbt_object - | nbt_list''' - p[0] = ('nbt_path', p[1]) - + """condition : nbt_object + | nbt_list""" + p[0] = ("nbt_path", p[1]) + + #### If python def p_block_ifelse_command(p): - '''codeblock : if const_value newlines blocklist else newlines blocklist end''' - p[0] = python_if_block(p.lineno(1), p[2], p[4], p[7]) + """codeblock : if const_value newlines blocklist else newlines blocklist end""" + p[0] = python_if_block(p.lineno(1), p[2], p[4], p[7]) + #### While def p_block_while(p): - '''codeblock : while conditions newlines blocklist end''' - p[0] = while_block(p.lineno(1), [('If', p[2])], p[4]) - + """codeblock : while conditions newlines blocklist end""" + p[0] = while_block(p.lineno(1), [("If", p[2])], p[4]) + + def p_block_while_execute(p): - '''codeblock : while conditions execute_items newlines blocklist end''' - p[0] = while_block(p.lineno(1), [('If', p[2])] + p[3], p[5]) + """codeblock : while conditions execute_items newlines blocklist end""" + p[0] = while_block(p.lineno(1), [("If", p[2])] + p[3], p[5]) -#### For + +#### For def p_block_for_index_by(p): - '''codeblock : for variable EQUALS expr to expr by expr newlines blocklist end''' - p[0] = for_index_block(p.lineno(1), p[2], p[4], p[6], p[8], p[10]) - + """codeblock : for variable EQUALS expr to expr by expr newlines blocklist end""" + p[0] = for_index_block(p.lineno(1), p[2], p[4], p[6], p[8], p[10]) + + def p_block_for_index(p): - '''codeblock : for variable EQUALS expr to expr newlines blocklist end''' - p[0] = for_index_block(p.lineno(1), p[2], p[4], p[6], None, p[8]) - + """codeblock : for variable EQUALS expr to expr newlines blocklist end""" + p[0] = for_index_block(p.lineno(1), p[2], p[4], p[6], None, p[8]) + + #### Switch def p_switch(p): - '''codeblock : switch expr newlines cases end''' - p[0] = switch_block(p.lineno(1), p[2], p[4]) - + """codeblock : switch expr newlines cases end""" + p[0] = switch_block(p.lineno(1), p[2], p[4]) + + def p_cases_one(p): - '''cases : switch_case newlines''' - p[0] = [p[1]] - + """cases : switch_case newlines""" + p[0] = [p[1]] + + def p_cases_multiple(p): - '''cases : switch_case newlines cases''' - p[0] = [p[1]] + p[3] - + """cases : switch_case newlines cases""" + p[0] = [p[1]] + p[3] + + def p_switch_case_single(p): - '''switch_case : case const_value newlines blocklist end''' - p[0] = ('range', (p[2], p[2], p[4]), p.lineno(1)) + """switch_case : case const_value newlines blocklist end""" + p[0] = ("range", (p[2], p[2], p[4]), p.lineno(1)) + def p_switch_case_range(p): - '''switch_case : case const_value to const_value newlines blocklist end''' - p[0] = ('range', (p[2], p[4], p[6]), p.lineno(1)) - + """switch_case : case const_value to const_value newlines blocklist end""" + p[0] = ("range", (p[2], p[4], p[6]), p.lineno(1)) + + def p_switch_case_python(p): - '''switch_case : case DOLLAR ID in const_value newlines blocklist end''' - p[0] = ('python', (p[3], p[5], p[7]), p.lineno(1)) + """switch_case : case DOLLAR ID in const_value newlines blocklist end""" + p[0] = ("python", (p[3], p[5], p[7]), p.lineno(1)) + #### Block Switch def p_block_switch(p): - '''codeblock : switch block opt_coords newlines block_cases end''' - p[0] = block_switch_block(p.lineno(1), p[3], p[5], False) - + """codeblock : switch block opt_coords newlines block_cases end""" + p[0] = block_switch_block(p.lineno(1), p[3], p[5], False) + + def p_block_id_switch(p): - '''codeblock : switch block expr newlines block_cases end''' - p[0] = block_id_switch_block(p.lineno(1), p[3], p[5], False) + """codeblock : switch block expr newlines block_cases end""" + p[0] = block_id_switch_block(p.lineno(1), p[3], p[5], False) + def p_block_data_switch(p): - '''codeblock : switch block_data opt_coords newlines block_cases end''' - p[0] = block_switch_block(p.lineno(1), p[3], p[5], True) - + """codeblock : switch block_data opt_coords newlines block_cases end""" + p[0] = block_switch_block(p.lineno(1), p[3], p[5], True) + + def p_block_data_id_switch(p): - '''codeblock : switch block_data expr newlines block_cases end''' - p[0] = block_id_switch_block(p.lineno(1), p[3], p[5], True) - + """codeblock : switch block_data expr newlines block_cases end""" + p[0] = block_id_switch_block(p.lineno(1), p[3], p[5], True) + + def p_opt_coords(p): - '''opt_coords : at relcoords''' - p[0] = p[2] - + """opt_coords : at relcoords""" + p[0] = p[2] + + def p_opt_coords_empty(p): - '''opt_coords : empty''' - p[0] = relcoords() - + """opt_coords : empty""" + p[0] = relcoords() + + def p_block_cases_empty(p): - '''block_cases : empty''' - p[0] = [] - + """block_cases : empty""" + p[0] = [] + + def p_block_cases_multi(p): - '''block_cases : block_case newlines block_cases''' - p[0] = [p[1]] + p[3] + """block_cases : block_case newlines block_cases""" + p[0] = [p[1]] + p[3] + def p_block_case_default(p): - '''block_case : default newlines blocklist end''' - p[0] = block_case(None, None, p[3], True) - + """block_case : default newlines blocklist end""" + p[0] = block_case(None, None, p[3], True) + + def p_block_case_specific(p): - '''block_case : case ID opt_block_properties newlines blocklist end - | case TIMES opt_block_properties newlines blocklist end''' - p[0] = block_case(p[2], p[3], p[5], False) - + """block_case : case ID opt_block_properties newlines blocklist end + | case TIMES opt_block_properties newlines blocklist end""" + p[0] = block_case(p[2], p[3], p[5], False) + + def p_opt_block_properties_empty(p): - '''opt_block_properties : empty''' - p[0] = [] - -def p_opt_block_properties(p): - '''opt_block_properties : LBRACK block_properties RBRACK''' - p[0] = p[2] - + """opt_block_properties : empty""" + p[0] = [] + + +def p_opt_block_properties(p): + """opt_block_properties : LBRACK block_properties RBRACK""" + p[0] = p[2] + + def p_block_property(p): - '''block_property : ID EQUALS ID - | ID EQUALS virtualinteger - | facing EQUALS ID - | facing EQUALS virtualinteger''' - p[0] = (p[1], p[3]) - + """block_property : ID EQUALS ID + | ID EQUALS virtualinteger + | facing EQUALS ID + | facing EQUALS virtualinteger""" + p[0] = (p[1], p[3]) + + def p_block_properties_one(p): - '''block_properties : block_property''' - p[0] = [p[1]] - + """block_properties : block_property""" + p[0] = [p[1]] + + def p_block_properties_multi(p): - '''block_properties : block_property COMMA block_properties''' - p[0] = [p[1]] + p[3] - -#### Tell/Title + """block_properties : block_property COMMA block_properties""" + p[0] = [p[1]] + p[3] + + +#### Tell/Title def p_block_tell(p): - '''codeblock : tell fullselector string''' - p[0] = tell_block(p.lineno(1), p[2], p[3]) - + """codeblock : tell fullselector string""" + p[0] = tell_block(p.lineno(1), p[2], p[3]) + + def p_block_title(p): - '''codeblock : title fullselector string - | subtitle fullselector string - | actionbar fullselector string''' - p[0] = title_block(p.lineno(1), p[1], p[2], None, p[3]) - - + """codeblock : title fullselector string + | subtitle fullselector string + | actionbar fullselector string""" + p[0] = title_block(p.lineno(1), p[1], p[2], None, p[3]) + + def p_block_title_times(p): - '''codeblock : title fullselector const_value const_value const_value string - | subtitle fullselector const_value const_value const_value string - | actionbar fullselector const_value const_value const_value string''' - p[0] = title_block(p.lineno(1), p[1], p[2], (p[3], p[4], p[5]), p[6]) - + """codeblock : title fullselector const_value const_value const_value string + | subtitle fullselector const_value const_value const_value string + | actionbar fullselector const_value const_value const_value string""" + p[0] = title_block(p.lineno(1), p[1], p[2], (p[3], p[4], p[5]), p[6]) + + def p_block_selector_assignment(p): - '''codeblock : selector_assignment - | selector_define_block''' - p[0] = p[1] - - + """codeblock : selector_assignment + | selector_define_block""" + p[0] = p[1] + + def p_block_with_anonymous_block(p): - '''codeblock : with_anonymous_block''' - p[0] = p[1] + """codeblock : with_anonymous_block""" + p[0] = p[1] + def p_block_function_call(p): - '''codeblock : function_call_block - | method_call_block - | template_function_call_block - | macro_call - | pythonassignment - | python_tuple_assignment''' - p[0] = p[1] - + """codeblock : function_call_block + | method_call_block + | template_function_call_block + | macro_call + | pythonassignment + | python_tuple_assignment""" + p[0] = p[1] + + #### Push/pop def p_block_push(p): - '''codeblock : push exprlist''' - p[0] = push_block(p.lineno(1), p[2]) - + """codeblock : push exprlist""" + p[0] = push_block(p.lineno(1), p[2]) + + def p_var_list_one(p): - '''var_list : variable''' - p[0] = [p[1]] - + """var_list : variable""" + p[0] = [p[1]] + + def p_var_list_empty(p): - '''var_list : empty''' - p[0] = [] - + """var_list : empty""" + p[0] = [] + + def p_var_list(p): - '''var_list : variable COMMA var_list''' - p[0] = [p[1]] + p[3] - + """var_list : variable COMMA var_list""" + p[0] = [p[1]] + p[3] + + def p_block_pop(p): - '''codeblock : pop var_list''' - p[0] = pop_block(p.lineno(1), p[2]) - + """codeblock : pop var_list""" + p[0] = pop_block(p.lineno(1), p[2]) + + #### String def p_string(p): - '''string : NORMSTRING''' - p[0] = p[1][1:-1] - + """string : NORMSTRING""" + p[0] = p[1][1:-1] + + #### Number def p_integer(p): - '''integer : DECIMAL - | HEX - | BINARY''' - p[0] = p[1] - + """integer : DECIMAL + | HEX + | BINARY""" + p[0] = p[1] + + def p_integer_minus(p): - '''integer : MINUS DECIMAL - | MINUS HEX - | MINUS BINARY''' - p[0] = str(-int(p[2])) + """integer : MINUS DECIMAL + | MINUS HEX + | MINUS BINARY""" + p[0] = str(-int(p[2])) + def p_number_integer(p): - '''number : integer - | float_val''' - p[0] = p[1] - + """number : integer + | float_val""" + p[0] = p[1] + + def p_float_val(p): - '''float_val : FLOAT''' - p[0] = p[1] - + """float_val : FLOAT""" + p[0] = p[1] + + def p_float_val_minus(p): - '''float_val : MINUS FLOAT''' - p[0] = str(-float(p[2])) - + """float_val : MINUS FLOAT""" + p[0] = str(-float(p[2])) + + #### Qualifier list def p_qualifiers_multiple(p): - '''qualifiers : qualifiers COMMA qualifier - | qualifiers and qualifier''' - p[0] = p[1] + "," + p[3] + """qualifiers : qualifiers COMMA qualifier + | qualifiers and qualifier""" + p[0] = p[1] + "," + p[3] + def p_qualifiers_one(p): - '''qualifiers : qualifier''' - p[0] = p[1] + """qualifiers : qualifier""" + p[0] = p[1] + def p_qualifiers(p): - '''qualifiers : empty''' - p[0] = "" - + """qualifiers : empty""" + p[0] = "" + + #### Qualifier def p_qualifier_binop(p): - '''qualifier : ID EQUALS virtualinteger - | ID EQUALS ID - | name EQUALS ID - | ID EQUALEQUAL virtualinteger - | ID GEQ virtualinteger - | ID LEQ virtualinteger - | ID GT virtualinteger - | ID LT virtualinteger - | ID EQUALS json_object''' - p[0] = p[1] + p[2] + p[3] - + """qualifier : ID EQUALS virtualinteger + | ID EQUALS ID + | name EQUALS ID + | ID EQUALEQUAL virtualinteger + | ID GEQ virtualinteger + | ID LEQ virtualinteger + | ID GT virtualinteger + | ID LT virtualinteger + | ID EQUALS json_object""" + p[0] = p[1] + p[2] + p[3] + + def p_qualifier_builtin(p): - '''qualifier : ID EQUALS virtualnumber DOT DOT virtualnumber - | ID EQUALS DOT DOT virtualnumber - | ID EQUALS virtualnumber DOT DOT''' - p[0] = ''.join(p[1:]) + """qualifier : ID EQUALS virtualnumber DOT DOT virtualnumber + | ID EQUALS DOT DOT virtualnumber + | ID EQUALS virtualnumber DOT DOT""" + p[0] = "".join(p[1:]) + def p_qualifier_empty(p): - '''qualifier : ID EQUALS''' - p[0] = p[1] + p[2] - + """qualifier : ID EQUALS""" + p[0] = p[1] + p[2] + + def p_qualifier_is_not(p): - '''qualifier : ID EQUALS NOT ID''' - p[0] = p[1] + p[2] + p[3] + p[4] + """qualifier : ID EQUALS NOT ID""" + p[0] = p[1] + p[2] + p[3] + p[4] + def p_qualifier_is(p): - '''qualifier : ID''' - p[0] = p[1] + """qualifier : ID""" + p[0] = p[1] + def p_qualifier_not(p): - '''qualifier : not ID''' - p[0] = 'not ' + p[2] + """qualifier : not ID""" + p[0] = "not " + p[2] + #### Full Selector def p_fullselector(p): - '''fullselector : ATID''' - p[0] = f'@{p[1]}[]' + """fullselector : ATID""" + p[0] = f"@{p[1]}[]" + def p_fullselector_qualifiers(p): - '''fullselector : ATID LBRACK virtualinteger RBRACK - | ATID LBRACK qualifiers RBRACK''' - p[0] = f'@{p[1]}[{p[3]}]' - + """fullselector : ATID LBRACK virtualinteger RBRACK + | ATID LBRACK qualifiers RBRACK""" + p[0] = f"@{p[1]}[{p[3]}]" + + #### Relative Coordinates def p_relcoord_number(p): - '''relcoord : const_value''' - p[0] = relcoord('', p[1]) + """relcoord : const_value""" + p[0] = relcoord("", p[1]) + def p_relcoord_relnumber(p): - '''relcoord : TILDE const_value''' - p[0] = relcoord('~', p[2]) - + """relcoord : TILDE const_value""" + p[0] = relcoord("~", p[2]) + + def p_relcoord_relzero(p): - '''relcoord : TILDE - | TILDEEMPTY''' - p[0] = relcoord('~', const_string('')) - + """relcoord : TILDE + | TILDEEMPTY""" + p[0] = relcoord("~", const_string("")) + + # Optional Virtual Number def p_optional_const_value(p): - '''optional_const_value : const_value''' - p[0] = p[1] + """optional_const_value : const_value""" + p[0] = p[1] + def p_optional_const_value_empty(p): - '''optional_const_value : empty''' - p[0] = const_string('') + """optional_const_value : empty""" + p[0] = const_string("") + #### Local Coordinates def p_localcoord_localnumber(p): - '''localcoord : POWER optional_const_value''' - p[0] = relcoord('^', p[2]) - + """localcoord : POWER optional_const_value""" + p[0] = relcoord("^", p[2]) + + # Relcoords def p_relcoords(p): - '''relcoords : relcoord relcoord relcoord - | localcoord localcoord localcoord''' - p[0] = relcoords((p[1], p[2], p[3])) - + """relcoords : relcoord relcoord relcoord + | localcoord localcoord localcoord""" + p[0] = relcoords((p[1], p[2], p[3])) + + def p_relcoords_vector_relative(p): - '''relcoords : TILDE const_vector - | POWER const_vector''' - p[0] = relcoord_vector(p.lineno(1), p[1], p[2]) + """relcoords : TILDE const_vector + | POWER const_vector""" + p[0] = relcoord_vector(p.lineno(1), p[1], p[2]) + def p_relcoords_vector(p): - '''relcoords : const_vector''' - p[0] = relcoord_vector(p.lineno(1), '', p[1]) - - -#### Virtual number + """relcoords : const_vector""" + p[0] = relcoord_vector(p.lineno(1), "", p[1]) + + +#### Virtual number def p_const_value_interpreted(p): - '''const_value : DOLLAR string''' - p[0] = interpreted_python(p[2], p.lineno(1)) - + """const_value : DOLLAR string""" + p[0] = interpreted_python(p[2], p.lineno(1)) + + def p_const_value_expr(p): - '''const_value : pyexpr''' - p[0] = interpreted_python(p[1], p.lineno(1)) - + """const_value : pyexpr""" + p[0] = interpreted_python(p[1], p.lineno(1)) + + def p_const_vector(p): - '''const_vector : LT pyexpr GT %prec VECTOR''' - p[0] = interpreted_python(p[2], p.lineno(1)) - + """const_vector : LT pyexpr GT %prec VECTOR""" + p[0] = interpreted_python(p[2], p.lineno(1)) + + def p_pyexpr_single(p): - '''pyexpr : number - | NORMSTRING''' - p[0] = p[1] - + """pyexpr : number + | NORMSTRING""" + p[0] = p[1] + + def p_pyexpr_binop(p): - '''pyexpr : pyexpr PLUS pyexpr %prec PLUS - | pyexpr MINUS pyexpr %prec MINUS - | pyexpr TIMES pyexpr %prec TIMES - | pyexpr DIVIDE pyexpr %prec DIVIDE - | pyexpr MOD pyexpr %prec MOD - | pyexpr EQUALEQUAL pyexpr %prec COMP - | pyexpr LEQ pyexpr %prec COMP - | pyexpr GEQ pyexpr %prec COMP - | pyexpr LT pyexpr %prec COMP - | pyexpr GT pyexpr %prec COMP''' - p[0] = p[1] + p[2] + p[3] - + """pyexpr : pyexpr PLUS pyexpr %prec PLUS + | pyexpr MINUS pyexpr %prec MINUS + | pyexpr TIMES pyexpr %prec TIMES + | pyexpr DIVIDE pyexpr %prec DIVIDE + | pyexpr MOD pyexpr %prec MOD + | pyexpr EQUALEQUAL pyexpr %prec COMP + | pyexpr LEQ pyexpr %prec COMP + | pyexpr GEQ pyexpr %prec COMP + | pyexpr LT pyexpr %prec COMP + | pyexpr GT pyexpr %prec COMP""" + p[0] = p[1] + p[2] + p[3] + + def p_pyexpr_binop_double(p): - '''pyexpr : pyexpr NOT EQUALS pyexpr %prec COMP - | pyexpr TIMES TIMES pyexpr %prec POWER''' - p[0] = p[1] + p[2] + p[3] + p[4] - + """pyexpr : pyexpr NOT EQUALS pyexpr %prec COMP + | pyexpr TIMES TIMES pyexpr %prec POWER""" + p[0] = p[1] + p[2] + p[3] + p[4] + + def p_pyexpr_binop_spaced(p): - '''pyexpr : pyexpr or pyexpr - | pyexpr and pyexpr''' - p[0] = p[1] + ' ' + p[2] + ' ' + p[3] - + """pyexpr : pyexpr or pyexpr + | pyexpr and pyexpr""" + p[0] = p[1] + " " + p[2] + " " + p[3] + + def p_pyexpr_unary(p): - '''pyexpr : MINUS pyexpr''' - p[0] = p[1] + p[2] - + """pyexpr : MINUS pyexpr""" + p[0] = p[1] + p[2] + + def p_pyexpr_expr_list_empty(p): - '''pyexpr_expr_list : empty''' - p[0] = '' + """pyexpr_expr_list : empty""" + p[0] = "" + def p_pyexpr_expr_list_one(p): - '''pyexpr_expr_list : pyexpr''' - p[0] = p[1] + """pyexpr_expr_list : pyexpr""" + p[0] = p[1] + def p_pyexpr_expr_list_multi(p): - '''pyexpr_expr_list : pyexpr COMMA optnewlines pyexpr_expr_list''' - p[0] = p[1] + p[2] + p[4] - + """pyexpr_expr_list : pyexpr COMMA optnewlines pyexpr_expr_list""" + p[0] = p[1] + p[2] + p[4] + + def p_pyexpr_array(p): - '''pyexpr : LBRACK optnewlines pyexpr_expr_list optnewlines RBRACK - | LPAREN optnewlines pyexpr_expr_list optnewlines RPAREN''' - p[0] = p[1] + p[3] + p[5] - + """pyexpr : LBRACK optnewlines pyexpr_expr_list optnewlines RBRACK + | LPAREN optnewlines pyexpr_expr_list optnewlines RPAREN""" + p[0] = p[1] + p[3] + p[5] + + def p_pyexpr_function_call(p): - '''pyexpr : DOLLAR FUNCTIONID optnewlines pyexpr_expr_list optnewlines RPAREN''' - p[0] = p[2] + '(' + p[4] + p[6] - + """pyexpr : DOLLAR FUNCTIONID optnewlines pyexpr_expr_list optnewlines RPAREN""" + p[0] = p[2] + "(" + p[4] + p[6] + + def p_pyexpr_array_lookup(p): - '''pyexpr : pyexpr LBRACK pyexpr RBRACK''' - p[0] = p[1] + p[2] + p[3] + p[4] - + """pyexpr : pyexpr LBRACK pyexpr RBRACK""" + p[0] = p[1] + p[2] + p[3] + p[4] + + def p_pyexpr_member(p): - '''pyexpr : pyexpr DOT pyexpr''' - p[0] = p[1] + p[2] + p[3] - + """pyexpr : pyexpr DOT pyexpr""" + p[0] = p[1] + p[2] + p[3] + + def p_pyexpr_pyid(p): - '''pyid : DOLLAR ID''' - p[0] = p[2] + """pyid : DOLLAR ID""" + p[0] = p[2] + def p_pyexpr_var(p): - '''pyexpr : pyid''' - p[0] = p[1] - + """pyexpr : pyid""" + p[0] = p[1] + + def p_pymap_pair(p): - '''pymap_pair : pyexpr COLON optnewlines pyexpr''' - p[0] = p[1] + p[2] + p[4] - + """pymap_pair : pyexpr COLON optnewlines pyexpr""" + p[0] = p[1] + p[2] + p[4] + + def p_pymap_pair_list_empty(p): - '''pymap_pair_list : empty''' - p[0] = '' - + """pymap_pair_list : empty""" + p[0] = "" + + def p_pymap_pair_list_one(p): - '''pymap_pair_list : pymap_pair''' - p[0] = p[1] + """pymap_pair_list : pymap_pair""" + p[0] = p[1] + def p_pymap_pair_list(p): - '''pymap_pair_list : pymap_pair COMMA optnewlines pymap_pair_list''' - p[0] = p[1] + p[2] + p[4] - + """pymap_pair_list : pymap_pair COMMA optnewlines pymap_pair_list""" + p[0] = p[1] + p[2] + p[4] + + def p_pyexpr_map(p): - '''pyexpr : LCURLY optnewlines pymap_pair_list optnewlines RCURLY''' - p[0] = p[1] + p[3] + p[5] + """pyexpr : LCURLY optnewlines pymap_pair_list optnewlines RCURLY""" + p[0] = p[1] + p[3] + p[5] + - #### Virtual integer def p_virtualinteger_literal(p): - '''virtualinteger : integer''' - p[0] = p[1] - + """virtualinteger : integer""" + p[0] = p[1] + + def p_virtualinteger_symbol(p): - '''virtualinteger : DOLLAR ID''' - p[0] = '$' + p[2] - + """virtualinteger : DOLLAR ID""" + p[0] = "$" + p[2] + + #### Virtual number def p_virtualnumber_literal(p): - '''virtualnumber : number''' - p[0] = p[1] - + """virtualnumber : number""" + p[0] = p[1] + + def p_virtualnumber_symbol(p): - '''virtualnumber : DOLLAR ID''' - p[0] = '$' + p[2] + """virtualnumber : DOLLAR ID""" + p[0] = "$" + p[2] + #### Block tags def p_blocktag(p): - '''blocktag : define block_tag ID newlines block_list end''' - p[0] = block_tag_block(p.lineno(1), p[3], p[5]) - + """blocktag : define block_tag ID newlines block_list end""" + p[0] = block_tag_block(p.lineno(1), p[3], p[5]) + + def p_block_list(p): - '''block_list : ID newlines block_list''' - p[0] = [p[1]] + p[3] - + """block_list : ID newlines block_list""" + p[0] = [p[1]] + p[3] + + def p_block_list_one(p): - '''block_list : ID newlines''' - p[0] = [p[1]] + """block_list : ID newlines""" + p[0] = [p[1]] + #### Block tags def p_entitytag(p): - '''entitytag : define entity_tag ID newlines entity_list end''' - p[0] = entity_tag_block(p.lineno(1), p[3], p[5]) - + """entitytag : define entity_tag ID newlines entity_list end""" + p[0] = entity_tag_block(p.lineno(1), p[3], p[5]) + + def p_entity_list(p): - '''entity_list : ID newlines entity_list''' - p[0] = [p[1]] + p[3] - + """entity_list : ID newlines entity_list""" + p[0] = [p[1]] + p[3] + + def p_entity_list_one(p): - '''entity_list : ID newlines''' - p[0] = [p[1]] - - + """entity_list : ID newlines""" + p[0] = [p[1]] + + #### Item tags def p_itemtag(p): - '''itemtag : define item_tag ID newlines item_list end''' - p[0] = item_tag_block(p.lineno(1), p[3], p[5]) - + """itemtag : define item_tag ID newlines item_list end""" + p[0] = item_tag_block(p.lineno(1), p[3], p[5]) + + def p_item_list(p): - '''item_list : ID newlines item_list''' - p[0] = [p[1]] + p[3] - + """item_list : ID newlines item_list""" + p[0] = [p[1]] + p[3] + + def p_item_list_one(p): - '''item_list : ID newlines''' - p[0] = [p[1]] + """item_list : ID newlines""" + p[0] = [p[1]] + #### Pointer Declaration def p_pointer_decl(p): - '''pointer_decl : ID COLON fullselector''' - p[0] = pointer_decl_block(p.lineno(0), p[1], p[3]) + """pointer_decl : ID COLON fullselector""" + p[0] = pointer_decl_block(p.lineno(0), p[1], p[3]) + #### Block definition def p_block_define_block(p): - '''block_define_block : define LBRACK ID RBRACK newlines block_definition end''' - p[0] = block_definition_block(p.lineno(1), p[3], p[6], relcoords()) - + """block_define_block : define LBRACK ID RBRACK newlines block_definition end""" + p[0] = block_definition_block(p.lineno(1), p[3], p[6], relcoords()) + + def p_block_define_block_coords(p): - '''block_define_block : define LBRACK ID RBRACK at relcoords newlines block_definition end''' - p[0] = block_definition_block(p.lineno(1), p[3], p[8], p[6]) - + """block_define_block : define LBRACK ID RBRACK at relcoords newlines block_definition end""" + p[0] = block_definition_block(p.lineno(1), p[3], p[8], p[6]) + + def p_block_definition_empty(p): - '''block_definition : empty''' - p[0] = [] - + """block_definition : empty""" + p[0] = [] + + def p_block_definition(p): - '''block_definition : block_item newlines block_definition''' - p[0] = [p[1]] + p[3] - + """block_definition : block_item newlines block_definition""" + p[0] = [p[1]] + p[3] + + def p_block_item_path_noscale(p): - '''block_item : ID COLON data_path data_type''' - p[0] = number_macro_path(p[1], [], p[3], p[4]) - + """block_item : ID COLON data_path data_type""" + p[0] = number_macro_path(p[1], [], p[3], p[4]) + + def p_block_item_path_scale(p): - '''block_item : ID COLON data_path data_type const_value''' - p[0] = number_macro_path(p[1], [], p[3], p[4], p[5]) - + """block_item : ID COLON data_path data_type const_value""" + p[0] = number_macro_path(p[1], [], p[3], p[4], p[5]) + + def p_block_item_macro_path_noscale(p): - '''block_item : ID LBRACK macro_params RBRACK COLON data_path data_type''' - p[0] = number_macro_path(p[1], p[3], p[6], p[7]) + """block_item : ID LBRACK macro_params RBRACK COLON data_path data_type""" + p[0] = number_macro_path(p[1], p[3], p[6], p[7]) + def p_block_item_macro_path_scale(p): - '''block_item : ID LBRACK macro_params RBRACK COLON data_path data_type const_value''' - p[0] = number_macro_path(p[1], p[3], p[6], p[7], p[8]) - + """block_item : ID LBRACK macro_params RBRACK COLON data_path data_type const_value""" + p[0] = number_macro_path(p[1], p[3], p[6], p[7], p[8]) + + #### Selector Assignment def p_uuid(p): - '''uuid : integer MINUS integer MINUS integer MINUS integer MINUS integer''' - p[0] = f'{int(p[1]):X}-{int(p[3]):X}-{int(p[5]):X}-{int(p[7]):X}-{int(p[9]):X}' + """uuid : integer MINUS integer MINUS integer MINUS integer MINUS integer""" + p[0] = ( + f"{int(p[1]):X}-{int(p[3]):X}-{int(p[5]):X}-{int(p[7]):X}-{int(p[9]):X}" + ) + def p_selector_assignment(p): - '''selector_assignment : ATID EQUALS fullselector''' - p[0] = selector_assignment_block(p.lineno(1), p[1], p[3]) - + """selector_assignment : ATID EQUALS fullselector""" + p[0] = selector_assignment_block(p.lineno(1), p[1], p[3]) + + def p_selector_define(p): - '''selector_define_block : define ATID EQUALS fullselector newlines selector_definition end - | define ATID COLON fullselector newlines selector_definition end''' - p[0] = selector_definition_block(p.lineno(1), p[2], p[4], None, p[6]) - + """selector_define_block : define ATID EQUALS fullselector newlines selector_definition end + | define ATID COLON fullselector newlines selector_definition end""" + p[0] = selector_definition_block(p.lineno(1), p[2], p[4], None, p[6]) + + def p_selector_define_uuid(p): - '''selector_define_block : define ATID COLON uuid LPAREN fullselector RPAREN newlines selector_definition end''' - p[0] = selector_definition_block(p.lineno(1), p[2], p[6], p[4], p[9]) + """selector_define_block : define ATID COLON uuid LPAREN fullselector RPAREN newlines selector_definition end""" + p[0] = selector_definition_block(p.lineno(1), p[2], p[6], p[4], p[9]) + def p_selector_definition_empty(p): - '''selector_definition : empty''' - p[0] = [] - + """selector_definition : empty""" + p[0] = [] + + def p_selector_definition(p): - '''selector_definition : selector_item newlines selector_definition''' - p[0] = [p[1]] + p[3] - + """selector_definition : selector_item newlines selector_definition""" + p[0] = [p[1]] + p[3] + + def p_selector_item_tag(p): - '''selector_item : create json_object''' - p[0] = ('Tag', p[2]) - + """selector_item : create json_object""" + p[0] = ("Tag", p[2]) + + def p_selector_item_path_scale(p): - '''selector_item : ID EQUALS data_path data_type const_value - | ID COLON data_path data_type const_value''' - p[0] = ('Path', (p[1], p[3], p[4], p[5])) - + """selector_item : ID EQUALS data_path data_type const_value + | ID COLON data_path data_type const_value""" + p[0] = ("Path", (p[1], p[3], p[4], p[5])) + + def p_selector_item_path(p): - '''selector_item : ID EQUALS data_path data_type - | ID COLON data_path data_type''' - p[0] = ('Path', (p[1], p[3], p[4], None)) + """selector_item : ID EQUALS data_path data_type + | ID COLON data_path data_type""" + p[0] = ("Path", (p[1], p[3], p[4], None)) + def p_selector_item_vector_path_scale(p): - '''selector_item : LT ID GT EQUALS data_path data_type const_value - | LT ID GT COLON data_path data_type const_value''' - p[0] = ('VectorPath', (p[2], p[5], p[6], p[7])) + """selector_item : LT ID GT EQUALS data_path data_type const_value + | LT ID GT COLON data_path data_type const_value""" + p[0] = ("VectorPath", (p[2], p[5], p[6], p[7])) + def p_selector_item_vector_path(p): - '''selector_item : LT ID GT EQUALS data_path data_type - | LT ID GT COLON data_path data_type''' - p[0] = ('VectorPath', (p[2], p[5], p[6], None)) - + """selector_item : LT ID GT EQUALS data_path data_type + | LT ID GT COLON data_path data_type""" + p[0] = ("VectorPath", (p[2], p[5], p[6], None)) + + def p_selector_item_method(p): - '''selector_item : functionsection''' - p[0] = ('Method', p[1]) - + """selector_item : functionsection""" + p[0] = ("Method", p[1]) + + def p_selector_pointer(p): - '''selector_item : ID EQUALS fullselector - | ID COLON fullselector''' - p[0] = ('Pointer', (p[1], p[3])) - + """selector_item : ID EQUALS fullselector + | ID COLON fullselector""" + p[0] = ("Pointer", (p[1], p[3])) + + def p_selector_array(p): - '''selector_item : array_definition''' - p[1].selector_based = True - p[0] = ('Array', p[1]) - + """selector_item : array_definition""" + p[1].selector_based = True + p[0] = ("Array", p[1]) + + def p_selector_predicate(p): - '''selector_item : predicate_definition''' - p[0] = ('Predicate', p[1]) - + """selector_item : predicate_definition""" + p[0] = ("Predicate", p[1]) + + def p_data_path_id(p): - '''data_path : ID - | facing''' - p[0] = p[1] - + """data_path : ID + | facing""" + p[0] = p[1] + + def p_data_path_array(p): - '''data_path : ID LBRACK virtualinteger RBRACK''' - p[0] = f'{p[1]}[{p[3]}]' - + """data_path : ID LBRACK virtualinteger RBRACK""" + p[0] = f"{p[1]}[{p[3]}]" + + def p_data_path_array_match(p): - '''data_path : ID LBRACK json_object RBRACK''' - p[0] = p[1] + p[2] + p[3] + p[4] - + """data_path : ID LBRACK json_object RBRACK""" + p[0] = p[1] + p[2] + p[3] + p[4] + + def p_data_path_object_match(p): - '''data_path : ID json_object''' - p[0] = p[1] + p[2] - + """data_path : ID json_object""" + p[0] = p[1] + p[2] + + def p_data_path_multi(p): - '''data_path : data_path DOT data_path''' - p[0] = f'{p[1]}.{p[3]}' - + """data_path : data_path DOT data_path""" + p[0] = f"{p[1]}.{p[3]}" + + def p_data_type(p): - '''data_type : ID''' - if p[1] not in ['byte', 'double', 'float', 'int', 'long', 'short']: - raise SyntaxError(f'Syntax Error: Invalid path type "{{}}" at line {p.lineno(1)}.') - p[0] = p[1] - + """data_type : ID""" + if p[1] not in ["byte", "double", "float", "int", "long", "short"]: + raise SyntaxError( + f'Syntax Error: Invalid path type "{{}}" at line {p.lineno(1)}.' + ) + p[0] = p[1] + + #### Array def p_array_definition(p): - '''array_definition : array ID LBRACK const_value RBRACK''' - p[0] = array_definition_block(p.lineno(1), p[2], const_number(0), p[4], False) - + """array_definition : array ID LBRACK const_value RBRACK""" + p[0] = array_definition_block( + p.lineno(1), p[2], const_number(0), p[4], False + ) + + def p_array_definition_range(p): - '''array_definition : array ID LBRACK const_value to const_value RBRACK''' - p[0] = array_definition_block(p.lineno(1), p[2], p[4], p[6], False) - + """array_definition : array ID LBRACK const_value to const_value RBRACK""" + p[0] = array_definition_block(p.lineno(1), p[2], p[4], p[6], False) + + #### Create def p_block_create(p): - '''codeblock : create_block''' - p[0] = p[1] - + """codeblock : create_block""" + p[0] = p[1] + + def p_create(p): - '''create_block : create ATID relcoords''' - p[0] = create_block(p.lineno(1), p[2], p[3], None) - + """create_block : create ATID relcoords""" + p[0] = create_block(p.lineno(1), p[2], p[3], None) + + def p_create_nocoords(p): - '''create_block : create ATID''' - p[0] = create_block(p.lineno(1), p[2], relcoords(), None) + """create_block : create ATID""" + p[0] = create_block(p.lineno(1), p[2], relcoords(), None) + def p_create_index(p): - '''create_block : create ATID LBRACK const_value RBRACK relcoords''' - p[0] = create_block(p.lineno(1), p[2], p[6], p[4]) - + """create_block : create ATID LBRACK const_value RBRACK relcoords""" + p[0] = create_block(p.lineno(1), p[2], p[6], p[4]) + + def p_create_index_nocoords(p): - '''create_block : create ATID LBRACK const_value RBRACK''' - p[0] = create_block(p.lineno(1), p[2], relcoords(), p[4]) + """create_block : create ATID LBRACK const_value RBRACK""" + p[0] = create_block(p.lineno(1), p[2], relcoords(), p[4]) + #### Define name def p_define_name(p): - '''codeblock : define name ID EQUALS NORMSTRING''' - p[0] = define_name_block(p.lineno(1), p[3], p[5]) - + """codeblock : define name ID EQUALS NORMSTRING""" + p[0] = define_name_block(p.lineno(1), p[3], p[5]) + + #### Python Assignment def p_pythonassignment_interpreted_string(p): - '''pythonassignment : DOLLAR ID EQUALS const_value''' - p[0] = python_assignment_block(p.lineno(1), p[2], p[4]) - + """pythonassignment : DOLLAR ID EQUALS const_value""" + p[0] = python_assignment_block(p.lineno(1), p[2], p[4]) + + #### Python Tuple Assignment def p_python_tuple_two(p): - '''python_tuple : DOLLAR ID COMMA DOLLAR ID''' - p[0] = [p[2], p[5]] - + """python_tuple : DOLLAR ID COMMA DOLLAR ID""" + p[0] = [p[2], p[5]] + + def p_python_tuple_multi(p): - '''python_tuple : DOLLAR ID COMMA python_tuple''' - p[0] = [p[2]] + p[4] - + """python_tuple : DOLLAR ID COMMA python_tuple""" + p[0] = [p[2]] + p[4] + + def p_python_tuple_assignment(p): - '''python_tuple_assignment : python_tuple EQUALS const_value''' - p[0] = python_tuple_assignment_block(p.lineno(1), p[1], p[3]) + """python_tuple_assignment : python_tuple EQUALS const_value""" + p[0] = python_tuple_assignment_block(p.lineno(1), p[1], p[3]) + #### NBT Assignment def p_nbt_assignment(p): - '''codeblock : nbt_list EQUALS nbt_source - | nbt_object EQUALS nbt_source''' - p[0] = nbt_data_block(p.lineno(1), p[1], 'set', p[3]) - + """codeblock : nbt_list EQUALS nbt_source + | nbt_object EQUALS nbt_source""" + p[0] = nbt_data_block(p.lineno(1), p[1], "set", p[3]) + + def p_nbt_merge(p): - '''codeblock : nbt_object PLUSEQUALS nbt_source''' - p[0] = nbt_data_block(p.lineno(1), p[1], 'merge', p[3]) - + """codeblock : nbt_object PLUSEQUALS nbt_source""" + p[0] = nbt_data_block(p.lineno(1), p[1], "merge", p[3]) + + def p_nbt_append(p): - '''codeblock : nbt_list PLUSEQUALS nbt_source''' - p[0] = nbt_data_block(p.lineno(1), p[1], 'append', p[3]) - + """codeblock : nbt_list PLUSEQUALS nbt_source""" + p[0] = nbt_data_block(p.lineno(1), p[1], "append", p[3]) + + def p_nbt_list_entity(p): - '''nbt_list : fullselector DOT LBRACK data_path RBRACK''' - p[0] = entity_nbt_path(p[1], p[4]) + """nbt_list : fullselector DOT LBRACK data_path RBRACK""" + p[0] = entity_nbt_path(p[1], p[4]) + def p_nbt_list_storage(p): - '''nbt_list : COLON LBRACK data_path RBRACK''' - p[0] = storage_nbt_path(None, p[3]) - + """nbt_list : COLON LBRACK data_path RBRACK""" + p[0] = storage_nbt_path(None, p[3]) + + def p_nbt_list_storage_target(p): - '''nbt_list : ID COLON LBRACK data_path RBRACK''' - p[0] = storage_nbt_path(p[1], p[4]) - + """nbt_list : ID COLON LBRACK data_path RBRACK""" + p[0] = storage_nbt_path(p[1], p[4]) + + def p_nbt_list_block(p): - '''nbt_list : block_coords DOT LBRACK data_path RBRACK''' - p[0] = block_nbt_path(p[1], p[4]) - + """nbt_list : block_coords DOT LBRACK data_path RBRACK""" + p[0] = block_nbt_path(p[1], p[4]) + + def p_nbt_object_entity(p): - '''nbt_object : fullselector DOT LCURLY data_path RCURLY''' - p[0] = entity_nbt_path(p[1], p[4]) - + """nbt_object : fullselector DOT LCURLY data_path RCURLY""" + p[0] = entity_nbt_path(p[1], p[4]) + + def p_nbt_object_storage(p): - '''nbt_object : COLON LCURLY data_path RCURLY''' - p[0] = storage_nbt_path(None, p[3]) - + """nbt_object : COLON LCURLY data_path RCURLY""" + p[0] = storage_nbt_path(None, p[3]) + + def p_nbt_object_storage_target(p): - '''nbt_object : ID COLON LCURLY data_path RCURLY''' - p[0] = storage_nbt_path(p[1], p[4]) - + """nbt_object : ID COLON LCURLY data_path RCURLY""" + p[0] = storage_nbt_path(p[1], p[4]) + + def p_nbt_object_block(p): - '''nbt_object : block_coords DOT LCURLY data_path RCURLY''' - p[0] = block_nbt_path(p[1], p[4]) - + """nbt_object : block_coords DOT LCURLY data_path RCURLY""" + p[0] = block_nbt_path(p[1], p[4]) + + def p_nbt_source_path_entity(p): - '''nbt_path : fullselector DOT data_path''' - p[0] = entity_nbt_path(p[1], p[3]) + """nbt_path : fullselector DOT data_path""" + p[0] = entity_nbt_path(p[1], p[3]) + def p_nbt_source_path_storage(p): - '''nbt_object : COLON data_path''' - p[0] = storage_nbt_path(None, p[2]) - + """nbt_object : COLON data_path""" + p[0] = storage_nbt_path(None, p[2]) + + def p_nbt_source_path_storage_target(p): - '''nbt_object : ID COLON data_path''' - p[0] = storage_nbt_path(p[1], p[3]) - + """nbt_object : ID COLON data_path""" + p[0] = storage_nbt_path(p[1], p[3]) + + def p_nbt_source_path_block(p): - '''nbt_path : block_coords DOT data_path''' - p[0] = block_nbt_path(p[1], p[3]) - + """nbt_path : block_coords DOT data_path""" + p[0] = block_nbt_path(p[1], p[3]) + + def p_nbt_path(p): - '''nbt_path : nbt_object - | nbt_list''' - p[0] = p[1] - + """nbt_path : nbt_object + | nbt_list""" + p[0] = p[1] + + def p_nbt_source_object(p): - '''nbt_source : nbt_path''' - p[0] = p[1] - + """nbt_source : nbt_path""" + p[0] = p[1] + + def p_nbt_source_json(p): - '''nbt_source : json_object''' - p[0] = nbt_json(p[1]) + """nbt_source : json_object""" + p[0] = nbt_json(p[1]) + def p_nbt_source_string(p): - '''nbt_source : NORMSTRING''' - p[0] = nbt_json(p[1]) - + """nbt_source : NORMSTRING""" + p[0] = nbt_json(p[1]) + + def p_block_coords(p): - '''block_coords : LBRACK relcoords RBRACK''' - p[0] = p[2] - + """block_coords : LBRACK relcoords RBRACK""" + p[0] = p[2] + + def p_block_coords_empty(p): - '''block_coords : LBRACK RBRACK''' - p[0] = relcoords() - + """block_coords : LBRACK RBRACK""" + p[0] = relcoords() + + def p_nbt_remove(p): - '''codeblock : remove nbt_path''' - p[0] = nbt_remove_block(p.lineno(1), p[2]) + """codeblock : remove nbt_path""" + p[0] = nbt_remove_block(p.lineno(1), p[2]) + - #### Assignment def p_return_expression(p): - '''codeblock : return expr''' - p[0] = scoreboard_assignment_block(p.lineno(1), scoreboard_var('Global', 'ReturnValue'), '=', p[2]) - + """codeblock : return expr""" + p[0] = scoreboard_assignment_block( + p.lineno(1), scoreboard_var("Global", "ReturnValue"), "=", p[2] + ) + + def p_assignment(p): - '''codeblock : variable EQUALS expr - | variable PLUSEQUALS expr - | variable MINUSEQUALS expr - | variable TIMESEQUALS expr - | variable DIVIDEEQUALS expr - | variable MODEQUALS expr''' - p[0] = scoreboard_assignment_block(p.lineno(1), p[1], p[2], p[3]) - + """codeblock : variable EQUALS expr + | variable PLUSEQUALS expr + | variable MINUSEQUALS expr + | variable TIMESEQUALS expr + | variable DIVIDEEQUALS expr + | variable MODEQUALS expr""" + p[0] = scoreboard_assignment_block(p.lineno(1), p[1], p[2], p[3]) + + def p_assignment_unary_default(p): - '''codeblock : variable PLUSPLUS - | variable MINUSMINUS''' - op = p[2][0]+'=' - operand = virtualint_var('1') - p[0] = scoreboard_assignment_block(p.lineno(1), p[1], op, operand) + """codeblock : variable PLUSPLUS + | variable MINUSMINUS""" + op = p[2][0] + "=" + operand = virtualint_var("1") + p[0] = scoreboard_assignment_block(p.lineno(1), p[1], op, operand) + def p_assignment_create(p): - '''codeblock : variable EQUALS create_block''' - p[0] = scoreboard_assignment_block(p.lineno(1), p[1], p[2], create_expr(p[3])) - + """codeblock : variable EQUALS create_block""" + p[0] = scoreboard_assignment_block( + p.lineno(1), p[1], p[2], create_expr(p[3]) + ) + + #### Vector assignment def p_vector_assignment_vector(p): - '''codeblock : vector_var EQUALS vector_expr - | vector_var PLUSEQUALS vector_expr - | vector_var MINUSEQUALS vector_expr''' - p[0] = vector_assignment_block(p.lineno(1), p[1], p[2], p[3]) - + """codeblock : vector_var EQUALS vector_expr + | vector_var PLUSEQUALS vector_expr + | vector_var MINUSEQUALS vector_expr""" + p[0] = vector_assignment_block(p.lineno(1), p[1], p[2], p[3]) + + def p_vector_assignment_scalar(p): - '''codeblock : vector_var EQUALS expr - | vector_var PLUSEQUALS expr - | vector_var MINUSEQUALS expr - | vector_var TIMESEQUALS expr - | vector_var DIVIDEEQUALS expr - | vector_var MODEQUALS expr''' - p[0] = vector_assignment_scalar_block(p.lineno(1), p[1], p[2], p[3]) - + """codeblock : vector_var EQUALS expr + | vector_var PLUSEQUALS expr + | vector_var MINUSEQUALS expr + | vector_var TIMESEQUALS expr + | vector_var DIVIDEEQUALS expr + | vector_var MODEQUALS expr""" + p[0] = vector_assignment_scalar_block(p.lineno(1), p[1], p[2], p[3]) + + #### Vector LHS def p_vector_var_id(p): - '''vector_var : LT ID GT''' - p[0] = ('VAR_ID', p[2]) + """vector_var : LT ID GT""" + p[0] = ("VAR_ID", p[2]) + def p_vector_var_sel_id(p): - '''vector_var : fullselector DOT LT ID GT''' - p[0] = ('SEL_VAR_ID', (p[1], p[4])) - -def p_vector_var_components(p): - '''vector_var : LT variable COMMA variable COMMA variable GT''' - p[0] = ('VAR_COMPONENTS', [p[2], p[4], p[6]]) - + """vector_var : fullselector DOT LT ID GT""" + p[0] = ("SEL_VAR_ID", (p[1], p[4])) + + +def p_vector_var_components(p): + """vector_var : LT variable COMMA variable COMMA variable GT""" + p[0] = ("VAR_COMPONENTS", [p[2], p[4], p[6]]) + + def p_vector_var_const_vector(p): - '''vector_var : const_vector''' - p[0] = ('VAR_CONST', p[1]) + """vector_var : const_vector""" + p[0] = ("VAR_CONST", p[1]) + #### Arithmetic expressions def p_expr_var(p): - '''expr : variable''' - p[0] = p[1] + """expr : variable""" + p[0] = p[1] + def p_expr_binary(p): - '''expr : expr PLUS expr - | expr MINUS expr - | expr TIMES expr - | expr DIVIDE expr - | expr MOD expr''' - - p[0] = binop_expr(p[1], p[2], p[3]) - + """expr : expr PLUS expr + | expr MINUS expr + | expr TIMES expr + | expr DIVIDE expr + | expr MOD expr""" + + p[0] = binop_expr(p[1], p[2], p[3]) + + def p_expr_power(p): - '''expr : expr POWER integer''' - p[0] = binop_expr(p[1], p[2], virtualint_var(p[3])) - + """expr : expr POWER integer""" + p[0] = binop_expr(p[1], p[2], virtualint_var(p[3])) + + def p_expr_dot(p): - '''expr : vector_expr TIMES vector_expr''' - p[0] = dot_expr(p[1], p[3]) + """expr : vector_expr TIMES vector_expr""" + p[0] = dot_expr(p[1], p[3]) + def p_expr_function(p): - '''expr : function_call''' - p[0] = func_expr(p[1]) + """expr : function_call""" + p[0] = func_expr(p[1]) + def p_expr_method(p): - '''expr : method_call''' - p[0] = method_expr(p[1]) - + """expr : method_call""" + p[0] = method_expr(p[1]) + + def p_expr_group(p): - '''expr : LPAREN expr RPAREN''' - p[0] = p[2] + """expr : LPAREN expr RPAREN""" + p[0] = p[2] + def p_expr_unary(p): - '''expr : MINUS expr %prec UMINUS''' - p[0] = unary_expr('-', p[2]) - - + """expr : MINUS expr %prec UMINUS""" + p[0] = unary_expr("-", p[2]) + + ### Vector expressions def p_vector_expr_group(p): - '''vector_expr : LPAREN vector_expr RPAREN''' - p[0] = p[2] + """vector_expr : LPAREN vector_expr RPAREN""" + p[0] = p[2] + def p_vector_expr_vector_triplet(p): - '''vector_expr : LT expr COMMA expr COMMA expr GT''' - p[0] = vector_expr((p[2], p[4], p[6])) - + """vector_expr : LT expr COMMA expr COMMA expr GT""" + p[0] = vector_expr((p[2], p[4], p[6])) + + def p_vector_expr_vector_unit(p): - '''vector_expr : LT ID GT''' - p[0] = vector_var_expr(p[2]) - + """vector_expr : LT ID GT""" + p[0] = vector_var_expr(p[2]) + + def p_vector_expr_const_vector(p): - '''vector_expr : const_vector''' - p[0] = vector_var_const_vector(p[1]) - + """vector_expr : const_vector""" + p[0] = vector_var_const_vector(p[1]) + + def p_vector_expr_selector_vector(p): - '''vector_expr : fullselector DOT LT ID GT''' - p[0] = sel_vector_var_expr(p[1], p[4]) - + """vector_expr : fullselector DOT LT ID GT""" + p[0] = sel_vector_var_expr(p[1], p[4]) + + def p_vector_expr_binop_vector(p): - '''vector_expr : vector_expr PLUS vector_expr - | vector_expr MINUS vector_expr''' - p[0] = vector_binop_vector_expr(p[1], p[2], p[3]) - + """vector_expr : vector_expr PLUS vector_expr + | vector_expr MINUS vector_expr""" + p[0] = vector_binop_vector_expr(p[1], p[2], p[3]) + + def p_vector_expr_binop_scalar(p): - '''vector_expr : vector_expr PLUS expr - | vector_expr MINUS expr - | vector_expr TIMES expr - | vector_expr DIVIDE expr - | vector_expr MOD expr''' - p[0] = vector_binop_scalar_expr(p[1], p[2], p[3]) - + """vector_expr : vector_expr PLUS expr + | vector_expr MINUS expr + | vector_expr TIMES expr + | vector_expr DIVIDE expr + | vector_expr MOD expr""" + p[0] = vector_binop_scalar_expr(p[1], p[2], p[3]) + + def p_vector_expr_binop_scalar_reversed(p): - '''vector_expr : expr PLUS vector_expr - | expr TIMES vector_expr''' - p[0] = vector_binop_scalar_expr(p[3], p[2], p[1]) - + """vector_expr : expr PLUS vector_expr + | expr TIMES vector_expr""" + p[0] = vector_binop_scalar_expr(p[3], p[2], p[1]) + + def p_vector_expr_negative(p): - '''vector_expr : MINUS vector_expr''' - p[0] = vector_binop_scalar_expr(p[2], '*', virtualint_var(-1)) - + """vector_expr : MINUS vector_expr""" + p[0] = vector_binop_scalar_expr(p[2], "*", virtualint_var(-1)) + + def p_vector_expr_here(p): - '''vector_expr : here''' - p[0] = vector_here_expr(None) + """vector_expr : here""" + p[0] = vector_here_expr(None) + def p_vector_expr_here_scale(p): - '''vector_expr : here LPAREN const_value RPAREN''' - p[0] = vector_here_expr(p[3]) - + """vector_expr : here LPAREN const_value RPAREN""" + p[0] = vector_here_expr(p[3]) + + #### Json (can't implement until COLON is an available token) def p_json_object(p): - '''json_object : LCURLY optnewlines json_members optnewlines RCURLY''' - p[0] = p[1] + p[3] + p[5] - + """json_object : LCURLY optnewlines json_members optnewlines RCURLY""" + p[0] = p[1] + p[3] + p[5] + + def p_json_members(p): - '''json_members : json_pair''' - p[0] = p[1] - + """json_members : json_pair""" + p[0] = p[1] + + def p_json_members_multi(p): - '''json_members : json_pair COMMA optnewlines json_members''' - p[0] = p[1] + p[2] + p[4] - + """json_members : json_pair COMMA optnewlines json_members""" + p[0] = p[1] + p[2] + p[4] + + def p_json_members_empty(p): - '''json_members : empty''' - p[0] = '' - + """json_members : empty""" + p[0] = "" + + def p_json_pair(p): - '''json_pair : ID COLON optnewlines json_value - | string COLON optnewlines json_value - | facing COLON optnewlines json_value - | block COLON optnewlines json_value - | predicate COLON optnewlines json_value''' - p[0] = '"' + p[1] + '"' + p[2] + p[4] - + """json_pair : ID COLON optnewlines json_value + | string COLON optnewlines json_value + | facing COLON optnewlines json_value + | block COLON optnewlines json_value + | predicate COLON optnewlines json_value""" + p[0] = '"' + p[1] + '"' + p[2] + p[4] + + def p_json_value(p): - '''json_value : number - | json_object - | json_array - | json_literal_array - | true - | false''' - p[0] = p[1] - + """json_value : number + | json_object + | json_array + | json_literal_array + | true + | false""" + p[0] = p[1] + + def p_json_value_dollar_id(p): - '''json_value : DOLLAR ID''' - p[0] = p[1] + p[2] - + """json_value : DOLLAR ID""" + p[0] = p[1] + p[2] + + def p_json_value_typed_number(p): - '''json_value : number ID''' - if p[2].lower() not in ['b', 'f', 's', 'd', 'l']: - raise SyntaxError(f'Invalid type "{p[2]}" for number "{p[1]}" at line {p.lineno(1)}') - - p[0] = p[1] + p[2] - + """json_value : number ID""" + if p[2].lower() not in ["b", "f", "s", "d", "l"]: + raise SyntaxError( + f'Invalid type "{p[2]}" for number "{p[1]}" at line {p.lineno(1)}' + ) + + p[0] = p[1] + p[2] + + def p_json_value_string(p): - '''json_value : string''' - p[0] = '"' + p[1] + '"' - + """json_value : string""" + p[0] = '"' + p[1] + '"' + + def p_json_array(p): - '''json_array : LBRACK optnewlines json_elements optnewlines RBRACK''' - p[0] = p[1] + p[3] + p[5] - + """json_array : LBRACK optnewlines json_elements optnewlines RBRACK""" + p[0] = p[1] + p[3] + p[5] + + def p_json_elements(p): - '''json_elements : json_value''' - p[0] = p[1] - + """json_elements : json_value""" + p[0] = p[1] + + def p_json_elements_multi(p): - '''json_elements : json_value COMMA optnewlines json_elements''' - p[0] = p[1] + p[2] + p[4] - + """json_elements : json_value COMMA optnewlines json_elements""" + p[0] = p[1] + p[2] + p[4] + + def p_json_elements_empty(p): - '''json_elements : empty''' - p[0] = '' + """json_elements : empty""" + p[0] = "" + def p_json_literal_array(p): - '''json_literal_array : LBRACK optnewlines ID SEMICOLON optnewlines json_literal_elements optnewlines RBRACK''' - if p[3].lower() not in ['b', 'i', 'l']: - raise SyntaxError(f'Invalid type "{p[3]}" for literal array at line {p.lineno(1)}') + """json_literal_array : LBRACK optnewlines ID SEMICOLON optnewlines json_literal_elements optnewlines RBRACK""" + if p[3].lower() not in ["b", "i", "l"]: + raise SyntaxError( + f'Invalid type "{p[3]}" for literal array at line {p.lineno(1)}' + ) + + p[0] = p[1] + p[3] + p[4] + p[6] + p[8] - p[0] = p[1] + p[3] + p[4] + p[6] + p[8] def p_json_literal_element_one(p): - '''json_literal_elements : json_literal_value''' - p[0] = p[1] - + """json_literal_elements : json_literal_value""" + p[0] = p[1] + + def p_json_literal_elements_multi(p): - '''json_literal_elements : json_literal_value COMMA optnewlines json_literal_elements''' - p[0] = p[1] + p[2] + p[4] - + """json_literal_elements : json_literal_value COMMA optnewlines json_literal_elements""" + p[0] = p[1] + p[2] + p[4] + + def p_json_literal_elements_empty(p): - '''json_literal_elements : empty''' - p[0] = '' + """json_literal_elements : empty""" + p[0] = "" + def p_json_literal_value(p): - '''json_literal_value : number''' - p[0] = p[1] - + """json_literal_value : number""" + p[0] = p[1] + + def p_json_literal_value_dollar_id(p): - '''json_literal_value : DOLLAR ID''' - p[0] = p[1] + p[2] - + """json_literal_value : DOLLAR ID""" + p[0] = p[1] + p[2] + + #### Crafting recipes def p_shaped_recipe(p): - '''shaped_recipe : shaped recipe newlines recipe_lines keys newlines recipe_key_list end newlines result COLON const_value ID newlines end''' - p[0] = shaped_recipe_block(p.lineno(1), p[4], p[7], p[12], p[13]) - + """shaped_recipe : shaped recipe newlines recipe_lines keys newlines recipe_key_list end newlines result COLON const_value ID newlines end""" + p[0] = shaped_recipe_block(p.lineno(1), p[4], p[7], p[12], p[13]) + + def p_recipe_lines(p): - '''recipe_lines : string newlines recipe_lines''' - p[0] = [p[1]] + p[3] - + """recipe_lines : string newlines recipe_lines""" + p[0] = [p[1]] + p[3] + + def p_recipe_lines_empty(p): - '''recipe_lines : empty''' - p[0] = [] + """recipe_lines : empty""" + p[0] = [] + def p_recipe_key_item(p): - '''recipe_key_item : ID EQUALS ID COLON ID''' - if len(p[1]) != 1: - raise SyntaxError(f'Recipe key "{p[1]}" at line {p.lineno(1)} is not a single character.') - - if p[3] not in ['item', 'tag']: - raise SyntaxError(f'Recipe key type "{p[3]}" at line {p.lineno(1)} must be "block" or "tag".') - - p[0] = (p[1], p[3], p[5]) - + """recipe_key_item : ID EQUALS ID COLON ID""" + if len(p[1]) != 1: + raise SyntaxError( + f'Recipe key "{p[1]}" at line {p.lineno(1)} is not a single character.' + ) + + if p[3] not in ["item", "tag"]: + raise SyntaxError( + f'Recipe key type "{p[3]}" at line {p.lineno(1)} must be "block" or "tag".' + ) + + p[0] = (p[1], p[3], p[5]) + + def p_recipe_key_list(p): - '''recipe_key_list : recipe_key_item newlines recipe_key_list''' - p[0] = [p[1]] + p[3] - + """recipe_key_list : recipe_key_item newlines recipe_key_list""" + p[0] = [p[1]] + p[3] + + def p_recipe_key_list_empty(p): - '''recipe_key_list : empty''' - p[0] = [] - + """recipe_key_list : empty""" + p[0] = [] + + #### Advancements def p_advancement_definition(p): - '''advancement_definition : advancement ID json_object''' - p[0] = advancement_definition_block(p.lineno(1), p[2], p[3]) - + """advancement_definition : advancement ID json_object""" + p[0] = advancement_definition_block(p.lineno(1), p[2], p[3]) #### Loot Tables def p_loot_table_type(p): - '''loot_table_type : block''' - types = { - 'block': 'blocks', - } - if p[1] not in types: - raise SyntaxError(f'Invalid loot table type "{p[1]}" at line {p.lineno(1)}.') - - p[0] = types[p[1]] - + """loot_table_type : block""" + types = { + "block": "blocks", + } + if p[1] not in types: + raise SyntaxError( + f'Invalid loot table type "{p[1]}" at line {p.lineno(1)}.' + ) + + p[0] = types[p[1]] + + def p_loot_table_definition(p): - '''loot_table_definition : loot_table loot_table_type ID json_object''' - p[0] = loot_table_definition_block(p.lineno(1), p[2], p[3], p[4]) + """loot_table_definition : loot_table loot_table_type ID json_object""" + p[0] = loot_table_definition_block(p.lineno(1), p[2], p[3], p[4]) + def p_loot_table_definition(p): - '''loot_table_definition : loot_table loot_table_type ID COLON ID json_object''' - p[0] = loot_table_definition_block(p.lineno(1), p[2], p[3] + p[4] + p[5], p[6]) - + """loot_table_definition : loot_table loot_table_type ID COLON ID json_object""" + p[0] = loot_table_definition_block( + p.lineno(1), p[2], p[3] + p[4] + p[5], p[6] + ) + + #### Predicates def p_predicate_definition(p): - '''predicate_definition : predicate ID json_object''' - p[0] = predicate_definition_block(p.lineno(1), p[2], p[3]) - + """predicate_definition : predicate ID json_object""" + p[0] = predicate_definition_block(p.lineno(1), p[2], p[3]) + + #### Item Modifiers def p_item_modifier_definition(p): - '''item_modifier_definition : item_modifier ID json_object''' - p[0] = item_modifier_definition_block(p.lineno(1), p[2], p[3]) - + """item_modifier_definition : item_modifier ID json_object""" + p[0] = item_modifier_definition_block(p.lineno(1), p[2], p[3]) + + #### Empty def p_empty(p): - '''empty : ''' + """empty :""" + def p_error(p): - if p == None: - raise SyntaxError('Syntax error: unexpected End of File') - else: - raise SyntaxError('Syntax error at line {} column {}. Unexpected {} symbol "{}" in state {}.'.format(p.lineno, scriptlex.find_column(bparser.data, p), p.type, p.value.replace('\n', '\\n'), bparser.state)) + if p == None: + raise SyntaxError("Syntax error: unexpected End of File") + else: + raise SyntaxError( + 'Syntax error at line {} column {}. Unexpected {} symbol "{}" in state {}.'.format( + p.lineno, + scriptlex.find_column(bparser.data, p), + p.type, + p.value.replace("\n", "\\n"), + bparser.state, + ) + ) + bparser = yacc.yacc() -def parse(data,debug=0): - scriptlex.lexer.lineno = 1 - bparser.error = 0 - bparser.data = data - try: - p = bparser.parse(data,debug=debug,tracking=True) - return p - except SyntaxError as e: - print(e) - except Exception as e: - print(traceback.format_exc()) \ No newline at end of file + +def parse(data, debug=0): + scriptlex.lexer.lineno = 1 + bparser.error = 0 + bparser.data = data + try: + p = bparser.parse(data, debug=debug, tracking=True) + return p + except SyntaxError as e: + print(e) + except Exception as e: + print(traceback.format_exc()) diff --git a/selector_definition.py b/selector_definition.py index f8dae41..88c155d 100644 --- a/selector_definition.py +++ b/selector_definition.py @@ -1,226 +1,254 @@ from CompileError import CompileError + def split_qualifier(qualifier): - for op in ['==', '<=', '>=', '<', '>']: - if op in qualifier: - before,after = tuple(qualifier.split(op, 1)) - before = before.strip() - after = after.strip() - - return before, op, after - - return None - + for op in ["==", "<=", ">=", "<", ">"]: + if op in qualifier: + before, after = tuple(qualifier.split(op, 1)) + before = before.strip() + after = after.strip() + + return before, op, after + + return None + + def isNumber(s): - try: - float(s) - return True - except ValueError: - return False - + try: + float(s) + return True + except ValueError: + return False + + class selector_definition(object): - def __init__(self, selector, env): - self.parts = [] - self.scores_min = {} - self.scores_max = {} - self.environment = env - self.tag = None - self.paths = {} - self.vector_paths = {} - self.pointers = {} - self.uuid = None - self.predicates = {} - - selector = env.apply_replacements(selector) - - base_name = selector - - if base_name[0] == '@': - base_name = base_name[1:] - - if '[' in base_name: - base_name = base_name.split('[')[0] - - if base_name in env.selectors: - base_selector = env.selectors[base_name] - - self.base_name = base_selector.base_name - - for part in base_selector.parts: - self.parts.append(part) - - for var in base_selector.scores_min: - self.scores_min[var] = base_selector.scores_min[var] - - for var in base_selector.scores_max: - self.scores_max[var] = base_selector.scores_max[var] - - for var in base_selector.paths: - self.paths[var] = base_selector.paths[var] - - for var in base_selector.vector_paths: - self.vector_paths[var] = base_selector.vector_paths[var] - - for var in base_selector.pointers: - self.pointers[var] = base_selector.pointers[var] - - for var in base_selector.predicates: - self.predicates[var] = base_selector.predicates[var] - - self.tag = base_selector.tag - - self.uuid = base_selector.uuid - else: - if len(base_name) != 1: - raise CompileError(f'Tried to create selector with base name @{base_name}') - - self.base_name = base_name - - if '[' in selector and ']' in selector: - parts = selector[selector.find('[')+1:selector.rfind(']')].split(',') - parts = [part.strip() for part in parts] - - if len(parts) == 1: - try: - index = int(parts[0]) - self.uuid = f'0-0-0-0-{index + hash(base_name) % (2 ** 32):X}' - return - except: - None - - nbt_part = None - lbrack = 0 - rbrack = 0 - - for part in parts: - if len(part) == 0: - continue - - if part.startswith('nbt') or part.startswith('scores'): - lbrack = part.count('{') - rbrack = part.count('}') - - if rbrack < lbrack: - nbt_part = part - continue - - if nbt_part != None: - lbrack += part.count('{') - rbrack += part.count('}') - if rbrack < lbrack: - nbt_part = nbt_part + ',' + part - continue - else: - part = nbt_part + ',' + part - nbt_part = None - - op_parts = split_qualifier(part) - if op_parts == None: - if '=' in part: - subparts = part.split('=') - subparts = [part.strip() for part in subparts] - if subparts[0] == 'scores': - subparts = [subparts[0], '='.join(subparts[1:])] - type = subparts[1] - if subparts[0] == 'type' and not type.startswith('minecraft:') and not type.startswith('!minecraft:'): - if subparts[1].startswith('!'): - if type in env.entity_tags: - subparts[1] = f'!#{env.namespace}:{subparts[1][1:]}' - else: - subparts[1] = '!minecraft:' + subparts[1][1:] - else: - if type in env.entity_tags: - subparts[1] = f'#{env.namespace}:{subparts[1]}' - else: - subparts[1] = 'minecraft:' + subparts[1] - - self.set_part(subparts[0], subparts[1]) - else: - if len(part) >= 5 and part[:4].upper() == "NOT ": - self.scores_max[part[4:]] = 0 - env.register_objective(part[4:]) - else: - if part in self.predicates: - if ':' in part: - self.parts.append(['predicate', part]) - else: - self.parts.append(['predicate', f'{env.namespace}:{part}']) - else: - self.scores_min[part] = 1 - env.register_objective(part) - else: - before, op, after = op_parts - - if not isNumber(after): - raise SyntaxError(f'"{after}" is not a number in "{selector}"') - - if op == '==': - self.scores_min[before] = int(after) - self.scores_max[before] = int(after) - elif op == '<=': - self.scores_max[before] = int(after) - elif op == '>=': - self.scores_min[before] = int(after) - elif op == '<': - self.scores_max[before] = int(after)-1 - elif op == '>': - self.scores_min[before] = int(after)+1 - - env.register_objective(before) - - def compile(self): - if self.uuid: - return self.uuid - - major_parts = [] - base_name = self.base_name - parts = self.parts - if base_name == 'e' and ('type', 'minecraft:player') in parts: - parts.remove(('type', 'minecraft:player')) - base_name = 'a' - - if len(parts) > 0: - major_parts.append(','.join(['='.join(part) for part in parts])) - - if len(self.scores_min) != 0 or len(self.scores_max) != 0: - score_parts = [] - - for var in self.scores_min: - if var in self.scores_max: - if self.scores_min[var] == self.scores_max[var]: - score_parts.append(f'{var}={self.scores_min[var]}') - else: - score_parts.append(f'{var}={self.scores_min[var]}..{self.scores_max[var]}') - else: - score_parts.append(f'{var}={self.scores_min[var]}..') - for var in self.scores_max: - if var not in self.scores_min: - score_parts.append(f'{var}=..{self.scores_max[var]}') - - major_parts.append(f"scores={{{','.join(score_parts)}}}") - - return f"@{base_name}[{','.join(major_parts)}]" - - def get_type(self): - for part in self.parts: - if part[0] == 'type': - return part[1] - - return None - - def set_part(self, name, value): - self.parts = [part for part in self.parts if part[0] != name] - self.parts.append((name, value)) - - def single_entity(self): - if self.uuid: - return True - - if self.base_name == 's' or self.base_name == 'p': - return True - - for part in self.parts: - if part[0] == 'limit' and part[1] == '1': - return True - - return False \ No newline at end of file + def __init__(self, selector, env): + self.parts = [] + self.scores_min = {} + self.scores_max = {} + self.environment = env + self.tag = None + self.paths = {} + self.vector_paths = {} + self.pointers = {} + self.uuid = None + self.predicates = {} + + selector = env.apply_replacements(selector) + + base_name = selector + + if base_name[0] == "@": + base_name = base_name[1:] + + if "[" in base_name: + base_name = base_name.split("[")[0] + + if base_name in env.selectors: + base_selector = env.selectors[base_name] + + self.base_name = base_selector.base_name + + for part in base_selector.parts: + self.parts.append(part) + + for var in base_selector.scores_min: + self.scores_min[var] = base_selector.scores_min[var] + + for var in base_selector.scores_max: + self.scores_max[var] = base_selector.scores_max[var] + + for var in base_selector.paths: + self.paths[var] = base_selector.paths[var] + + for var in base_selector.vector_paths: + self.vector_paths[var] = base_selector.vector_paths[var] + + for var in base_selector.pointers: + self.pointers[var] = base_selector.pointers[var] + + for var in base_selector.predicates: + self.predicates[var] = base_selector.predicates[var] + + self.tag = base_selector.tag + + self.uuid = base_selector.uuid + else: + if len(base_name) != 1: + raise CompileError( + f"Tried to create selector with base name @{base_name}" + ) + + self.base_name = base_name + + if "[" in selector and "]" in selector: + parts = selector[ + selector.find("[") + 1 : selector.rfind("]") + ].split(",") + parts = [part.strip() for part in parts] + + if len(parts) == 1: + try: + index = int(parts[0]) + self.uuid = ( + f"0-0-0-0-{index + hash(base_name) % (2 ** 32):X}" + ) + return + except: + None + + nbt_part = None + lbrack = 0 + rbrack = 0 + + for part in parts: + if len(part) == 0: + continue + + if part.startswith("nbt") or part.startswith("scores"): + lbrack = part.count("{") + rbrack = part.count("}") + + if rbrack < lbrack: + nbt_part = part + continue + + if nbt_part != None: + lbrack += part.count("{") + rbrack += part.count("}") + if rbrack < lbrack: + nbt_part = nbt_part + "," + part + continue + else: + part = nbt_part + "," + part + nbt_part = None + + op_parts = split_qualifier(part) + if op_parts == None: + if "=" in part: + subparts = part.split("=") + subparts = [part.strip() for part in subparts] + if subparts[0] == "scores": + subparts = [subparts[0], "=".join(subparts[1:])] + type = subparts[1] + if ( + subparts[0] == "type" + and not type.startswith("minecraft:") + and not type.startswith("!minecraft:") + ): + if subparts[1].startswith("!"): + if type in env.entity_tags: + subparts[1] = ( + f"!#{env.namespace}:{subparts[1][1:]}" + ) + else: + subparts[1] = ( + "!minecraft:" + subparts[1][1:] + ) + else: + if type in env.entity_tags: + subparts[1] = ( + f"#{env.namespace}:{subparts[1]}" + ) + else: + subparts[1] = "minecraft:" + subparts[1] + + self.set_part(subparts[0], subparts[1]) + else: + if len(part) >= 5 and part[:4].upper() == "NOT ": + self.scores_max[part[4:]] = 0 + env.register_objective(part[4:]) + else: + if part in self.predicates: + if ":" in part: + self.parts.append(["predicate", part]) + else: + self.parts.append( + [ + "predicate", + f"{env.namespace}:{part}", + ] + ) + else: + self.scores_min[part] = 1 + env.register_objective(part) + else: + before, op, after = op_parts + + if not isNumber(after): + raise SyntaxError( + f'"{after}" is not a number in "{selector}"' + ) + + if op == "==": + self.scores_min[before] = int(after) + self.scores_max[before] = int(after) + elif op == "<=": + self.scores_max[before] = int(after) + elif op == ">=": + self.scores_min[before] = int(after) + elif op == "<": + self.scores_max[before] = int(after) - 1 + elif op == ">": + self.scores_min[before] = int(after) + 1 + + env.register_objective(before) + + def compile(self): + if self.uuid: + return self.uuid + + major_parts = [] + base_name = self.base_name + parts = self.parts + if base_name == "e" and ("type", "minecraft:player") in parts: + parts.remove(("type", "minecraft:player")) + base_name = "a" + + if len(parts) > 0: + major_parts.append(",".join(["=".join(part) for part in parts])) + + if len(self.scores_min) != 0 or len(self.scores_max) != 0: + score_parts = [] + + for var in self.scores_min: + if var in self.scores_max: + if self.scores_min[var] == self.scores_max[var]: + score_parts.append(f"{var}={self.scores_min[var]}") + else: + score_parts.append( + f"{var}={self.scores_min[var]}..{self.scores_max[var]}" + ) + else: + score_parts.append(f"{var}={self.scores_min[var]}..") + for var in self.scores_max: + if var not in self.scores_min: + score_parts.append(f"{var}=..{self.scores_max[var]}") + + major_parts.append(f"scores={{{','.join(score_parts)}}}") + + return f"@{base_name}[{','.join(major_parts)}]" + + def get_type(self): + for part in self.parts: + if part[0] == "type": + return part[1] + + return None + + def set_part(self, name, value): + self.parts = [part for part in self.parts if part[0] != name] + self.parts.append((name, value)) + + def single_entity(self): + if self.uuid: + return True + + if self.base_name == "s" or self.base_name == "p": + return True + + for part in self.parts: + if part[0] == "limit" and part[1] == "1": + return True + + return False diff --git a/source_file.py b/source_file.py index 141c36b..4620b5e 100644 --- a/source_file.py +++ b/source_file.py @@ -1,38 +1,39 @@ import os import time + class source_file(object): - def __init__(self, filename): - self.filename = os.path.abspath(filename) - self.modified = self.get_last_modified() - self.last_size = os.path.getsize(filename) - - def get_last_modified(self): - return time.ctime(os.path.getmtime(self.filename)) - - def was_updated(self): - t = self.get_last_modified() - if t > self.modified: - self.modified = t - return True - else: - return False - - def get_base_name(self): - return os.path.basename(self.filename) - - def get_directory(self): - return os.path.dirname(self.filename) - - def get_text(self, only_new_text = False): - text = "" - while len(text) == 0: - with open(self.filename, 'r') as content_file: - if only_new_text: - content_file.seek(self.last_size) - text = content_file.read() - - time.sleep(0.1) - - self.last_size = os.path.getsize(self.filename) - return text \ No newline at end of file + def __init__(self, filename): + self.filename = os.path.abspath(filename) + self.modified = self.get_last_modified() + self.last_size = os.path.getsize(filename) + + def get_last_modified(self): + return time.ctime(os.path.getmtime(self.filename)) + + def was_updated(self): + t = self.get_last_modified() + if t > self.modified: + self.modified = t + return True + else: + return False + + def get_base_name(self): + return os.path.basename(self.filename) + + def get_directory(self): + return os.path.dirname(self.filename) + + def get_text(self, only_new_text=False): + text = "" + while len(text) == 0: + with open(self.filename, "r") as content_file: + if only_new_text: + content_file.seek(self.last_size) + text = content_file.read() + + time.sleep(0.1) + + self.last_size = os.path.getsize(self.filename) + return text diff --git a/tellraw.py b/tellraw.py index 04464ee..f1adb33 100644 --- a/tellraw.py +++ b/tellraw.py @@ -1,8 +1,7 @@ import copy -from scratch_tracker import scratch_tracker from CompileError import CompileError -''' +""" {C for color {U for underline, {u to exit underline, same for {D bold, {S strikethrough and {I italic {- to clear formatting @@ -12,205 +11,248 @@ (@Selector) to display a selector name (@Selector.Score) to display a score (Score) to display a Global score. -''' +""" + def getPropertiesText(properties): - text = "" - if properties["color"] != None: - text = text + ',"color":"' + properties["color"] + '"' - if properties["bold"]: - text = text + ',"bold":true' - if properties["underlined"]: - text = text + ',"underlined":true' - if properties["italic"]: - text = text + ',"italic":true' - if properties["strikethrough"]: - text = text + ',"strikethrough":true' - - return text - + text = "" + if properties["color"] != None: + text = text + ',"color":"' + properties["color"] + '"' + if properties["bold"]: + text = text + ',"bold":true' + if properties["underlined"]: + text = text + ',"underlined":true' + if properties["italic"]: + text = text + ',"italic":true' + if properties["strikethrough"]: + text = text + ',"strikethrough":true' + + return text + + def formatJsonText(func, text): - formatted = '[""' - local_scratch = [] - - for segment, properties in parseTextFormatting(text): - propertiesText = getPropertiesText(properties) - if isinstance(segment, str): - formatted = formatted + ',{{"text":"{0}"{1}}}'.format(segment.replace('"', '\\"'), getPropertiesText(properties)) - else: - unformatted, command = segment - if unformatted == None: - parts = command.split(".") - if len(parts) > 2: - raise CompileError(f'Json text has invalid () text: "{command}"') - if len(parts) == 1: - if len(parts[0]) == 0: - raise CompileError('Empty () in json text.') - elif parts[0][0] == '@': - formatted = formatted + f',{{"selector":"{parts[0]}"{getPropertiesText(properties)}}}' - elif ':' in parts[0]: - storage_parts = parts[0].split(':') - if len(storage_parts) != 2: - raise CompileError(f'Unable to parse storage variable "{parts[0]}"') - if len(storage_parts[0]) == 0: - target = func.namespace - else: - target = storage_parts[0] - formatted = formatted + f',{{"nbt":"{storage_parts[1]}","storage":"{target}"}}' - else: - formatted = formatted + f',{{"score":{{"name":"Global","objective":"{parts[0]}"{getPropertiesText(properties)}}}}}' - if len(parts) == 2: - name = parts[0] - name_def = func.get_name_definition(parts[0]) - if name_def: - name = name_def - formatted = formatted + f',{{"score":{{"name":"{name}","objective":"{parts[1]}"{getPropertiesText(properties)}}}}}' - elif command == None: - formatted = formatted + f',{{"text":"{0}"{1}}}'.format(unformatted.replace('"', '\\"'), getPropertiesText(properties)) - else: - command = command.replace('"', '\\"') - if command.startswith('http'): - action = 'open_url' - elif command.startswith('//'): - action = 'suggest_command' - command = command[1:] - elif command.startswith('call '): - action = 'run_command' - command = f'/function {func.namespace}:{command[len("call "):]}' - else: - action = 'run_command' - formatted = formatted + ',{{"text":"{0}","clickEvent":{{"action":"{1}","value":"{2}"}}{3}}}'.format(unformatted.replace('"', '\\"'), action, command, getPropertiesText(properties)) - - formatted = formatted + "]" - - for scratch_var in local_scratch: - func.free_scratch(scratch_var) - - return formatted + formatted = '[""' + local_scratch = [] + + for segment, properties in parseTextFormatting(text): + propertiesText = getPropertiesText(properties) + if isinstance(segment, str): + formatted = formatted + ',{{"text":"{0}"{1}}}'.format( + segment.replace('"', '\\"'), getPropertiesText(properties) + ) + else: + unformatted, command = segment + if unformatted == None: + parts = command.split(".") + if len(parts) > 2: + raise CompileError( + f'Json text has invalid () text: "{command}"' + ) + if len(parts) == 1: + if len(parts[0]) == 0: + raise CompileError("Empty () in json text.") + elif parts[0][0] == "@": + formatted = ( + formatted + + f',{{"selector":"{parts[0]}"{getPropertiesText(properties)}}}' + ) + elif ":" in parts[0]: + storage_parts = parts[0].split(":") + if len(storage_parts) != 2: + raise CompileError( + f'Unable to parse storage variable "{parts[0]}"' + ) + if len(storage_parts[0]) == 0: + target = func.namespace + else: + target = storage_parts[0] + formatted = ( + formatted + + f',{{"nbt":"{storage_parts[1]}","storage":"{target}"}}' + ) + else: + formatted = ( + formatted + + f',{{"score":{{"name":"Global","objective":"{parts[0]}"{getPropertiesText(properties)}}}}}' + ) + if len(parts) == 2: + name = parts[0] + name_def = func.get_name_definition(parts[0]) + if name_def: + name = name_def + formatted = ( + formatted + + f',{{"score":{{"name":"{name}","objective":"{parts[1]}"{getPropertiesText(properties)}}}}}' + ) + elif command == None: + formatted = formatted + f',{{"text":"{0}"{1}}}'.format( + unformatted.replace('"', '\\"'), + getPropertiesText(properties), + ) + else: + command = command.replace('"', '\\"') + if command.startswith("http"): + action = "open_url" + elif command.startswith("//"): + action = "suggest_command" + command = command[1:] + elif command.startswith("call "): + action = "run_command" + command = ( + f'/function {func.namespace}:{command[len("call "):]}' + ) + else: + action = "run_command" + formatted = ( + formatted + + ',{{"text":"{0}","clickEvent":{{"action":"{1}","value":"{2}"}}{3}}}'.format( + unformatted.replace('"', '\\"'), + action, + command, + getPropertiesText(properties), + ) + ) + + formatted = formatted + "]" + + for scratch_var in local_scratch: + func.free_scratch(scratch_var) + + return formatted + COLORS = { - "k": "black", - "K": "dark_gray", - "w": "gray", - "W": "white", - "r": "dark_red", - "R": "red", - "g": "dark_green", - "G": "green", - "b": "dark_blue", - "B": "blue", - "y": "gold", - "Y": "yellow", - "c": "dark_aqua", - "C": "aqua", - "m": "dark_purple", - "M": "light_purple", + "k": "black", + "K": "dark_gray", + "w": "gray", + "W": "white", + "r": "dark_red", + "R": "red", + "g": "dark_green", + "G": "green", + "b": "dark_blue", + "B": "blue", + "y": "gold", + "Y": "yellow", + "c": "dark_aqua", + "C": "aqua", + "m": "dark_purple", + "M": "light_purple", } - + + def parseTextFormatting(text): - NONE = 1 - FORMATTED = 2 - ENDFORMATTED = 3 - COMMAND = 4 - SCOREBOARD = 5 - PROPERTY = 6 - - escaped = False - - mode = NONE - seg = "" - formatted = "" - - segments = [] - properties = {"color": None, "bold": False, "underlined": False, "italic": False, "strikethrough": False} - - for ch in text: - if ch == "\\" and not escaped: - escaped = True - elif escaped: - seg = seg + ch - escaped = False - elif mode == NONE: - if ch == "[": - if len(seg) > 0: - segments.append((seg, copy.copy(properties))) - seg = "" - mode = FORMATTED - elif ch == "(": - if len(seg) > 0: - segments.append((seg, copy.copy(properties))) - seg = "" - mode = SCOREBOARD - elif ch == "{": - if len(seg) > 0: - segments.append((seg, copy.copy(properties))) - seg = "" - mode = PROPERTY - else: - seg = seg + ch - elif mode == FORMATTED: - if ch == "]": - formatted = seg - seg = "" - mode = ENDFORMATTED - else: - seg = seg + ch - elif mode == ENDFORMATTED: - if ch == "(": - mode = COMMAND - else: - segments.append(((formatted, None), copy.copy(properties))) - formatted = "" - mode = NONE - seg = seg + ch - elif mode == COMMAND: - if ch == ")": - segments.append(((formatted, seg), copy.copy(properties))) - seg = "" - formatted = "" - mode = NONE - else: - seg = seg + ch - elif mode == SCOREBOARD: - if ch == ")": - segments.append(((None, seg), copy.copy(properties))) - seg = "" - mode = NONE - else: - seg = seg + ch - elif mode == PROPERTY: - if ch in COLORS: - properties["color"] = COLORS[ch] - elif ch == "-": - properties["color"] = None - properties["bold"] = False - properties["underlined"] = False - properties["italic"] = False - properties["strikethrough"] = False - elif ch == "D": - properties["bold"] = True - elif ch == "d": - properties["bold"] = False - elif ch == "U": - properties["underlined"] = True - elif ch == "u": - properties["underlined"] = False - elif ch == "I": - properties["italic"] = True - elif ch == "i": - properties["italic"] = False - elif ch == "S": - properties["strikethrough"] = True - elif ch == "s": - properties["strikethrough"] = False - elif ch == "{": - seg = seg + ch - else: - raise CompileError(f'Unexpected formatting character {{{ch} in tell command') - - mode = NONE - - if len(seg) > 0: - segments.append((seg, copy.copy(properties))) - - return segments + NONE = 1 + FORMATTED = 2 + ENDFORMATTED = 3 + COMMAND = 4 + SCOREBOARD = 5 + PROPERTY = 6 + + escaped = False + + mode = NONE + seg = "" + formatted = "" + + segments = [] + properties = { + "color": None, + "bold": False, + "underlined": False, + "italic": False, + "strikethrough": False, + } + + for ch in text: + if ch == "\\" and not escaped: + escaped = True + elif escaped: + seg = seg + ch + escaped = False + elif mode == NONE: + if ch == "[": + if len(seg) > 0: + segments.append((seg, copy.copy(properties))) + seg = "" + mode = FORMATTED + elif ch == "(": + if len(seg) > 0: + segments.append((seg, copy.copy(properties))) + seg = "" + mode = SCOREBOARD + elif ch == "{": + if len(seg) > 0: + segments.append((seg, copy.copy(properties))) + seg = "" + mode = PROPERTY + else: + seg = seg + ch + elif mode == FORMATTED: + if ch == "]": + formatted = seg + seg = "" + mode = ENDFORMATTED + else: + seg = seg + ch + elif mode == ENDFORMATTED: + if ch == "(": + mode = COMMAND + else: + segments.append(((formatted, None), copy.copy(properties))) + formatted = "" + mode = NONE + seg = seg + ch + elif mode == COMMAND: + if ch == ")": + segments.append(((formatted, seg), copy.copy(properties))) + seg = "" + formatted = "" + mode = NONE + else: + seg = seg + ch + elif mode == SCOREBOARD: + if ch == ")": + segments.append(((None, seg), copy.copy(properties))) + seg = "" + mode = NONE + else: + seg = seg + ch + elif mode == PROPERTY: + if ch in COLORS: + properties["color"] = COLORS[ch] + elif ch == "-": + properties["color"] = None + properties["bold"] = False + properties["underlined"] = False + properties["italic"] = False + properties["strikethrough"] = False + elif ch == "D": + properties["bold"] = True + elif ch == "d": + properties["bold"] = False + elif ch == "U": + properties["underlined"] = True + elif ch == "u": + properties["underlined"] = False + elif ch == "I": + properties["italic"] = True + elif ch == "i": + properties["italic"] = False + elif ch == "S": + properties["strikethrough"] = True + elif ch == "s": + properties["strikethrough"] = False + elif ch == "{": + seg = seg + ch + else: + raise CompileError( + f"Unexpected formatting character {{{ch} in tell command" + ) + + mode = NONE + + if len(seg) > 0: + segments.append((seg, copy.copy(properties))) + + return segments diff --git a/unittest/mock_block.py b/unittest/mock_block.py index 65b27e9..7610086 100644 --- a/unittest/mock_block.py +++ b/unittest/mock_block.py @@ -1,10 +1,12 @@ class mock_block(object): - def __init__(self, command = 'mock_block_command', raiseException = False, line=0): - self.command = command - self.raiseException = raiseException - self.line = line - - def compile(self, func): - if self.raiseException: - raise Exception('mock exception') - func.add_command(self.command) \ No newline at end of file + def __init__( + self, command="mock_block_command", raiseException=False, line=0 + ): + self.command = command + self.raiseException = raiseException + self.line = line + + def compile(self, func): + if self.raiseException: + raise Exception("mock exception") + func.add_command(self.command) diff --git a/unittest/mock_environment.py b/unittest/mock_environment.py index 0cd16f4..5a5b2ee 100644 --- a/unittest/mock_environment.py +++ b/unittest/mock_environment.py @@ -1,77 +1,77 @@ class mock_environment(object): - def __init__(self): - self.dollarid = {} - self.functions = {} - self.self_selector = None - self.selectors = {} - self.objectives = [] - self.scratch = 0 - self.selector_definitions = {} - self.arrays = {} - self.block_tags = {} - self.scale = 1000 - self.cloned_environments = [] - self.applied = [] - self.copied_dollarids = [] - self.pointers = {} - - def clone(self, new_function_name=None): - env = mock_environment() - env.function_name = new_function_name - self.cloned_environments.append(env) - return env - - def apply(self, text): - self.applied.append(text) - - return text - - def get_unique_id(self): - return 1 - - @property - def namespace(self): - return 'test_namespace' - - def register_function(self, name, func): - self.functions[name] = func - - def set_dollarid(self, id, val): - self.dollarid[id] = val - - def update_self_selector(self, selector): - self.self_selector = selector - - def register_local(self, var): - None - - def apply_replacements(self, text): - return text - - def register_objective(self, objective): - self.objectives.append(objective) - - def is_scratch(self, id): - return 'scratch' in id - - def get_scratch(self): - self.scratch += 1 - return f'test_scratch{self.scratch}' - - def free_scratch(self, id): - None - - def get_selector_definition(self, selector_text): - return self.selector_definitions[selector_text] - - def get_arrayconst_var(self, name, idxval): - return f'{name}{idxval}' - - def copy_dollarid(self, id1, id2): - self.dollarid[id1] = self.dollarid[id2] - - def get_python_env(self): - return self.dollarid - - def add_pointer(self, id, selector): - self.pointers[id] = selector \ No newline at end of file + def __init__(self): + self.dollarid = {} + self.functions = {} + self.self_selector = None + self.selectors = {} + self.objectives = [] + self.scratch = 0 + self.selector_definitions = {} + self.arrays = {} + self.block_tags = {} + self.scale = 1000 + self.cloned_environments = [] + self.applied = [] + self.copied_dollarids = [] + self.pointers = {} + + def clone(self, new_function_name=None): + env = mock_environment() + env.function_name = new_function_name + self.cloned_environments.append(env) + return env + + def apply(self, text): + self.applied.append(text) + + return text + + def get_unique_id(self): + return 1 + + @property + def namespace(self): + return "test_namespace" + + def register_function(self, name, func): + self.functions[name] = func + + def set_dollarid(self, id, val): + self.dollarid[id] = val + + def update_self_selector(self, selector): + self.self_selector = selector + + def register_local(self, var): + None + + def apply_replacements(self, text): + return text + + def register_objective(self, objective): + self.objectives.append(objective) + + def is_scratch(self, id): + return "scratch" in id + + def get_scratch(self): + self.scratch += 1 + return f"test_scratch{self.scratch}" + + def free_scratch(self, id): + None + + def get_selector_definition(self, selector_text): + return self.selector_definitions[selector_text] + + def get_arrayconst_var(self, name, idxval): + return f"{name}{idxval}" + + def copy_dollarid(self, id1, id2): + self.dollarid[id1] = self.dollarid[id2] + + def get_python_env(self): + return self.dollarid + + def add_pointer(self, id, selector): + self.pointers[id] = selector diff --git a/unittest/mock_global_context.py b/unittest/mock_global_context.py index 10ff129..d008a2e 100644 --- a/unittest/mock_global_context.py +++ b/unittest/mock_global_context.py @@ -1,14 +1,13 @@ class mock_global_context(object): - def __init__(self): - self.temp = 0 - self.scratch = {} - + def __init__(self): + self.temp = 0 + self.scratch = {} - def allocate_temp(self, size): - self.temp = size - - def allocate_scratch(self, prefix, size): - self.scratch[prefix] = size - - def get_scratch_prefix(self, name): - return f'{name}_prefix' + def allocate_temp(self, size): + self.temp = size + + def allocate_scratch(self, prefix, size): + self.scratch[prefix] = size + + def get_scratch_prefix(self, name): + return f"{name}_prefix" diff --git a/unittest/mock_mcfunction.py b/unittest/mock_mcfunction.py index 0dbbbe8..8b38bbb 100644 --- a/unittest/mock_mcfunction.py +++ b/unittest/mock_mcfunction.py @@ -1,220 +1,226 @@ -import math from mock_environment import mock_environment from mock_selector_definition import mock_selector_definition + class mock_mcfunction(object): - def __init__(self): - self.commands = [] - self.dollarid = {} - self.atid = {} - self.macros = {} - self.template_functions = {} - self.arrays = {} - self.block_tags = {} - self.namespace = 'test_namespace' - self.functions = {} - self.selectors = {} - self.child_functions = [] - self.created = [] - self.compiled_blocks = [] - self.scratch = 0 - self.cloned_environments = [] - self.environment_pushes = 0 - self.environment_pops = 0 - self.constants = {} - self.finalized = False - self.temp = 0 - self.switch_calls = [] - self.execute_command_calls = [] - self.set_var = {} - self.self_selector = None - - def add_operation(self, selector, id1, operation, id2): - self.add_command(f"scoreboard players operation {selector} {id1} {operation} {selector} {id2}") - - def add_command(self, command): - self.commands.append(command) - - def insert_command(self, command, index): - self.commands.insert(index, command) - - def get_utf8_text(self): - return '' - - def defined_objectives(self): - return {} - - def register_local(self, id): - None - - def finalize(self): - self.finalized = True - - def single_command(self): - return None - - def check_single_entity(self, selector): - return False - - def get_path(self, selector, var): - None - - def set_path(self, selector, var): - None - - def get_vector_path(self, selector, var, assignto): - return False - - def set_vector_path(self, selector, var, values): - return True - - def register_objective(self, objective): - None - - def register_array(self, name, from_val, to_val): - self.arrays[name] = (from_val, to_val) - - def apply_replacements(self, text): - return text - - def register_block_tag(self, name, blocks): - self.block_tags[name] = blocks - - def get_scale(self): - return 1000 - - def set_scale(self, scale): - None - - scale = property(get_scale, set_scale) - - def get_scratch(self): - self.scratch += 1 - return f'test_scratch{self.scratch}' - - def free_scratch(self, id): - None - - def apply_environment(self, text): - return text - - def add_constant(self, val): - self.constants[val] = True - return 'test_constant' - - def allocate_rand(self, val): - None - - def get_friendly_name(self): - return 'test_friendly_name' - - def get_random_objective(self): - return 'test_random_objective' - - def register_function(self, name, func): - self.functions[name] = func - - def get_unique_id(self): - return 1 - - def update_self_selector(self, selector): - self.self_selector = selector - - def get_python_env(self): - return self.dollarid - - def clone_environment(self): - env = mock_environment() - self.cloned_environments.append(env) - return env - - def get_combined_selector(self, selector): - return mock_selector_definition() - - def set_dollarid(self, id, val): - self.dollarid[id] = val - - def get_dollarid(self, id): - return self.dollarid[id] - - def set_atid(self, id, fullselector): - self.selectors[id] = mock_selector_definition() - self.selectors[id].selector = fullselector - - return self.selectors[id] - - def push_environment(self, new_env): - self.environment_pushes += 1 - - def pop_environment(self): - self.environment_pops += 1 - - def run_create(self, atid, relcoords): - self.created.append((atid, relcoords)) - return True - - def perform_execute(self, type, line_num, exec_items, sub): - return True - - def create_child_function(self): - child = mock_mcfunction() - self.child_functions.append(child) - return child - - def compile_blocks(self, lines): - self.compiled_blocks.append(lines) - return True - - def is_scratch(self, var): - return False - - def get_temp_var(self): - self.temp += 1 - return f'temp{self.temp}' - - def free_temp_var(self, var): - None - - def switch_cases(self, var, cases, switch_func_name = 'switch', case_func_name = 'case'): - self.switch_calls.append((var, cases, switch_func_name, case_func_name)) - - return True - - def get_execute_command(self, exec_items, exec_func): - self.execute_command_calls.append(exec_items) - - return 'execute_dummy ' - - def get_variable(self, variable, initialize): - self.scratch += 1 - return (f'Global', 'var{self.scratch}') - - def set_variable(self, variable): - self.set_var[variable] = True - - def get_arrayconst_var(self, name, idxval): - return f'{name}{idxval}' - - def get_modifiable_id(self, id, assignto): - if assignto != None: - if id != assignto: - self.add_operation('Global', assignto, '=', id) - id = assignto - else: - return id - else: - newId = self.get_scratch() - self.add_operation('Global', newId, '=', id) - id = newId - - return id - - def evaluate_params(self, params): - return True - - def eval(self, expr, line): - try: - return eval(expr, globals(), self.get_python_env()) - except Exception as e: - print(e) - raise ValueError(f'Could not evaluate "{expr}" at line {line}') + def __init__(self): + self.commands = [] + self.dollarid = {} + self.atid = {} + self.macros = {} + self.template_functions = {} + self.arrays = {} + self.block_tags = {} + self.namespace = "test_namespace" + self.functions = {} + self.selectors = {} + self.child_functions = [] + self.created = [] + self.compiled_blocks = [] + self.scratch = 0 + self.cloned_environments = [] + self.environment_pushes = 0 + self.environment_pops = 0 + self.constants = {} + self.finalized = False + self.temp = 0 + self.switch_calls = [] + self.execute_command_calls = [] + self.set_var = {} + self.self_selector = None + + def add_operation(self, selector, id1, operation, id2): + self.add_command( + f"scoreboard players operation {selector} {id1} {operation} {selector} {id2}" + ) + + def add_command(self, command): + self.commands.append(command) + + def insert_command(self, command, index): + self.commands.insert(index, command) + + def get_utf8_text(self): + return "" + + def defined_objectives(self): + return {} + + def register_local(self, id): + None + + def finalize(self): + self.finalized = True + + def single_command(self): + return None + + def check_single_entity(self, selector): + return False + + def get_path(self, selector, var): + None + + def set_path(self, selector, var): + None + + def get_vector_path(self, selector, var, assignto): + return False + + def set_vector_path(self, selector, var, values): + return True + + def register_objective(self, objective): + None + + def register_array(self, name, from_val, to_val): + self.arrays[name] = (from_val, to_val) + + def apply_replacements(self, text): + return text + + def register_block_tag(self, name, blocks): + self.block_tags[name] = blocks + + def get_scale(self): + return 1000 + + def set_scale(self, scale): + None + + scale = property(get_scale, set_scale) + + def get_scratch(self): + self.scratch += 1 + return f"test_scratch{self.scratch}" + + def free_scratch(self, id): + None + + def apply_environment(self, text): + return text + + def add_constant(self, val): + self.constants[val] = True + return "test_constant" + + def allocate_rand(self, val): + None + + def get_friendly_name(self): + return "test_friendly_name" + + def get_random_objective(self): + return "test_random_objective" + + def register_function(self, name, func): + self.functions[name] = func + + def get_unique_id(self): + return 1 + + def update_self_selector(self, selector): + self.self_selector = selector + + def get_python_env(self): + return self.dollarid + + def clone_environment(self): + env = mock_environment() + self.cloned_environments.append(env) + return env + + def get_combined_selector(self, selector): + return mock_selector_definition() + + def set_dollarid(self, id, val): + self.dollarid[id] = val + + def get_dollarid(self, id): + return self.dollarid[id] + + def set_atid(self, id, fullselector): + self.selectors[id] = mock_selector_definition() + self.selectors[id].selector = fullselector + + return self.selectors[id] + + def push_environment(self, new_env): + self.environment_pushes += 1 + + def pop_environment(self): + self.environment_pops += 1 + + def run_create(self, atid, relcoords): + self.created.append((atid, relcoords)) + return True + + def perform_execute(self, type, line_num, exec_items, sub): + return True + + def create_child_function(self): + child = mock_mcfunction() + self.child_functions.append(child) + return child + + def compile_blocks(self, lines): + self.compiled_blocks.append(lines) + return True + + def is_scratch(self, var): + return False + + def get_temp_var(self): + self.temp += 1 + return f"temp{self.temp}" + + def free_temp_var(self, var): + None + + def switch_cases( + self, var, cases, switch_func_name="switch", case_func_name="case" + ): + self.switch_calls.append( + (var, cases, switch_func_name, case_func_name) + ) + + return True + + def get_execute_command(self, exec_items, exec_func): + self.execute_command_calls.append(exec_items) + + return "execute_dummy " + + def get_variable(self, variable, initialize): + self.scratch += 1 + return (f"Global", "var{self.scratch}") + + def set_variable(self, variable): + self.set_var[variable] = True + + def get_arrayconst_var(self, name, idxval): + return f"{name}{idxval}" + + def get_modifiable_id(self, id, assignto): + if assignto != None: + if id != assignto: + self.add_operation("Global", assignto, "=", id) + id = assignto + else: + return id + else: + newId = self.get_scratch() + self.add_operation("Global", newId, "=", id) + id = newId + + return id + + def evaluate_params(self, params): + return True + + def eval(self, expr, line): + try: + return eval(expr, globals(), self.get_python_env()) + except Exception as e: + print(e) + raise ValueError(f'Could not evaluate "{expr}" at line {line}') diff --git a/unittest/mock_mcworld.py b/unittest/mock_mcworld.py index de7addb..923606c 100644 --- a/unittest/mock_mcworld.py +++ b/unittest/mock_mcworld.py @@ -1,24 +1,25 @@ last_created = None + class mock_mcworld(object): - def __init__(self, dir, namespace): - self.dir = dir - self.namespace = namespace - self.functions = [] - self.clocks = [] - self.tags = [] - self.desc = None - self.written = False - - def write_functions(self, functions): - self.functions += functions - - def write_tags(self, clocks, tags): - self.clocks += clocks - self.tags += tags - - def write_mcmeta(self, desc): - self.desc = desc - - def write_zip(self): - self.written = True \ No newline at end of file + def __init__(self, dir, namespace): + self.dir = dir + self.namespace = namespace + self.functions = [] + self.clocks = [] + self.tags = [] + self.desc = None + self.written = False + + def write_functions(self, functions): + self.functions += functions + + def write_tags(self, clocks, tags): + self.clocks += clocks + self.tags += tags + + def write_mcmeta(self, desc): + self.desc = desc + + def write_zip(self): + self.written = True diff --git a/unittest/mock_parsed.py b/unittest/mock_parsed.py index bf678c0..36c54dc 100644 --- a/unittest/mock_parsed.py +++ b/unittest/mock_parsed.py @@ -1,15 +1,15 @@ class mock_parsed(object): - def __init__(self, *args): - self.p = [None] + list(args) - - def __getitem__(self, key): - return self.p[key] - - def __setitem__(self, key, value): - self.p[key] = value - - def lineno(self, key): - return 0 - - def __len__(self): - return len(self.p) \ No newline at end of file + def __init__(self, *args): + self.p = [None] + list(args) + + def __getitem__(self, key): + return self.p[key] + + def __setitem__(self, key, value): + self.p[key] = value + + def lineno(self, key): + return 0 + + def __len__(self): + return len(self.p) diff --git a/unittest/mock_selector_definition.py b/unittest/mock_selector_definition.py index 7e5cf91..d4ab8fa 100644 --- a/unittest/mock_selector_definition.py +++ b/unittest/mock_selector_definition.py @@ -1,19 +1,19 @@ class mock_selector_definition(object): - def __init__(self): - self.scores_min = {} - self.scores_max = {} - self.parts = {} - self.paths = {} - self.vector_paths = {} - self.is_single_entity = False - self.type = None - self.tag = '' - - def set_part(self, part, val): - self.parts[part] = val - - def single_entity(self): - return self.is_single_entity - - def get_type(self): - return self.type \ No newline at end of file + def __init__(self): + self.scores_min = {} + self.scores_max = {} + self.parts = {} + self.paths = {} + self.vector_paths = {} + self.is_single_entity = False + self.type = None + self.tag = "" + + def set_part(self, part, val): + self.parts[part] = val + + def single_entity(self): + return self.is_single_entity + + def get_type(self): + return self.type diff --git a/unittest/mock_source_file.py b/unittest/mock_source_file.py index ac3688b..7729a50 100644 --- a/unittest/mock_source_file.py +++ b/unittest/mock_source_file.py @@ -1,20 +1,21 @@ import time + class mock_source_file(object): - def __init__(self, base_name='unittest.cbscript', text=''): - self.base_name = base_name - self.text = text - self.time = 0 - self.updated = True - - def get_last_modified(self): - return time.ctime(self.time) - - def get_base_name(self): - return self.base_name - - def get_text(self): - return self.text - - def was_updated(self): - return self.updated \ No newline at end of file + def __init__(self, base_name="unittest.cbscript", text=""): + self.base_name = base_name + self.text = text + self.time = 0 + self.updated = True + + def get_last_modified(self): + return time.ctime(self.time) + + def get_base_name(self): + return self.base_name + + def get_text(self): + return self.text + + def was_updated(self): + return self.updated diff --git a/unittest/test.bat b/unittest/test.bat index 7404e3b..513f90d 100644 --- a/unittest/test.bat +++ b/unittest/test.bat @@ -3,4 +3,4 @@ set PYTHONPATH=.. call coverage run --omit ./* unit_test.py 2> %tmp%\test_results.txt call coverage report call coverage html -type %tmp%\test_results.txt \ No newline at end of file +type %tmp%\test_results.txt diff --git a/unittest/unit_test.py b/unittest/unit_test.py index 5a69826..20316ba 100644 --- a/unittest/unit_test.py +++ b/unittest/unit_test.py @@ -41,14 +41,17 @@ from block_types.selector_definition_block import selector_definition_block from block_types.switch_block import switch_block from block_types.tell_block import tell_block -from block_types.template_function_call_block import template_function_call_block +from block_types.template_function_call_block import ( + template_function_call_block, +) from block_types.title_block import title_block from block_types.vector_assignment_block import vector_assignment_block -from block_types.vector_assignment_scalar_block import vector_assignment_scalar_block +from block_types.vector_assignment_scalar_block import ( + vector_assignment_scalar_block, +) from block_types.while_block import while_block from data_types.const_number import const_number -from data_types.const_string import const_string from data_types.python_identifier import python_identifier from data_types.interpreted_python import interpreted_python from data_types.relcoord import relcoord @@ -67,3079 +70,3847 @@ from scalar_expressions.unary_expr import unary_expr from vector_expressions.sel_vector_var_expr import sel_vector_var_expr -from vector_expressions.vector_binop_scalar_expr import vector_binop_scalar_expr -from vector_expressions.vector_binop_vector_expr import vector_binop_vector_expr +from vector_expressions.vector_binop_scalar_expr import ( + vector_binop_scalar_expr, +) +from vector_expressions.vector_binop_vector_expr import ( + vector_binop_vector_expr, +) from vector_expressions.vector_expr import vector_expr from vector_expressions.vector_here_expr import vector_here_expr from vector_expressions.vector_var_expr import vector_var_expr + def dummy_relcoords(x, y, z): - return relcoords(( - relcoord('', const_number(x)), - relcoord('', const_number(y)), - relcoord('', const_number(z)), - )) + return relcoords( + ( + relcoord("", const_number(x)), + relcoord("", const_number(y)), + relcoord("", const_number(z)), + ) + ) + class test_cbscript(unittest.TestCase): - def test_is_number(self): - self.assertTrue(environment.isNumber('1')) - self.assertTrue(environment.isNumber('0')) - self.assertTrue(environment.isNumber('1.0')) - self.assertFalse(environment.isNumber(float('inf'))) - self.assertFalse(environment.isNumber(float('nan'))) - self.assertFalse(environment.isNumber(None)) - self.assertFalse(environment.isNumber('test')) - - def test_is_int(self): - self.assertTrue(environment.isInt('1')) - self.assertTrue(environment.isInt('0')) - self.assertFalse(environment.isInt('1.0')) - self.assertFalse(environment.isInt(float('inf'))) - self.assertFalse(environment.isInt(float('nan'))) - self.assertFalse(environment.isInt(None)) - self.assertFalse(environment.isInt('test')) - - def test_factor(self): - self.assertEqual(list(factor(20)), [2, 2, 5]) - self.assertEqual(list(factor(2)), [2]) - self.assertEqual(list(factor(1)), []) - - def test_compile_runs_without_error(self): - func = mock_mcfunction() - - func.arrays['test'] = (0, 5) - block = array_assignment_block(0, 'test', 'Const', 1, num_expr(1)) - block.compile(func) - - block = array_definition_block(0, 'test', const_number('0'), const_number('5')) - block.compile(func) - - block = block_tag_block(0, 'test', ['test_block']) - block.compile(func) - - block = command_block(0, 'test') - block.compile(func) - - block = comment_block(0, '#test') - block.compile(func) - - block = create_block(0, '@test', ['0', '0', '0']) - block.compile(func) - - block = execute_block(0, [], [command_block(0, 'test_command')]) - block.compile(func) - - block = for_index_block(0, 'test', num_expr(0), num_expr(5), num_expr(2), [command_block(0, 'test_command')]) - block.compile(func) - - block = for_selector_block(0, '@test', '@a', [command_block(0, 'test_command')]) - block.compile(func) - - block = function_call_block(0, 'test_function', []) - block.compile(func) - - func.macros['test_macro'] = ([], [command_block(0, 'test_command')]) - block = macro_call_block(0, 'test_macro', []) - block.compile(func) - - block = method_call_block(0, '@test_selector', 'test_method', []) - block.compile(func) - - block = move_block(0, '@a', dummy_relcoords(0, 0, 0)) - block.compile(func) - - block = python_assignment_block(0, 'test_id', interpreted_python('1+1', 0)) - block.compile(func) - - block = python_for_block(0, 'test_id', interpreted_python('range(3)', 0), [command_block(0, 'test_command')]) - block.compile(func) - - block = python_if_block(0, interpreted_python('1', 0), [command_block(0, 'true_command')], [command_block(0, 'false_command')]) - block.compile(func) - block = python_if_block(0, interpreted_python('0', 0), [command_block(0, 'true_command')], [command_block(0, 'false_command')]) - block.compile(func) - - var = ('Var', ('@s', 'test')) - block = scoreboard_assignment_block(0, (var, '+=', num_expr(1))) - block.compile(func) - - block = selector_assignment_block(0, 'test', '@a') - block.compile(func) - - tag = ('Tag', '{}') - path = ('Path', ('test_path', 'test', 'float', const_number(1000))) - vpath = ('VectorPath', ('test_vector_id', 'test_vector', 'float', const_number(1))) - block = selector_definition_block(0, 'test_id', '@a', [tag, path, vpath]) - block.compile(func) - - block = switch_block(0, ('NUM', 1), []) - block.compile(func) - case1 = ('python', ('test_id', interpreted_python('range(3, 6)'), [command_block(0, 'test_python')])) - case2 = ('range', (const_number('1'), const_number('2'), [command_block(0, 'test_range_1_2')])) - block = switch_block(0, num_expr(1), [case1, case2]) - block.compile(func) - - block = tell_block(0, '@a', '{rhi') - block.compile(func) - - func.template_functions['test_template_function'] = ([], [], [command_block(0, 'test_command')]) - block = template_function_call_block(0, 'test_template_function', [], []) - block.compile(func) - - block = title_block(0, 'subtitle', '@a', [const_number('1'), const_number('2'), const_number('3')], '{rtest') - block.compile(func) - - var = ('VAR_ID', 'test') - block = vector_assignment_block(0, var, '+=', vector_here_expr(const_number(1000))) - block.compile(func) - - var = ('VAR_ID', 'test') - block = vector_assignment_scalar_block(0, var, '+=', num_expr(1)) - block.compile(func) - - block = while_block(0, [], [command_block(0, 'test_command')]) - block.compile(func) - - def test_compile_vector_assignment_scalar(self): - func = mock_mcfunction() - - block = vector_assignment_scalar_block(0, ('VAR_ID', 'test_vector'), '*=', num_expr(2)) - block.compile(func) - - self.assertEqual(len(func.commands), 4) - self.assertEqual(func.commands[0], 'scoreboard players set Global test_scratch1 2') - for i in range(3): - self.assertEqual(func.commands[i+1], f'scoreboard players operation Global _test_vector_{i} *= Global test_scratch1') - - def test_compile_vector_assignment(self): - func = mock_mcfunction() - - block = vector_assignment_block(0, ('VAR_ID', 'test_vector'), '+=', vector_expr([num_expr(2), num_expr(3), num_expr(4)])) - block.compile(func) - - self.assertEqual(len(func.commands), 6) - for i in range(3): - self.assertEqual(func.commands[i], f'scoreboard players set Global test_scratch{i+1} {i+2}') - self.assertEqual(func.commands[i+3], f'scoreboard players operation Global _test_vector_{i} += Global test_scratch{i+1}') - - def test_compile_comment(self): - func = mock_mcfunction() - - block = comment_block(0, '#test') - block.compile(func) - self.assertTrue('#test' in func.commands) - - def test_compile_command(self): - func = mock_mcfunction() - block = command_block(0, 'say hi') - block.compile(func) - self.assertTrue('say hi' in func.commands) - - def test_compile_move(self): - func = mock_mcfunction() - block = move_block(0, '@s', dummy_relcoords(1, 1, 1)) - block.compile(func) - self.assertTrue('execute at @s run tp @s 1 1 1' in func.commands) - - block = move_block(0, '@a', relcoords(( - relcoord('^', const_number(0)), - relcoord('^', const_number(0)), - relcoord('^', const_number(1)), - ))) - block.compile(func) - self.assertTrue('execute as @a at @s run tp @s ^0 ^0 ^1' in func.commands) - - def test_compile_python_assignment(self): - func = mock_mcfunction() - - block = python_assignment_block(0, 'test', interpreted_python('1+1', 0)) - block.compile(func) - self.assertTrue('test' in func.dollarid) - self.assertEqual(func.dollarid['test'], 2) - - block = python_assignment_block(0, 'test2', interpreted_python('1/0', 0)) - with self.assertRaises(Exception) as context: - block.compile(func) - self.assertEqual(len(func.dollarid), 1) - - block = python_assignment_block(0, 'test3', interpreted_python('math.sqrt(9)', 0)) - block.compile(func) - self.assertTrue('test3' in func.dollarid) - self.assertEqual(func.dollarid['test3'], 3) - - def test_compile_python_for(self): - func = mock_mcfunction() - - block = python_for_block(0, 'i', interpreted_python('range(3)', 0), [command_block(0, '/say $i')]) - block.compile(func) - - block = python_for_block(0, 'i', interpreted_python('[]', 0), []) - block.compile(func) - - block = python_for_block(0, 'i', '1', []) - with self.assertRaises(Exception) as context: - block.compile(func) - - block = python_for_block(0, 'i', 'range(1/0)', []) - with self.assertRaises(Exception) as context: - block.compile(func) - - def test_compile_selector_assignment(self): - func = mock_mcfunction() - - block = selector_assignment_block(0, 'test', '@s[x=1]') - block.compile(func) - - self.assertEqual(func.selectors['test'].selector, '@s[x=1]') - - def test_compile_array_assignment(self): - func = mock_mcfunction() - func.arrays['test_array'] = (0, 5) - - block = array_assignment_block(0, 'test_array', 'Const', 1, num_expr(2)) - block.compile(func) - self.assertTrue('scoreboard players set Global test_array1 2' in func.commands) - - func.arrays['test_array2'] = (0, 10) - block = array_assignment_block(0, 'test_array2', 'Expr', num_expr(2), num_expr(3)) - block.compile(func) - self.assertTrue('scoreboard players set Global test_array2Val 3' in func.commands) - self.assertTrue('scoreboard players set Global test_array2Idx 2' in func.commands) - self.assertTrue('function test_namespace:array_test_array2_set' in func.commands) - - def test_compile_array_definition(self): - func = mock_mcfunction() - - block = array_definition_block(0, 'test_array', const_number(0), const_number(5)) - block.compile(func) - - self.assertTrue('test_array' in func.arrays) - self.assertEqual(func.arrays['test_array'], (0, 5)) - - self.assertEqual(len(func.child_functions), 2) - self.assertTrue('array_test_array_set' in func.functions) - self.assertTrue('array_test_array_get' in func.functions) - - def test_compile_block_tag(self): - func = mock_mcfunction() - - block = block_tag_block(0, 'test_block_tag', ['test_block', 'test_block2']) - block.compile(func) - - self.assertTrue('test_block_tag' in func.block_tags) - self.assertTrue(func.block_tags['test_block_tag'] == ['test_block', 'test_block2']) - - def test_compile_create(self): - func = mock_mcfunction() - - block = create_block(0, '@test', ['0', '0', '0']) - block.compile(func) - - self.assertEqual(len(func.created), 1) - - def test_compile_execute(self): - func = mock_mcfunction() - - block = execute_block(0, 'test', 'sub') - block.compile(func) - - self.assertEqual(len(func.child_functions), 1) - self.assertEqual(func.execute_command_calls, ['test']) - - def test_compile_for_selector(self): - func = mock_mcfunction() - - block = for_selector_block(0, 'test', '@a', command_block(1, 'test_command')) - block.compile(func) - - self.assertEqual(len(func.child_functions), 1) - self.assertTrue('test' in func.child_functions[0].selectors) - - def test_compile_for_index(self): - func = mock_mcfunction() - - block = for_index_block(0, 'test_idx', num_expr(1), num_expr(5), num_expr(2), []) - block.compile(func) - - self.assertEqual(func.commands, [ - 'scoreboard players set Global test_idx 1', - 'scoreboard players set Global test_scratch1 5', - 'scoreboard players set Global test_scratch2 2', - 'execute if score Global test_scratch2 matches ..-1 if score Global test_idx >= Global test_scratch1 run function test_namespace:for001_ln0', - 'execute if score Global test_scratch2 matches 1.. if score Global test_idx <= Global test_scratch1 run function test_namespace:for001_ln0' - ]) - - self.assertEqual(len(func.child_functions), 1) - self.assertEqual(func.child_functions[0].commands, [ - 'scoreboard players operation Global test_idx += Global test_scratch2', - 'execute if score Global test_scratch2 matches ..-1 if score Global test_idx >= Global test_scratch1 run function test_namespace:for001_ln0', - 'execute if score Global test_scratch2 matches 1.. if score Global test_idx <= Global test_scratch1 run function test_namespace:for001_ln0' - ]) - - def test_compile_function_call(self): - func = mock_mcfunction() - - block = function_call_block(0, 'test_function', [num_expr(1)]) - block.compile(func) - - self.assertEqual(func.commands, ['function test_namespace:test_function']) - - def test_compile_macro_call(self): - func = mock_mcfunction() - macro = (['test_param'],[]) - func.macros['test_macro'] = macro - - block = macro_call_block(0, 'test_macro', [const_number('10')]) - block.compile(func) - - self.assertEqual(len(func.child_functions), 0) - self.assertEqual(len(func.cloned_environments), 1) - self.assertTrue('test_param' in func.cloned_environments[0].dollarid) - self.assertEqual(func.cloned_environments[0].dollarid['test_param'], 10) - - self.assertEqual(func.environment_pushes, 1) - self.assertEqual(func.environment_pops, 1) - - def test_compile_method_call(self): - func = mock_mcfunction() - - block = method_call_block(0, '@test_selector', 'test_method', [num_expr(1)]) - block.compile(func) - - self.assertEqual(func.commands, ['execute as @test_selector run function test_namespace:test_method']) - - def test_compile_python_if(self): - func = mock_mcfunction() - - block = python_if_block(0, interpreted_python('1', 0), [1], [2]) - block.compile(func) - - self.assertTrue([1] in func.compiled_blocks) - - func = mock_mcfunction() - - block = python_if_block(0, interpreted_python('0', 0), [1], [2]) - block.compile(func) - - self.assertTrue([2] in func.compiled_blocks) - - func = mock_mcfunction() - - block = python_if_block(0, interpreted_python('1', 0), [1], None) - block.compile(func) - - self.assertTrue([1] in func.compiled_blocks) - - func = mock_mcfunction() - - block = python_if_block(0, interpreted_python('0', 0), [1], None) - block.compile(func) - - self.assertEqual(len(func.compiled_blocks), 0) - - def test_compile_scoreboard_assignment(self): - func = mock_mcfunction() - - var = ('Var', ('Global', 'test_var')) - block = scoreboard_assignment_block(0, (var, '+=', num_expr(1))) - block.compile(func) - - self.assertEqual(func.commands, ['/scoreboard players add Global var1 1']) - - func = mock_mcfunction() - - block = scoreboard_assignment_block(0, (var, '=', num_expr(1))) - block.compile(func) - - self.assertEqual(func.commands, ['/scoreboard players set Global var1 1']) - - func = mock_mcfunction() - - block = scoreboard_assignment_block(0, (var, '*=', num_expr(1))) - block.compile(func) - - self.assertEqual(func.commands, ['/scoreboard players operation Global var1 *= test_constant Constant']) - self.assertTrue(1 in func.constants) - - def test_compile_selector_definition(self): - func = mock_mcfunction() - - items = [ - ('Tag', '{}'), - ('Path', ('test_path', 'path.to.data', 'float', const_number(100))), - ('VectorPath', ('test_vector_path', 'path.to.vector', 'int', const_number(200))), - ('Method', ('function', 'test_method', [], [], [])), - ] - block = selector_definition_block(0, 'test_selector', '@a', items) - block.compile(func) - - self.assertTrue('test_selector' in func.selectors) - - selector = func.selectors['test_selector'] - self.assertEqual(selector.selector, '@a') - - self.assertTrue('test_path' in selector.paths) - self.assertEqual(selector.paths['test_path'], ('path.to.data', 'float', 100)) - - self.assertTrue('test_vector_path' in selector.vector_paths) - self.assertEqual(selector.vector_paths['test_vector_path'], ('path.to.vector', 'int', 200)) - - # TODO: verify the method was created - - def test_compile_switch(self): - func = mock_mcfunction() - - case1 = ('range',(const_number(1), const_number(3), [])) - case2 = ('python', ('test_id', interpreted_python('range(4, 6)'), [])) - block = switch_block(0, num_expr(2), [case1, case2]) - block.compile(func) - - self.assertEqual(func.switch_calls, [( - 'test_scratch1', - [ - (1, 3, [], 'Unknown', None), - (4, 4, [], 'Unknown', 'test_id'), - (5, 5, [], 'Unknown', 'test_id') - ], - 'switch', - 'case') - ]) - self.assertEqual(func.commands, ['scoreboard players set Global test_scratch1 2']) - - def test_compile_tell(self): - func = mock_mcfunction() - - block = tell_block(0, '@a', '{rhi') - block.compile(func) - - self.assertEqual(func.commands, ['/tellraw @a ["",{"text":"hi","color":"dark_red"}]']) - - def test_compile_template_function_call(self): - func = mock_mcfunction() - func.template_functions['test_template_function'] = (['test_macro_param'], ['test_function_param'], []) - - block = template_function_call_block(0, 'test_template_function', [const_number('10')], [num_expr('15')]) - block.compile(func) - - self.assertEqual(func.commands, [ - 'scoreboard players set Global Param0 15', - 'function test_namespace:test_template_function_10' - ]) - self.assertTrue('test_template_function_10' in func.functions) - self.assertTrue('test_macro_param' in func.functions['test_template_function_10'].environment.dollarid) - self.assertEqual(func.functions['test_template_function_10'].environment.dollarid['test_macro_param'], 10) - - func = mock_mcfunction() - func.template_functions['test_template_function'] = (['test_macro_param'], [], []) - func.dollarid['test_id'] = 5 - - block = template_function_call_block(0, 'test_template_function', [python_identifier('test_id')], []) - block.compile(func) - - self.assertTrue('test_template_function_5' in func.functions) - self.assertEqual(func.functions['test_template_function_5'].environment.dollarid['test_macro_param'], 5) - - def test_compile_title(self): - func = mock_mcfunction() - - block = title_block(0, 'subtitle', '@a', [const_number('0'), const_number('1'), const_number('2')], '{rtest') - block.compile(func) - - self.assertEqual(func.commands, [ - '/title @a times 0 1 2', - '/title @a subtitle ["",{"text":"test","color":"dark_red"}]' - ]) - - def test_compile_while(self): - func = mock_mcfunction() - - block = while_block(0, 'test', ['test_block']) - block.compile(func) - - self.assertEqual(func.commands, ['execute_dummy run function test_namespace:while001_ln0']) - self.assertEqual(func.execute_command_calls, ['test']) - self.assertEqual(len(func.child_functions), 1) - self.assertEqual(func.child_functions[0].compiled_blocks[0], ['test_block']) - self.assertTrue('execute_dummy run function test_namespace:while001_ln0' in func.child_functions[0].commands) - - def test_arrayconst_expr(self): - func = mock_mcfunction() - func.arrays['test_array'] = (0, 5) - - expr = arrayconst_expr('test_array', '1') - id = expr.compile(func, None) - - self.assertEqual(id, 'test_array1') - - def test_arrayexpr_expr(self): - func = mock_mcfunction() - func.arrays['test_array'] = (0, 5) - - expr = arrayexpr_expr('test_array', num_expr(3)) - id = expr.compile(func, None) - - self.assertEqual(id, 'test_arrayVal') - - def test_binop_expr(self): - func = mock_mcfunction() - - expr = binop_expr(num_expr(3), '+', num_expr(4)) - id = expr.compile(func, 'test_id') - - self.assertEqual(id, 'test_id') - self.assertTrue('scoreboard players set Global test_id 3' in func.commands) - self.assertTrue('scoreboard players add Global test_id 4' in func.commands) - - expr = binop_expr(num_expr(3), '+', selvar_expr('Global', 'test_var')) - id = expr.compile(func, 'test_id2') - - self.assertEqual(id, 'test_id2') - self.assertTrue('scoreboard players operation Global test_id2 = Global test_var' in func.commands) - self.assertTrue('scoreboard players add Global test_id2 3' in func.commands) - - expr = binop_expr(num_expr(5), '^', num_expr(2)) - id = expr.compile(func, 'test_id3') - - self.assertEqual(id, 'test_scratch1') - self.assertEqual(func.commands, [ - 'scoreboard players set Global test_id 3', - 'scoreboard players add Global test_id 4', - 'scoreboard players operation Global test_id2 = Global test_var', - 'scoreboard players add Global test_id2 3', - 'scoreboard players set Global test_id3 5', - 'scoreboard players operation Global test_scratch1 = Global test_id3', - 'scoreboard players operation Global test_scratch1 *= Global test_id3' - ]) - - expr = binop_expr(num_expr(5), '^', selvar_expr('Global', 'test_var')) - id = expr.compile(func, 'test_id4') - self.assertEqual(id, None) - - def test_create_expr(self): - func = mock_mcfunction() - - expr = create_expr(create_block(0, '@test', ['0', '0', '0'])) - id = expr.compile(func, 'test_id') - - self.assertEqual(id, 'test_id') - self.assertEqual(func.commands, [ - 'scoreboard players add @e _age 1', - 'scoreboard players add @e _age 1', - 'scoreboard players add Global _unique 1', - 'scoreboard players operation @@test[_age==1] _id = Global _unique', - 'scoreboard players operation Global test_id = Global _unique']) - self.assertEqual(func.created, [('@test', ['0', '0', '0'])]) - - def test_dot_expr(self): - func = mock_mcfunction() - - expr = dot_expr(vector_var_expr('vec1'), vector_var_expr('vec2')) - id = expr.compile(func, 'test_id5') - - self.assertEqual(id, 'test_scratch1') - self.assertEqual(len(func.commands), 8) - - def test_func_expr(self): - func = mock_mcfunction() - - expr = func_expr(function_call_block(0, 'sin', [num_expr(1)])) - id = expr.compile(func, 'test_id') - - self.assertEqual(id, 'test_id') - self.assertEqual(func.commands, [ - 'scoreboard players set Global test_scratch1 1', - 'scoreboard players operation Global temp1 = Global test_scratch1', - 'scoreboard players operation Global temp1 %= test_constant Constant', - 'scoreboard players add Global temp1 360', - 'scoreboard players operation Global temp1 %= test_constant Constant', - 'scoreboard players operation Global test_id = Global test_scratch1', - 'scoreboard players operation Global temp2 = Global temp1', - 'scoreboard players operation Global temp2 %= test_constant Constant', - 'scoreboard players operation Global test_id = Global temp2', - 'scoreboard players operation Global test_id *= test_constant Constant', - 'scoreboard players set Global test_scratch2 180', - 'scoreboard players operation Global test_scratch3 = Global test_scratch2', - 'scoreboard players operation Global test_scratch3 -= Global temp2', - 'scoreboard players operation Global test_id *= Global test_scratch3', - 'scoreboard players set Global test_scratch4 40500', - 'scoreboard players operation Global test_scratch5 = Global test_scratch4', - 'scoreboard players operation Global test_scratch6 = Global temp2', - 'scoreboard players set Global test_scratch7 180', - 'scoreboard players operation Global test_scratch8 = Global test_scratch7', - 'scoreboard players operation Global test_scratch8 -= Global temp2', - 'scoreboard players operation Global test_scratch6 *= Global test_scratch8', - 'scoreboard players operation Global test_scratch5 -= Global test_scratch6', - 'scoreboard players operation Global test_id /= Global test_scratch5', - 'execute if score Global temp1 matches 180.. run scoreboard players operation Global test_id *= minus Constant' - ]) - - func = mock_mcfunction() - - expr = func_expr(function_call_block(0, 'cos', [num_expr(1)])) - id = expr.compile(func, 'test_id') - - self.assertEqual(id, 'test_id') - self.assertEqual(func.commands, [ - 'scoreboard players set Global test_scratch1 1', - 'scoreboard players operation Global temp1 = Global test_scratch1', - 'scoreboard players operation Global temp1 %= test_constant Constant', - 'scoreboard players add Global temp1 450', - 'scoreboard players operation Global temp1 %= test_constant Constant', - 'scoreboard players operation Global test_id = Global test_scratch1', - 'scoreboard players operation Global temp2 = Global temp1', - 'scoreboard players operation Global temp2 %= test_constant Constant', - 'scoreboard players operation Global test_id = Global temp2', - 'scoreboard players operation Global test_id *= test_constant Constant', - 'scoreboard players set Global test_scratch2 180', - 'scoreboard players operation Global test_scratch3 = Global test_scratch2', - 'scoreboard players operation Global test_scratch3 -= Global temp2', - 'scoreboard players operation Global test_id *= Global test_scratch3', - 'scoreboard players set Global test_scratch4 40500', - 'scoreboard players operation Global test_scratch5 = Global test_scratch4', - 'scoreboard players operation Global test_scratch6 = Global temp2', - 'scoreboard players set Global test_scratch7 180', - 'scoreboard players operation Global test_scratch8 = Global test_scratch7', - 'scoreboard players operation Global test_scratch8 -= Global temp2', - 'scoreboard players operation Global test_scratch6 *= Global test_scratch8', - 'scoreboard players operation Global test_scratch5 -= Global test_scratch6', - 'scoreboard players operation Global test_id /= Global test_scratch5', - 'execute if score Global temp1 matches 180.. run scoreboard players operation Global test_id *= minus Constant' - ]) - - func = mock_mcfunction() - - expr = func_expr(function_call_block(0, 'sqrt', [num_expr(1)])) - id = expr.compile(func, 'test_id') - - self.assertEqual(id, 'test_scratch62') - self.assertEqual(len(func.commands), 107) - - func = mock_mcfunction() - - expr = func_expr(function_call_block(0, 'sqrt', [])) - id = expr.compile(func, 'test_id') - - self.assertEqual(id, None) - - func = mock_mcfunction() - - expr = func_expr(function_call_block(0, 'abs', [num_expr(-1)])) - id = expr.compile(func, 'test_id') - - self.assertEqual(id, 'test_id') - self.assertEqual(func.commands, [ - 'scoreboard players set Global test_id -1', - 'execute if score Global test_id matches ..-1 run scoreboard players operation Global test_id *= minus Constant' - ]) - - func = mock_mcfunction() - - expr = func_expr(function_call_block(0, 'abs', [])) - id = expr.compile(func, 'test_id') - - self.assertEqual(id, None) - - func = mock_mcfunction() - - expr = func_expr(function_call_block(0, 'rand', [num_expr(10)])) - id = expr.compile(func, 'test_id') - - self.assertEqual(id, 'test_scratch1') - self.assertEqual(func.commands, [ - 'scoreboard players set Global test_scratch1 0', - 'scoreboard players operation Global test_scratch1 += @e[type=armor_stand, test_random_objective <= 1, limit=1, sort=random] test_random_objective', - 'scoreboard players operation Global test_scratch1 *= test_constant Constant', - 'scoreboard players operation Global test_scratch1 += @e[type=armor_stand, test_random_objective <= 4, limit=1, sort=random] test_random_objective' - ]) - - func = mock_mcfunction() - - expr = func_expr(function_call_block(0, 'rand', [num_expr(2), num_expr(10)])) - id = expr.compile(func, 'test_id') - - self.assertEqual(id, 'test_scratch1') - self.assertEqual(func.commands, [ - 'scoreboard players set Global test_scratch1 0', - 'scoreboard players operation Global test_scratch1 += @e[type=armor_stand, test_random_objective <= 1, limit=1, sort=random] test_random_objective', - 'scoreboard players operation Global test_scratch1 *= test_constant Constant', 'scoreboard players operation Global test_scratch1 += @e[type=armor_stand, test_random_objective <= 1, limit=1, sort=random] test_random_objective', - 'scoreboard players operation Global test_scratch1 *= test_constant Constant', 'scoreboard players operation Global test_scratch1 += @e[type=armor_stand, test_random_objective <= 1, limit=1, sort=random] test_random_objective', - 'scoreboard players add Global test_scratch1 2' - ]) - - func = mock_mcfunction() - - expr = func_expr(function_call_block(0, 'test_function', [])) - id = expr.compile(func, 'test_id') - - self.assertEqual(id, 'ReturnValue') - self.assertTrue('function test_namespace:test_function' in func.commands) - - def test_num_expr(self): - func = mock_mcfunction() - - expr = num_expr(5) - self.assertEqual(int(expr.const_value(func)), 5) - id = expr.compile(func, 'test_id') - - self.assertEqual(id, 'test_id') - self.assertTrue('scoreboard players set Global test_id 5' in func.commands) - - def test_scale_expr(self): - func = mock_mcfunction() - - expr = scale_expr() - self.assertEqual(expr.const_value(func), 1000) - id = expr.compile(func, 'test_id') - - self.assertEqual(id, 'test_id') - self.assertTrue('scoreboard players set Global test_id 1000' in func.commands) - - def test_selector_expr(self): - func = mock_mcfunction() - func.check_single_entity = lambda (x): True - - expr = selector_expr('@p') - id = expr.compile(func, 'test_id') - - self.assertEqual(id, 'test_id') - self.assertEqual(func.commands, [ - 'scoreboard players add Global _unique 1', - 'execute unless score @p _id matches 0.. run scoreboard players operation @p _id = Global _unique', - 'scoreboard players operation Global test_id = @p _id' - ]) - - def test_selvar_expr(self): - func = mock_mcfunction() - - expr = selvar_expr('@a', 'test_var') - id = expr.compile(func, 'test_id') - - self.assertEqual(id, 'test_id') - self.assertTrue('scoreboard players operation Global test_id = @a test_var' in func.commands) - - def test_unary_expr(self): - func = mock_mcfunction() - - expr = unary_expr('-', num_expr(5)) - id = expr.compile(func, 'test_id') - - self.assertEqual(id, 'test_id') - self.assertTrue('scoreboard players set Global test_id 5' in func.commands) - self.assertTrue('scoreboard players operation Global test_id *= minus Constant' in func.commands) - - def test_sel_vector_var_expr(self): - func = mock_mcfunction() - - expr = sel_vector_var_expr('@test', 'test_var') - ids = expr.compile(func, ['x', 'y', 'z']) - - self.assertEqual(ids, ['x', 'y', 'z']) - for left, right in [('x', 0), ('y', 1), ('z', 2)]: - self.assertTrue(f'scoreboard players operation Global {left} = @test _test_var_{right}'in func.commands) - - def test_vector_binop_scalar_expr(self): - func = mock_mcfunction() - - expr = vector_binop_scalar_expr(vector_var_expr('test_vector'), '*', num_expr(2)) - ids = expr.compile(func, ['x', 'y', 'z']) - - self.assertEqual(ids, ['x', 'y', 'z']) - self.assertEqual(func.commands, [ - 'scoreboard players operation Global x = Global _test_vector_0', - 'scoreboard players operation Global y = Global _test_vector_1', - 'scoreboard players operation Global z = Global _test_vector_2', - 'scoreboard players set Global test_scratch1 2', - 'scoreboard players operation Global x *= Global test_scratch1', - 'scoreboard players operation Global y *= Global test_scratch1', - 'scoreboard players operation Global z *= Global test_scratch1' - ]) - - def test_vector_binop_vector_expr(self): - func = mock_mcfunction() - - expr = vector_binop_vector_expr(vector_var_expr('test_vector1'), '+', vector_var_expr('test_vector2')) - ids = expr.compile(func, ['x', 'y', 'z']) - - self.assertEqual(ids, ['x', 'y', 'z']) - self.assertEqual(func.commands, [ - 'scoreboard players operation Global x = Global _test_vector1_0', - 'scoreboard players operation Global y = Global _test_vector1_1', - 'scoreboard players operation Global z = Global _test_vector1_2', - 'scoreboard players operation Global x += Global _test_vector2_0', - 'scoreboard players operation Global y += Global _test_vector2_1', - 'scoreboard players operation Global z += Global _test_vector2_2' - ]) - - def test_vector_expr(self): - func = mock_mcfunction() - - expr = vector_expr([num_expr(1), num_expr(2), num_expr(3)]) - ids = expr.compile(func, ['x', 'y', 'z']) - - self.assertEqual(ids, ['x', 'y', 'z']) - for left, right in [('x', 1), ('y', 2), ('z', 3)]: - self.assertTrue(f'scoreboard players set Global {left} {right}'in func.commands) - - def test_vector_here_expr(self): - func = mock_mcfunction() - - expr = vector_here_expr(const_number(100)) - ids = expr.compile(func, ['x', 'y', 'z']) - - self.assertEqual(ids, ['x', 'y', 'z']) - self.assertEqual(func.commands, [ - 'scoreboard players add @e _age 1', - 'summon area_effect_cloud', - 'scoreboard players add @e _age 1', - 'execute store result score Global x run data get entity @e[_age==1,limit=1] Pos[0] 100', - 'execute store result score Global y run data get entity @e[_age==1,limit=1] Pos[1] 100', - 'execute store result score Global z run data get entity @e[_age==1,limit=1] Pos[2] 100', - '/kill @e[_age==1]' - ]) - - def test_vector_var_expr(self): - func = mock_mcfunction() - - expr = vector_var_expr('test_vector') - ids = expr.compile(func, ['x', 'y', 'z']) - - self.assertEqual(ids, ['_test_vector_0', '_test_vector_1', '_test_vector_2']) - - def test_selector_definition(self): - env = mock_environment() - - sel = selector_definition('@a', env) - self.assertEqual(sel.compile(), '@a[]') - - env = mock_environment() - - sel = selector_definition('@a[test>0]', env) - self.assertEqual(sel.compile(), '@a[scores={test=1..}]') - - env = mock_environment() - env.selectors['test_selector'] = selector_definition('@a[nbt={test:"test_val"}]', env) - - sel = selector_definition('@test_selector[nbt={test2:"test_val2"}]', env) - # TODO: merge nbt tags via the json module - self.assertEqual(sel.compile(), '@a[nbt={test:"test_val"},nbt={test2:"test_val2"}]') - - env = mock_environment() - - sel = selector_definition('@a[test==0]', env) - self.assertEqual(sel.compile(), '@a[scores={test=0}]') - - env = mock_environment() - - sel = selector_definition('@a[test>=0,test<=0]', env) - self.assertEqual(sel.compile(), '@a[scores={test=0}]') - - env = mock_environment() - - sel = selector_definition('@e[type=creeper]', env) - self.assertEqual(sel.compile(), '@e[type=minecraft:creeper]') - self.assertEqual(sel.get_type(), 'minecraft:creeper') - self.assertFalse(sel.single_entity()) - - env = mock_environment() - - sel = selector_definition('@e[limit=1]', env) - self.assertTrue(sel.single_entity()) - - env = mock_environment() - - sel = selector_definition('@p', env) - self.assertTrue(sel.single_entity()) - - env = mock_environment() - - sel = selector_definition('@s', env) - self.assertTrue(sel.single_entity()) - - env = mock_environment() - env.selectors['test_selector'] = selector_definition('@e[test==0]', env) - env.selectors['test_selector'].set_part('type', 'creeper') - env.selectors['test_selector'].paths['test_path'] = 1 - env.selectors['test_selector'].vector_paths['test_vector_path'] = 2 - - sel = selector_definition('@test_selector[test2>0]', env) - self.assertEqual(sel.compile(), '@e[type=creeper,scores={test=0,test2=1..}]') - self.assertEqual(sel.paths['test_path'], 1) - self.assertEqual(sel.vector_paths['test_vector_path'], 2) - - env = mock_environment() - - with self.assertRaises(ValueError): - selector_definition('@none', env) - - env = mock_environment() - - sel = selector_definition('@e[nbt={test:"test_val",test2:{test3:"test_val3"}}]', env) - # TODO: merge nbt tags via the json module - self.assertEqual(sel.compile(), '@e[nbt={test:"test_val",test2:{test3:"test_val3"}}]') - - env = mock_environment() - - with self.assertRaises(SyntaxError): - sel = selector_definition('@a[test>test2]', env) - - def test_get_friendly_name(self): - self.assertEqual(global_context.get_friendly_name('test .,:{}='), 'CBtest_______') - - def test_global_context_register_block_tag(self): - gc = global_context.global_context('test_namespace') - - gc.register_block_tag('test_block_tag', ['test_block']) - self.assertEqual(gc.block_tags['test_block_tag'], ['test_block']) - - def test_global_context_get_unique_id(self): - gc = global_context.global_context('test_namespace') - - self.assertEqual(gc.get_unique_id(), 1) - self.assertEqual(gc.get_unique_id(), 2) - - def test_global_context_register_clock(self): - gc = global_context.global_context('test_namespace') - - gc.register_clock('test_clock') - self.assertEqual(gc.clocks, ['test_clock']) - - def test_global_context_register_function(self): - gc = global_context.global_context('test_namespace') - f = mock_mcfunction() - - gc.register_function('test_function', f) - self.assertEqual(gc.functions['test_function'], f) - with self.assertRaises(Exception): - gc.register_function('test_function', f) - - def test_global_context_register_array(self): - gc = global_context.global_context('test_namespace') - - gc.register_array('test_array', 0, 5) - self.assertEqual(gc.arrays['test_array'], (0, 5)) - with self.assertRaises(Exception): - gc.register_array('test_array', 0, 5) - - def test_global_context_register_objective(self): - gc = global_context.global_context('test_namespace') - - gc.register_objective('test_objective') - self.assertTrue('test_objective' in gc.objectives) - - with self.assertRaises(Exception): - gc.register_objective('test_objective_name_too_long') - - def test_global_context_get_constant_name(self): - gc = global_context.global_context('test_namespace') - f = mock_mcfunction() - - gc.register_function('reset', f) - self.assertEqual(gc.get_reset_function(), f) - - self.assertEqual(global_context.get_constant_name(0), 'c0') - self.assertEqual(global_context.get_constant_name(1), 'c1') - self.assertEqual(global_context.get_constant_name(-1), 'minus') - self.assertEqual(global_context.get_constant_name(-2), 'cm2') - - def test_global_context_add_constant(self): - gc = global_context.global_context('test_namespace') - - self.assertEqual(gc.add_constant(1), 'c1') - self.assertTrue(1 in gc.constants) - - def test_global_context_add_constant_definitions(self): - gc = global_context.global_context('test_namespace') - f = mock_mcfunction() - - gc.register_function('reset', f) - gc.add_constant(1) - gc.add_constant(-1) - gc.add_constant_definitions() - - self.assertEqual(f.commands, [ - '/scoreboard objectives add Constant dummy', - '/scoreboard players set minus Constant -1', - '/scoreboard players set c1 Constant 1' - ]) - - def test_global_context_allocate_scratch(self): - gc = global_context.global_context('test_namespace') - - gc.allocate_scratch('test_prefix', 2) - self.assertEqual(gc.scratch['test_prefix'], 2) - gc.allocate_scratch('test_prefix', 3) - self.assertEqual(gc.scratch['test_prefix'], 3) - gc.allocate_scratch('test_prefix', 2) - self.assertEqual(gc.scratch['test_prefix'], 3) - - def test_global_context_allocate_temp(self): - gc = global_context.global_context('test_namespace') - - gc.allocate_temp(2) - self.assertEqual(gc.temp, 2) - gc.allocate_temp(3) - self.assertEqual(gc.temp, 3) - gc.allocate_temp(2) - self.assertEqual(gc.temp, 3) - - def test_global_context_allocate_rand(self): - gc = global_context.global_context('test_namespace') - - gc.allocate_rand(2) - self.assertEqual(gc.rand, 2) - gc.allocate_rand(3) - self.assertEqual(gc.rand, 3) - gc.allocate_rand(2) - self.assertEqual(gc.rand, 3) - - def test_global_context_finalize_functions(self): - gc = global_context.global_context('test_namespace') - f = mock_mcfunction() - - gc.register_function('reset', f) - gc.finalize_functions() - - self.assertTrue(f.finalized) - - def test_global_context_get_scratch_prefix(self): - gc = global_context.global_context('test_namespace') - - self.assertEqual(gc.get_scratch_prefix('test'), 'tes') - self.assertEqual(gc.get_scratch_prefix('test'), 'tes2') - self.assertEqual(gc.get_scratch_prefix('test'), 'tes3') - - def test_global_context_get_random_objective(self): - gc = global_context.global_context('test_namespace') - - self.assertEqual(gc.get_random_objective(), 'RVtest_namespace') - - def test_scratch_tracker_temp(self): - gc = mock_global_context() - - st = scratch_tracker(gc) - self.assertEqual(st.get_temp_var(), 'temp0') - self.assertEqual(st.temp[0], True) - self.assertEqual(st.get_temp_var(), 'temp1') - self.assertEqual(st.temp[1], True) - st.free_temp_var('temp0') - self.assertEqual(st.temp[0], False) - self.assertEqual(st.temp[1], True) - self.assertEqual(gc.temp, 2) - self.assertEqual(st.get_temp_var(), 'temp0') - - def test_scratch_tracker_scratch(self): - gc = mock_global_context() - - st = scratch_tracker(gc) - st.prefix = 'test' - self.assertEqual(st.get_scratch(), 'test_scratch0') - self.assertEqual(st.scratch[0], True) - self.assertEqual(st.get_scratch(), 'test_scratch1') - self.assertEqual(st.scratch[1], True) - st.free_scratch('test_scratch0') - self.assertEqual(st.scratch[0], False) - self.assertEqual(st.scratch[1], True) - self.assertEqual(gc.scratch['test'], 2) - self.assertEqual(st.get_scratch(), 'test_scratch0') - - st.free_scratch('not_scratch') - - def test_scratch_tracker_vector(self): - gc = mock_global_context() - - st = scratch_tracker(gc) - st.prefix = 'test' - - self.assertEqual(st.get_scratch_vector(), ['test_scratch0', 'test_scratch1', 'test_scratch2']) - self.assertEqual(gc.scratch['test'], 3) - for i in range(3): - self.assertEqual(st.scratch[i], True) - - def test_scratch_tracker_get_allocated_variables(self): - gc = mock_global_context() - - st = scratch_tracker(gc) - st.prefix = 'test' - - st.get_scratch() - st.get_scratch() - st.get_scratch() - st.free_scratch('test_scratch1') - - st.get_temp_var() - st.get_temp_var() - st.get_temp_var() - st.free_temp_var('temp0') - - self.assertEqual(st.get_allocated_variables(), [ - 'test_scratch0', - 'test_scratch1', - 'test_scratch2', - 'temp0', - 'temp1', - 'temp2' - ]) - - def test_cbscript_check_for_update(self): - source = mock_source_file() - source.updated = False - - compiles = [0] - - script = cbscript(source, None) - script.compiles = 0 - - def count_compiles(self): - self.compiles += 1 - script.try_to_compile = new.instancemethod(count_compiles, script, None) - - self.assertEqual(script.compiles, 0) - script.check_for_update() - self.assertEqual(script.compiles, 0) - source.updated = True - script.check_for_update() - self.assertEqual(script.compiles, 1) - - def test_cbscript_try_to_compile(self): - source = mock_source_file() - - script = cbscript(source, None) - script.log_lines = [] - def mock_log(self, text): - self.log_lines.append(text) - script.log = new.instancemethod(mock_log, script, None) - script.compile_all = new.instancemethod(lambda s: True, script, None) - - script.try_to_compile() - self.assertEqual(script.log_lines, [ - 'Compiling unittest...', - 'Script successfully applied.' - ]) - - script = cbscript(source, None) - script.log_lines = [] - script.log = new.instancemethod(mock_log, script, None) - script.compile_all = new.instancemethod(lambda s: False, script, None) - - script.try_to_compile() - self.assertEqual(script.log_lines, [ - 'Compiling unittest...', - 'Script had compile error(s).\x07' - ]) - - def bad_parse(text): - raise SyntaxError('Test error') - script = cbscript(source, bad_parse) - script.log_lines = [] - script.log = new.instancemethod(mock_log, script, None) - - script.try_to_compile() - self.assertEqual(script.log_lines, [ - 'Compiling unittest...', - 'Test error\x07' - ]) - - def bad_compile(text): - raise Exception('Test exception') - script = cbscript(source, None) - script.log_lines = [] - script.log = new.instancemethod(mock_log, script, None) - script.tracebacks = 0 - def mock_log_traceback(self): - self.tracebacks += 1 - script.log_traceback = new.instancemethod(mock_log_traceback, script, None) - script.compile_all = new.instancemethod(bad_compile, script, None) - - script.try_to_compile() - self.assertEqual(script.log_lines, [ - 'Compiling unittest...', - 'Compiler encountered unexpected error during compilation:\x07' - ]) - self.assertEqual(script.tracebacks, 1) - - def test_cbscript_compile_all(self): - source = mock_source_file() - - parsed = {} - parsed['scale'] = 100 - parsed['assignments'] = [block_tag_block(0, 'test_tag', ['test_block'])] - parsed['sections'] = [ - ('macro', 'test_macro', [], [], []), - ('template_function', 'test_template_function', [], [], []), - ('function', 'reset', [], [], [scoreboard_assignment_block(0, (('Var', ('Global', 'test_var')), '=', func_expr(function_call_block(0, 'rand', [num_expr(5)]))))]), - ('clock', 'test_clock', [], [] ,[]), - ] - parsed['dir'] = 'test_dir' - parsed['desc'] = 'test description' - - script = cbscript(source, lambda t: ('program', parsed)) - def mock_create_world(self, dir, namespace): - world = mock_mcworld(dir, namespace) - self.mock_world = world - return world - script.create_world = new.instancemethod(mock_create_world, script, None) - - self.assertTrue(script.compile_all()) - world = script.mock_world - self.assertEqual(world.functions, ['reset', 'test_clock']) - self.assertEqual(world.clocks, ['test_clock']) - self.assertEqual(world.tags, ['test_tag']) - self.assertEqual(world.desc, 'test description') - self.assertTrue(world.written) - self.assertTrue('test_var' in script.global_context.objectives) - self.assertEqual(script.global_context.get_reset_function().commands, [ - 'scoreboard objectives add test_var dummy', - 'kill @e[type=minecraft:armor_stand,name=RandBasis,scores={RVunittest=0..}]', - 'scoreboard objectives add RVunittest dummy', - 'summon minecraft:armor_stand ~ ~ ~ {CustomName:"\\"RandBasis\\"", "Invulnerable":1b, "Invisible":1b, "Marker":1b, "NoGravity":1b}', - 'scoreboard players add @e[type=minecraft:armor_stand,name=RandBasis] RVunittest 1', - 'summon minecraft:armor_stand ~ ~ ~ {CustomName:"\\"RandBasis\\"", "Invulnerable":1b, "Invisible":1b, "Marker":1b, "NoGravity":1b}', - 'scoreboard players add @e[type=minecraft:armor_stand,name=RandBasis] RVunittest 1', - 'summon minecraft:armor_stand ~ ~ ~ {CustomName:"\\"RandBasis\\"", "Invulnerable":1b, "Invisible":1b, "Marker":1b, "NoGravity":1b}', - 'scoreboard players add @e[type=minecraft:armor_stand,name=RandBasis] RVunittest 1', - 'summon minecraft:armor_stand ~ ~ ~ {CustomName:"\\"RandBasis\\"", "Invulnerable":1b, "Invisible":1b, "Marker":1b, "NoGravity":1b}', - 'scoreboard players add @e[type=minecraft:armor_stand,name=RandBasis] RVunittest 1', - 'summon minecraft:armor_stand ~ ~ ~ {CustomName:"\\"RandBasis\\"", "Invulnerable":1b, "Invisible":1b, "Marker":1b, "NoGravity":1b}', - 'scoreboard players add @e[type=minecraft:armor_stand,name=RandBasis] RVunittest 1', - 'scoreboard players remove @e[type=minecraft:armor_stand,name=RandBasis] RVunittest 1', - 'scoreboard objectives add res_scratch0 dummy', - 'scoreboard players set Global res_scratch0 0', - 'scoreboard players operation Global res_scratch0 += @e[type=minecraft:armor_stand,limit=1,sort=random,scores={RVunittest=..4}] RVunittest', - 'scoreboard players operation Global test_var = Global res_scratch0', - ]) - - def test_tellraw_get_properties_text(self): - properties = { - 'color': 'red', - 'bold': True, - 'underlined': True, - 'italic': True, - 'strikethrough': True - } - self.assertEqual(tellraw.getPropertiesText(properties), ',"color":"red","bold":true,"underlined":true,"italic":true,"strikethrough":true') - - properties = { - 'color': None, - 'bold': False, - 'underlined': False, - 'italic': False, - 'strikethrough': False - } - self.assertEqual(tellraw.getPropertiesText(properties), '') - - def test_tellraw_format_json_text(self): - func = mock_mcfunction() - - self.assertEqual( - tellraw.formatJsonText(func, 'test'), - '["",{"text":"test"}]' - ) - - self.assertEqual( - tellraw.formatJsonText(func, '{rtest'), - '["",{"text":"test","color":"dark_red"}]' - ) - - self.assertEqual( - tellraw.formatJsonText(func, '[test text](/test_command)'), - '["",{"text":"test text","clickEvent":{"action":"run_command","value":"/test_command"}}]' - ) - - self.assertEqual( - tellraw.formatJsonText(func, '(global_var)'), - '["",{"score":{"name":"Global","objective":"global_var"}}]' - ) - - self.assertEqual( - tellraw.formatJsonText(func, '(@test_selector.test_var)'), - '["",{"score":{"name":"@s","objective":"test_scratch1"}}]' - ) - - with self.assertRaises(SyntaxError): - tellraw.formatJsonText(func, '(a.b.c)') - - self.assertEqual( - tellraw.formatJsonText(func, '(@test_selector[])'), - '["",{"selector":"@test_selector[]"}]' - ) - - with self.assertRaises(SyntaxError): - tellraw.formatJsonText(func, 'test () text'), - - self.assertEqual( - tellraw.formatJsonText(func, '[link](http://sethbling.com)'), - '["",{"text":"link","clickEvent":{"action":"open_url","value":"http://sethbling.com"}}]' - ) - - self.assertEqual( - tellraw.formatJsonText(func, '[link](//suggest_test)'), - '["",{"text":"link","clickEvent":{"action":"suggest_command","value":"/suggest_test"}}]' - ) - - def test_tellraw_parse_text_formatting(self): - self.assertEqual( - tellraw.parseTextFormatting('\('), - [('(', {'color': None, 'underlined': False, 'strikethrough': False, 'bold': False, 'italic': False})] - ) - - self.assertEqual( - tellraw.parseTextFormatting('a['), - [('a', {'color': None, 'underlined': False, 'strikethrough': False, 'bold': False, 'italic': False})] - ) - - self.assertEqual( - tellraw.parseTextFormatting('a{'), - [('a', {'color': None, 'underlined': False, 'strikethrough': False, 'bold': False, 'italic': False})] - ) - - self.assertEqual( - tellraw.parseTextFormatting('[formatted]test'), - [ - (('formatted', None), {'color': None, 'underlined': False, 'strikethrough': False, 'bold': False, 'italic': False}), - ('test', {'color': None, 'underlined': False, 'strikethrough': False, 'bold': False, 'italic': False}) - ] - ) - - self.assertEqual( - tellraw.parseTextFormatting('{r{Utest{-clear'), - [ - ('test', {'color': 'dark_red', 'underlined': True, 'strikethrough': False, 'bold': False, 'italic': False}), - ('clear', {'color': None, 'underlined': False, 'strikethrough': False, 'bold': False, 'italic': False}) - ] - ) - - self.assertEqual( - tellraw.parseTextFormatting('{Utest{uclear'), - [ - ('test', {'color': None, 'underlined': True, 'strikethrough': False, 'bold': False, 'italic': False}), - ('clear', {'color': None, 'underlined': False, 'strikethrough': False, 'bold': False, 'italic': False}) - ] - ) - - self.assertEqual( - tellraw.parseTextFormatting('{Stest{sclear'), - [ - ('test', {'color': None, 'underlined': False, 'strikethrough': True, 'bold': False, 'italic': False}), - ('clear', {'color': None, 'underlined': False, 'strikethrough': False, 'bold': False, 'italic': False}) - ] - ) - - self.assertEqual( - tellraw.parseTextFormatting('{Dtest{dclear'), - [ - ('test', {'color': None, 'underlined': False, 'strikethrough': False, 'bold': True, 'italic': False}), - ('clear', {'color': None, 'underlined': False, 'strikethrough': False, 'bold': False, 'italic': False}) - ] - ) - - self.assertEqual( - tellraw.parseTextFormatting('{Itest{iclear'), - [ - ('test', {'color': None, 'underlined': False, 'strikethrough': False, 'bold': False, 'italic': True}), - ('clear', {'color': None, 'underlined': False, 'strikethrough': False, 'bold': False, 'italic': False}) - ] - ) - - self.assertEqual( - tellraw.parseTextFormatting('{{'), - [('{', {'color': None, 'underlined': False, 'strikethrough': False, 'bold': False, 'italic': False})] - ) - - with self.assertRaises(SyntaxError): - tellraw.parseTextFormatting('{+') - - self.assertEqual( - tellraw.parseTextFormatting('\{'), - [('{', {'color': None, 'underlined': False, 'strikethrough': False, 'bold': False, 'italic': False})] - ) - - def test_parser(self): - mcfunction.line_numbers = [] - - p = mock_parsed('test1') - scriptparse.p_parsed_assignment(p) - self.assertEqual(p[0], ('program', 'test1')) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed('test2') - scriptparse.p_parsed_expr(p) - self.assertEqual(p[0], ('expr', 'test2')) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed('comments', None, 'dir', None, 'desc', 'scale', 'assignments', 'sections') - scriptparse.p_program(p) - self.assertEqual(p[0], {'assignments': 'assignments', 'scale': 'scale', 'sections': 'sections', 'dir': 'dir', 'desc': 'desc'}) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(None, 'desc', None) - scriptparse.p_optdesc(p) - self.assertEqual(p[0], 'desc') - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(None) - scriptparse.p_optdesc(p) - self.assertEqual(p[0], 'No Description') - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(None, 500, None) - scriptparse.p_optscale(p) - self.assertEqual(p[0], 500) - - p = mock_parsed(None) - scriptparse.p_optscale_none(p) - self.assertEqual(p[0], 1000) - - p = mock_parsed('section', None, ['sections']) - scriptparse.p_sections_multiple(p) - self.assertEqual(p[0], ['section', 'sections']) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(None) - scriptparse.p_sections_empty(p) - self.assertEqual(p[0], []) - - p = mock_parsed(['comment'], ('type', 'name', ['template_params'], ['params'], ['lines'])) - scriptparse.p_section_commented(p) - p_type, p_name, p_template_params, p_params, p_lines = p[0] - self.assertEqual(p_type, 'type') - self.assertEqual(p_name, 'name') - self.assertEqual(p_template_params, ['template_params']) - self.assertEqual(p_params, ['params']) - self.assertEqual(type(p_lines[0]), comment_block) - self.assertEqual(p_lines[0].text, '#comment') - self.assertEqual(p_lines[1], 'lines') - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed('comment', None, ['comments']) - scriptparse.p_optcomments(p) - self.assertEqual(p[0], ['comment', 'comments']) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(None) - scriptparse.p_optcomments_empty(p) - self.assertEqual(p[0], []) - - p = mock_parsed('section') - scriptparse.p_section(p) - self.assertEqual(p[0], 'section') - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(None, None, 'lines', None) - scriptparse.p_resetsection(p) - self.assertEqual(p[0], ('reset', 'reset', [], [], 'lines')) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - with self.assertRaises(SyntaxError): - scriptparse.validate_mcfunction_name('Test') - scriptparse.validate_mcfunction_name('test') - - p = mock_parsed(None, 'id', None, 'lines', None) - scriptparse.p_clocksection(p) - self.assertEqual(p[0], ('clock', 'id', [], [], 'lines')) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(None, 'id', None, ['id_list'], None, None, 'lines', None) - scriptparse.p_functionsection(p) - self.assertEqual(p[0], ('function', 'id', [], ['id_list'], 'lines')) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(None, 'id', None, ['macro_params'], None, None, ['id_list'], None, None, 'lines', None) - scriptparse.p_template_function_section(p) - self.assertEqual(p[0], ('template_function', 'id', ['macro_params'], ['id_list'], 'lines')) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(None, None, 'id', 'macro_args', None, 'lines', None) - scriptparse.p_macrosection(p) - self.assertEqual(p[0], ('macro', 'id', [], 'macro_args', 'lines')) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(None, 'params', None) - scriptparse.p_macro_args(p) - self.assertEqual(p[0], 'params') - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(None) - scriptparse.p_macro_args_empty(p) - self.assertEqual(p[0], []) - - p = mock_parsed(None, 'id', None, ['params']) - scriptparse.p_macro_params(p) - self.assertEqual(p[0], ['id', 'params']) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(None, 'macro_id') - scriptparse.p_macro_params_one(p) - self.assertEqual(p[0], ['macro_id']) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(None) - scriptparse.p_macro_params_empty(p) - self.assertEqual(p[0], []) - - p = mock_parsed(None, None) - scriptparse.p_newlines(p) - self.assertEqual(p[0], None) - - p = mock_parsed(None) - scriptparse.p_newlines(p) - self.assertEqual(p[0], None) - - p = mock_parsed(None) - scriptparse.p_optnewlines(p) - self.assertEqual(p[0], None) - - p = mock_parsed('id', None, ['ids']) - scriptparse.p_id_list(p) - self.assertEqual(p[0], ['id', 'ids']) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed('id') - scriptparse.p_id_list_one(p) - self.assertEqual(p[0], ['id']) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(None) - scriptparse.p_id_list_empty(p) - self.assertEqual(p[0], []) - - p = mock_parsed('assignment', None, ['assignments']) - scriptparse.p_optassignments_multiple(p) - self.assertEqual(p[0], ['assignment', 'assignments']) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed('comment', None, ['assignments']) - scriptparse.p_optassignments_comment(p) - self.assertEqual(p[0], ['assignments']) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(None) - scriptparse.p_optassignments_empty(p) - self.assertEqual(p[0], []) - - p = mock_parsed('fullselector', None, 'id') - scriptparse.p_variable_selector(p) - self.assertEqual(p[0], ('Var', ('fullselector', 'id'))) - - p = mock_parsed('id') - scriptparse.p_variable_global(p) - self.assertEqual(p[0], ('Var', ('Global', 'id'))) - - p = mock_parsed('id', None, 'idx') - scriptparse.p_variable_array_const(p) - self.assertEqual(p[0], ('ArrayConst', ('id', 'idx'))) - - p = mock_parsed('id', None, 'expr') - scriptparse.p_variable_array_expr(p) - self.assertEqual(p[0], ('ArrayExpr', ('id', 'expr'))) - - p = mock_parsed('#comment') - scriptparse.p_optcomment(p) - self.assertEqual(len(p[0]), 1) - self.assertTrue(type(p[0][0]) is comment_block) - self.assertEqual(p[0][0].text, '#comment') - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(None) - scriptparse.p_optcomment_empty(p) - self.assertEqual(p[0], []) - - p = mock_parsed('codeblock', ['optcomment'], None, ['lines']) - scriptparse.p_blocklist_multiple(p) - self.assertEqual(p[0], ['optcomment', 'codeblock', 'lines']) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(None) - scriptparse.p_blocklist_empty(p) - self.assertEqual(p[0], []) - - p = mock_parsed('#comment') - scriptparse.p_block_comment(p) - self.assertTrue(type(p[0]) is comment_block) - self.assertEqual(p[0].text, '#comment') - self.assertEqual(p[0].line, 0) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed('command') - scriptparse.p_block_command(p) - self.assertTrue(type(p[0]) is command_block) - self.assertEqual(p[0].text, 'command') - self.assertEqual(p[0].line, 0) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(None, 'selector', 'coords') - scriptparse.p_block_move(p) - self.assertTrue(type(p[0]) is move_block) - self.assertEqual(p[0].selector, 'selector') - self.assertEqual(p[0].coords, 'coords') - self.assertEqual(p[0].line, 0) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(None, None, 'id', None, interpreted_python('[1]', 0), None, 'lines', None) - func = mock_mcfunction() - scriptparse.p_block_for(p) - self.assertTrue(type(p[0]) is python_for_block) - self.assertEqual(p[0].id, 'id') - self.assertEqual(p[0].val.get_value(func), [1]) - self.assertEqual(p[0].sub, 'lines') - self.assertEqual(p[0].line, 0) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(None, 'var', None, 'lines', None) - scriptparse.p_execute_as_id_global(p) - self.assertTrue(type(p[0]) is execute_block) - self.assertEqual(p[0].exec_items, [('AsId',('var', None))]) - self.assertEqual(p[0].sub, 'lines') - self.assertEqual(p[0].line, 0) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(None, 'var', None, '@id', None, None, 'lines', None) - scriptparse.p_execute_as_id_type_global(p) - self.assertTrue(type(p[0]) is execute_block) - self.assertEqual(p[0].exec_items, [('AsId',('var', '@id'))]) - self.assertEqual(p[0].sub, 'lines') - self.assertEqual(p[0].line, 0) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(None, 'var', None, 'line') - scriptparse.p_execute_as_id_do_global(p) - self.assertTrue(type(p[0]) is execute_block) - self.assertEqual(p[0].exec_items, [('AsId',('var', None))]) - self.assertEqual(p[0].sub, ['line']) - self.assertEqual(p[0].line, 0) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(None, 'var', None, '@id', None, None, 'line') - scriptparse.p_execute_as_id_do_type_global(p) - self.assertTrue(type(p[0]) is execute_block) - self.assertEqual(p[0].exec_items, [('AsId',('var', '@id'))]) - self.assertEqual(p[0].sub, ['line']) - self.assertEqual(p[0].line, 0) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(None, 'create', None, 'lines', None) - scriptparse.p_execute_as_create(p) - self.assertTrue(type(p[0]) is execute_block) - self.assertEqual(p[0].exec_items, [('AsCreate','create')]) - self.assertEqual(p[0].sub, 'lines') - self.assertEqual(p[0].line, 0) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(None, 'create', None, 'line') - scriptparse.p_execute_as_create_do(p) - self.assertTrue(type(p[0]) is execute_block) - self.assertEqual(p[0].exec_items, [('AsCreate','create')]) - self.assertEqual(p[0].sub, ['line']) - self.assertEqual(p[0].line, 0) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed('items', None, 'lines', None) - scriptparse.p_execute_chain(p) - self.assertTrue(type(p[0]) is execute_block) - self.assertEqual(p[0].exec_items, 'items') - self.assertEqual(p[0].sub, 'lines') - self.assertEqual(p[0].line, 0) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed('items', None, 'line') - scriptparse.p_execute_chain_inline(p) - self.assertTrue(type(p[0]) is execute_block) - self.assertEqual(p[0].exec_items, 'items') - self.assertEqual(p[0].sub, ['line']) - self.assertEqual(p[0].line, 0) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed('item') - scriptparse.p_execute_items_one(p) - self.assertEqual(p[0], ['item']) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed('item', ['items']) - scriptparse.p_execute_items(p) - self.assertEqual(p[0], ['item', 'items']) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(None, 'conditions') - scriptparse.p_execute_if_condition(p) - self.assertEqual(p[0], ('If', 'conditions')) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(None, 'conditions') - scriptparse.p_execute_unless_condition(p) - self.assertEqual(p[0], ('Unless', 'conditions')) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(None, 'fullselector') - scriptparse.p_execute_as(p) - self.assertEqual(p[0], ('As', 'fullselector')) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(None, 'fullselector') - scriptparse.p_execute_rotated(p) - self.assertEqual(p[0], ('Rotated', 'fullselector')) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(None, 'relcoords') - scriptparse.p_execute_facing_coords(p) - self.assertEqual(p[0], ('FacingCoords', 'relcoords')) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(None, 'fullselector') - scriptparse.p_execute_facing_entity(p) - self.assertEqual(p[0], ('FacingEntity', 'fullselector')) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - for axes in ['x','y','z','xy','xz','yz','xyz']: - p = mock_parsed(None, axes) - scriptparse.p_execute_align(p) - self.assertEqual(p[0], ('Align', axes)) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(None, '') - with self.assertRaises(SyntaxError): - scriptparse.p_execute_align(p) - - p = mock_parsed(None, 'fullselector') - scriptparse.p_execute_at_selector(p) - self.assertEqual(p[0], ('At', ('fullselector', None))) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(None, 'relcoords') - scriptparse.p_execute_at_relcoords(p) - self.assertEqual(p[0], ('At', (None, 'relcoords'))) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(None, 'fullselector', 'relcoords') - scriptparse.p_execute_at_selector_relcoords(p) - self.assertEqual(p[0], ('At', ('fullselector', 'relcoords'))) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(None, 'vector_expr') - scriptparse.p_execute_at_vector(p) - self.assertEqual(p[0], ('AtVector', (None, 'vector_expr'))) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(None, None, '200', None, 'vector_expr') - scriptparse.p_execute_at_vector_scale(p) - self.assertEqual(p[0], ('AtVector', ('200', 'vector_expr'))) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(None, 'overworld') - scriptparse.p_execute_in_dimension(p) - self.assertEqual(p[0], ('In', 'overworld')) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(None, 'id', None, '@id', None, 'lines', None) - scriptparse.p_for_selector(p) - self.assertTrue(type(p[0]) is for_selector_block) - self.assertEqual(p[0].id, 'id') - self.assertEqual(p[0].selector, '@id') - self.assertEqual(p[0].sub, 'lines') - self.assertEqual(p[0].line, 0) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed('condition') - scriptparse.p_conditions_one(p) - self.assertEqual(p[0], ['condition']) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed('condition', None, ['conditions']) - scriptparse.p_conditions(p) - self.assertEqual(p[0], ['condition', 'conditions']) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed('var', None, 'fullselector') - scriptparse.p_condition_pointer(p) - self.assertEqual(p[0], ('pointer', ('var', 'fullselector'))) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed('fullselector', None, 'var') - scriptparse.p_condition_pointer_reversed(p) - self.assertEqual(p[0], ('pointer', ('var', 'fullselector'))) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed('fullselector') - scriptparse.p_condition_fullselector(p) - self.assertEqual(p[0], ('selector', 'fullselector')) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed('var', '<', 'comp') - scriptparse.p_condition_score(p) - self.assertEqual(p[0], ('score', ('var', '<', 'comp'))) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed('var', '==', 'comp') - scriptparse.p_condition_score(p) - self.assertEqual(p[0], ('score', ('var', '=', 'comp'))) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed('v1', '==', 'v2') - scriptparse.p_condition_vector_equality(p) - self.assertEqual(p[0], ('vector_equality', ('v1', 'v2'))) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed('var') - func = mock_mcfunction() - scriptparse.p_condition_bool(p) - self.assertEqual(p[0][0], 'score') - self.assertEqual(p[0][1][0], 'var') - self.assertEqual(p[0][1][1], '>') - self.assertEqual(p[0][1][2][0], 'num') - self.assertEqual(p[0][1][2][1].get_value(func), 0) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(None, 'var') - func = mock_mcfunction() - scriptparse.p_condition_not_bool(p) - self.assertEqual(p[0][0], 'score') - self.assertEqual(p[0][1][0], 'var') - self.assertEqual(p[0][1][1], '<=') - self.assertEqual(p[0][1][2][0], 'num') - self.assertEqual(p[0][1][2][1].get_value(func), 0) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(None, 'relcoords', 'id') - scriptparse.p_condition_block(p) - self.assertEqual(p[0], ('block', ('relcoords', 'id'))) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed('100') - func = mock_mcfunction() - scriptparse.p_comparison_num(p) - self.assertEqual(p[0][0], 'num') - self.assertEqual(p[0][1].get_value(func), 100) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(None, const_number('100'), None) - scriptparse.p_comparison_expr(p) - self.assertEqual(p[0][0], 'num') - self.assertEqual(p[0][1].get_value(func), 100) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed('var') - scriptparse.p_comparison_global(p) - self.assertEqual(p[0], ('score', 'var')) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(None, interpreted_python('1', 0), None, 'lines', None) - func = mock_mcfunction() - scriptparse.p_block_if_command(p) - self.assertTrue(type(p[0]) is python_if_block) - self.assertEqual(p[0].val.get_value(func), 1) - self.assertEqual(p[0].sub, 'lines') - self.assertEqual(p[0].else_sub, None) - self.assertEqual(p[0].line, 0) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(None, interpreted_python('1', 0), None, 'lines', None, None, 'else_lines', None) - func = mock_mcfunction() - scriptparse.p_block_ifelse_command(p) - self.assertTrue(type(p[0]) is python_if_block) - self.assertEqual(p[0].val.get_value(func), 1) - self.assertEqual(p[0].sub, 'lines') - self.assertEqual(p[0].else_sub, 'else_lines') - self.assertEqual(p[0].line, 0) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(None, 'conditions', None, 'lines', None) - scriptparse.p_block_while(p) - self.assertTrue(type(p[0]) is while_block) - self.assertEqual(p[0].exec_items, [('If', 'conditions')]) - self.assertEqual(p[0].sub, 'lines') - self.assertEqual(p[0].line, 0) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(None, 'conditions', ['items'], None, 'lines', None) - scriptparse.p_block_while_execute(p) - self.assertTrue(type(p[0]) is while_block) - self.assertEqual(p[0].exec_items, [('If', 'conditions'), 'items']) - self.assertEqual(p[0].sub, 'lines') - self.assertEqual(p[0].line, 0) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(None, 'id', None, 'from', None, 'to', None, 'by', None, 'lines', None) - scriptparse.p_block_for_index_by(p) - self.assertTrue(type(p[0]) is for_index_block) - self.assertEqual(p[0].var, 'id') - self.assertEqual(p[0].fr, 'from') - self.assertEqual(p[0].to, 'to') - self.assertEqual(p[0].by, 'by') - self.assertEqual(p[0].sub, 'lines') - self.assertEqual(p[0].line, 0) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(None, 'id', None, 'from', None, 'to', None, 'lines', None) - scriptparse.p_block_for_index(p) - self.assertTrue(type(p[0]) is for_index_block) - self.assertEqual(p[0].var, 'id') - self.assertEqual(p[0].fr, 'from') - self.assertEqual(p[0].to, 'to') - self.assertEqual(p[0].by, None) - self.assertEqual(p[0].sub, 'lines') - self.assertEqual(p[0].line, 0) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(None, 'expr', None, 'cases', None) - scriptparse.p_switch(p) - self.assertTrue(type(p[0]) is switch_block) - self.assertEqual(p[0].expr, 'expr') - self.assertEqual(p[0].cases_raw, 'cases') - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed('case') - scriptparse.p_cases_one(p) - self.assertEqual(p[0], ['case']) - - p = mock_parsed('case', None, ['cases']) - scriptparse.p_cases_multiple(p) - self.assertEqual(p[0], ['case', 'cases']) - - p = mock_parsed(None, '100', None, 'lines', None) - scriptparse.p_switch_case_single(p) - self.assertEqual(p[0], ('range', ('100', '100', 'lines'))) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(None, '100', None, '200', None, 'lines', None) - scriptparse.p_switch_case_range(p) - self.assertEqual(p[0], ('range', ('100', '200', 'lines'))) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(None, None, 'id', None, 'code', None, 'lines', None) - scriptparse.p_switch_case_python(p) - self.assertEqual(p[0], ('python', ('id', 'code', 'lines'))) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(None, 'fullselector', 'text') - scriptparse.p_block_tell(p) - self.assertTrue(type(p[0]) is tell_block) - self.assertEqual(p[0].selector, 'fullselector') - self.assertEqual(p[0].unformatted, 'text') - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed('title', 'selector', 'text') - scriptparse.p_block_title(p) - self.assertTrue(type(p[0]) is title_block) - self.assertEqual(p[0].subtype, 'title') - self.assertEqual(p[0].selector, 'selector') - self.assertEqual(p[0].times, None) - self.assertEqual(p[0].unformatted, 'text') - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed('subtitle', 'selector', '1', '2', '3', 'text') - scriptparse.p_block_title_times(p) - self.assertTrue(type(p[0]) is title_block) - self.assertEqual(p[0].subtype, 'subtitle') - self.assertEqual(p[0].selector, 'selector') - self.assertEqual(p[0].times, ('1', '2', '3')) - self.assertEqual(p[0].unformatted, 'text') - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed('call') - scriptparse.p_block_function_call(p) - self.assertEqual(p[0], 'call') - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(('var', 'op', 'expr')) - scriptparse.p_block_math(p) - self.assertTrue(type(p[0]) is scoreboard_assignment_block) - self.assertEqual(p[0].var, 'var') - self.assertEqual(p[0].op, 'op') - self.assertEqual(p[0].expr, 'expr') - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed('selector_assignment') - scriptparse.p_block_selector_assignment(p) - self.assertEqual(p[0], 'selector_assignment') - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed('100') - scriptparse.p_integer(p) - self.assertEqual(p[0], '100') - - p = mock_parsed(None, '100') - scriptparse.p_integer_minus(p) - self.assertEqual(p[0], '-100') - - p = mock_parsed('100') - scriptparse.p_number_integer(p) - self.assertEqual(p[0], '100') - - p = mock_parsed('1.0') - scriptparse.p_float_val(p) - self.assertEqual(p[0], '1.0') - - p = mock_parsed(None, '1.0') - scriptparse.p_float_val_minus(p) - self.assertEqual(p[0], '-1.0') - - func = mock_mcfunction() - func.dollarid['test3'] = 10 - p = mock_parsed(None, '5 + test3') - scriptparse.p_const_value_interpreted(p) - self.assertEqual(p[0].get_value(func), 15) - - p = mock_parsed(None, None, 'id', None, 'blocks', None) - scriptparse.p_blocktag(p) - self.assertTrue(type(p[0]) is block_tag_block) - self.assertEqual(p[0].name, 'id') - self.assertEqual(p[0].blocks, 'blocks') - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed('block', None, ['blocks']) - scriptparse.p_block_list(p) - self.assertEqual(p[0], ['block', 'blocks']) - - p = mock_parsed('block') - scriptparse.p_block_list_one(p) - self.assertEqual(p[0], ['block']) - - p = mock_parsed('id', None, 'fullselector') - scriptparse.p_selector_assignment(p) - self.assertTrue(type(p[0]) is selector_assignment_block) - self.assertEqual(p[0].id, 'id') - self.assertEqual(p[0].fullselector, 'fullselector') - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(None, 'id', None, 'fullselector', None, 'def', None) - scriptparse.p_selector_define(p) - self.assertTrue(type(p[0]) is selector_definition_block) - self.assertEqual(p[0].id, 'id') - self.assertEqual(p[0].fullselector, 'fullselector') - self.assertEqual(p[0].items, 'def') - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed('item', None, ['items']) - scriptparse.p_selector_definition(p) - self.assertEqual(p[0], ['item', 'items']) - - p = mock_parsed(None) - scriptparse.p_selector_definition_empty(p) - self.assertEqual(p[0], []) - - p = mock_parsed(None, 'data') - scriptparse.p_selector_item_tag(p) - self.assertEqual(p[0], ('Tag', 'data')) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed('id', None, 'path', 'type', 'scale') - scriptparse.p_selector_item_path_scale(p) - self.assertEqual(p[0], ('Path', ('id', 'path', 'type', 'scale'))) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed('id', None, 'path', 'type') - scriptparse.p_selector_item_path(p) - self.assertEqual(p[0], ('Path', ('id', 'path', 'type', None))) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(None, 'id', None, None, 'path', 'type', 'scale') - scriptparse.p_selector_item_vector_path_scale(p) - self.assertEqual(p[0], ('VectorPath', ('id', 'path', 'type', 'scale'))) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(None, 'id', None, None, 'path', 'type') - scriptparse.p_selector_item_vector_path(p) - self.assertEqual(p[0], ('VectorPath', ('id', 'path', 'type', None))) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed('function') - scriptparse.p_selector_item_method(p) - self.assertEqual(p[0], ('Method', 'function')) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed('id') - scriptparse.p_data_path_id(p) - self.assertEqual(p[0], 'id') - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed('id', None, '1', None) - scriptparse.p_data_path_array(p) - self.assertEqual(p[0], 'id[1]') - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed('a', None, 'b') - scriptparse.p_data_path_multi(p) - self.assertEqual(p[0], 'a.b') - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed('byte') - scriptparse.p_data_type(p) - self.assertEqual(p[0], 'byte') - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(None, 'id', None, const_number('1'), None) - func = mock_mcfunction() - scriptparse.p_array_definition(p) - self.assertTrue(type(p[0]) is array_definition_block) - self.assertEqual(p[0].name, 'id') - self.assertEqual(p[0].from_val.get_value(func), 0) - self.assertEqual(p[0].to_val.get_value(func), 1) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(None, 'id', None, '1', None, '2', None) - scriptparse.p_array_definition_range(p) - self.assertTrue(type(p[0]) is array_definition_block) - self.assertEqual(p[0].name, 'id') - self.assertEqual(p[0].from_val, '1') - self.assertEqual(p[0].to_val, '2') - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed('create_block') - scriptparse.p_block_create(p) - self.assertEqual(p[0], 'create_block') - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(None, 'id', 'relcoords') - scriptparse.p_create(p) - self.assertTrue(type(p[0]) is create_block) - self.assertEqual(p[0].atid, 'id') - self.assertEqual(p[0].relcoords, 'relcoords') - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(None, 'id') - func = mock_mcfunction() - scriptparse.p_create_nocoords(p) - self.assertTrue(type(p[0]) is create_block) - self.assertEqual(p[0].atid, 'id') - self.assertEqual(p[0].relcoords.get_value(func), '~ ~ ~') - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed('qualifiers', None, 'qualifier') - scriptparse.p_qualifiers_multiple(p) - self.assertEqual(p[0], 'qualifiers,qualifier') - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed('qualifier') - scriptparse.p_qualifiers_one(p) - self.assertEqual(p[0], 'qualifier') - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(None) - scriptparse.p_qualifiers(p) - self.assertEqual(p[0], '') - - p = mock_parsed('100') - scriptparse.p_qualifier_integer(p) - self.assertEqual(p[0], '100') - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed('id', '<=', 'id2') - scriptparse.p_qualifier_binop(p) - self.assertEqual(p[0], 'id<=id2') - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed('id', '=', '100', '.', '.', '200') - scriptparse.p_qualifier_builtin(p) - self.assertEqual(p[0], 'id=100..200') - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed('id', '=') - scriptparse.p_qualifier_empty(p) - self.assertEqual(p[0], 'id=') - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed('id', '=', '!', 'id2') - scriptparse.p_qualifier_is_not(p) - self.assertEqual(p[0], 'id=!id2') - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed('id') - scriptparse.p_qualifier_is(p) - self.assertEqual(p[0], 'id') - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed('not', 'id') - scriptparse.p_qualifier_not(p) - self.assertEqual(p[0], 'not id') - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed('id') - scriptparse.p_fullselector_symbol(p) - self.assertEqual(p[0], '@id[]') - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed('id', None, 'qualifiers', None) - scriptparse.p_fullselector_symbol(p) - self.assertEqual(p[0], '@id[qualifiers]') - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(const_number('100')) - func = mock_mcfunction() - scriptparse.p_relcoord_number(p) - self.assertEqual(p[0].get_value(func), '100') - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(None, const_number('100')) - func = mock_mcfunction() - scriptparse.p_relcoord_relnumber(p) - self.assertEqual(p[0].get_value(func), '~100') - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(None) - func = mock_mcfunction() - scriptparse.p_relcoord_relzero(p) - self.assertEqual(p[0].get_value(func), '~') - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed('^', const_number('100')) - func = mock_mcfunction() - scriptparse.p_localcoord_localnumber(p) - self.assertEqual(p[0].get_value(func), '^100') - - p = mock_parsed(relcoord('', const_number('1')), relcoord('', const_number('2')), relcoord('', const_number('3'))) - func = mock_mcfunction() - scriptparse.p_relcoords(p) - self.assertEqual(p[0].get_value(func), '1 2 3') - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(None, 'expr') - scriptparse.p_return_expression(p) - self.assertEqual(p[0], (('Var', ('Global', 'ReturnValue')), '=', 'expr')) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed('var', '+=', 'expr') - scriptparse.p_assignment(p) - self.assertEqual(p[0], ('var', '+=', 'expr')) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed('var', '++') - scriptparse.p_assignment_unary_default(p) - var, op, expr = p[0] - self.assertEqual(var, 'var') - self.assertEqual(op, '+=') - self.assertTrue(type(expr) is num_expr) - self.assertEqual(expr.const_value(), '1') - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed('var', '=', 'selector') - scriptparse.p_assignment_selector_global(p) - var, op, expr = p[0] - self.assertEqual(var, 'var') - self.assertEqual(op, '=') - self.assertTrue(type(expr) is selector_expr) - self.assertEqual(expr.selector, 'selector') - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed('var', '=', 'create') - scriptparse.p_assignment_create(p) - var, op, expr = p[0] - self.assertEqual(var, 'var') - self.assertEqual(op, '=') - self.assertTrue(type(expr) is create_expr) - self.assertEqual(expr.create_block, 'create') - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed('var', '+=', 'expr') - scriptparse.p_vector_assignment_vector(p) - self.assertTrue(type(p[0]) is vector_assignment_block) - self.assertEqual(p[0].var, 'var') - self.assertEqual(p[0].op, '+=') - self.assertEqual(p[0].expr, 'expr') - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed('var', '+=', 'expr') - scriptparse.p_vector_assignment_scalar(p) - self.assertTrue(type(p[0]) is vector_assignment_scalar_block) - self.assertEqual(p[0].var, 'var') - self.assertEqual(p[0].op, '+=') - self.assertEqual(p[0].expr, 'expr') - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(None, 'id', None) - scriptparse.p_vector_var_id(p) - self.assertEqual(p[0], ('VAR_ID', 'id')) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed('selector', None, None, 'id', None) - scriptparse.p_vector_var_sel_id(p) - self.assertEqual(p[0], ('SEL_VAR_ID', ('selector', 'id'))) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(None, 'a', None, 'b', None, 'c', None) - scriptparse.p_vector_var_components(p) - self.assertEqual(p[0], ('VAR_COMPONENTS', ['a', 'b', 'c'])) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed('a', None, 'b') - scriptparse.p_expr_dot(p) - self.assertTrue(type(p[0]) is dot_expr) - self.assertEqual(p[0].lhs, 'a') - self.assertEqual(p[0].rhs, 'b') - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed('100') - scriptparse.p_expr_number(p) - self.assertTrue(type(p[0]) is num_expr) - self.assertEqual(p[0].val, '100') - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(None) - scriptparse.p_expr_scale(p) - self.assertTrue(type(p[0]) is scale_expr) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed('id') - scriptparse.p_expr_variable(p) - self.assertTrue(type(p[0]) is selvar_expr) - self.assertEqual(p[0].sel, 'Global') - self.assertEqual(p[0].var, 'id') - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed('id', None, '100', None) - scriptparse.p_expr_array_const(p) - self.assertTrue(type(p[0]) is arrayconst_expr) - self.assertEqual(p[0].name, 'id') - self.assertEqual(p[0].idx, '100') - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed('id', None, 'expr', None) - scriptparse.p_expr_array_expr(p) - self.assertTrue(type(p[0]) is arrayexpr_expr) - self.assertEqual(p[0].name, 'id') - self.assertEqual(p[0].idx_expr, 'expr') - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed('selector', None, 'id') - scriptparse.p_expr_selector_variable(p) - self.assertTrue(type(p[0]) is selvar_expr) - self.assertEqual(p[0].sel, 'selector') - self.assertEqual(p[0].var, 'id') - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed('call') - scriptparse.p_expr_function(p) - self.assertTrue(type(p[0]) is func_expr) - self.assertEqual(p[0].function_call, 'call') - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(None, 'group', None) - scriptparse.p_expr_group(p) - self.assertEqual(p[0], 'group') - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed('-', num_expr(100)) - scriptparse.p_expr_unary(p) - self.assertTrue(type(p[0]) is num_expr) - self.assertEqual(p[0].val, '-100') - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed('-', scale_expr()) - scriptparse.p_expr_unary(p) - self.assertTrue(type(p[0]) is unary_expr) - self.assertEqual(p[0].type, '-') - self.assertTrue(type(p[0].expr) is scale_expr) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(None, 'group', None) - scriptparse.p_vector_expr_paren(p) - self.assertEqual(p[0], 'group') - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(None, 'a', None, 'b', None, 'c', None) - scriptparse.p_vector_expr_vector_triplet(p) - self.assertTrue(type(p[0]) is vector_expr) - self.assertEqual(p[0].exprs, ('a', 'b', 'c')) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(None, 'id', None) - scriptparse.p_vector_expr_vector_unit(p) - self.assertTrue(type(p[0]) is vector_var_expr) - self.assertEqual(p[0].vector_id, ('id')) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed('selector', None, None, 'id', None) - scriptparse.p_vector_expr_selector_vector(p) - self.assertTrue(type(p[0]) is sel_vector_var_expr) - self.assertEqual(p[0].sel, ('selector')) - self.assertEqual(p[0].id, ('id')) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed('expr1', '+', 'expr2') - scriptparse.p_vector_expr_binop_vector(p) - self.assertTrue(type(p[0]) is vector_binop_vector_expr) - self.assertEqual(p[0].lhs, ('expr1')) - self.assertEqual(p[0].op, ('+')) - self.assertEqual(p[0].rhs, ('expr2')) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed('expr1', '+', 'expr2') - scriptparse.p_vector_expr_binop_scalar(p) - self.assertTrue(type(p[0]) is vector_binop_scalar_expr) - self.assertEqual(p[0].lhs, ('expr1')) - self.assertEqual(p[0].op, ('+')) - self.assertEqual(p[0].rhs, ('expr2')) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed('expr1', '+', 'expr2') - scriptparse.p_vector_expr_binop_scalar_reversed(p) - self.assertTrue(type(p[0]) is vector_binop_scalar_expr) - self.assertEqual(p[0].lhs, ('expr2')) - self.assertEqual(p[0].op, ('+')) - self.assertEqual(p[0].rhs, ('expr1')) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed('-', 'expr') - scriptparse.p_vector_expr_negative(p) - self.assertTrue(type(p[0]) is vector_binop_scalar_expr) - self.assertEqual(p[0].lhs, ('expr')) - self.assertEqual(p[0].op, ('*')) - self.assertTrue(type(p[0].rhs) is num_expr) - self.assertEqual(p[0].rhs.const_value(), '-1') - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(None) - scriptparse.p_vector_expr_here(p) - self.assertTrue(type(p[0]) is vector_here_expr) - self.assertEqual(p[0].scale, None) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(None, None, '100', None) - scriptparse.p_vector_expr_here_scale(p) - self.assertTrue(type(p[0]) is vector_here_expr) - self.assertEqual(p[0].scale, '100') - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed('id', None, 'exprs', None) - scriptparse.p_function_call(p) - self.assertTrue(type(p[0]) is function_call_block) - self.assertEqual(p[0].dest, 'id') - self.assertEqual(p[0].args, 'exprs') - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed('selector', None, 'id', None, 'exprs', None) - scriptparse.p_method_call(p) - self.assertTrue(type(p[0]) is method_call_block) - self.assertEqual(p[0].selector, 'selector') - self.assertEqual(p[0].dest, 'id') - self.assertEqual(p[0].params, 'exprs') - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(['exprs'], None, 'expr') - scriptparse.p_exprlist_multiple(p) - self.assertEqual(p[0], ['exprs', 'expr']) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed('expr') - scriptparse.p_exprlist_single(p) - self.assertEqual(p[0], ['expr']) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(None) - scriptparse.p_exprlist_empty(p) - self.assertEqual(p[0], []) - - p = mock_parsed('id', None, 'macro_params', None, None, 'function_params', None) - scriptparse.p_template_function_call(p) - self.assertTrue(type(p[0]) is template_function_call_block) - self.assertEqual(p[0].function, 'id') - self.assertEqual(p[0].template_args, 'macro_params') - self.assertEqual(p[0].args, 'function_params') - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(None, 'id', 'macro_params') - scriptparse.p_macro_call(p) - self.assertTrue(type(p[0]) is macro_call_block) - self.assertEqual(p[0].macro, 'id') - self.assertEqual(p[0].args, 'macro_params') - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(None, 'params', None) - scriptparse.p_macro_call_args(p) - self.assertEqual(p[0], 'params') - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(None) - scriptparse.p_macro_call_args_empty(p) - self.assertEqual(p[0], []) - - p = mock_parsed('param', None, ['params']) - scriptparse.p_macro_call_params(p) - self.assertEqual(p[0], ['param', 'params']) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed('param') - scriptparse.p_macro_call_params_one(p) - self.assertEqual(p[0], ['param']) - self.assertEqual(mcfunction.get_line(p[0]), 0) - - p = mock_parsed(None) - scriptparse.p_macro_call_params_empty(p) - self.assertEqual(p[0], []) - - p = mock_parsed('100') - scriptparse.p_macro_call_param_number(p) - self.assertEqual(p[0], '100') - self.assertEqual(mcfunction.get_line(p[0]), 0) - - def test_mcfunction_get_modifiable_id(self): - env = mock_environment() - func = mcfunction.mcfunction(env) - - id = func.get_modifiable_id('test', 'assign') - self.assertEqual(id, 'assign') - self.assertEqual(func.commands, ['scoreboard players operation Global assign = Global test']) - - env = mock_environment() - func = mcfunction.mcfunction(env) - - id = func.get_modifiable_id('test', 'test') - self.assertEqual(id, 'test') - self.assertEqual(func.commands, []) - - env = mock_environment() - func = mcfunction.mcfunction(env) - - id = func.get_modifiable_id('test', None) - self.assertEqual(id, 'test_scratch1') - self.assertEqual(func.commands, ['scoreboard players operation Global test_scratch1 = Global test']) - - env = mock_environment() - func = mcfunction.mcfunction(env) - - id = func.get_modifiable_id('test_scratch1', None) - self.assertEqual(id, 'test_scratch1') - self.assertEqual(func.commands, []) - - def test_mcfunction_evaluate_params(self): - env = mock_environment() - func = mcfunction.mcfunction(env) - - self.assertTrue(func.evaluate_params([num_expr(1)])) - self.assertEqual(func.commands, [ - 'scoreboard players set Global test_scratch1 1', - 'scoreboard players operation Global Param0 = Global test_scratch1' - ]) - - def test_mcfunction_get_variable_non_single_entity(self): - env = mock_environment() - sel = mock_selector_definition() - sel.paths['test_path'] = 'path', 'float', 100 - sel.base_name = '@e' - sel.is_single_entity = False - env.selectors['test_selector'] = sel - env.selector_definitions['@test_selector'] = sel - func = mcfunction.mcfunction(env) - - var = 'Var', ('@test_selector', 'test_path') - - with self.assertRaises(Exception): - var_ret = func.get_variable(var, True) - - def test_mcfunction_get_variable_path(self): - env = mock_environment() - sel = mock_selector_definition() - sel.paths['test_path'] = 'path', 'float', 100 - sel.base_name = '@s' - sel.is_single_entity = True - env.selectors['test_selector'] = sel - env.selector_definitions['@test_selector'] = sel - func = mcfunction.mcfunction(env) - - var = 'Var', ('@test_selector', 'test_path') - - var_ret = func.get_variable(var, True) - self.assertEqual(var_ret, var[1]) - self.assertEqual(func.commands, ['execute store result score @test_selector test_path run data get entity @test_selector path 100']) - - def test_mcfunction_get_variable_arrayconst(self): - env = mock_environment() - func = mcfunction.mcfunction(env) - - var = 'ArrayConst', ('test_array', interpreted_python('1')) - var_ret = func.get_variable(var, True) - - self.assertEqual(var_ret, ('Global', 'test_array1')) - self.assertEqual(func.commands, []) - - def test_mcfunction_get_variable_arrayexpr(self): - env = mock_environment() - func = mcfunction.mcfunction(env) - env.arrays['test_array'] = (0, 10) - - var = 'ArrayExpr', ('test_array', num_expr(1)) - var_ret = func.get_variable(var, True) - - self.assertEqual(var_ret, ('Global', 'test_arrayVal')) - self.assertEqual(func.commands, [ - 'scoreboard players set Global test_arrayIdx 1', - 'function test_namespace:array_test_array_get' - ]) - - def test_mcfunction_get_variable_arrayexpr_noarray(self): - env = mock_environment() - func = mcfunction.mcfunction(env) - - var = 'ArrayExpr', ('test_array', num_expr(1)) - with self.assertRaises(NameError): - var_ret = func.get_variable(var, True) - - def test_mcfunction_set_variable_var(self): - env = mock_environment() - sel = mock_selector_definition() - sel.paths['test_path'] = 'path', 'float', 100 - sel.base_name = '@s' - sel.is_single_entity = True - env.selectors['test_selector'] = sel - env.selector_definitions['@test_selector'] = sel - func = mcfunction.mcfunction(env) - - var = 'Var', ('@test_selector', 'test_path') - - func.set_variable(var) - self.assertEqual(func.commands, ['execute store result entity @test_selector path float 0.01 run scoreboard players get @test_selector test_path']) - - def test_mcfunction_set_variable_arrayexpr(self): - env = mock_environment() - func = mcfunction.mcfunction(env) - - var = ('ArrayExpr', ('test_array', num_expr(1))) - - func.set_variable(var) - self.assertEqual(func.commands, ['function test_namespace:array_test_array_set']) - - def test_mcfunction_get_if_chain_selector(self): - env = mock_environment() - func = mcfunction.mcfunction(env) - - condition = 'selector', '@p' - chain = func.get_if_chain([condition]) - - self.assertEqual(chain, 'if entity @p ') - - def test_mcfunction_get_if_chain_score_num(self): - env = mock_environment() - func = mcfunction.mcfunction(env) - - for op, match in [ - ('>', '2..'), - ('<', '..0'), - ('>=', '1..'), - ('<=', '..1'), - ('=', '1..1'), - ]: - condition = 'score', (('Var', ('@test_selector', 'test_var')), op, ('num', interpreted_python('1'))) - chain = func.get_if_chain([condition]) - - self.assertEqual(chain, f'if score @test_selector test_var matches {match} ') - - def test_mcfunction_get_if_chain_score_var(self): - env = mock_environment() - func = mcfunction.mcfunction(env) - - condition = 'score', (('Var', ('@test_selector', 'test_var')), '>', ('score', ('Var', ('@test_selector2', 'test_var2')))) - chain = func.get_if_chain([condition]) - - self.assertEqual(chain, 'if score @test_selector test_var > @test_selector2 test_var2 ') - - def test_mcfunction_get_if_chain_score_bad_comparison_type(self): - env = mock_environment() - func = mcfunction.mcfunction(env) - - condition = 'score', (('Var', ('@test_selector', 'test_var')), '>', ('bad', None)) - with self.assertRaises(ValueError): - func.get_if_chain([condition]) - - def test_mcfunction_get_if_chain_pointer(self): - env = mock_environment() - func = mcfunction.mcfunction(env) - - condition = 'pointer', (('Var', ('@test_selector', 'test_var')), '@test_selector2') - chain = func.get_if_chain([condition]) - - self.assertEqual(chain, 'if score @test_selector test_var = @test_selector2 _id ') - - def test_mcfunction_get_if_chain_vector_equality_var_id(self): - env = mock_environment() - func = mcfunction.mcfunction(env) - - condition = 'vector_equality', (('VAR_ID','var1'),('VAR_ID','var2')) - chain = func.get_if_chain([condition]) - - self.assertEqual(chain, 'if score Global _var1_0 = Global _var2_0 if score Global _var1_1 = Global _var2_1 if score Global _var1_2 = Global _var2_2 ') - - def test_mcfunction_get_if_chain_vector_equality_sel_var_id(self): - env = mock_environment() - func = mcfunction.mcfunction(env) - - condition = 'vector_equality', (('SEL_VAR_ID',('@sel1','var1')),('SEL_VAR_ID',('@sel2','var2'))) - chain = func.get_if_chain([condition]) - - self.assertEqual(chain, 'if score @sel1 _var1_0 = @sel2 _var2_0 if score @sel1 _var1_1 = @sel2 _var2_1 if score @sel1 _var1_2 = @sel2 _var2_2 ') - - def test_mcfunction_mcfunction_get_if_chain_vector_equality_var_components(self): - env = mock_environment() - func = mcfunction.mcfunction(env) - - condition = 'vector_equality', (('VAR_COMPONENTS',[('a1', 'x1'), ('b1', 'y1'), ('c1', 'z1')]),('VAR_COMPONENTS',[('a2', 'x2'), ('b2', 'y2'), ('c2', 'z2')])) - chain = func.get_if_chain([condition]) - - self.assertEqual(chain, 'if score a1 x1 = a2 x2 if score b1 y1 = b2 y2 if score c1 z1 = c2 z2 ') - - def test_mcfunction_mcfunction_get_if_chain_unless(self): - env = mock_environment() - func = mcfunction.mcfunction(env) - - condition = 'vector_equality', (('VAR_ID','var1'),('VAR_ID','var2')) - with self.assertRaises(ValueError): - func.get_if_chain([condition], 'unless') - - def test_mcfunction_mcfunction_get_if_chain_block(self): - env = mock_environment() - env.block_tags['test_block_tag'] = ['test_block1'] - func = mcfunction.mcfunction(env) - - condition1 = 'block', (dummy_relcoords(1, 2, 3), 'test_block_tag') - condition2 = 'block', (dummy_relcoords(4, 5, 6), 'test_block2') - chain = func.get_if_chain([condition1, condition2]) - - self.assertEqual(chain, 'if block 1 2 3 #test_namespace:test_block_tag if block 4 5 6 minecraft:test_block2 ') - - def test_mcfunction_mcfunction_get_if_chain_bad_type(self): - env = mock_environment() - func = mcfunction.mcfunction(env) - - condition = 'bad', None - with self.assertRaises(ValueError): - func.get_if_chain([condition]) - - def test_mcfunction_execute_command_multiple_as(self): - env = mock_environment() - func = mcfunction.mcfunction(env) - exec_func = mock_mcfunction() - - cmd = func.get_execute_command([('As', None), ('As', None)], exec_func) - self.assertEqual(cmd, None) - - def test_mcfunction_execute_command_if(self): - env = mock_environment() - func = mcfunction.mcfunction(env) - exec_func = mock_mcfunction() - - item = 'If', [('selector', '@p')] - - cmd = func.get_execute_command([item], exec_func) - self.assertEqual(cmd, 'execute if entity @p ') - - def test_mcfunction_execute_command_unless(self): - env = mock_environment() - func = mcfunction.mcfunction(env) - exec_func = mock_mcfunction() - - item = 'Unless', [('selector', '@p')] - - cmd = func.get_execute_command([item], exec_func) - self.assertEqual(cmd, 'execute unless entity @p ') - - def test_mcfunction_execute_command_as_id_attype(self): - env = mock_environment() - func = mcfunction.mcfunction(env) - exec_func = mock_mcfunction() - - item = 'AsId', (('Var', ('Global', 'test_var')), 'at_type') - - cmd = func.get_execute_command([item], exec_func) - self.assertEqual(func.commands, ['scoreboard players operation Global _id = Global test_var']) - self.assertEqual(cmd, 'execute as @e if score @s _id = Global _id ') - self.assertEqual(exec_func.self_selector, '@at_type') - - def test_mcfunction_execute_command_as_id(self): - env = mock_environment() - func = mcfunction.mcfunction(env) - exec_func = mock_mcfunction() - - item = 'AsId', (('Var', ('Global', 'test_var')), None) - - cmd = func.get_execute_command([item], exec_func) - self.assertEqual(func.commands, ['scoreboard players operation Global _id = Global test_var']) - self.assertEqual(cmd, 'execute as @e if score @s _id = Global _id ') - - def test_mcfunction_execute_command_as_create(self): - env = mock_environment() - func = mcfunction.mcfunction(env) - exec_func = mock_mcfunction() - sel = mock_selector_definition() - sel.type = 'creeper' - env.selectors['test_id'] = sel - - item = 'AsCreate', create_block(0, 'test_id', relcoords([relcoord('', const_number('1')), relcoord('', const_number('2')), relcoord('', const_number('3'))])) - - cmd = func.get_execute_command([item], exec_func) - self.assertEqual(func.commands, [ - 'scoreboard players add @e _age 1', - 'summon creeper 1 2 3 ', - 'scoreboard players add @e _age 1' - ]) - self.assertEqual(cmd, 'execute as @e[_age==1] ') - - def test_mcfunction_execute_command_as_create_multiple(self): - env = mock_environment() - func = mcfunction.mcfunction(env) - exec_func = mock_mcfunction() - - item = 'AsCreate', create_block(0, 'test_id', ['1', '2', '3']) - item2 = 'If', [('selector', '@p')] - - cmd = func.get_execute_command([item, item2], exec_func) - - self.assertEqual(cmd, None) - - def test_mcfunction_execute_command_rotated_etc(self): - env = mock_environment() - func = mcfunction.mcfunction(env) - exec_func = mock_mcfunction() - - for type, code, target, target_code, extra in [ - ('As', 'as', '@p', '@p', ''), - ('Rotated', 'rotated as', '@p', '@p', ''), - ('FacingCoords', 'facing', dummy_relcoords(1, 2, 3), '1 2 3', ''), - ('FacingEntity', 'facing entity', '@p', '@p', ' feet'), - ('Align', 'align', 'xyz', 'xyz', ''), - ('In', 'in', 'the_end', 'the_end', ''), - ]: - item = type, target - - cmd = func.get_execute_command([item], exec_func) - self.assertEqual(cmd, f'execute {code} {target_code}{extra} ') - - def test_mcfunction_execute_command_at_selector_coords(self): - env = mock_environment() - func = mcfunction.mcfunction(env) - exec_func = mock_mcfunction() - - item = 'At', ('@test_selector', dummy_relcoords(1, 2, 3)) - - cmd = func.get_execute_command([item], exec_func) - self.assertEqual(cmd, 'execute at @test_selector positioned 1 2 3 ') - - def test_mcfunction_execute_command_at_selector(self): - env = mock_environment() - func = mcfunction.mcfunction(env) - exec_func = mock_mcfunction() - - item = 'At', ('@test_selector', None) - - cmd = func.get_execute_command([item], exec_func) - self.assertEqual(cmd, 'execute at @test_selector ') - - def test_mcfunction_execute_command_at_coords(self): - env = mock_environment() - func = mcfunction.mcfunction(env) - exec_func = mock_mcfunction() - - item = 'At', (None, dummy_relcoords(1, 2, 3)) - - cmd = func.get_execute_command([item], exec_func) - self.assertEqual(cmd, 'execute positioned 1 2 3 ') - - def test_mcfunction_execute_command_at_vector(self): - env = mock_environment() - func = mcfunction.mcfunction(env) - exec_func = mock_mcfunction() - - item = 'AtVector', (None, vector_var_expr('test_vector')) - - cmd = func.get_execute_command([item], exec_func) - self.assertEqual(cmd, 'execute at @e[_age == 1] ') - self.assertEqual(func.commands, [ - 'scoreboard players add @e _age 1', - 'summon area_effect_cloud', - 'scoreboard players add @e _age 1', - 'execute store result entity @e[_age==1,limit=1] Pos[0] double 0.001 run scoreboard players get Global _test_vector_0', - 'execute store result entity @e[_age==1,limit=1] Pos[1] double 0.001 run scoreboard players get Global _test_vector_1', - 'execute store result entity @e[_age==1,limit=1] Pos[2] double 0.001 run scoreboard players get Global _test_vector_2' - ]) - self.assertEqual(exec_func.commands, ['/kill @e[_age == 1]']) - - def test_mcfunction_execute_command_at_vector_scale(self): - env = mock_environment() - func = mcfunction.mcfunction(env) - exec_func = mock_mcfunction() - - item = 'AtVector', (const_number(200), vector_var_expr('test_vector')) - - cmd = func.get_execute_command([item], exec_func) - self.assertEqual(cmd, 'execute at @e[_age == 1] ') - self.assertEqual(func.commands, [ - 'scoreboard players add @e _age 1', - 'summon area_effect_cloud', - 'scoreboard players add @e _age 1', - 'execute store result entity @e[_age==1,limit=1] Pos[0] double 0.005 run scoreboard players get Global _test_vector_0', - 'execute store result entity @e[_age==1,limit=1] Pos[1] double 0.005 run scoreboard players get Global _test_vector_1', - 'execute store result entity @e[_age==1,limit=1] Pos[2] double 0.005 run scoreboard players get Global _test_vector_2' - ]) - self.assertEqual(exec_func.commands, ['/kill @e[_age == 1]']) - - def test_mcfunction_execute_command_at_vector_multiple(self): - env = mock_environment() - func = mcfunction.mcfunction(env) - exec_func = mock_mcfunction() - - item1 = 'AtVector', (const_number(200), vector_var_expr('test_vector')) - item2 = 'AtVector', (const_number(200), vector_var_expr('test_vector')) - - cmd = func.get_execute_command([item1, item2], exec_func) - self.assertEqual(cmd, None) - - def test_mcfunction_switch_cases_four(self): - env = mock_environment() - func = mcfunction.mcfunction(env) - - case1 = 1, 2, [mock_block('command1')], 0, None - case2 = 3, 3, [mock_block('command2')], 0, None - case3 = 4, 5, [mock_block('command3')], 0, None - case4 = 6, 10, [mock_block('command4')], 0, None - - self.assertTrue(func.switch_cases('switch_var', [case1, case2, case3, case4])) - self.assertEqual(func.commands, [ - 'execute if score Global switch_var matches 1..2 run command1', - 'execute if score Global switch_var matches 3..3 run command2', - 'execute if score Global switch_var matches 4..5 run command3', - 'execute if score Global switch_var matches 6..10 run command4' - ]) - - def test_mcfunction_switch_cases_three(self): - env = mock_environment() - func = mcfunction.mcfunction(env) - - case1 = 1, 2, [mock_block('command1')], 0, None - case2 = 3, 3, [mock_block('command2')], 0, 'test_python_var' - case3 = 4, 5, [mock_block('command3')], 0, None - - self.assertTrue(func.switch_cases('switch_var', [case1, case2, case3])) - self.assertEqual(func.commands, [ - 'execute if score Global switch_var matches 1..2 run command1', - 'execute if score Global switch_var matches 3..3 run command2', - 'execute if score Global switch_var matches 4..5 run command3' - ]) - self.assertEqual(env.cloned_environments[1].dollarid['test_python_var'], 3) - - def test_mcfunction_switch_cases_multiline(self): - env = mock_environment() - func = mcfunction.mcfunction(env) - - case1 = 1, 2, [mock_block('command1')], 0, None - case2 = 3, 3, [mock_block('command2'), mock_block('command5')], 0, None, - case3 = 4, 5, [mock_block('command3'), mock_block('command4')], 0, None - - self.assertTrue(func.switch_cases('switch_var', [case1, case2, case3])) - self.assertEqual(func.commands, [ - 'execute if score Global switch_var matches 1..2 run command1', - 'execute if score Global switch_var matches 3..3 run function test_namespace:case3_001_ln0', - 'execute if score Global switch_var matches 4..5 run function test_namespace:case4-5_001_ln0' - ]) - self.assertEqual(env.functions['case3_001_ln0'].commands, ['command2', 'command5']) - self.assertEqual(env.functions['case4-5_001_ln0'].commands, ['command3', 'command4']) - - def test_mcfunction_switch_cases_five(self): - env = mock_environment() - func = mcfunction.mcfunction(env) - - case1 = 1, 2, [mock_block('command1')], 0, None - case2 = 3, 3, [mock_block('command2')], 0, None - case3 = 4, 5, [mock_block('command3')], 0, None - case4 = 6, 10, [mock_block('command4')], 0, None - case5 = 11, 15, [mock_block('command5')], 0, None - - self.assertTrue(func.switch_cases('switch_var', [case1, case2, case3, case4, case5])) - self.assertEqual(func.commands, [ - 'execute if score Global switch_var matches 1..2 run command1', - 'execute if score Global switch_var matches 3..3 run command2', - 'execute if score Global switch_var matches 4..5 run command3', - 'execute if score Global switch_var matches 6..15 run function test_namespace:switch6-15_001_ln0', - ]) - self.assertEqual(env.functions['switch6-15_001_ln0'].commands, [ - 'execute if score Global switch_var matches 6..10 run command4', - 'execute if score Global switch_var matches 11..15 run command5' - ]) - - def test_mcfunction_switch_cases_error(self): - env = mock_environment() - func = mcfunction.mcfunction(env) - - case1 = 1, 2, [mock_block('command1')], 0, None - case2 = 3, 3, [mock_block('command2')], 0, 'test_python_var' - case3 = 4, 5, [mock_block('command3')], 0, None - case4 = 6, 7, [mock_block('command4')], 0, None - case5 = 8, 9, [mock_block(raiseException=True, line=1)], 0, None - - self.assertFalse(func.switch_cases('switch_var', [case1, case2, case3, case4, case5])) - - def test_mcfunction_add_operation(self): - env = mock_environment() - func = mcfunction.mcfunction(env) - - func.add_operation('@test_selector', 'var1', '+=', 'var2') - self.assertEqual(env.applied, [ - '@test_selector', - 'scoreboard players operation @test_selector var1 += @test_selector var2' - ]) - self.assertEqual(func.commands, ['scoreboard players operation @test_selector var1 += @test_selector var2']) - - def test_mcfunction_insert_command_empty(self): - env = mock_environment() - func = mcfunction.mcfunction(env) - - func.insert_command('', 0) - self.assertEqual(func.commands, []) - - def test_mcfunction_get_vector_path(self): - env = mock_environment() - sel = mock_selector_definition() - sel.vector_paths['test_var'] = 'path.to.data', 'float', None - sel.is_single_entity = True - env.selectors['test_selector'] = sel - env.selector_definitions['@test_selector[x=1]'] = sel - func = mcfunction.mcfunction(env) - - self.assertTrue(func.get_vector_path('@test_selector[x=1]', 'test_var', ['assign_var1', 'assign_var2', 'assign_var3'])) - self.assertEqual(func.commands, [ - 'execute store result score Global assign_var1 run data get entity @test_selector[x=1] path.to.data[0] 1000', - 'execute store result score Global assign_var2 run data get entity @test_selector[x=1] path.to.data[1] 1000', - 'execute store result score Global assign_var3 run data get entity @test_selector[x=1] path.to.data[2] 1000' - ]) - - def test_mcfunction_set_selector_path(self): - env = mock_environment() - sel = mock_selector_definition() - sel.vector_paths['test_var'] = 'path.to.data', 'float', None - sel.is_single_entity = True - env.selectors['test_selector'] = sel - env.selector_definitions['@test_selector[x=1]'] = sel - func = mcfunction.mcfunction(env) - - self.assertTrue(func.set_vector_path('@test_selector[x=1]', 'test_var', ['x', 'y', 'z'])) - self.assertEqual(func.commands, [ - 'execute store result entity @test_selector[x=1] path.to.data[0] float 0.001 run scoreboard players get Global x', - 'execute store result entity @test_selector[x=1] path.to.data[1] float 0.001 run scoreboard players get Global y', - 'execute store result entity @test_selector[x=1] path.to.data[2] float 0.001 run scoreboard players get Global z' - ]) - - def test_environment_clone(self): - gc = mock_global_context() - env = environment.environment(gc) - - new_env = env.clone('new_name') - - self.assertEqual(new_env.scratch.prefix, 'new_name_prefix') - - def test_environment_copy_dollarid(self): - gc = mock_global_context() - env = environment.environment(gc) - - env.dollarid['test1'] = '10' - env.copy_dollarid('$test2', '-$test1') - - self.assertTrue('test2' in env.dollarid) - self.assertEqual(env.dollarid['test2'], '-10') - - env.dollarid['test3'] = '20.0' - env.copy_dollarid('$test4', '-$test3') - - self.assertTrue('test4' in env.dollarid) - self.assertEqual(env.dollarid['test4'], '-20.0') - - env.dollarid['test5'] = 'string' - with self.assertRaises(ValueError) as context: - env.copy_dollarid('$test6', '-$test5') - - -if __name__ == '__main__': - unittest.main() \ No newline at end of file + def test_is_number(self): + self.assertTrue(environment.isNumber("1")) + self.assertTrue(environment.isNumber("0")) + self.assertTrue(environment.isNumber("1.0")) + self.assertFalse(environment.isNumber(float("inf"))) + self.assertFalse(environment.isNumber(float("nan"))) + self.assertFalse(environment.isNumber(None)) + self.assertFalse(environment.isNumber("test")) + + def test_is_int(self): + self.assertTrue(environment.isInt("1")) + self.assertTrue(environment.isInt("0")) + self.assertFalse(environment.isInt("1.0")) + self.assertFalse(environment.isInt(float("inf"))) + self.assertFalse(environment.isInt(float("nan"))) + self.assertFalse(environment.isInt(None)) + self.assertFalse(environment.isInt("test")) + + def test_factor(self): + self.assertEqual(list(factor(20)), [2, 2, 5]) + self.assertEqual(list(factor(2)), [2]) + self.assertEqual(list(factor(1)), []) + + def test_compile_runs_without_error(self): + func = mock_mcfunction() + + func.arrays["test"] = (0, 5) + block = array_assignment_block(0, "test", "Const", 1, num_expr(1)) + block.compile(func) + + block = array_definition_block( + 0, "test", const_number("0"), const_number("5") + ) + block.compile(func) + + block = block_tag_block(0, "test", ["test_block"]) + block.compile(func) + + block = command_block(0, "test") + block.compile(func) + + block = comment_block(0, "#test") + block.compile(func) + + block = create_block(0, "@test", ["0", "0", "0"]) + block.compile(func) + + block = execute_block(0, [], [command_block(0, "test_command")]) + block.compile(func) + + block = for_index_block( + 0, + "test", + num_expr(0), + num_expr(5), + num_expr(2), + [command_block(0, "test_command")], + ) + block.compile(func) + + block = for_selector_block( + 0, "@test", "@a", [command_block(0, "test_command")] + ) + block.compile(func) + + block = function_call_block(0, "test_function", []) + block.compile(func) + + func.macros["test_macro"] = ([], [command_block(0, "test_command")]) + block = macro_call_block(0, "test_macro", []) + block.compile(func) + + block = method_call_block(0, "@test_selector", "test_method", []) + block.compile(func) + + block = move_block(0, "@a", dummy_relcoords(0, 0, 0)) + block.compile(func) + + block = python_assignment_block( + 0, "test_id", interpreted_python("1+1", 0) + ) + block.compile(func) + + block = python_for_block( + 0, + "test_id", + interpreted_python("range(3)", 0), + [command_block(0, "test_command")], + ) + block.compile(func) + + block = python_if_block( + 0, + interpreted_python("1", 0), + [command_block(0, "true_command")], + [command_block(0, "false_command")], + ) + block.compile(func) + block = python_if_block( + 0, + interpreted_python("0", 0), + [command_block(0, "true_command")], + [command_block(0, "false_command")], + ) + block.compile(func) + + var = ("Var", ("@s", "test")) + block = scoreboard_assignment_block(0, (var, "+=", num_expr(1))) + block.compile(func) + + block = selector_assignment_block(0, "test", "@a") + block.compile(func) + + tag = ("Tag", "{}") + path = ("Path", ("test_path", "test", "float", const_number(1000))) + vpath = ( + "VectorPath", + ("test_vector_id", "test_vector", "float", const_number(1)), + ) + block = selector_definition_block( + 0, "test_id", "@a", [tag, path, vpath] + ) + block.compile(func) + + block = switch_block(0, ("NUM", 1), []) + block.compile(func) + case1 = ( + "python", + ( + "test_id", + interpreted_python("range(3, 6)"), + [command_block(0, "test_python")], + ), + ) + case2 = ( + "range", + ( + const_number("1"), + const_number("2"), + [command_block(0, "test_range_1_2")], + ), + ) + block = switch_block(0, num_expr(1), [case1, case2]) + block.compile(func) + + block = tell_block(0, "@a", "{rhi") + block.compile(func) + + func.template_functions["test_template_function"] = ( + [], + [], + [command_block(0, "test_command")], + ) + block = template_function_call_block( + 0, "test_template_function", [], [] + ) + block.compile(func) + + block = title_block( + 0, + "subtitle", + "@a", + [const_number("1"), const_number("2"), const_number("3")], + "{rtest", + ) + block.compile(func) + + var = ("VAR_ID", "test") + block = vector_assignment_block( + 0, var, "+=", vector_here_expr(const_number(1000)) + ) + block.compile(func) + + var = ("VAR_ID", "test") + block = vector_assignment_scalar_block(0, var, "+=", num_expr(1)) + block.compile(func) + + block = while_block(0, [], [command_block(0, "test_command")]) + block.compile(func) + + def test_compile_vector_assignment_scalar(self): + func = mock_mcfunction() + + block = vector_assignment_scalar_block( + 0, ("VAR_ID", "test_vector"), "*=", num_expr(2) + ) + block.compile(func) + + self.assertEqual(len(func.commands), 4) + self.assertEqual( + func.commands[0], "scoreboard players set Global test_scratch1 2" + ) + for i in range(3): + self.assertEqual( + func.commands[i + 1], + f"scoreboard players operation Global _test_vector_{i} *= Global test_scratch1", + ) + + def test_compile_vector_assignment(self): + func = mock_mcfunction() + + block = vector_assignment_block( + 0, + ("VAR_ID", "test_vector"), + "+=", + vector_expr([num_expr(2), num_expr(3), num_expr(4)]), + ) + block.compile(func) + + self.assertEqual(len(func.commands), 6) + for i in range(3): + self.assertEqual( + func.commands[i], + f"scoreboard players set Global test_scratch{i+1} {i+2}", + ) + self.assertEqual( + func.commands[i + 3], + f"scoreboard players operation Global _test_vector_{i} += Global test_scratch{i+1}", + ) + + def test_compile_comment(self): + func = mock_mcfunction() + + block = comment_block(0, "#test") + block.compile(func) + self.assertTrue("#test" in func.commands) + + def test_compile_command(self): + func = mock_mcfunction() + block = command_block(0, "say hi") + block.compile(func) + self.assertTrue("say hi" in func.commands) + + def test_compile_move(self): + func = mock_mcfunction() + block = move_block(0, "@s", dummy_relcoords(1, 1, 1)) + block.compile(func) + self.assertTrue("execute at @s run tp @s 1 1 1" in func.commands) + + block = move_block( + 0, + "@a", + relcoords( + ( + relcoord("^", const_number(0)), + relcoord("^", const_number(0)), + relcoord("^", const_number(1)), + ) + ), + ) + block.compile(func) + self.assertTrue( + "execute as @a at @s run tp @s ^0 ^0 ^1" in func.commands + ) + + def test_compile_python_assignment(self): + func = mock_mcfunction() + + block = python_assignment_block( + 0, "test", interpreted_python("1+1", 0) + ) + block.compile(func) + self.assertTrue("test" in func.dollarid) + self.assertEqual(func.dollarid["test"], 2) + + block = python_assignment_block( + 0, "test2", interpreted_python("1/0", 0) + ) + with self.assertRaises(Exception) as context: + block.compile(func) + self.assertEqual(len(func.dollarid), 1) + + block = python_assignment_block( + 0, "test3", interpreted_python("math.sqrt(9)", 0) + ) + block.compile(func) + self.assertTrue("test3" in func.dollarid) + self.assertEqual(func.dollarid["test3"], 3) + + def test_compile_python_for(self): + func = mock_mcfunction() + + block = python_for_block( + 0, + "i", + interpreted_python("range(3)", 0), + [command_block(0, "/say $i")], + ) + block.compile(func) + + block = python_for_block(0, "i", interpreted_python("[]", 0), []) + block.compile(func) + + block = python_for_block(0, "i", "1", []) + with self.assertRaises(Exception) as context: + block.compile(func) + + block = python_for_block(0, "i", "range(1/0)", []) + with self.assertRaises(Exception) as context: + block.compile(func) + + def test_compile_selector_assignment(self): + func = mock_mcfunction() + + block = selector_assignment_block(0, "test", "@s[x=1]") + block.compile(func) + + self.assertEqual(func.selectors["test"].selector, "@s[x=1]") + + def test_compile_array_assignment(self): + func = mock_mcfunction() + func.arrays["test_array"] = (0, 5) + + block = array_assignment_block( + 0, "test_array", "Const", 1, num_expr(2) + ) + block.compile(func) + self.assertTrue( + "scoreboard players set Global test_array1 2" in func.commands + ) + + func.arrays["test_array2"] = (0, 10) + block = array_assignment_block( + 0, "test_array2", "Expr", num_expr(2), num_expr(3) + ) + block.compile(func) + self.assertTrue( + "scoreboard players set Global test_array2Val 3" in func.commands + ) + self.assertTrue( + "scoreboard players set Global test_array2Idx 2" in func.commands + ) + self.assertTrue( + "function test_namespace:array_test_array2_set" in func.commands + ) + + def test_compile_array_definition(self): + func = mock_mcfunction() + + block = array_definition_block( + 0, "test_array", const_number(0), const_number(5) + ) + block.compile(func) + + self.assertTrue("test_array" in func.arrays) + self.assertEqual(func.arrays["test_array"], (0, 5)) + + self.assertEqual(len(func.child_functions), 2) + self.assertTrue("array_test_array_set" in func.functions) + self.assertTrue("array_test_array_get" in func.functions) + + def test_compile_block_tag(self): + func = mock_mcfunction() + + block = block_tag_block( + 0, "test_block_tag", ["test_block", "test_block2"] + ) + block.compile(func) + + self.assertTrue("test_block_tag" in func.block_tags) + self.assertTrue( + func.block_tags["test_block_tag"] == ["test_block", "test_block2"] + ) + + def test_compile_create(self): + func = mock_mcfunction() + + block = create_block(0, "@test", ["0", "0", "0"]) + block.compile(func) + + self.assertEqual(len(func.created), 1) + + def test_compile_execute(self): + func = mock_mcfunction() + + block = execute_block(0, "test", "sub") + block.compile(func) + + self.assertEqual(len(func.child_functions), 1) + self.assertEqual(func.execute_command_calls, ["test"]) + + def test_compile_for_selector(self): + func = mock_mcfunction() + + block = for_selector_block( + 0, "test", "@a", command_block(1, "test_command") + ) + block.compile(func) + + self.assertEqual(len(func.child_functions), 1) + self.assertTrue("test" in func.child_functions[0].selectors) + + def test_compile_for_index(self): + func = mock_mcfunction() + + block = for_index_block( + 0, "test_idx", num_expr(1), num_expr(5), num_expr(2), [] + ) + block.compile(func) + + self.assertEqual( + func.commands, + [ + "scoreboard players set Global test_idx 1", + "scoreboard players set Global test_scratch1 5", + "scoreboard players set Global test_scratch2 2", + "execute if score Global test_scratch2 matches ..-1 if score Global test_idx >= Global test_scratch1 run function test_namespace:for001_ln0", + "execute if score Global test_scratch2 matches 1.. if score Global test_idx <= Global test_scratch1 run function test_namespace:for001_ln0", + ], + ) + + self.assertEqual(len(func.child_functions), 1) + self.assertEqual( + func.child_functions[0].commands, + [ + "scoreboard players operation Global test_idx += Global test_scratch2", + "execute if score Global test_scratch2 matches ..-1 if score Global test_idx >= Global test_scratch1 run function test_namespace:for001_ln0", + "execute if score Global test_scratch2 matches 1.. if score Global test_idx <= Global test_scratch1 run function test_namespace:for001_ln0", + ], + ) + + def test_compile_function_call(self): + func = mock_mcfunction() + + block = function_call_block(0, "test_function", [num_expr(1)]) + block.compile(func) + + self.assertEqual( + func.commands, ["function test_namespace:test_function"] + ) + + def test_compile_macro_call(self): + func = mock_mcfunction() + macro = (["test_param"], []) + func.macros["test_macro"] = macro + + block = macro_call_block(0, "test_macro", [const_number("10")]) + block.compile(func) + + self.assertEqual(len(func.child_functions), 0) + self.assertEqual(len(func.cloned_environments), 1) + self.assertTrue("test_param" in func.cloned_environments[0].dollarid) + self.assertEqual( + func.cloned_environments[0].dollarid["test_param"], 10 + ) + + self.assertEqual(func.environment_pushes, 1) + self.assertEqual(func.environment_pops, 1) + + def test_compile_method_call(self): + func = mock_mcfunction() + + block = method_call_block( + 0, "@test_selector", "test_method", [num_expr(1)] + ) + block.compile(func) + + self.assertEqual( + func.commands, + [ + "execute as @test_selector run function test_namespace:test_method" + ], + ) + + def test_compile_python_if(self): + func = mock_mcfunction() + + block = python_if_block(0, interpreted_python("1", 0), [1], [2]) + block.compile(func) + + self.assertTrue([1] in func.compiled_blocks) + + func = mock_mcfunction() + + block = python_if_block(0, interpreted_python("0", 0), [1], [2]) + block.compile(func) + + self.assertTrue([2] in func.compiled_blocks) + + func = mock_mcfunction() + + block = python_if_block(0, interpreted_python("1", 0), [1], None) + block.compile(func) + + self.assertTrue([1] in func.compiled_blocks) + + func = mock_mcfunction() + + block = python_if_block(0, interpreted_python("0", 0), [1], None) + block.compile(func) + + self.assertEqual(len(func.compiled_blocks), 0) + + def test_compile_scoreboard_assignment(self): + func = mock_mcfunction() + + var = ("Var", ("Global", "test_var")) + block = scoreboard_assignment_block(0, (var, "+=", num_expr(1))) + block.compile(func) + + self.assertEqual( + func.commands, ["/scoreboard players add Global var1 1"] + ) + + func = mock_mcfunction() + + block = scoreboard_assignment_block(0, (var, "=", num_expr(1))) + block.compile(func) + + self.assertEqual( + func.commands, ["/scoreboard players set Global var1 1"] + ) + + func = mock_mcfunction() + + block = scoreboard_assignment_block(0, (var, "*=", num_expr(1))) + block.compile(func) + + self.assertEqual( + func.commands, + [ + "/scoreboard players operation Global var1 *= test_constant Constant" + ], + ) + self.assertTrue(1 in func.constants) + + def test_compile_selector_definition(self): + func = mock_mcfunction() + + items = [ + ("Tag", "{}"), + ( + "Path", + ("test_path", "path.to.data", "float", const_number(100)), + ), + ( + "VectorPath", + ( + "test_vector_path", + "path.to.vector", + "int", + const_number(200), + ), + ), + ("Method", ("function", "test_method", [], [], [])), + ] + block = selector_definition_block(0, "test_selector", "@a", items) + block.compile(func) + + self.assertTrue("test_selector" in func.selectors) + + selector = func.selectors["test_selector"] + self.assertEqual(selector.selector, "@a") + + self.assertTrue("test_path" in selector.paths) + self.assertEqual( + selector.paths["test_path"], ("path.to.data", "float", 100) + ) + + self.assertTrue("test_vector_path" in selector.vector_paths) + self.assertEqual( + selector.vector_paths["test_vector_path"], + ("path.to.vector", "int", 200), + ) + + # TODO: verify the method was created + + def test_compile_switch(self): + func = mock_mcfunction() + + case1 = ("range", (const_number(1), const_number(3), [])) + case2 = ("python", ("test_id", interpreted_python("range(4, 6)"), [])) + block = switch_block(0, num_expr(2), [case1, case2]) + block.compile(func) + + self.assertEqual( + func.switch_calls, + [ + ( + "test_scratch1", + [ + (1, 3, [], "Unknown", None), + (4, 4, [], "Unknown", "test_id"), + (5, 5, [], "Unknown", "test_id"), + ], + "switch", + "case", + ) + ], + ) + self.assertEqual( + func.commands, ["scoreboard players set Global test_scratch1 2"] + ) + + def test_compile_tell(self): + func = mock_mcfunction() + + block = tell_block(0, "@a", "{rhi") + block.compile(func) + + self.assertEqual( + func.commands, + ['/tellraw @a ["",{"text":"hi","color":"dark_red"}]'], + ) + + def test_compile_template_function_call(self): + func = mock_mcfunction() + func.template_functions["test_template_function"] = ( + ["test_macro_param"], + ["test_function_param"], + [], + ) + + block = template_function_call_block( + 0, "test_template_function", [const_number("10")], [num_expr("15")] + ) + block.compile(func) + + self.assertEqual( + func.commands, + [ + "scoreboard players set Global Param0 15", + "function test_namespace:test_template_function_10", + ], + ) + self.assertTrue("test_template_function_10" in func.functions) + self.assertTrue( + "test_macro_param" + in func.functions["test_template_function_10"].environment.dollarid + ) + self.assertEqual( + func.functions["test_template_function_10"].environment.dollarid[ + "test_macro_param" + ], + 10, + ) + + func = mock_mcfunction() + func.template_functions["test_template_function"] = ( + ["test_macro_param"], + [], + [], + ) + func.dollarid["test_id"] = 5 + + block = template_function_call_block( + 0, "test_template_function", [python_identifier("test_id")], [] + ) + block.compile(func) + + self.assertTrue("test_template_function_5" in func.functions) + self.assertEqual( + func.functions["test_template_function_5"].environment.dollarid[ + "test_macro_param" + ], + 5, + ) + + def test_compile_title(self): + func = mock_mcfunction() + + block = title_block( + 0, + "subtitle", + "@a", + [const_number("0"), const_number("1"), const_number("2")], + "{rtest", + ) + block.compile(func) + + self.assertEqual( + func.commands, + [ + "/title @a times 0 1 2", + '/title @a subtitle ["",{"text":"test","color":"dark_red"}]', + ], + ) + + def test_compile_while(self): + func = mock_mcfunction() + + block = while_block(0, "test", ["test_block"]) + block.compile(func) + + self.assertEqual( + func.commands, + ["execute_dummy run function test_namespace:while001_ln0"], + ) + self.assertEqual(func.execute_command_calls, ["test"]) + self.assertEqual(len(func.child_functions), 1) + self.assertEqual( + func.child_functions[0].compiled_blocks[0], ["test_block"] + ) + self.assertTrue( + "execute_dummy run function test_namespace:while001_ln0" + in func.child_functions[0].commands + ) + + def test_arrayconst_expr(self): + func = mock_mcfunction() + func.arrays["test_array"] = (0, 5) + + expr = arrayconst_expr("test_array", "1") + id = expr.compile(func, None) + + self.assertEqual(id, "test_array1") + + def test_arrayexpr_expr(self): + func = mock_mcfunction() + func.arrays["test_array"] = (0, 5) + + expr = arrayexpr_expr("test_array", num_expr(3)) + id = expr.compile(func, None) + + self.assertEqual(id, "test_arrayVal") + + def test_binop_expr(self): + func = mock_mcfunction() + + expr = binop_expr(num_expr(3), "+", num_expr(4)) + id = expr.compile(func, "test_id") + + self.assertEqual(id, "test_id") + self.assertTrue( + "scoreboard players set Global test_id 3" in func.commands + ) + self.assertTrue( + "scoreboard players add Global test_id 4" in func.commands + ) + + expr = binop_expr(num_expr(3), "+", selvar_expr("Global", "test_var")) + id = expr.compile(func, "test_id2") + + self.assertEqual(id, "test_id2") + self.assertTrue( + "scoreboard players operation Global test_id2 = Global test_var" + in func.commands + ) + self.assertTrue( + "scoreboard players add Global test_id2 3" in func.commands + ) + + expr = binop_expr(num_expr(5), "^", num_expr(2)) + id = expr.compile(func, "test_id3") + + self.assertEqual(id, "test_scratch1") + self.assertEqual( + func.commands, + [ + "scoreboard players set Global test_id 3", + "scoreboard players add Global test_id 4", + "scoreboard players operation Global test_id2 = Global test_var", + "scoreboard players add Global test_id2 3", + "scoreboard players set Global test_id3 5", + "scoreboard players operation Global test_scratch1 = Global test_id3", + "scoreboard players operation Global test_scratch1 *= Global test_id3", + ], + ) + + expr = binop_expr(num_expr(5), "^", selvar_expr("Global", "test_var")) + id = expr.compile(func, "test_id4") + self.assertEqual(id, None) + + def test_create_expr(self): + func = mock_mcfunction() + + expr = create_expr(create_block(0, "@test", ["0", "0", "0"])) + id = expr.compile(func, "test_id") + + self.assertEqual(id, "test_id") + self.assertEqual( + func.commands, + [ + "scoreboard players add @e _age 1", + "scoreboard players add @e _age 1", + "scoreboard players add Global _unique 1", + "scoreboard players operation @@test[_age==1] _id = Global _unique", + "scoreboard players operation Global test_id = Global _unique", + ], + ) + self.assertEqual(func.created, [("@test", ["0", "0", "0"])]) + + def test_dot_expr(self): + func = mock_mcfunction() + + expr = dot_expr(vector_var_expr("vec1"), vector_var_expr("vec2")) + id = expr.compile(func, "test_id5") + + self.assertEqual(id, "test_scratch1") + self.assertEqual(len(func.commands), 8) + + def test_func_expr(self): + func = mock_mcfunction() + + expr = func_expr(function_call_block(0, "sin", [num_expr(1)])) + id = expr.compile(func, "test_id") + + self.assertEqual(id, "test_id") + self.assertEqual( + func.commands, + [ + "scoreboard players set Global test_scratch1 1", + "scoreboard players operation Global temp1 = Global test_scratch1", + "scoreboard players operation Global temp1 %= test_constant Constant", + "scoreboard players add Global temp1 360", + "scoreboard players operation Global temp1 %= test_constant Constant", + "scoreboard players operation Global test_id = Global test_scratch1", + "scoreboard players operation Global temp2 = Global temp1", + "scoreboard players operation Global temp2 %= test_constant Constant", + "scoreboard players operation Global test_id = Global temp2", + "scoreboard players operation Global test_id *= test_constant Constant", + "scoreboard players set Global test_scratch2 180", + "scoreboard players operation Global test_scratch3 = Global test_scratch2", + "scoreboard players operation Global test_scratch3 -= Global temp2", + "scoreboard players operation Global test_id *= Global test_scratch3", + "scoreboard players set Global test_scratch4 40500", + "scoreboard players operation Global test_scratch5 = Global test_scratch4", + "scoreboard players operation Global test_scratch6 = Global temp2", + "scoreboard players set Global test_scratch7 180", + "scoreboard players operation Global test_scratch8 = Global test_scratch7", + "scoreboard players operation Global test_scratch8 -= Global temp2", + "scoreboard players operation Global test_scratch6 *= Global test_scratch8", + "scoreboard players operation Global test_scratch5 -= Global test_scratch6", + "scoreboard players operation Global test_id /= Global test_scratch5", + "execute if score Global temp1 matches 180.. run scoreboard players operation Global test_id *= minus Constant", + ], + ) + + func = mock_mcfunction() + + expr = func_expr(function_call_block(0, "cos", [num_expr(1)])) + id = expr.compile(func, "test_id") + + self.assertEqual(id, "test_id") + self.assertEqual( + func.commands, + [ + "scoreboard players set Global test_scratch1 1", + "scoreboard players operation Global temp1 = Global test_scratch1", + "scoreboard players operation Global temp1 %= test_constant Constant", + "scoreboard players add Global temp1 450", + "scoreboard players operation Global temp1 %= test_constant Constant", + "scoreboard players operation Global test_id = Global test_scratch1", + "scoreboard players operation Global temp2 = Global temp1", + "scoreboard players operation Global temp2 %= test_constant Constant", + "scoreboard players operation Global test_id = Global temp2", + "scoreboard players operation Global test_id *= test_constant Constant", + "scoreboard players set Global test_scratch2 180", + "scoreboard players operation Global test_scratch3 = Global test_scratch2", + "scoreboard players operation Global test_scratch3 -= Global temp2", + "scoreboard players operation Global test_id *= Global test_scratch3", + "scoreboard players set Global test_scratch4 40500", + "scoreboard players operation Global test_scratch5 = Global test_scratch4", + "scoreboard players operation Global test_scratch6 = Global temp2", + "scoreboard players set Global test_scratch7 180", + "scoreboard players operation Global test_scratch8 = Global test_scratch7", + "scoreboard players operation Global test_scratch8 -= Global temp2", + "scoreboard players operation Global test_scratch6 *= Global test_scratch8", + "scoreboard players operation Global test_scratch5 -= Global test_scratch6", + "scoreboard players operation Global test_id /= Global test_scratch5", + "execute if score Global temp1 matches 180.. run scoreboard players operation Global test_id *= minus Constant", + ], + ) + + func = mock_mcfunction() + + expr = func_expr(function_call_block(0, "sqrt", [num_expr(1)])) + id = expr.compile(func, "test_id") + + self.assertEqual(id, "test_scratch62") + self.assertEqual(len(func.commands), 107) + + func = mock_mcfunction() + + expr = func_expr(function_call_block(0, "sqrt", [])) + id = expr.compile(func, "test_id") + + self.assertEqual(id, None) + + func = mock_mcfunction() + + expr = func_expr(function_call_block(0, "abs", [num_expr(-1)])) + id = expr.compile(func, "test_id") + + self.assertEqual(id, "test_id") + self.assertEqual( + func.commands, + [ + "scoreboard players set Global test_id -1", + "execute if score Global test_id matches ..-1 run scoreboard players operation Global test_id *= minus Constant", + ], + ) + + func = mock_mcfunction() + + expr = func_expr(function_call_block(0, "abs", [])) + id = expr.compile(func, "test_id") + + self.assertEqual(id, None) + + func = mock_mcfunction() + + expr = func_expr(function_call_block(0, "rand", [num_expr(10)])) + id = expr.compile(func, "test_id") + + self.assertEqual(id, "test_scratch1") + self.assertEqual( + func.commands, + [ + "scoreboard players set Global test_scratch1 0", + "scoreboard players operation Global test_scratch1 += @e[type=armor_stand, test_random_objective <= 1, limit=1, sort=random] test_random_objective", + "scoreboard players operation Global test_scratch1 *= test_constant Constant", + "scoreboard players operation Global test_scratch1 += @e[type=armor_stand, test_random_objective <= 4, limit=1, sort=random] test_random_objective", + ], + ) + + func = mock_mcfunction() + + expr = func_expr( + function_call_block(0, "rand", [num_expr(2), num_expr(10)]) + ) + id = expr.compile(func, "test_id") + + self.assertEqual(id, "test_scratch1") + self.assertEqual( + func.commands, + [ + "scoreboard players set Global test_scratch1 0", + "scoreboard players operation Global test_scratch1 += @e[type=armor_stand, test_random_objective <= 1, limit=1, sort=random] test_random_objective", + "scoreboard players operation Global test_scratch1 *= test_constant Constant", + "scoreboard players operation Global test_scratch1 += @e[type=armor_stand, test_random_objective <= 1, limit=1, sort=random] test_random_objective", + "scoreboard players operation Global test_scratch1 *= test_constant Constant", + "scoreboard players operation Global test_scratch1 += @e[type=armor_stand, test_random_objective <= 1, limit=1, sort=random] test_random_objective", + "scoreboard players add Global test_scratch1 2", + ], + ) + + func = mock_mcfunction() + + expr = func_expr(function_call_block(0, "test_function", [])) + id = expr.compile(func, "test_id") + + self.assertEqual(id, "ReturnValue") + self.assertTrue( + "function test_namespace:test_function" in func.commands + ) + + def test_num_expr(self): + func = mock_mcfunction() + + expr = num_expr(5) + self.assertEqual(int(expr.const_value(func)), 5) + id = expr.compile(func, "test_id") + + self.assertEqual(id, "test_id") + self.assertTrue( + "scoreboard players set Global test_id 5" in func.commands + ) + + def test_scale_expr(self): + func = mock_mcfunction() + + expr = scale_expr() + self.assertEqual(expr.const_value(func), 1000) + id = expr.compile(func, "test_id") + + self.assertEqual(id, "test_id") + self.assertTrue( + "scoreboard players set Global test_id 1000" in func.commands + ) + + def test_selector_expr(self): + func = mock_mcfunction() + func.check_single_entity = lambda x: True + + expr = selector_expr("@p") + id = expr.compile(func, "test_id") + + self.assertEqual(id, "test_id") + self.assertEqual( + func.commands, + [ + "scoreboard players add Global _unique 1", + "execute unless score @p _id matches 0.. run scoreboard players operation @p _id = Global _unique", + "scoreboard players operation Global test_id = @p _id", + ], + ) + + def test_selvar_expr(self): + func = mock_mcfunction() + + expr = selvar_expr("@a", "test_var") + id = expr.compile(func, "test_id") + + self.assertEqual(id, "test_id") + self.assertTrue( + "scoreboard players operation Global test_id = @a test_var" + in func.commands + ) + + def test_unary_expr(self): + func = mock_mcfunction() + + expr = unary_expr("-", num_expr(5)) + id = expr.compile(func, "test_id") + + self.assertEqual(id, "test_id") + self.assertTrue( + "scoreboard players set Global test_id 5" in func.commands + ) + self.assertTrue( + "scoreboard players operation Global test_id *= minus Constant" + in func.commands + ) + + def test_sel_vector_var_expr(self): + func = mock_mcfunction() + + expr = sel_vector_var_expr("@test", "test_var") + ids = expr.compile(func, ["x", "y", "z"]) + + self.assertEqual(ids, ["x", "y", "z"]) + for left, right in [("x", 0), ("y", 1), ("z", 2)]: + self.assertTrue( + f"scoreboard players operation Global {left} = @test _test_var_{right}" + in func.commands + ) + + def test_vector_binop_scalar_expr(self): + func = mock_mcfunction() + + expr = vector_binop_scalar_expr( + vector_var_expr("test_vector"), "*", num_expr(2) + ) + ids = expr.compile(func, ["x", "y", "z"]) + + self.assertEqual(ids, ["x", "y", "z"]) + self.assertEqual( + func.commands, + [ + "scoreboard players operation Global x = Global _test_vector_0", + "scoreboard players operation Global y = Global _test_vector_1", + "scoreboard players operation Global z = Global _test_vector_2", + "scoreboard players set Global test_scratch1 2", + "scoreboard players operation Global x *= Global test_scratch1", + "scoreboard players operation Global y *= Global test_scratch1", + "scoreboard players operation Global z *= Global test_scratch1", + ], + ) + + def test_vector_binop_vector_expr(self): + func = mock_mcfunction() + + expr = vector_binop_vector_expr( + vector_var_expr("test_vector1"), + "+", + vector_var_expr("test_vector2"), + ) + ids = expr.compile(func, ["x", "y", "z"]) + + self.assertEqual(ids, ["x", "y", "z"]) + self.assertEqual( + func.commands, + [ + "scoreboard players operation Global x = Global _test_vector1_0", + "scoreboard players operation Global y = Global _test_vector1_1", + "scoreboard players operation Global z = Global _test_vector1_2", + "scoreboard players operation Global x += Global _test_vector2_0", + "scoreboard players operation Global y += Global _test_vector2_1", + "scoreboard players operation Global z += Global _test_vector2_2", + ], + ) + + def test_vector_expr(self): + func = mock_mcfunction() + + expr = vector_expr([num_expr(1), num_expr(2), num_expr(3)]) + ids = expr.compile(func, ["x", "y", "z"]) + + self.assertEqual(ids, ["x", "y", "z"]) + for left, right in [("x", 1), ("y", 2), ("z", 3)]: + self.assertTrue( + f"scoreboard players set Global {left} {right}" + in func.commands + ) + + def test_vector_here_expr(self): + func = mock_mcfunction() + + expr = vector_here_expr(const_number(100)) + ids = expr.compile(func, ["x", "y", "z"]) + + self.assertEqual(ids, ["x", "y", "z"]) + self.assertEqual( + func.commands, + [ + "scoreboard players add @e _age 1", + "summon area_effect_cloud", + "scoreboard players add @e _age 1", + "execute store result score Global x run data get entity @e[_age==1,limit=1] Pos[0] 100", + "execute store result score Global y run data get entity @e[_age==1,limit=1] Pos[1] 100", + "execute store result score Global z run data get entity @e[_age==1,limit=1] Pos[2] 100", + "/kill @e[_age==1]", + ], + ) + + def test_vector_var_expr(self): + func = mock_mcfunction() + + expr = vector_var_expr("test_vector") + ids = expr.compile(func, ["x", "y", "z"]) + + self.assertEqual( + ids, ["_test_vector_0", "_test_vector_1", "_test_vector_2"] + ) + + def test_selector_definition(self): + env = mock_environment() + + sel = selector_definition("@a", env) + self.assertEqual(sel.compile(), "@a[]") + + env = mock_environment() + + sel = selector_definition("@a[test>0]", env) + self.assertEqual(sel.compile(), "@a[scores={test=1..}]") + + env = mock_environment() + env.selectors["test_selector"] = selector_definition( + '@a[nbt={test:"test_val"}]', env + ) + + sel = selector_definition( + '@test_selector[nbt={test2:"test_val2"}]', env + ) + # TODO: merge nbt tags via the json module + self.assertEqual( + sel.compile(), '@a[nbt={test:"test_val"},nbt={test2:"test_val2"}]' + ) + + env = mock_environment() + + sel = selector_definition("@a[test==0]", env) + self.assertEqual(sel.compile(), "@a[scores={test=0}]") + + env = mock_environment() + + sel = selector_definition("@a[test>=0,test<=0]", env) + self.assertEqual(sel.compile(), "@a[scores={test=0}]") + + env = mock_environment() + + sel = selector_definition("@e[type=creeper]", env) + self.assertEqual(sel.compile(), "@e[type=minecraft:creeper]") + self.assertEqual(sel.get_type(), "minecraft:creeper") + self.assertFalse(sel.single_entity()) + + env = mock_environment() + + sel = selector_definition("@e[limit=1]", env) + self.assertTrue(sel.single_entity()) + + env = mock_environment() + + sel = selector_definition("@p", env) + self.assertTrue(sel.single_entity()) + + env = mock_environment() + + sel = selector_definition("@s", env) + self.assertTrue(sel.single_entity()) + + env = mock_environment() + env.selectors["test_selector"] = selector_definition( + "@e[test==0]", env + ) + env.selectors["test_selector"].set_part("type", "creeper") + env.selectors["test_selector"].paths["test_path"] = 1 + env.selectors["test_selector"].vector_paths["test_vector_path"] = 2 + + sel = selector_definition("@test_selector[test2>0]", env) + self.assertEqual( + sel.compile(), "@e[type=creeper,scores={test=0,test2=1..}]" + ) + self.assertEqual(sel.paths["test_path"], 1) + self.assertEqual(sel.vector_paths["test_vector_path"], 2) + + env = mock_environment() + + with self.assertRaises(ValueError): + selector_definition("@none", env) + + env = mock_environment() + + sel = selector_definition( + '@e[nbt={test:"test_val",test2:{test3:"test_val3"}}]', env + ) + # TODO: merge nbt tags via the json module + self.assertEqual( + sel.compile(), + '@e[nbt={test:"test_val",test2:{test3:"test_val3"}}]', + ) + + env = mock_environment() + + with self.assertRaises(SyntaxError): + sel = selector_definition("@a[test>test2]", env) + + def test_get_friendly_name(self): + self.assertEqual( + global_context.get_friendly_name("test .,:{}="), "CBtest_______" + ) + + def test_global_context_register_block_tag(self): + gc = global_context.global_context("test_namespace") + + gc.register_block_tag("test_block_tag", ["test_block"]) + self.assertEqual(gc.block_tags["test_block_tag"], ["test_block"]) + + def test_global_context_get_unique_id(self): + gc = global_context.global_context("test_namespace") + + self.assertEqual(gc.get_unique_id(), 1) + self.assertEqual(gc.get_unique_id(), 2) + + def test_global_context_register_clock(self): + gc = global_context.global_context("test_namespace") + + gc.register_clock("test_clock") + self.assertEqual(gc.clocks, ["test_clock"]) + + def test_global_context_register_function(self): + gc = global_context.global_context("test_namespace") + f = mock_mcfunction() + + gc.register_function("test_function", f) + self.assertEqual(gc.functions["test_function"], f) + with self.assertRaises(Exception): + gc.register_function("test_function", f) + + def test_global_context_register_array(self): + gc = global_context.global_context("test_namespace") + + gc.register_array("test_array", 0, 5) + self.assertEqual(gc.arrays["test_array"], (0, 5)) + with self.assertRaises(Exception): + gc.register_array("test_array", 0, 5) + + def test_global_context_register_objective(self): + gc = global_context.global_context("test_namespace") + + gc.register_objective("test_objective") + self.assertTrue("test_objective" in gc.objectives) + + with self.assertRaises(Exception): + gc.register_objective("test_objective_name_too_long") + + def test_global_context_get_constant_name(self): + gc = global_context.global_context("test_namespace") + f = mock_mcfunction() + + gc.register_function("reset", f) + self.assertEqual(gc.get_reset_function(), f) + + self.assertEqual(global_context.get_constant_name(0), "c0") + self.assertEqual(global_context.get_constant_name(1), "c1") + self.assertEqual(global_context.get_constant_name(-1), "minus") + self.assertEqual(global_context.get_constant_name(-2), "cm2") + + def test_global_context_add_constant(self): + gc = global_context.global_context("test_namespace") + + self.assertEqual(gc.add_constant(1), "c1") + self.assertTrue(1 in gc.constants) + + def test_global_context_add_constant_definitions(self): + gc = global_context.global_context("test_namespace") + f = mock_mcfunction() + + gc.register_function("reset", f) + gc.add_constant(1) + gc.add_constant(-1) + gc.add_constant_definitions() + + self.assertEqual( + f.commands, + [ + "/scoreboard objectives add Constant dummy", + "/scoreboard players set minus Constant -1", + "/scoreboard players set c1 Constant 1", + ], + ) + + def test_global_context_allocate_scratch(self): + gc = global_context.global_context("test_namespace") + + gc.allocate_scratch("test_prefix", 2) + self.assertEqual(gc.scratch["test_prefix"], 2) + gc.allocate_scratch("test_prefix", 3) + self.assertEqual(gc.scratch["test_prefix"], 3) + gc.allocate_scratch("test_prefix", 2) + self.assertEqual(gc.scratch["test_prefix"], 3) + + def test_global_context_allocate_temp(self): + gc = global_context.global_context("test_namespace") + + gc.allocate_temp(2) + self.assertEqual(gc.temp, 2) + gc.allocate_temp(3) + self.assertEqual(gc.temp, 3) + gc.allocate_temp(2) + self.assertEqual(gc.temp, 3) + + def test_global_context_allocate_rand(self): + gc = global_context.global_context("test_namespace") + + gc.allocate_rand(2) + self.assertEqual(gc.rand, 2) + gc.allocate_rand(3) + self.assertEqual(gc.rand, 3) + gc.allocate_rand(2) + self.assertEqual(gc.rand, 3) + + def test_global_context_finalize_functions(self): + gc = global_context.global_context("test_namespace") + f = mock_mcfunction() + + gc.register_function("reset", f) + gc.finalize_functions() + + self.assertTrue(f.finalized) + + def test_global_context_get_scratch_prefix(self): + gc = global_context.global_context("test_namespace") + + self.assertEqual(gc.get_scratch_prefix("test"), "tes") + self.assertEqual(gc.get_scratch_prefix("test"), "tes2") + self.assertEqual(gc.get_scratch_prefix("test"), "tes3") + + def test_global_context_get_random_objective(self): + gc = global_context.global_context("test_namespace") + + self.assertEqual(gc.get_random_objective(), "RVtest_namespace") + + def test_scratch_tracker_temp(self): + gc = mock_global_context() + + st = scratch_tracker(gc) + self.assertEqual(st.get_temp_var(), "temp0") + self.assertEqual(st.temp[0], True) + self.assertEqual(st.get_temp_var(), "temp1") + self.assertEqual(st.temp[1], True) + st.free_temp_var("temp0") + self.assertEqual(st.temp[0], False) + self.assertEqual(st.temp[1], True) + self.assertEqual(gc.temp, 2) + self.assertEqual(st.get_temp_var(), "temp0") + + def test_scratch_tracker_scratch(self): + gc = mock_global_context() + + st = scratch_tracker(gc) + st.prefix = "test" + self.assertEqual(st.get_scratch(), "test_scratch0") + self.assertEqual(st.scratch[0], True) + self.assertEqual(st.get_scratch(), "test_scratch1") + self.assertEqual(st.scratch[1], True) + st.free_scratch("test_scratch0") + self.assertEqual(st.scratch[0], False) + self.assertEqual(st.scratch[1], True) + self.assertEqual(gc.scratch["test"], 2) + self.assertEqual(st.get_scratch(), "test_scratch0") + + st.free_scratch("not_scratch") + + def test_scratch_tracker_vector(self): + gc = mock_global_context() + + st = scratch_tracker(gc) + st.prefix = "test" + + self.assertEqual( + st.get_scratch_vector(), + ["test_scratch0", "test_scratch1", "test_scratch2"], + ) + self.assertEqual(gc.scratch["test"], 3) + for i in range(3): + self.assertEqual(st.scratch[i], True) + + def test_scratch_tracker_get_allocated_variables(self): + gc = mock_global_context() + + st = scratch_tracker(gc) + st.prefix = "test" + + st.get_scratch() + st.get_scratch() + st.get_scratch() + st.free_scratch("test_scratch1") + + st.get_temp_var() + st.get_temp_var() + st.get_temp_var() + st.free_temp_var("temp0") + + self.assertEqual( + st.get_allocated_variables(), + [ + "test_scratch0", + "test_scratch1", + "test_scratch2", + "temp0", + "temp1", + "temp2", + ], + ) + + def test_cbscript_check_for_update(self): + source = mock_source_file() + source.updated = False + + compiles = [0] + + script = cbscript(source, None) + script.compiles = 0 + + def count_compiles(self): + self.compiles += 1 + + script.try_to_compile = new.instancemethod( + count_compiles, script, None + ) + + self.assertEqual(script.compiles, 0) + script.check_for_update() + self.assertEqual(script.compiles, 0) + source.updated = True + script.check_for_update() + self.assertEqual(script.compiles, 1) + + def test_cbscript_try_to_compile(self): + source = mock_source_file() + + script = cbscript(source, None) + script.log_lines = [] + + def mock_log(self, text): + self.log_lines.append(text) + + script.log = new.instancemethod(mock_log, script, None) + script.compile_all = new.instancemethod(lambda s: True, script, None) + + script.try_to_compile() + self.assertEqual( + script.log_lines, + ["Compiling unittest...", "Script successfully applied."], + ) + + script = cbscript(source, None) + script.log_lines = [] + script.log = new.instancemethod(mock_log, script, None) + script.compile_all = new.instancemethod(lambda s: False, script, None) + + script.try_to_compile() + self.assertEqual( + script.log_lines, + ["Compiling unittest...", "Script had compile error(s).\x07"], + ) + + def bad_parse(text): + raise SyntaxError("Test error") + + script = cbscript(source, bad_parse) + script.log_lines = [] + script.log = new.instancemethod(mock_log, script, None) + + script.try_to_compile() + self.assertEqual( + script.log_lines, ["Compiling unittest...", "Test error\x07"] + ) + + def bad_compile(text): + raise Exception("Test exception") + + script = cbscript(source, None) + script.log_lines = [] + script.log = new.instancemethod(mock_log, script, None) + script.tracebacks = 0 + + def mock_log_traceback(self): + self.tracebacks += 1 + + script.log_traceback = new.instancemethod( + mock_log_traceback, script, None + ) + script.compile_all = new.instancemethod(bad_compile, script, None) + + script.try_to_compile() + self.assertEqual( + script.log_lines, + [ + "Compiling unittest...", + "Compiler encountered unexpected error during compilation:\x07", + ], + ) + self.assertEqual(script.tracebacks, 1) + + def test_cbscript_compile_all(self): + source = mock_source_file() + + parsed = {} + parsed["scale"] = 100 + parsed["assignments"] = [ + block_tag_block(0, "test_tag", ["test_block"]) + ] + parsed["sections"] = [ + ("macro", "test_macro", [], [], []), + ("template_function", "test_template_function", [], [], []), + ( + "function", + "reset", + [], + [], + [ + scoreboard_assignment_block( + 0, + ( + ("Var", ("Global", "test_var")), + "=", + func_expr( + function_call_block(0, "rand", [num_expr(5)]) + ), + ), + ) + ], + ), + ("clock", "test_clock", [], [], []), + ] + parsed["dir"] = "test_dir" + parsed["desc"] = "test description" + + script = cbscript(source, lambda t: ("program", parsed)) + + def mock_create_world(self, dir, namespace): + world = mock_mcworld(dir, namespace) + self.mock_world = world + return world + + script.create_world = new.instancemethod( + mock_create_world, script, None + ) + + self.assertTrue(script.compile_all()) + world = script.mock_world + self.assertEqual(world.functions, ["reset", "test_clock"]) + self.assertEqual(world.clocks, ["test_clock"]) + self.assertEqual(world.tags, ["test_tag"]) + self.assertEqual(world.desc, "test description") + self.assertTrue(world.written) + self.assertTrue("test_var" in script.global_context.objectives) + self.assertEqual( + script.global_context.get_reset_function().commands, + [ + "scoreboard objectives add test_var dummy", + "kill @e[type=minecraft:armor_stand,name=RandBasis,scores={RVunittest=0..}]", + "scoreboard objectives add RVunittest dummy", + 'summon minecraft:armor_stand ~ ~ ~ {CustomName:"\\"RandBasis\\"", "Invulnerable":1b, "Invisible":1b, "Marker":1b, "NoGravity":1b}', + "scoreboard players add @e[type=minecraft:armor_stand,name=RandBasis] RVunittest 1", + 'summon minecraft:armor_stand ~ ~ ~ {CustomName:"\\"RandBasis\\"", "Invulnerable":1b, "Invisible":1b, "Marker":1b, "NoGravity":1b}', + "scoreboard players add @e[type=minecraft:armor_stand,name=RandBasis] RVunittest 1", + 'summon minecraft:armor_stand ~ ~ ~ {CustomName:"\\"RandBasis\\"", "Invulnerable":1b, "Invisible":1b, "Marker":1b, "NoGravity":1b}', + "scoreboard players add @e[type=minecraft:armor_stand,name=RandBasis] RVunittest 1", + 'summon minecraft:armor_stand ~ ~ ~ {CustomName:"\\"RandBasis\\"", "Invulnerable":1b, "Invisible":1b, "Marker":1b, "NoGravity":1b}', + "scoreboard players add @e[type=minecraft:armor_stand,name=RandBasis] RVunittest 1", + 'summon minecraft:armor_stand ~ ~ ~ {CustomName:"\\"RandBasis\\"", "Invulnerable":1b, "Invisible":1b, "Marker":1b, "NoGravity":1b}', + "scoreboard players add @e[type=minecraft:armor_stand,name=RandBasis] RVunittest 1", + "scoreboard players remove @e[type=minecraft:armor_stand,name=RandBasis] RVunittest 1", + "scoreboard objectives add res_scratch0 dummy", + "scoreboard players set Global res_scratch0 0", + "scoreboard players operation Global res_scratch0 += @e[type=minecraft:armor_stand,limit=1,sort=random,scores={RVunittest=..4}] RVunittest", + "scoreboard players operation Global test_var = Global res_scratch0", + ], + ) + + def test_tellraw_get_properties_text(self): + properties = { + "color": "red", + "bold": True, + "underlined": True, + "italic": True, + "strikethrough": True, + } + self.assertEqual( + tellraw.getPropertiesText(properties), + ',"color":"red","bold":true,"underlined":true,"italic":true,"strikethrough":true', + ) + + properties = { + "color": None, + "bold": False, + "underlined": False, + "italic": False, + "strikethrough": False, + } + self.assertEqual(tellraw.getPropertiesText(properties), "") + + def test_tellraw_format_json_text(self): + func = mock_mcfunction() + + self.assertEqual( + tellraw.formatJsonText(func, "test"), '["",{"text":"test"}]' + ) + + self.assertEqual( + tellraw.formatJsonText(func, "{rtest"), + '["",{"text":"test","color":"dark_red"}]', + ) + + self.assertEqual( + tellraw.formatJsonText(func, "[test text](/test_command)"), + '["",{"text":"test text","clickEvent":{"action":"run_command","value":"/test_command"}}]', + ) + + self.assertEqual( + tellraw.formatJsonText(func, "(global_var)"), + '["",{"score":{"name":"Global","objective":"global_var"}}]', + ) + + self.assertEqual( + tellraw.formatJsonText(func, "(@test_selector.test_var)"), + '["",{"score":{"name":"@s","objective":"test_scratch1"}}]', + ) + + with self.assertRaises(SyntaxError): + tellraw.formatJsonText(func, "(a.b.c)") + + self.assertEqual( + tellraw.formatJsonText(func, "(@test_selector[])"), + '["",{"selector":"@test_selector[]"}]', + ) + + with self.assertRaises(SyntaxError): + tellraw.formatJsonText(func, "test () text"), + + self.assertEqual( + tellraw.formatJsonText(func, "[link](http://sethbling.com)"), + '["",{"text":"link","clickEvent":{"action":"open_url","value":"http://sethbling.com"}}]', + ) + + self.assertEqual( + tellraw.formatJsonText(func, "[link](//suggest_test)"), + '["",{"text":"link","clickEvent":{"action":"suggest_command","value":"/suggest_test"}}]', + ) + + def test_tellraw_parse_text_formatting(self): + self.assertEqual( + tellraw.parseTextFormatting("\("), + [ + ( + "(", + { + "color": None, + "underlined": False, + "strikethrough": False, + "bold": False, + "italic": False, + }, + ) + ], + ) + + self.assertEqual( + tellraw.parseTextFormatting("a["), + [ + ( + "a", + { + "color": None, + "underlined": False, + "strikethrough": False, + "bold": False, + "italic": False, + }, + ) + ], + ) + + self.assertEqual( + tellraw.parseTextFormatting("a{"), + [ + ( + "a", + { + "color": None, + "underlined": False, + "strikethrough": False, + "bold": False, + "italic": False, + }, + ) + ], + ) + + self.assertEqual( + tellraw.parseTextFormatting("[formatted]test"), + [ + ( + ("formatted", None), + { + "color": None, + "underlined": False, + "strikethrough": False, + "bold": False, + "italic": False, + }, + ), + ( + "test", + { + "color": None, + "underlined": False, + "strikethrough": False, + "bold": False, + "italic": False, + }, + ), + ], + ) + + self.assertEqual( + tellraw.parseTextFormatting("{r{Utest{-clear"), + [ + ( + "test", + { + "color": "dark_red", + "underlined": True, + "strikethrough": False, + "bold": False, + "italic": False, + }, + ), + ( + "clear", + { + "color": None, + "underlined": False, + "strikethrough": False, + "bold": False, + "italic": False, + }, + ), + ], + ) + + self.assertEqual( + tellraw.parseTextFormatting("{Utest{uclear"), + [ + ( + "test", + { + "color": None, + "underlined": True, + "strikethrough": False, + "bold": False, + "italic": False, + }, + ), + ( + "clear", + { + "color": None, + "underlined": False, + "strikethrough": False, + "bold": False, + "italic": False, + }, + ), + ], + ) + + self.assertEqual( + tellraw.parseTextFormatting("{Stest{sclear"), + [ + ( + "test", + { + "color": None, + "underlined": False, + "strikethrough": True, + "bold": False, + "italic": False, + }, + ), + ( + "clear", + { + "color": None, + "underlined": False, + "strikethrough": False, + "bold": False, + "italic": False, + }, + ), + ], + ) + + self.assertEqual( + tellraw.parseTextFormatting("{Dtest{dclear"), + [ + ( + "test", + { + "color": None, + "underlined": False, + "strikethrough": False, + "bold": True, + "italic": False, + }, + ), + ( + "clear", + { + "color": None, + "underlined": False, + "strikethrough": False, + "bold": False, + "italic": False, + }, + ), + ], + ) + + self.assertEqual( + tellraw.parseTextFormatting("{Itest{iclear"), + [ + ( + "test", + { + "color": None, + "underlined": False, + "strikethrough": False, + "bold": False, + "italic": True, + }, + ), + ( + "clear", + { + "color": None, + "underlined": False, + "strikethrough": False, + "bold": False, + "italic": False, + }, + ), + ], + ) + + self.assertEqual( + tellraw.parseTextFormatting("{{"), + [ + ( + "{", + { + "color": None, + "underlined": False, + "strikethrough": False, + "bold": False, + "italic": False, + }, + ) + ], + ) + + with self.assertRaises(SyntaxError): + tellraw.parseTextFormatting("{+") + + self.assertEqual( + tellraw.parseTextFormatting("\{"), + [ + ( + "{", + { + "color": None, + "underlined": False, + "strikethrough": False, + "bold": False, + "italic": False, + }, + ) + ], + ) + + def test_parser(self): + mcfunction.line_numbers = [] + + p = mock_parsed("test1") + scriptparse.p_parsed_assignment(p) + self.assertEqual(p[0], ("program", "test1")) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed("test2") + scriptparse.p_parsed_expr(p) + self.assertEqual(p[0], ("expr", "test2")) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed( + "comments", + None, + "dir", + None, + "desc", + "scale", + "assignments", + "sections", + ) + scriptparse.p_program(p) + self.assertEqual( + p[0], + { + "assignments": "assignments", + "scale": "scale", + "sections": "sections", + "dir": "dir", + "desc": "desc", + }, + ) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed(None, "desc", None) + scriptparse.p_optdesc(p) + self.assertEqual(p[0], "desc") + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed(None) + scriptparse.p_optdesc(p) + self.assertEqual(p[0], "No Description") + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed(None, 500, None) + scriptparse.p_optscale(p) + self.assertEqual(p[0], 500) + + p = mock_parsed(None) + scriptparse.p_optscale_none(p) + self.assertEqual(p[0], 1000) + + p = mock_parsed("section", None, ["sections"]) + scriptparse.p_sections_multiple(p) + self.assertEqual(p[0], ["section", "sections"]) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed(None) + scriptparse.p_sections_empty(p) + self.assertEqual(p[0], []) + + p = mock_parsed( + ["comment"], + ("type", "name", ["template_params"], ["params"], ["lines"]), + ) + scriptparse.p_section_commented(p) + p_type, p_name, p_template_params, p_params, p_lines = p[0] + self.assertEqual(p_type, "type") + self.assertEqual(p_name, "name") + self.assertEqual(p_template_params, ["template_params"]) + self.assertEqual(p_params, ["params"]) + self.assertEqual(type(p_lines[0]), comment_block) + self.assertEqual(p_lines[0].text, "#comment") + self.assertEqual(p_lines[1], "lines") + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed("comment", None, ["comments"]) + scriptparse.p_optcomments(p) + self.assertEqual(p[0], ["comment", "comments"]) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed(None) + scriptparse.p_optcomments_empty(p) + self.assertEqual(p[0], []) + + p = mock_parsed("section") + scriptparse.p_section(p) + self.assertEqual(p[0], "section") + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed(None, None, "lines", None) + scriptparse.p_resetsection(p) + self.assertEqual(p[0], ("reset", "reset", [], [], "lines")) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + with self.assertRaises(SyntaxError): + scriptparse.validate_mcfunction_name("Test") + scriptparse.validate_mcfunction_name("test") + + p = mock_parsed(None, "id", None, "lines", None) + scriptparse.p_clocksection(p) + self.assertEqual(p[0], ("clock", "id", [], [], "lines")) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed( + None, "id", None, ["id_list"], None, None, "lines", None + ) + scriptparse.p_functionsection(p) + self.assertEqual(p[0], ("function", "id", [], ["id_list"], "lines")) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed( + None, + "id", + None, + ["macro_params"], + None, + None, + ["id_list"], + None, + None, + "lines", + None, + ) + scriptparse.p_template_function_section(p) + self.assertEqual( + p[0], + ( + "template_function", + "id", + ["macro_params"], + ["id_list"], + "lines", + ), + ) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed(None, None, "id", "macro_args", None, "lines", None) + scriptparse.p_macrosection(p) + self.assertEqual(p[0], ("macro", "id", [], "macro_args", "lines")) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed(None, "params", None) + scriptparse.p_macro_args(p) + self.assertEqual(p[0], "params") + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed(None) + scriptparse.p_macro_args_empty(p) + self.assertEqual(p[0], []) + + p = mock_parsed(None, "id", None, ["params"]) + scriptparse.p_macro_params(p) + self.assertEqual(p[0], ["id", "params"]) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed(None, "macro_id") + scriptparse.p_macro_params_one(p) + self.assertEqual(p[0], ["macro_id"]) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed(None) + scriptparse.p_macro_params_empty(p) + self.assertEqual(p[0], []) + + p = mock_parsed(None, None) + scriptparse.p_newlines(p) + self.assertEqual(p[0], None) + + p = mock_parsed(None) + scriptparse.p_newlines(p) + self.assertEqual(p[0], None) + + p = mock_parsed(None) + scriptparse.p_optnewlines(p) + self.assertEqual(p[0], None) + + p = mock_parsed("id", None, ["ids"]) + scriptparse.p_id_list(p) + self.assertEqual(p[0], ["id", "ids"]) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed("id") + scriptparse.p_id_list_one(p) + self.assertEqual(p[0], ["id"]) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed(None) + scriptparse.p_id_list_empty(p) + self.assertEqual(p[0], []) + + p = mock_parsed("assignment", None, ["assignments"]) + scriptparse.p_optassignments_multiple(p) + self.assertEqual(p[0], ["assignment", "assignments"]) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed("comment", None, ["assignments"]) + scriptparse.p_optassignments_comment(p) + self.assertEqual(p[0], ["assignments"]) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed(None) + scriptparse.p_optassignments_empty(p) + self.assertEqual(p[0], []) + + p = mock_parsed("fullselector", None, "id") + scriptparse.p_variable_selector(p) + self.assertEqual(p[0], ("Var", ("fullselector", "id"))) + + p = mock_parsed("id") + scriptparse.p_variable_global(p) + self.assertEqual(p[0], ("Var", ("Global", "id"))) + + p = mock_parsed("id", None, "idx") + scriptparse.p_variable_array_const(p) + self.assertEqual(p[0], ("ArrayConst", ("id", "idx"))) + + p = mock_parsed("id", None, "expr") + scriptparse.p_variable_array_expr(p) + self.assertEqual(p[0], ("ArrayExpr", ("id", "expr"))) + + p = mock_parsed("#comment") + scriptparse.p_optcomment(p) + self.assertEqual(len(p[0]), 1) + self.assertTrue(type(p[0][0]) is comment_block) + self.assertEqual(p[0][0].text, "#comment") + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed(None) + scriptparse.p_optcomment_empty(p) + self.assertEqual(p[0], []) + + p = mock_parsed("codeblock", ["optcomment"], None, ["lines"]) + scriptparse.p_blocklist_multiple(p) + self.assertEqual(p[0], ["optcomment", "codeblock", "lines"]) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed(None) + scriptparse.p_blocklist_empty(p) + self.assertEqual(p[0], []) + + p = mock_parsed("#comment") + scriptparse.p_block_comment(p) + self.assertTrue(type(p[0]) is comment_block) + self.assertEqual(p[0].text, "#comment") + self.assertEqual(p[0].line, 0) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed("command") + scriptparse.p_block_command(p) + self.assertTrue(type(p[0]) is command_block) + self.assertEqual(p[0].text, "command") + self.assertEqual(p[0].line, 0) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed(None, "selector", "coords") + scriptparse.p_block_move(p) + self.assertTrue(type(p[0]) is move_block) + self.assertEqual(p[0].selector, "selector") + self.assertEqual(p[0].coords, "coords") + self.assertEqual(p[0].line, 0) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed( + None, + None, + "id", + None, + interpreted_python("[1]", 0), + None, + "lines", + None, + ) + func = mock_mcfunction() + scriptparse.p_block_for(p) + self.assertTrue(type(p[0]) is python_for_block) + self.assertEqual(p[0].id, "id") + self.assertEqual(p[0].val.get_value(func), [1]) + self.assertEqual(p[0].sub, "lines") + self.assertEqual(p[0].line, 0) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed(None, "var", None, "lines", None) + scriptparse.p_execute_as_id_global(p) + self.assertTrue(type(p[0]) is execute_block) + self.assertEqual(p[0].exec_items, [("AsId", ("var", None))]) + self.assertEqual(p[0].sub, "lines") + self.assertEqual(p[0].line, 0) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed(None, "var", None, "@id", None, None, "lines", None) + scriptparse.p_execute_as_id_type_global(p) + self.assertTrue(type(p[0]) is execute_block) + self.assertEqual(p[0].exec_items, [("AsId", ("var", "@id"))]) + self.assertEqual(p[0].sub, "lines") + self.assertEqual(p[0].line, 0) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed(None, "var", None, "line") + scriptparse.p_execute_as_id_do_global(p) + self.assertTrue(type(p[0]) is execute_block) + self.assertEqual(p[0].exec_items, [("AsId", ("var", None))]) + self.assertEqual(p[0].sub, ["line"]) + self.assertEqual(p[0].line, 0) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed(None, "var", None, "@id", None, None, "line") + scriptparse.p_execute_as_id_do_type_global(p) + self.assertTrue(type(p[0]) is execute_block) + self.assertEqual(p[0].exec_items, [("AsId", ("var", "@id"))]) + self.assertEqual(p[0].sub, ["line"]) + self.assertEqual(p[0].line, 0) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed(None, "create", None, "lines", None) + scriptparse.p_execute_as_create(p) + self.assertTrue(type(p[0]) is execute_block) + self.assertEqual(p[0].exec_items, [("AsCreate", "create")]) + self.assertEqual(p[0].sub, "lines") + self.assertEqual(p[0].line, 0) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed(None, "create", None, "line") + scriptparse.p_execute_as_create_do(p) + self.assertTrue(type(p[0]) is execute_block) + self.assertEqual(p[0].exec_items, [("AsCreate", "create")]) + self.assertEqual(p[0].sub, ["line"]) + self.assertEqual(p[0].line, 0) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed("items", None, "lines", None) + scriptparse.p_execute_chain(p) + self.assertTrue(type(p[0]) is execute_block) + self.assertEqual(p[0].exec_items, "items") + self.assertEqual(p[0].sub, "lines") + self.assertEqual(p[0].line, 0) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed("items", None, "line") + scriptparse.p_execute_chain_inline(p) + self.assertTrue(type(p[0]) is execute_block) + self.assertEqual(p[0].exec_items, "items") + self.assertEqual(p[0].sub, ["line"]) + self.assertEqual(p[0].line, 0) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed("item") + scriptparse.p_execute_items_one(p) + self.assertEqual(p[0], ["item"]) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed("item", ["items"]) + scriptparse.p_execute_items(p) + self.assertEqual(p[0], ["item", "items"]) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed(None, "conditions") + scriptparse.p_execute_if_condition(p) + self.assertEqual(p[0], ("If", "conditions")) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed(None, "conditions") + scriptparse.p_execute_unless_condition(p) + self.assertEqual(p[0], ("Unless", "conditions")) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed(None, "fullselector") + scriptparse.p_execute_as(p) + self.assertEqual(p[0], ("As", "fullselector")) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed(None, "fullselector") + scriptparse.p_execute_rotated(p) + self.assertEqual(p[0], ("Rotated", "fullselector")) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed(None, "relcoords") + scriptparse.p_execute_facing_coords(p) + self.assertEqual(p[0], ("FacingCoords", "relcoords")) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed(None, "fullselector") + scriptparse.p_execute_facing_entity(p) + self.assertEqual(p[0], ("FacingEntity", "fullselector")) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + for axes in ["x", "y", "z", "xy", "xz", "yz", "xyz"]: + p = mock_parsed(None, axes) + scriptparse.p_execute_align(p) + self.assertEqual(p[0], ("Align", axes)) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed(None, "") + with self.assertRaises(SyntaxError): + scriptparse.p_execute_align(p) + + p = mock_parsed(None, "fullselector") + scriptparse.p_execute_at_selector(p) + self.assertEqual(p[0], ("At", ("fullselector", None))) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed(None, "relcoords") + scriptparse.p_execute_at_relcoords(p) + self.assertEqual(p[0], ("At", (None, "relcoords"))) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed(None, "fullselector", "relcoords") + scriptparse.p_execute_at_selector_relcoords(p) + self.assertEqual(p[0], ("At", ("fullselector", "relcoords"))) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed(None, "vector_expr") + scriptparse.p_execute_at_vector(p) + self.assertEqual(p[0], ("AtVector", (None, "vector_expr"))) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed(None, None, "200", None, "vector_expr") + scriptparse.p_execute_at_vector_scale(p) + self.assertEqual(p[0], ("AtVector", ("200", "vector_expr"))) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed(None, "overworld") + scriptparse.p_execute_in_dimension(p) + self.assertEqual(p[0], ("In", "overworld")) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed(None, "id", None, "@id", None, "lines", None) + scriptparse.p_for_selector(p) + self.assertTrue(type(p[0]) is for_selector_block) + self.assertEqual(p[0].id, "id") + self.assertEqual(p[0].selector, "@id") + self.assertEqual(p[0].sub, "lines") + self.assertEqual(p[0].line, 0) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed("condition") + scriptparse.p_conditions_one(p) + self.assertEqual(p[0], ["condition"]) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed("condition", None, ["conditions"]) + scriptparse.p_conditions(p) + self.assertEqual(p[0], ["condition", "conditions"]) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed("var", None, "fullselector") + scriptparse.p_condition_pointer(p) + self.assertEqual(p[0], ("pointer", ("var", "fullselector"))) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed("fullselector", None, "var") + scriptparse.p_condition_pointer_reversed(p) + self.assertEqual(p[0], ("pointer", ("var", "fullselector"))) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed("fullselector") + scriptparse.p_condition_fullselector(p) + self.assertEqual(p[0], ("selector", "fullselector")) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed("var", "<", "comp") + scriptparse.p_condition_score(p) + self.assertEqual(p[0], ("score", ("var", "<", "comp"))) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed("var", "==", "comp") + scriptparse.p_condition_score(p) + self.assertEqual(p[0], ("score", ("var", "=", "comp"))) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed("v1", "==", "v2") + scriptparse.p_condition_vector_equality(p) + self.assertEqual(p[0], ("vector_equality", ("v1", "v2"))) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed("var") + func = mock_mcfunction() + scriptparse.p_condition_bool(p) + self.assertEqual(p[0][0], "score") + self.assertEqual(p[0][1][0], "var") + self.assertEqual(p[0][1][1], ">") + self.assertEqual(p[0][1][2][0], "num") + self.assertEqual(p[0][1][2][1].get_value(func), 0) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed(None, "var") + func = mock_mcfunction() + scriptparse.p_condition_not_bool(p) + self.assertEqual(p[0][0], "score") + self.assertEqual(p[0][1][0], "var") + self.assertEqual(p[0][1][1], "<=") + self.assertEqual(p[0][1][2][0], "num") + self.assertEqual(p[0][1][2][1].get_value(func), 0) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed(None, "relcoords", "id") + scriptparse.p_condition_block(p) + self.assertEqual(p[0], ("block", ("relcoords", "id"))) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed("100") + func = mock_mcfunction() + scriptparse.p_comparison_num(p) + self.assertEqual(p[0][0], "num") + self.assertEqual(p[0][1].get_value(func), 100) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed(None, const_number("100"), None) + scriptparse.p_comparison_expr(p) + self.assertEqual(p[0][0], "num") + self.assertEqual(p[0][1].get_value(func), 100) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed("var") + scriptparse.p_comparison_global(p) + self.assertEqual(p[0], ("score", "var")) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed(None, interpreted_python("1", 0), None, "lines", None) + func = mock_mcfunction() + scriptparse.p_block_if_command(p) + self.assertTrue(type(p[0]) is python_if_block) + self.assertEqual(p[0].val.get_value(func), 1) + self.assertEqual(p[0].sub, "lines") + self.assertEqual(p[0].else_sub, None) + self.assertEqual(p[0].line, 0) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed( + None, + interpreted_python("1", 0), + None, + "lines", + None, + None, + "else_lines", + None, + ) + func = mock_mcfunction() + scriptparse.p_block_ifelse_command(p) + self.assertTrue(type(p[0]) is python_if_block) + self.assertEqual(p[0].val.get_value(func), 1) + self.assertEqual(p[0].sub, "lines") + self.assertEqual(p[0].else_sub, "else_lines") + self.assertEqual(p[0].line, 0) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed(None, "conditions", None, "lines", None) + scriptparse.p_block_while(p) + self.assertTrue(type(p[0]) is while_block) + self.assertEqual(p[0].exec_items, [("If", "conditions")]) + self.assertEqual(p[0].sub, "lines") + self.assertEqual(p[0].line, 0) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed(None, "conditions", ["items"], None, "lines", None) + scriptparse.p_block_while_execute(p) + self.assertTrue(type(p[0]) is while_block) + self.assertEqual(p[0].exec_items, [("If", "conditions"), "items"]) + self.assertEqual(p[0].sub, "lines") + self.assertEqual(p[0].line, 0) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed( + None, + "id", + None, + "from", + None, + "to", + None, + "by", + None, + "lines", + None, + ) + scriptparse.p_block_for_index_by(p) + self.assertTrue(type(p[0]) is for_index_block) + self.assertEqual(p[0].var, "id") + self.assertEqual(p[0].fr, "from") + self.assertEqual(p[0].to, "to") + self.assertEqual(p[0].by, "by") + self.assertEqual(p[0].sub, "lines") + self.assertEqual(p[0].line, 0) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed( + None, "id", None, "from", None, "to", None, "lines", None + ) + scriptparse.p_block_for_index(p) + self.assertTrue(type(p[0]) is for_index_block) + self.assertEqual(p[0].var, "id") + self.assertEqual(p[0].fr, "from") + self.assertEqual(p[0].to, "to") + self.assertEqual(p[0].by, None) + self.assertEqual(p[0].sub, "lines") + self.assertEqual(p[0].line, 0) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed(None, "expr", None, "cases", None) + scriptparse.p_switch(p) + self.assertTrue(type(p[0]) is switch_block) + self.assertEqual(p[0].expr, "expr") + self.assertEqual(p[0].cases_raw, "cases") + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed("case") + scriptparse.p_cases_one(p) + self.assertEqual(p[0], ["case"]) + + p = mock_parsed("case", None, ["cases"]) + scriptparse.p_cases_multiple(p) + self.assertEqual(p[0], ["case", "cases"]) + + p = mock_parsed(None, "100", None, "lines", None) + scriptparse.p_switch_case_single(p) + self.assertEqual(p[0], ("range", ("100", "100", "lines"))) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed(None, "100", None, "200", None, "lines", None) + scriptparse.p_switch_case_range(p) + self.assertEqual(p[0], ("range", ("100", "200", "lines"))) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed(None, None, "id", None, "code", None, "lines", None) + scriptparse.p_switch_case_python(p) + self.assertEqual(p[0], ("python", ("id", "code", "lines"))) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed(None, "fullselector", "text") + scriptparse.p_block_tell(p) + self.assertTrue(type(p[0]) is tell_block) + self.assertEqual(p[0].selector, "fullselector") + self.assertEqual(p[0].unformatted, "text") + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed("title", "selector", "text") + scriptparse.p_block_title(p) + self.assertTrue(type(p[0]) is title_block) + self.assertEqual(p[0].subtype, "title") + self.assertEqual(p[0].selector, "selector") + self.assertEqual(p[0].times, None) + self.assertEqual(p[0].unformatted, "text") + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed("subtitle", "selector", "1", "2", "3", "text") + scriptparse.p_block_title_times(p) + self.assertTrue(type(p[0]) is title_block) + self.assertEqual(p[0].subtype, "subtitle") + self.assertEqual(p[0].selector, "selector") + self.assertEqual(p[0].times, ("1", "2", "3")) + self.assertEqual(p[0].unformatted, "text") + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed("call") + scriptparse.p_block_function_call(p) + self.assertEqual(p[0], "call") + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed(("var", "op", "expr")) + scriptparse.p_block_math(p) + self.assertTrue(type(p[0]) is scoreboard_assignment_block) + self.assertEqual(p[0].var, "var") + self.assertEqual(p[0].op, "op") + self.assertEqual(p[0].expr, "expr") + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed("selector_assignment") + scriptparse.p_block_selector_assignment(p) + self.assertEqual(p[0], "selector_assignment") + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed("100") + scriptparse.p_integer(p) + self.assertEqual(p[0], "100") + + p = mock_parsed(None, "100") + scriptparse.p_integer_minus(p) + self.assertEqual(p[0], "-100") + + p = mock_parsed("100") + scriptparse.p_number_integer(p) + self.assertEqual(p[0], "100") + + p = mock_parsed("1.0") + scriptparse.p_float_val(p) + self.assertEqual(p[0], "1.0") + + p = mock_parsed(None, "1.0") + scriptparse.p_float_val_minus(p) + self.assertEqual(p[0], "-1.0") + + func = mock_mcfunction() + func.dollarid["test3"] = 10 + p = mock_parsed(None, "5 + test3") + scriptparse.p_const_value_interpreted(p) + self.assertEqual(p[0].get_value(func), 15) + + p = mock_parsed(None, None, "id", None, "blocks", None) + scriptparse.p_blocktag(p) + self.assertTrue(type(p[0]) is block_tag_block) + self.assertEqual(p[0].name, "id") + self.assertEqual(p[0].blocks, "blocks") + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed("block", None, ["blocks"]) + scriptparse.p_block_list(p) + self.assertEqual(p[0], ["block", "blocks"]) + + p = mock_parsed("block") + scriptparse.p_block_list_one(p) + self.assertEqual(p[0], ["block"]) + + p = mock_parsed("id", None, "fullselector") + scriptparse.p_selector_assignment(p) + self.assertTrue(type(p[0]) is selector_assignment_block) + self.assertEqual(p[0].id, "id") + self.assertEqual(p[0].fullselector, "fullselector") + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed(None, "id", None, "fullselector", None, "def", None) + scriptparse.p_selector_define(p) + self.assertTrue(type(p[0]) is selector_definition_block) + self.assertEqual(p[0].id, "id") + self.assertEqual(p[0].fullselector, "fullselector") + self.assertEqual(p[0].items, "def") + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed("item", None, ["items"]) + scriptparse.p_selector_definition(p) + self.assertEqual(p[0], ["item", "items"]) + + p = mock_parsed(None) + scriptparse.p_selector_definition_empty(p) + self.assertEqual(p[0], []) + + p = mock_parsed(None, "data") + scriptparse.p_selector_item_tag(p) + self.assertEqual(p[0], ("Tag", "data")) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed("id", None, "path", "type", "scale") + scriptparse.p_selector_item_path_scale(p) + self.assertEqual(p[0], ("Path", ("id", "path", "type", "scale"))) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed("id", None, "path", "type") + scriptparse.p_selector_item_path(p) + self.assertEqual(p[0], ("Path", ("id", "path", "type", None))) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed(None, "id", None, None, "path", "type", "scale") + scriptparse.p_selector_item_vector_path_scale(p) + self.assertEqual(p[0], ("VectorPath", ("id", "path", "type", "scale"))) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed(None, "id", None, None, "path", "type") + scriptparse.p_selector_item_vector_path(p) + self.assertEqual(p[0], ("VectorPath", ("id", "path", "type", None))) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed("function") + scriptparse.p_selector_item_method(p) + self.assertEqual(p[0], ("Method", "function")) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed("id") + scriptparse.p_data_path_id(p) + self.assertEqual(p[0], "id") + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed("id", None, "1", None) + scriptparse.p_data_path_array(p) + self.assertEqual(p[0], "id[1]") + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed("a", None, "b") + scriptparse.p_data_path_multi(p) + self.assertEqual(p[0], "a.b") + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed("byte") + scriptparse.p_data_type(p) + self.assertEqual(p[0], "byte") + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed(None, "id", None, const_number("1"), None) + func = mock_mcfunction() + scriptparse.p_array_definition(p) + self.assertTrue(type(p[0]) is array_definition_block) + self.assertEqual(p[0].name, "id") + self.assertEqual(p[0].from_val.get_value(func), 0) + self.assertEqual(p[0].to_val.get_value(func), 1) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed(None, "id", None, "1", None, "2", None) + scriptparse.p_array_definition_range(p) + self.assertTrue(type(p[0]) is array_definition_block) + self.assertEqual(p[0].name, "id") + self.assertEqual(p[0].from_val, "1") + self.assertEqual(p[0].to_val, "2") + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed("create_block") + scriptparse.p_block_create(p) + self.assertEqual(p[0], "create_block") + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed(None, "id", "relcoords") + scriptparse.p_create(p) + self.assertTrue(type(p[0]) is create_block) + self.assertEqual(p[0].atid, "id") + self.assertEqual(p[0].relcoords, "relcoords") + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed(None, "id") + func = mock_mcfunction() + scriptparse.p_create_nocoords(p) + self.assertTrue(type(p[0]) is create_block) + self.assertEqual(p[0].atid, "id") + self.assertEqual(p[0].relcoords.get_value(func), "~ ~ ~") + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed("qualifiers", None, "qualifier") + scriptparse.p_qualifiers_multiple(p) + self.assertEqual(p[0], "qualifiers,qualifier") + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed("qualifier") + scriptparse.p_qualifiers_one(p) + self.assertEqual(p[0], "qualifier") + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed(None) + scriptparse.p_qualifiers(p) + self.assertEqual(p[0], "") + + p = mock_parsed("100") + scriptparse.p_qualifier_integer(p) + self.assertEqual(p[0], "100") + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed("id", "<=", "id2") + scriptparse.p_qualifier_binop(p) + self.assertEqual(p[0], "id<=id2") + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed("id", "=", "100", ".", ".", "200") + scriptparse.p_qualifier_builtin(p) + self.assertEqual(p[0], "id=100..200") + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed("id", "=") + scriptparse.p_qualifier_empty(p) + self.assertEqual(p[0], "id=") + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed("id", "=", "!", "id2") + scriptparse.p_qualifier_is_not(p) + self.assertEqual(p[0], "id=!id2") + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed("id") + scriptparse.p_qualifier_is(p) + self.assertEqual(p[0], "id") + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed("not", "id") + scriptparse.p_qualifier_not(p) + self.assertEqual(p[0], "not id") + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed("id") + scriptparse.p_fullselector_symbol(p) + self.assertEqual(p[0], "@id[]") + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed("id", None, "qualifiers", None) + scriptparse.p_fullselector_symbol(p) + self.assertEqual(p[0], "@id[qualifiers]") + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed(const_number("100")) + func = mock_mcfunction() + scriptparse.p_relcoord_number(p) + self.assertEqual(p[0].get_value(func), "100") + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed(None, const_number("100")) + func = mock_mcfunction() + scriptparse.p_relcoord_relnumber(p) + self.assertEqual(p[0].get_value(func), "~100") + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed(None) + func = mock_mcfunction() + scriptparse.p_relcoord_relzero(p) + self.assertEqual(p[0].get_value(func), "~") + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed("^", const_number("100")) + func = mock_mcfunction() + scriptparse.p_localcoord_localnumber(p) + self.assertEqual(p[0].get_value(func), "^100") + + p = mock_parsed( + relcoord("", const_number("1")), + relcoord("", const_number("2")), + relcoord("", const_number("3")), + ) + func = mock_mcfunction() + scriptparse.p_relcoords(p) + self.assertEqual(p[0].get_value(func), "1 2 3") + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed(None, "expr") + scriptparse.p_return_expression(p) + self.assertEqual( + p[0], (("Var", ("Global", "ReturnValue")), "=", "expr") + ) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed("var", "+=", "expr") + scriptparse.p_assignment(p) + self.assertEqual(p[0], ("var", "+=", "expr")) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed("var", "++") + scriptparse.p_assignment_unary_default(p) + var, op, expr = p[0] + self.assertEqual(var, "var") + self.assertEqual(op, "+=") + self.assertTrue(type(expr) is num_expr) + self.assertEqual(expr.const_value(), "1") + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed("var", "=", "selector") + scriptparse.p_assignment_selector_global(p) + var, op, expr = p[0] + self.assertEqual(var, "var") + self.assertEqual(op, "=") + self.assertTrue(type(expr) is selector_expr) + self.assertEqual(expr.selector, "selector") + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed("var", "=", "create") + scriptparse.p_assignment_create(p) + var, op, expr = p[0] + self.assertEqual(var, "var") + self.assertEqual(op, "=") + self.assertTrue(type(expr) is create_expr) + self.assertEqual(expr.create_block, "create") + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed("var", "+=", "expr") + scriptparse.p_vector_assignment_vector(p) + self.assertTrue(type(p[0]) is vector_assignment_block) + self.assertEqual(p[0].var, "var") + self.assertEqual(p[0].op, "+=") + self.assertEqual(p[0].expr, "expr") + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed("var", "+=", "expr") + scriptparse.p_vector_assignment_scalar(p) + self.assertTrue(type(p[0]) is vector_assignment_scalar_block) + self.assertEqual(p[0].var, "var") + self.assertEqual(p[0].op, "+=") + self.assertEqual(p[0].expr, "expr") + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed(None, "id", None) + scriptparse.p_vector_var_id(p) + self.assertEqual(p[0], ("VAR_ID", "id")) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed("selector", None, None, "id", None) + scriptparse.p_vector_var_sel_id(p) + self.assertEqual(p[0], ("SEL_VAR_ID", ("selector", "id"))) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed(None, "a", None, "b", None, "c", None) + scriptparse.p_vector_var_components(p) + self.assertEqual(p[0], ("VAR_COMPONENTS", ["a", "b", "c"])) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed("a", None, "b") + scriptparse.p_expr_dot(p) + self.assertTrue(type(p[0]) is dot_expr) + self.assertEqual(p[0].lhs, "a") + self.assertEqual(p[0].rhs, "b") + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed("100") + scriptparse.p_expr_number(p) + self.assertTrue(type(p[0]) is num_expr) + self.assertEqual(p[0].val, "100") + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed(None) + scriptparse.p_expr_scale(p) + self.assertTrue(type(p[0]) is scale_expr) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed("id") + scriptparse.p_expr_variable(p) + self.assertTrue(type(p[0]) is selvar_expr) + self.assertEqual(p[0].sel, "Global") + self.assertEqual(p[0].var, "id") + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed("id", None, "100", None) + scriptparse.p_expr_array_const(p) + self.assertTrue(type(p[0]) is arrayconst_expr) + self.assertEqual(p[0].name, "id") + self.assertEqual(p[0].idx, "100") + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed("id", None, "expr", None) + scriptparse.p_expr_array_expr(p) + self.assertTrue(type(p[0]) is arrayexpr_expr) + self.assertEqual(p[0].name, "id") + self.assertEqual(p[0].idx_expr, "expr") + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed("selector", None, "id") + scriptparse.p_expr_selector_variable(p) + self.assertTrue(type(p[0]) is selvar_expr) + self.assertEqual(p[0].sel, "selector") + self.assertEqual(p[0].var, "id") + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed("call") + scriptparse.p_expr_function(p) + self.assertTrue(type(p[0]) is func_expr) + self.assertEqual(p[0].function_call, "call") + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed(None, "group", None) + scriptparse.p_expr_group(p) + self.assertEqual(p[0], "group") + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed("-", num_expr(100)) + scriptparse.p_expr_unary(p) + self.assertTrue(type(p[0]) is num_expr) + self.assertEqual(p[0].val, "-100") + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed("-", scale_expr()) + scriptparse.p_expr_unary(p) + self.assertTrue(type(p[0]) is unary_expr) + self.assertEqual(p[0].type, "-") + self.assertTrue(type(p[0].expr) is scale_expr) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed(None, "group", None) + scriptparse.p_vector_expr_paren(p) + self.assertEqual(p[0], "group") + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed(None, "a", None, "b", None, "c", None) + scriptparse.p_vector_expr_vector_triplet(p) + self.assertTrue(type(p[0]) is vector_expr) + self.assertEqual(p[0].exprs, ("a", "b", "c")) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed(None, "id", None) + scriptparse.p_vector_expr_vector_unit(p) + self.assertTrue(type(p[0]) is vector_var_expr) + self.assertEqual(p[0].vector_id, ("id")) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed("selector", None, None, "id", None) + scriptparse.p_vector_expr_selector_vector(p) + self.assertTrue(type(p[0]) is sel_vector_var_expr) + self.assertEqual(p[0].sel, ("selector")) + self.assertEqual(p[0].id, ("id")) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed("expr1", "+", "expr2") + scriptparse.p_vector_expr_binop_vector(p) + self.assertTrue(type(p[0]) is vector_binop_vector_expr) + self.assertEqual(p[0].lhs, ("expr1")) + self.assertEqual(p[0].op, ("+")) + self.assertEqual(p[0].rhs, ("expr2")) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed("expr1", "+", "expr2") + scriptparse.p_vector_expr_binop_scalar(p) + self.assertTrue(type(p[0]) is vector_binop_scalar_expr) + self.assertEqual(p[0].lhs, ("expr1")) + self.assertEqual(p[0].op, ("+")) + self.assertEqual(p[0].rhs, ("expr2")) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed("expr1", "+", "expr2") + scriptparse.p_vector_expr_binop_scalar_reversed(p) + self.assertTrue(type(p[0]) is vector_binop_scalar_expr) + self.assertEqual(p[0].lhs, ("expr2")) + self.assertEqual(p[0].op, ("+")) + self.assertEqual(p[0].rhs, ("expr1")) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed("-", "expr") + scriptparse.p_vector_expr_negative(p) + self.assertTrue(type(p[0]) is vector_binop_scalar_expr) + self.assertEqual(p[0].lhs, ("expr")) + self.assertEqual(p[0].op, ("*")) + self.assertTrue(type(p[0].rhs) is num_expr) + self.assertEqual(p[0].rhs.const_value(), "-1") + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed(None) + scriptparse.p_vector_expr_here(p) + self.assertTrue(type(p[0]) is vector_here_expr) + self.assertEqual(p[0].scale, None) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed(None, None, "100", None) + scriptparse.p_vector_expr_here_scale(p) + self.assertTrue(type(p[0]) is vector_here_expr) + self.assertEqual(p[0].scale, "100") + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed("id", None, "exprs", None) + scriptparse.p_function_call(p) + self.assertTrue(type(p[0]) is function_call_block) + self.assertEqual(p[0].dest, "id") + self.assertEqual(p[0].args, "exprs") + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed("selector", None, "id", None, "exprs", None) + scriptparse.p_method_call(p) + self.assertTrue(type(p[0]) is method_call_block) + self.assertEqual(p[0].selector, "selector") + self.assertEqual(p[0].dest, "id") + self.assertEqual(p[0].params, "exprs") + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed(["exprs"], None, "expr") + scriptparse.p_exprlist_multiple(p) + self.assertEqual(p[0], ["exprs", "expr"]) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed("expr") + scriptparse.p_exprlist_single(p) + self.assertEqual(p[0], ["expr"]) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed(None) + scriptparse.p_exprlist_empty(p) + self.assertEqual(p[0], []) + + p = mock_parsed( + "id", None, "macro_params", None, None, "function_params", None + ) + scriptparse.p_template_function_call(p) + self.assertTrue(type(p[0]) is template_function_call_block) + self.assertEqual(p[0].function, "id") + self.assertEqual(p[0].template_args, "macro_params") + self.assertEqual(p[0].args, "function_params") + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed(None, "id", "macro_params") + scriptparse.p_macro_call(p) + self.assertTrue(type(p[0]) is macro_call_block) + self.assertEqual(p[0].macro, "id") + self.assertEqual(p[0].args, "macro_params") + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed(None, "params", None) + scriptparse.p_macro_call_args(p) + self.assertEqual(p[0], "params") + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed(None) + scriptparse.p_macro_call_args_empty(p) + self.assertEqual(p[0], []) + + p = mock_parsed("param", None, ["params"]) + scriptparse.p_macro_call_params(p) + self.assertEqual(p[0], ["param", "params"]) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed("param") + scriptparse.p_macro_call_params_one(p) + self.assertEqual(p[0], ["param"]) + self.assertEqual(mcfunction.get_line(p[0]), 0) + + p = mock_parsed(None) + scriptparse.p_macro_call_params_empty(p) + self.assertEqual(p[0], []) + + p = mock_parsed("100") + scriptparse.p_macro_call_param_number(p) + self.assertEqual(p[0], "100") + self.assertEqual(mcfunction.get_line(p[0]), 0) + + def test_mcfunction_get_modifiable_id(self): + env = mock_environment() + func = mcfunction.mcfunction(env) + + id = func.get_modifiable_id("test", "assign") + self.assertEqual(id, "assign") + self.assertEqual( + func.commands, + ["scoreboard players operation Global assign = Global test"], + ) + + env = mock_environment() + func = mcfunction.mcfunction(env) + + id = func.get_modifiable_id("test", "test") + self.assertEqual(id, "test") + self.assertEqual(func.commands, []) + + env = mock_environment() + func = mcfunction.mcfunction(env) + + id = func.get_modifiable_id("test", None) + self.assertEqual(id, "test_scratch1") + self.assertEqual( + func.commands, + [ + "scoreboard players operation Global test_scratch1 = Global test" + ], + ) + + env = mock_environment() + func = mcfunction.mcfunction(env) + + id = func.get_modifiable_id("test_scratch1", None) + self.assertEqual(id, "test_scratch1") + self.assertEqual(func.commands, []) + + def test_mcfunction_evaluate_params(self): + env = mock_environment() + func = mcfunction.mcfunction(env) + + self.assertTrue(func.evaluate_params([num_expr(1)])) + self.assertEqual( + func.commands, + [ + "scoreboard players set Global test_scratch1 1", + "scoreboard players operation Global Param0 = Global test_scratch1", + ], + ) + + def test_mcfunction_get_variable_non_single_entity(self): + env = mock_environment() + sel = mock_selector_definition() + sel.paths["test_path"] = "path", "float", 100 + sel.base_name = "@e" + sel.is_single_entity = False + env.selectors["test_selector"] = sel + env.selector_definitions["@test_selector"] = sel + func = mcfunction.mcfunction(env) + + var = "Var", ("@test_selector", "test_path") + + with self.assertRaises(Exception): + var_ret = func.get_variable(var, True) + + def test_mcfunction_get_variable_path(self): + env = mock_environment() + sel = mock_selector_definition() + sel.paths["test_path"] = "path", "float", 100 + sel.base_name = "@s" + sel.is_single_entity = True + env.selectors["test_selector"] = sel + env.selector_definitions["@test_selector"] = sel + func = mcfunction.mcfunction(env) + + var = "Var", ("@test_selector", "test_path") + + var_ret = func.get_variable(var, True) + self.assertEqual(var_ret, var[1]) + self.assertEqual( + func.commands, + [ + "execute store result score @test_selector test_path run data get entity @test_selector path 100" + ], + ) + + def test_mcfunction_get_variable_arrayconst(self): + env = mock_environment() + func = mcfunction.mcfunction(env) + + var = "ArrayConst", ("test_array", interpreted_python("1")) + var_ret = func.get_variable(var, True) + + self.assertEqual(var_ret, ("Global", "test_array1")) + self.assertEqual(func.commands, []) + + def test_mcfunction_get_variable_arrayexpr(self): + env = mock_environment() + func = mcfunction.mcfunction(env) + env.arrays["test_array"] = (0, 10) + + var = "ArrayExpr", ("test_array", num_expr(1)) + var_ret = func.get_variable(var, True) + + self.assertEqual(var_ret, ("Global", "test_arrayVal")) + self.assertEqual( + func.commands, + [ + "scoreboard players set Global test_arrayIdx 1", + "function test_namespace:array_test_array_get", + ], + ) + + def test_mcfunction_get_variable_arrayexpr_noarray(self): + env = mock_environment() + func = mcfunction.mcfunction(env) + + var = "ArrayExpr", ("test_array", num_expr(1)) + with self.assertRaises(NameError): + var_ret = func.get_variable(var, True) + + def test_mcfunction_set_variable_var(self): + env = mock_environment() + sel = mock_selector_definition() + sel.paths["test_path"] = "path", "float", 100 + sel.base_name = "@s" + sel.is_single_entity = True + env.selectors["test_selector"] = sel + env.selector_definitions["@test_selector"] = sel + func = mcfunction.mcfunction(env) + + var = "Var", ("@test_selector", "test_path") + + func.set_variable(var) + self.assertEqual( + func.commands, + [ + "execute store result entity @test_selector path float 0.01 run scoreboard players get @test_selector test_path" + ], + ) + + def test_mcfunction_set_variable_arrayexpr(self): + env = mock_environment() + func = mcfunction.mcfunction(env) + + var = ("ArrayExpr", ("test_array", num_expr(1))) + + func.set_variable(var) + self.assertEqual( + func.commands, ["function test_namespace:array_test_array_set"] + ) + + def test_mcfunction_get_if_chain_selector(self): + env = mock_environment() + func = mcfunction.mcfunction(env) + + condition = "selector", "@p" + chain = func.get_if_chain([condition]) + + self.assertEqual(chain, "if entity @p ") + + def test_mcfunction_get_if_chain_score_num(self): + env = mock_environment() + func = mcfunction.mcfunction(env) + + for op, match in [ + (">", "2.."), + ("<", "..0"), + (">=", "1.."), + ("<=", "..1"), + ("=", "1..1"), + ]: + condition = "score", ( + ("Var", ("@test_selector", "test_var")), + op, + ("num", interpreted_python("1")), + ) + chain = func.get_if_chain([condition]) + + self.assertEqual( + chain, f"if score @test_selector test_var matches {match} " + ) + + def test_mcfunction_get_if_chain_score_var(self): + env = mock_environment() + func = mcfunction.mcfunction(env) + + condition = "score", ( + ("Var", ("@test_selector", "test_var")), + ">", + ("score", ("Var", ("@test_selector2", "test_var2"))), + ) + chain = func.get_if_chain([condition]) + + self.assertEqual( + chain, + "if score @test_selector test_var > @test_selector2 test_var2 ", + ) + + def test_mcfunction_get_if_chain_score_bad_comparison_type(self): + env = mock_environment() + func = mcfunction.mcfunction(env) + + condition = "score", ( + ("Var", ("@test_selector", "test_var")), + ">", + ("bad", None), + ) + with self.assertRaises(ValueError): + func.get_if_chain([condition]) + + def test_mcfunction_get_if_chain_pointer(self): + env = mock_environment() + func = mcfunction.mcfunction(env) + + condition = "pointer", ( + ("Var", ("@test_selector", "test_var")), + "@test_selector2", + ) + chain = func.get_if_chain([condition]) + + self.assertEqual( + chain, "if score @test_selector test_var = @test_selector2 _id " + ) + + def test_mcfunction_get_if_chain_vector_equality_var_id(self): + env = mock_environment() + func = mcfunction.mcfunction(env) + + condition = "vector_equality", (("VAR_ID", "var1"), ("VAR_ID", "var2")) + chain = func.get_if_chain([condition]) + + self.assertEqual( + chain, + "if score Global _var1_0 = Global _var2_0 if score Global _var1_1 = Global _var2_1 if score Global _var1_2 = Global _var2_2 ", + ) + + def test_mcfunction_get_if_chain_vector_equality_sel_var_id(self): + env = mock_environment() + func = mcfunction.mcfunction(env) + + condition = "vector_equality", ( + ("SEL_VAR_ID", ("@sel1", "var1")), + ("SEL_VAR_ID", ("@sel2", "var2")), + ) + chain = func.get_if_chain([condition]) + + self.assertEqual( + chain, + "if score @sel1 _var1_0 = @sel2 _var2_0 if score @sel1 _var1_1 = @sel2 _var2_1 if score @sel1 _var1_2 = @sel2 _var2_2 ", + ) + + def test_mcfunction_mcfunction_get_if_chain_vector_equality_var_components( + self, + ): + env = mock_environment() + func = mcfunction.mcfunction(env) + + condition = "vector_equality", ( + ("VAR_COMPONENTS", [("a1", "x1"), ("b1", "y1"), ("c1", "z1")]), + ("VAR_COMPONENTS", [("a2", "x2"), ("b2", "y2"), ("c2", "z2")]), + ) + chain = func.get_if_chain([condition]) + + self.assertEqual( + chain, + "if score a1 x1 = a2 x2 if score b1 y1 = b2 y2 if score c1 z1 = c2 z2 ", + ) + + def test_mcfunction_mcfunction_get_if_chain_unless(self): + env = mock_environment() + func = mcfunction.mcfunction(env) + + condition = "vector_equality", (("VAR_ID", "var1"), ("VAR_ID", "var2")) + with self.assertRaises(ValueError): + func.get_if_chain([condition], "unless") + + def test_mcfunction_mcfunction_get_if_chain_block(self): + env = mock_environment() + env.block_tags["test_block_tag"] = ["test_block1"] + func = mcfunction.mcfunction(env) + + condition1 = "block", (dummy_relcoords(1, 2, 3), "test_block_tag") + condition2 = "block", (dummy_relcoords(4, 5, 6), "test_block2") + chain = func.get_if_chain([condition1, condition2]) + + self.assertEqual( + chain, + "if block 1 2 3 #test_namespace:test_block_tag if block 4 5 6 minecraft:test_block2 ", + ) + + def test_mcfunction_mcfunction_get_if_chain_bad_type(self): + env = mock_environment() + func = mcfunction.mcfunction(env) + + condition = "bad", None + with self.assertRaises(ValueError): + func.get_if_chain([condition]) + + def test_mcfunction_execute_command_multiple_as(self): + env = mock_environment() + func = mcfunction.mcfunction(env) + exec_func = mock_mcfunction() + + cmd = func.get_execute_command([("As", None), ("As", None)], exec_func) + self.assertEqual(cmd, None) + + def test_mcfunction_execute_command_if(self): + env = mock_environment() + func = mcfunction.mcfunction(env) + exec_func = mock_mcfunction() + + item = "If", [("selector", "@p")] + + cmd = func.get_execute_command([item], exec_func) + self.assertEqual(cmd, "execute if entity @p ") + + def test_mcfunction_execute_command_unless(self): + env = mock_environment() + func = mcfunction.mcfunction(env) + exec_func = mock_mcfunction() + + item = "Unless", [("selector", "@p")] + + cmd = func.get_execute_command([item], exec_func) + self.assertEqual(cmd, "execute unless entity @p ") + + def test_mcfunction_execute_command_as_id_attype(self): + env = mock_environment() + func = mcfunction.mcfunction(env) + exec_func = mock_mcfunction() + + item = "AsId", (("Var", ("Global", "test_var")), "at_type") + + cmd = func.get_execute_command([item], exec_func) + self.assertEqual( + func.commands, + ["scoreboard players operation Global _id = Global test_var"], + ) + self.assertEqual(cmd, "execute as @e if score @s _id = Global _id ") + self.assertEqual(exec_func.self_selector, "@at_type") + + def test_mcfunction_execute_command_as_id(self): + env = mock_environment() + func = mcfunction.mcfunction(env) + exec_func = mock_mcfunction() + + item = "AsId", (("Var", ("Global", "test_var")), None) + + cmd = func.get_execute_command([item], exec_func) + self.assertEqual( + func.commands, + ["scoreboard players operation Global _id = Global test_var"], + ) + self.assertEqual(cmd, "execute as @e if score @s _id = Global _id ") + + def test_mcfunction_execute_command_as_create(self): + env = mock_environment() + func = mcfunction.mcfunction(env) + exec_func = mock_mcfunction() + sel = mock_selector_definition() + sel.type = "creeper" + env.selectors["test_id"] = sel + + item = "AsCreate", create_block( + 0, + "test_id", + relcoords( + [ + relcoord("", const_number("1")), + relcoord("", const_number("2")), + relcoord("", const_number("3")), + ] + ), + ) + + cmd = func.get_execute_command([item], exec_func) + self.assertEqual( + func.commands, + [ + "scoreboard players add @e _age 1", + "summon creeper 1 2 3 ", + "scoreboard players add @e _age 1", + ], + ) + self.assertEqual(cmd, "execute as @e[_age==1] ") + + def test_mcfunction_execute_command_as_create_multiple(self): + env = mock_environment() + func = mcfunction.mcfunction(env) + exec_func = mock_mcfunction() + + item = "AsCreate", create_block(0, "test_id", ["1", "2", "3"]) + item2 = "If", [("selector", "@p")] + + cmd = func.get_execute_command([item, item2], exec_func) + + self.assertEqual(cmd, None) + + def test_mcfunction_execute_command_rotated_etc(self): + env = mock_environment() + func = mcfunction.mcfunction(env) + exec_func = mock_mcfunction() + + for type, code, target, target_code, extra in [ + ("As", "as", "@p", "@p", ""), + ("Rotated", "rotated as", "@p", "@p", ""), + ("FacingCoords", "facing", dummy_relcoords(1, 2, 3), "1 2 3", ""), + ("FacingEntity", "facing entity", "@p", "@p", " feet"), + ("Align", "align", "xyz", "xyz", ""), + ("In", "in", "the_end", "the_end", ""), + ]: + item = type, target + + cmd = func.get_execute_command([item], exec_func) + self.assertEqual(cmd, f"execute {code} {target_code}{extra} ") + + def test_mcfunction_execute_command_at_selector_coords(self): + env = mock_environment() + func = mcfunction.mcfunction(env) + exec_func = mock_mcfunction() + + item = "At", ("@test_selector", dummy_relcoords(1, 2, 3)) + + cmd = func.get_execute_command([item], exec_func) + self.assertEqual(cmd, "execute at @test_selector positioned 1 2 3 ") + + def test_mcfunction_execute_command_at_selector(self): + env = mock_environment() + func = mcfunction.mcfunction(env) + exec_func = mock_mcfunction() + + item = "At", ("@test_selector", None) + + cmd = func.get_execute_command([item], exec_func) + self.assertEqual(cmd, "execute at @test_selector ") + + def test_mcfunction_execute_command_at_coords(self): + env = mock_environment() + func = mcfunction.mcfunction(env) + exec_func = mock_mcfunction() + + item = "At", (None, dummy_relcoords(1, 2, 3)) + + cmd = func.get_execute_command([item], exec_func) + self.assertEqual(cmd, "execute positioned 1 2 3 ") + + def test_mcfunction_execute_command_at_vector(self): + env = mock_environment() + func = mcfunction.mcfunction(env) + exec_func = mock_mcfunction() + + item = "AtVector", (None, vector_var_expr("test_vector")) + + cmd = func.get_execute_command([item], exec_func) + self.assertEqual(cmd, "execute at @e[_age == 1] ") + self.assertEqual( + func.commands, + [ + "scoreboard players add @e _age 1", + "summon area_effect_cloud", + "scoreboard players add @e _age 1", + "execute store result entity @e[_age==1,limit=1] Pos[0] double 0.001 run scoreboard players get Global _test_vector_0", + "execute store result entity @e[_age==1,limit=1] Pos[1] double 0.001 run scoreboard players get Global _test_vector_1", + "execute store result entity @e[_age==1,limit=1] Pos[2] double 0.001 run scoreboard players get Global _test_vector_2", + ], + ) + self.assertEqual(exec_func.commands, ["/kill @e[_age == 1]"]) + + def test_mcfunction_execute_command_at_vector_scale(self): + env = mock_environment() + func = mcfunction.mcfunction(env) + exec_func = mock_mcfunction() + + item = "AtVector", (const_number(200), vector_var_expr("test_vector")) + + cmd = func.get_execute_command([item], exec_func) + self.assertEqual(cmd, "execute at @e[_age == 1] ") + self.assertEqual( + func.commands, + [ + "scoreboard players add @e _age 1", + "summon area_effect_cloud", + "scoreboard players add @e _age 1", + "execute store result entity @e[_age==1,limit=1] Pos[0] double 0.005 run scoreboard players get Global _test_vector_0", + "execute store result entity @e[_age==1,limit=1] Pos[1] double 0.005 run scoreboard players get Global _test_vector_1", + "execute store result entity @e[_age==1,limit=1] Pos[2] double 0.005 run scoreboard players get Global _test_vector_2", + ], + ) + self.assertEqual(exec_func.commands, ["/kill @e[_age == 1]"]) + + def test_mcfunction_execute_command_at_vector_multiple(self): + env = mock_environment() + func = mcfunction.mcfunction(env) + exec_func = mock_mcfunction() + + item1 = "AtVector", (const_number(200), vector_var_expr("test_vector")) + item2 = "AtVector", (const_number(200), vector_var_expr("test_vector")) + + cmd = func.get_execute_command([item1, item2], exec_func) + self.assertEqual(cmd, None) + + def test_mcfunction_switch_cases_four(self): + env = mock_environment() + func = mcfunction.mcfunction(env) + + case1 = 1, 2, [mock_block("command1")], 0, None + case2 = 3, 3, [mock_block("command2")], 0, None + case3 = 4, 5, [mock_block("command3")], 0, None + case4 = 6, 10, [mock_block("command4")], 0, None + + self.assertTrue( + func.switch_cases("switch_var", [case1, case2, case3, case4]) + ) + self.assertEqual( + func.commands, + [ + "execute if score Global switch_var matches 1..2 run command1", + "execute if score Global switch_var matches 3..3 run command2", + "execute if score Global switch_var matches 4..5 run command3", + "execute if score Global switch_var matches 6..10 run command4", + ], + ) + + def test_mcfunction_switch_cases_three(self): + env = mock_environment() + func = mcfunction.mcfunction(env) + + case1 = 1, 2, [mock_block("command1")], 0, None + case2 = 3, 3, [mock_block("command2")], 0, "test_python_var" + case3 = 4, 5, [mock_block("command3")], 0, None + + self.assertTrue(func.switch_cases("switch_var", [case1, case2, case3])) + self.assertEqual( + func.commands, + [ + "execute if score Global switch_var matches 1..2 run command1", + "execute if score Global switch_var matches 3..3 run command2", + "execute if score Global switch_var matches 4..5 run command3", + ], + ) + self.assertEqual( + env.cloned_environments[1].dollarid["test_python_var"], 3 + ) + + def test_mcfunction_switch_cases_multiline(self): + env = mock_environment() + func = mcfunction.mcfunction(env) + + case1 = 1, 2, [mock_block("command1")], 0, None + case2 = ( + 3, + 3, + [mock_block("command2"), mock_block("command5")], + 0, + None, + ) + case3 = 4, 5, [mock_block("command3"), mock_block("command4")], 0, None + + self.assertTrue(func.switch_cases("switch_var", [case1, case2, case3])) + self.assertEqual( + func.commands, + [ + "execute if score Global switch_var matches 1..2 run command1", + "execute if score Global switch_var matches 3..3 run function test_namespace:case3_001_ln0", + "execute if score Global switch_var matches 4..5 run function test_namespace:case4-5_001_ln0", + ], + ) + self.assertEqual( + env.functions["case3_001_ln0"].commands, ["command2", "command5"] + ) + self.assertEqual( + env.functions["case4-5_001_ln0"].commands, ["command3", "command4"] + ) + + def test_mcfunction_switch_cases_five(self): + env = mock_environment() + func = mcfunction.mcfunction(env) + + case1 = 1, 2, [mock_block("command1")], 0, None + case2 = 3, 3, [mock_block("command2")], 0, None + case3 = 4, 5, [mock_block("command3")], 0, None + case4 = 6, 10, [mock_block("command4")], 0, None + case5 = 11, 15, [mock_block("command5")], 0, None + + self.assertTrue( + func.switch_cases( + "switch_var", [case1, case2, case3, case4, case5] + ) + ) + self.assertEqual( + func.commands, + [ + "execute if score Global switch_var matches 1..2 run command1", + "execute if score Global switch_var matches 3..3 run command2", + "execute if score Global switch_var matches 4..5 run command3", + "execute if score Global switch_var matches 6..15 run function test_namespace:switch6-15_001_ln0", + ], + ) + self.assertEqual( + env.functions["switch6-15_001_ln0"].commands, + [ + "execute if score Global switch_var matches 6..10 run command4", + "execute if score Global switch_var matches 11..15 run command5", + ], + ) + + def test_mcfunction_switch_cases_error(self): + env = mock_environment() + func = mcfunction.mcfunction(env) + + case1 = 1, 2, [mock_block("command1")], 0, None + case2 = 3, 3, [mock_block("command2")], 0, "test_python_var" + case3 = 4, 5, [mock_block("command3")], 0, None + case4 = 6, 7, [mock_block("command4")], 0, None + case5 = 8, 9, [mock_block(raiseException=True, line=1)], 0, None + + self.assertFalse( + func.switch_cases( + "switch_var", [case1, case2, case3, case4, case5] + ) + ) + + def test_mcfunction_add_operation(self): + env = mock_environment() + func = mcfunction.mcfunction(env) + + func.add_operation("@test_selector", "var1", "+=", "var2") + self.assertEqual( + env.applied, + [ + "@test_selector", + "scoreboard players operation @test_selector var1 += @test_selector var2", + ], + ) + self.assertEqual( + func.commands, + [ + "scoreboard players operation @test_selector var1 += @test_selector var2" + ], + ) + + def test_mcfunction_insert_command_empty(self): + env = mock_environment() + func = mcfunction.mcfunction(env) + + func.insert_command("", 0) + self.assertEqual(func.commands, []) + + def test_mcfunction_get_vector_path(self): + env = mock_environment() + sel = mock_selector_definition() + sel.vector_paths["test_var"] = "path.to.data", "float", None + sel.is_single_entity = True + env.selectors["test_selector"] = sel + env.selector_definitions["@test_selector[x=1]"] = sel + func = mcfunction.mcfunction(env) + + self.assertTrue( + func.get_vector_path( + "@test_selector[x=1]", + "test_var", + ["assign_var1", "assign_var2", "assign_var3"], + ) + ) + self.assertEqual( + func.commands, + [ + "execute store result score Global assign_var1 run data get entity @test_selector[x=1] path.to.data[0] 1000", + "execute store result score Global assign_var2 run data get entity @test_selector[x=1] path.to.data[1] 1000", + "execute store result score Global assign_var3 run data get entity @test_selector[x=1] path.to.data[2] 1000", + ], + ) + + def test_mcfunction_set_selector_path(self): + env = mock_environment() + sel = mock_selector_definition() + sel.vector_paths["test_var"] = "path.to.data", "float", None + sel.is_single_entity = True + env.selectors["test_selector"] = sel + env.selector_definitions["@test_selector[x=1]"] = sel + func = mcfunction.mcfunction(env) + + self.assertTrue( + func.set_vector_path( + "@test_selector[x=1]", "test_var", ["x", "y", "z"] + ) + ) + self.assertEqual( + func.commands, + [ + "execute store result entity @test_selector[x=1] path.to.data[0] float 0.001 run scoreboard players get Global x", + "execute store result entity @test_selector[x=1] path.to.data[1] float 0.001 run scoreboard players get Global y", + "execute store result entity @test_selector[x=1] path.to.data[2] float 0.001 run scoreboard players get Global z", + ], + ) + + def test_environment_clone(self): + gc = mock_global_context() + env = environment.environment(gc) + + new_env = env.clone("new_name") + + self.assertEqual(new_env.scratch.prefix, "new_name_prefix") + + def test_environment_copy_dollarid(self): + gc = mock_global_context() + env = environment.environment(gc) + + env.dollarid["test1"] = "10" + env.copy_dollarid("$test2", "-$test1") + + self.assertTrue("test2" in env.dollarid) + self.assertEqual(env.dollarid["test2"], "-10") + + env.dollarid["test3"] = "20.0" + env.copy_dollarid("$test4", "-$test3") + + self.assertTrue("test4" in env.dollarid) + self.assertEqual(env.dollarid["test4"], "-20.0") + + env.dollarid["test5"] = "string" + with self.assertRaises(ValueError) as context: + env.copy_dollarid("$test6", "-$test5") + + +if __name__ == "__main__": + unittest.main() diff --git a/variable_types/array_const_var.py b/variable_types/array_const_var.py index b3194b6..ad793e8 100644 --- a/variable_types/array_const_var.py +++ b/variable_types/array_const_var.py @@ -2,69 +2,86 @@ from variable_types.scoreboard_var import scoreboard_var from CompileError import CompileError + class array_const_var(var_base): - def __init__(self, selector, array, idx): - self.selector = selector - self.array = array - self.idx = idx - - def check_array(self, func): - try: - idx_str = func.apply_replacements(self.idx) - val = int(idx_str) - except Exception as e: - print(e) - raise CompileError(f'"{idx_str}" is not an integer for array "{self.array}" index') - - if self.array not in func.arrays: - raise CompileError(f'Tried to use undefined array {self.array}') - from_val, to_val, selector_based = func.arrays[self.array] - if val < from_val or val > to_val: - raise CompileError(f'Index {val} for "array {self.array}[{from_val} to {to_val}]" is out of bounds.') + def __init__(self, selector, array, idx): + self.selector = selector + self.array = array + self.idx = idx + + def check_array(self, func): + try: + idx_str = func.apply_replacements(self.idx) + val = int(idx_str) + except Exception as e: + print(e) + raise CompileError( + f'"{idx_str}" is not an integer for array "{self.array}" index' + ) + + if self.array not in func.arrays: + raise CompileError(f"Tried to use undefined array {self.array}") + from_val, to_val, selector_based = func.arrays[self.array] + if val < from_val or val > to_val: + raise CompileError( + f'Index {val} for "array {self.array}[{from_val} to {to_val}]" is out of bounds.' + ) + + if selector_based and self.selector == "Global": + raise CompileError( + f"Tried to use selector-based array {self.array} without a selector." + ) + if not selector_based and self.selector != "Global": + raise CompileError( + f"Tried to use global array {self.array} with a selector." + ) + + def get_objective(self, func): + self.check_array(func) + idx_str = func.apply_replacements(self.idx) + return f"{self.array}{idx_str}" + + # Returns a scoreboard objective for this variable. + # If assignto isn't None, then this function may + # use the assignto objective to opimtize data flow. + def get_scoreboard_var(self, func, assignto=None): + return scoreboard_var(self.selector, self.get_objective(func)) + + # Returns a command that will get this variable's value to be used with "execute store result" + def get_command(self, func): + return f"scoreboard players get {self.selector} {self.get_objective(func)}" + + # Returns true if this variable is a scoreboard_var with the specified selector and objective, + # to reduce extranious copies. + def is_objective(self, func, selector, objective): + return selector == self.selector and objective == self.get_objective( + func + ) + + # Gets an assignto value for this variable if there is one. + def get_assignto(self, func): + return scoreboard_var("Global", self.get_objective(func)) - if selector_based and self.selector == 'Global': - raise CompileError(f'Tried to use selector-based array {self.array} without a selector.') - if not selector_based and self.selector != 'Global': - raise CompileError(f'Tried to use global array {self.array} with a selector.') - - def get_objective(self, func): - self.check_array(func) - idx_str = func.apply_replacements(self.idx) - return f'{self.array}{idx_str}' + # Copies the value from a target variable to this variable + def copy_from(self, func, var): + const_val = var.get_const_value(func) + if const_val != None: + func.add_command( + f"scoreboard players set {self.selector} {self.get_objective(func)} {const_val}" + ) + else: + func.add_command( + f"execute store result score {self.selector} {self.get_objective(func)} run {var.get_command(func)}" + ) - # Returns a scoreboard objective for this variable. - # If assignto isn't None, then this function may - # use the assignto objective to opimtize data flow. - def get_scoreboard_var(self, func, assignto=None): - return scoreboard_var(self.selector, self.get_objective(func)) - - # Returns a command that will get this variable's value to be used with "execute store result" - def get_command(self, func): - return f'scoreboard players get {self.selector} {self.get_objective(func)}' - - # Returns true if this variable is a scoreboard_var with the specified selector and objective, - # to reduce extranious copies. - def is_objective(self, func, selector, objective): - return selector == self.selector and objective == self.get_objective(func) - - # Gets an assignto value for this variable if there is one. - def get_assignto(self, func): - return scoreboard_var('Global', self.get_objective(func)) - - # Copies the value from a target variable to this variable - def copy_from(self, func, var): - const_val = var.get_const_value(func) - if const_val != None: - func.add_command(f'scoreboard players set {self.selector} {self.get_objective(func)} {const_val}') - else: - func.add_command(f'execute store result score {self.selector} {self.get_objective(func)} run {var.get_command(func)}') - - # Returns a scoreboard_var which can be modified as needed without side effects - def get_modifiable_var(self, func, assignto): - scratch_var = scoreboard_var('Global', func.get_scratch()) - scratch_var.copy_from(func, self) - return scratch_var + # Returns a scoreboard_var which can be modified as needed without side effects + def get_modifiable_var(self, func, assignto): + scratch_var = scoreboard_var("Global", func.get_scratch()) + scratch_var.copy_from(func, self) + return scratch_var - # Returns true if this varariable/expression references the specified scoreboard variable - def references_scoreboard_var(self, func, var): - return self.get_scoreboard_var(func).references_scoreboard_var(func, var) \ No newline at end of file + # Returns true if this varariable/expression references the specified scoreboard variable + def references_scoreboard_var(self, func, var): + return self.get_scoreboard_var(func).references_scoreboard_var( + func, var + ) diff --git a/variable_types/array_expr_var.py b/variable_types/array_expr_var.py index 08c45c6..0144a7f 100644 --- a/variable_types/array_expr_var.py +++ b/variable_types/array_expr_var.py @@ -1,99 +1,109 @@ from variable_types.var_base import var_base from variable_types.scoreboard_var import scoreboard_var + class array_expr_var(var_base): - def __init__(self, selector, array, idx_expr): - self.selector = selector - self.array = array - self.idx_expr = idx_expr - - def check_defined(self, func): - if self.array not in func.arrays: - print(f'Tried to use undefined array "{self.array}"') - return None - - from_val, to_val, selector_based = func.arrays[self.array] - - if selector_based and self.selector == 'Global': - raise CompileError(f'Tried to use selector-based array {self.array} without a selector.') - if not selector_based and self.selector != 'Global': - raise CompileError(f'Tried to use global array {self.array} with a selector.') - - def evaluate(self, func): - self.check_defined(func) - - index_name = f'{self.array}Idx' - expr_var = self.idx_expr.compile(func, index_name) - - index_var = scoreboard_var(self.selector, index_name) - index_var.copy_from(func, expr_var) - - if self.selector == '@s' or not self.selector.startswith('@'): - prefix = '' - else: - prefix = f'execute as {self.selector} run ' - - func.add_command(prefix + f'function {func.namespace}:array_{self.array.lower()}_get') - - expr_var.free_scratch(func) - - # Returns a scoreboard objective for this variable. - # If assignto isn't None, then this function may - # use the assignto objective to opimtize data flow. - def get_scoreboard_var(self, func, assignto=None): - self.evaluate(func) - - return scoreboard_var(self.selector, f'{self.array}Val') - - # Returns a command that will get this variable's value to be used with "execute store result" - def get_command(self, func): - return self.get_scoreboard_var(func).get_command(func) - - # Returns true if this variable is a scoreboard_var with the specified selector and objective, - # to reduce extranious copies. - def is_objective(self, func, selector, objective): - self.check_defined(func) - - return selector == self.selector and objective == f'{self.array}Idx' - - # Gets an assignto value for this variable if there is one. - def get_assignto(self, func): - self.check_defined(func) - - return scoreboard_var(f'Global', '{self.array}Idx') - - # Copies the value from a target variable to this variable - def copy_from(self, func, var): - self.check_defined(func) - - index_name = f'{self.array}Idx' - index_var = scoreboard_var(self.selector, index_name) - - expr_var = self.idx_expr.compile(func, index_name) - index_var.copy_from(func, expr_var) - - val_name = f'{self.array}Val' - val_var = scoreboard_var(self.selector, val_name) - - val_var.copy_from(func, var) - - if self.selector == '@s' or not self.selector.startswith('@'): - prefix = '' - else: - prefix = f'execute as {self.selector} run ' - - func.add_command(prefix + f'function {func.namespace}:array_{self.array.lower()}_set') - - expr_var.free_scratch(func) - val_var.free_scratch(func) - - - # Returns a scoreboard_var which can be modified as needed without side effects - def get_modifiable_var(self, func, assignto): - scratch_var = scoreboard_var('Global', func.get_scratch()) - scratch_var.copy_from(func, self) - return scratch_var - - # Returns true if this varariable/expression references the specified scoreboard variable - def references_scoreboard_var(self, func, var): - return self.idx_expr.references_scoreboard_var(func, var) \ No newline at end of file + def __init__(self, selector, array, idx_expr): + self.selector = selector + self.array = array + self.idx_expr = idx_expr + + def check_defined(self, func): + if self.array not in func.arrays: + print(f'Tried to use undefined array "{self.array}"') + return None + + from_val, to_val, selector_based = func.arrays[self.array] + + if selector_based and self.selector == "Global": + raise CompileError( + f"Tried to use selector-based array {self.array} without a selector." + ) + if not selector_based and self.selector != "Global": + raise CompileError( + f"Tried to use global array {self.array} with a selector." + ) + + def evaluate(self, func): + self.check_defined(func) + + index_name = f"{self.array}Idx" + expr_var = self.idx_expr.compile(func, index_name) + + index_var = scoreboard_var(self.selector, index_name) + index_var.copy_from(func, expr_var) + + if self.selector == "@s" or not self.selector.startswith("@"): + prefix = "" + else: + prefix = f"execute as {self.selector} run " + + func.add_command( + prefix + + f"function {func.namespace}:array_{self.array.lower()}_get" + ) + + expr_var.free_scratch(func) + + # Returns a scoreboard objective for this variable. + # If assignto isn't None, then this function may + # use the assignto objective to opimtize data flow. + def get_scoreboard_var(self, func, assignto=None): + self.evaluate(func) + + return scoreboard_var(self.selector, f"{self.array}Val") + + # Returns a command that will get this variable's value to be used with "execute store result" + def get_command(self, func): + return self.get_scoreboard_var(func).get_command(func) + + # Returns true if this variable is a scoreboard_var with the specified selector and objective, + # to reduce extranious copies. + def is_objective(self, func, selector, objective): + self.check_defined(func) + + return selector == self.selector and objective == f"{self.array}Idx" + + # Gets an assignto value for this variable if there is one. + def get_assignto(self, func): + self.check_defined(func) + + return scoreboard_var(f"Global", "{self.array}Idx") + + # Copies the value from a target variable to this variable + def copy_from(self, func, var): + self.check_defined(func) + + index_name = f"{self.array}Idx" + index_var = scoreboard_var(self.selector, index_name) + + expr_var = self.idx_expr.compile(func, index_name) + index_var.copy_from(func, expr_var) + + val_name = f"{self.array}Val" + val_var = scoreboard_var(self.selector, val_name) + + val_var.copy_from(func, var) + + if self.selector == "@s" or not self.selector.startswith("@"): + prefix = "" + else: + prefix = f"execute as {self.selector} run " + + func.add_command( + prefix + + f"function {func.namespace}:array_{self.array.lower()}_set" + ) + + expr_var.free_scratch(func) + val_var.free_scratch(func) + + # Returns a scoreboard_var which can be modified as needed without side effects + def get_modifiable_var(self, func, assignto): + scratch_var = scoreboard_var("Global", func.get_scratch()) + scratch_var.copy_from(func, self) + return scratch_var + + # Returns true if this varariable/expression references the specified scoreboard variable + def references_scoreboard_var(self, func, var): + return self.idx_expr.references_scoreboard_var(func, var) diff --git a/variable_types/block_path_var.py b/variable_types/block_path_var.py index ff0951d..45fb289 100644 --- a/variable_types/block_path_var.py +++ b/variable_types/block_path_var.py @@ -1,40 +1,47 @@ from variable_types.var_base import var_base from variable_types.scoreboard_var import scoreboard_var + class block_path_var(var_base): - def __init__(self, block_id, path_name, coords, macro_args): - self.block_id = block_id - self.path_name = path_name - self.coords = coords - self.macro_args = macro_args - - # Returns a scoreboard objective for this variable. - # If assignto isn't None, then this function may - # use the assignto objective to opimtize data flow. - def get_scoreboard_var(self, func, assignto=None): - block_def = func.get_block_definition(self.block_id) - - if assignto == None: - assignto = scoreboard_var('Global', func.get_scratch()) - - func.add_command(f'execute store result score {assignto.get_selvar(func)} run {self.get_command(func)}') - - return assignto - - # Returns a command that will get this variable's value to be used with "execute store result" - def get_command(self, func): - block_def = func.get_block_definition(self.block_id) - return block_def.get_command(func, self.path_name, self.coords, self.macro_args) - - # Copies the value from a target variable to this variable - def copy_from(self, func, var): - block_def = func.get_block_definition(self.block_id) - block_def.copy_from(func, self.path_name, self.coords, self.macro_args, var) - - var.free_scratch(func) - - # Returns a scoreboard_var which can be modified as needed without side effects - def get_modifiable_var(self, func, assignto): - scratch_var = scoreboard_var('Global', func.get_scratch()) - scratch_var.copy_from(func, self) - return scratch_var \ No newline at end of file + def __init__(self, block_id, path_name, coords, macro_args): + self.block_id = block_id + self.path_name = path_name + self.coords = coords + self.macro_args = macro_args + + # Returns a scoreboard objective for this variable. + # If assignto isn't None, then this function may + # use the assignto objective to opimtize data flow. + def get_scoreboard_var(self, func, assignto=None): + block_def = func.get_block_definition(self.block_id) + + if assignto == None: + assignto = scoreboard_var("Global", func.get_scratch()) + + func.add_command( + f"execute store result score {assignto.get_selvar(func)} run {self.get_command(func)}" + ) + + return assignto + + # Returns a command that will get this variable's value to be used with "execute store result" + def get_command(self, func): + block_def = func.get_block_definition(self.block_id) + return block_def.get_command( + func, self.path_name, self.coords, self.macro_args + ) + + # Copies the value from a target variable to this variable + def copy_from(self, func, var): + block_def = func.get_block_definition(self.block_id) + block_def.copy_from( + func, self.path_name, self.coords, self.macro_args, var + ) + + var.free_scratch(func) + + # Returns a scoreboard_var which can be modified as needed without side effects + def get_modifiable_var(self, func, assignto): + scratch_var = scoreboard_var("Global", func.get_scratch()) + scratch_var.copy_from(func, self) + return scratch_var diff --git a/variable_types/command_var.py b/variable_types/command_var.py index abbb932..31189e5 100644 --- a/variable_types/command_var.py +++ b/variable_types/command_var.py @@ -2,32 +2,35 @@ from .scoreboard_var import scoreboard_var from CompileError import CompileError + class command_var(var_base): - def __init__(self, output, command): - self.output = output - if command.startswith('/'): - command = command[1:] - self.command = command - - # Returns a scoreboard objective for this variable. - # If assignto isn't None, then this function may - # use the assignto objective to opimtize data flow. - def get_scoreboard_var(self, func, assignto=None): - if assignto == None: - assignto = scoreboard_var('Global', func.get_scratch()) - - func.add_command(f'execute store {self.output} score {assignto.get_selvar(func)} run {self.command}') - - return assignto - - # Returns a command that will get this variable's value to be used with "execute store result" - def get_command(self, func): - return self.command - - # Copies the value from a target variable to this variable - def copy_from(self, func, var): - raise CompileError('Cannot set the value of a command.') - - # Returns a scoreboard_var which can be modified as needed without side effects - def get_modifiable_var(self, func, assignto): - return self.get_scoreboard_var(func, assignto) \ No newline at end of file + def __init__(self, output, command): + self.output = output + if command.startswith("/"): + command = command[1:] + self.command = command + + # Returns a scoreboard objective for this variable. + # If assignto isn't None, then this function may + # use the assignto objective to opimtize data flow. + def get_scoreboard_var(self, func, assignto=None): + if assignto == None: + assignto = scoreboard_var("Global", func.get_scratch()) + + func.add_command( + f"execute store {self.output} score {assignto.get_selvar(func)} run {self.command}" + ) + + return assignto + + # Returns a command that will get this variable's value to be used with "execute store result" + def get_command(self, func): + return self.command + + # Copies the value from a target variable to this variable + def copy_from(self, func, var): + raise CompileError("Cannot set the value of a command.") + + # Returns a scoreboard_var which can be modified as needed without side effects + def get_modifiable_var(self, func, assignto): + return self.get_scoreboard_var(func, assignto) diff --git a/variable_types/scale_var.py b/variable_types/scale_var.py index 972dae2..64da61a 100644 --- a/variable_types/scale_var.py +++ b/variable_types/scale_var.py @@ -2,30 +2,31 @@ from variable_types.scoreboard_var import scoreboard_var from CompileError import CompileError + class scale_var(var_base): - def __init__(self): - None - - # Returns a scoreboard objective for this variable. - # If assignto isn't None, then this function may - # use the assignto objective to opimtize data flow. - def get_scoreboard_var(self, func, assignto=None): - return scoreboard_var(func.add_constant(func.scale), 'Constant') - - # Returns a command that will get this variable's value to be used with "execute store result" - def get_command(self, func): - return f'scoreboard players get Global {func.add_constant(func.scale)}' - - # Gets a constant integer value for this variable if there is one, otherwise returns None. - def get_const_value(self, func): - return func.scale - - # Copies the value from a target variable to this variable - def copy_from(self, func, var): - raise CompileError('Cannot set the value of the scale variable.') - - # Returns a scoreboard_var which can be modified as needed without side effects - def get_modifiable_var(self, func, assignto): - scratch_var = scoreboard_var('Global', func.get_scratch()) - scratch_var.copy_from(func, self) - return scratch_var \ No newline at end of file + def __init__(self): + None + + # Returns a scoreboard objective for this variable. + # If assignto isn't None, then this function may + # use the assignto objective to opimtize data flow. + def get_scoreboard_var(self, func, assignto=None): + return scoreboard_var(func.add_constant(func.scale), "Constant") + + # Returns a command that will get this variable's value to be used with "execute store result" + def get_command(self, func): + return f"scoreboard players get Global {func.add_constant(func.scale)}" + + # Gets a constant integer value for this variable if there is one, otherwise returns None. + def get_const_value(self, func): + return func.scale + + # Copies the value from a target variable to this variable + def copy_from(self, func, var): + raise CompileError("Cannot set the value of the scale variable.") + + # Returns a scoreboard_var which can be modified as needed without side effects + def get_modifiable_var(self, func, assignto): + scratch_var = scoreboard_var("Global", func.get_scratch()) + scratch_var.copy_from(func, self) + return scratch_var diff --git a/variable_types/scoreboard_var.py b/variable_types/scoreboard_var.py index 7fb5d6e..5e3cf7a 100644 --- a/variable_types/scoreboard_var.py +++ b/variable_types/scoreboard_var.py @@ -1,223 +1,241 @@ from variable_types.var_base import var_base + class scoreboard_var(var_base): - def __init__(self, selector, objective): - self.selector = selector - self.objective = objective - - def get_path(self, func): - if self.selector.startswith('@s'): - seldef = func.get_self_selector_definition() - else: - seldef = func.get_selector_definition(self.selector) - - if seldef != None: - if self.objective in seldef.paths: - return seldef.paths[self.objective] - - return None - - # Returns a scoreboard_var for this variable. - # If assignto isn't None, then this function may - # use the assignto objective to opimtize data flow. - def get_scoreboard_var(self, func, assignto=None): - path_data = self.get_path(func) - - if path_data: - if assignto == None: - assignto = scoreboard_var('Global', func.get_scratch()) - - assignto.copy_from(func, self) - - return assignto - else: - func.register_objective(self.objective) - - name_def = func.get_name_definition(self.selector) - if name_def != None: - return scoreboard_var(name_def, self.objective) - - return self - - def compile(self, func, assignto=None): - name_def = func.get_name_definition(self.selector) - if name_def != None: - return scoreboard_var(name_def, self.objective) - else: - return self - - # Returns a command that will get this variable's value to be used with "execute store result" - def get_command(self, func): - path_data = self.get_path(func) - if path_data: - path, data_type, scale = path_data - return f'data get entity {self.selector} {path} {scale}' - else: - func.register_objective(self.objective) - - selector = self.selector - name_def = func.get_name_definition(self.selector) - if name_def != None: - selector = name_def - - return f'scoreboard players get {selector} {self.objective}' - - # Returns an execute prefix that can be used to set this variable's value when paired with a get_command() command - def set_command(self, func): - path_data = self.get_path(func) - if path_data: - path, data_type, scale = path_data - return f'execute store result entity {self.selector} {path} {data_type} {1/float(scale)}' - else: - func.register_objective(self.objective) - - selector = self.selector - name_def = func.get_name_definition(self.selector) - if name_def != None: - selector = name_def - - return f'execute store result score {selector} {self.objective}' - - # Gets a constant integer value for this variable if there is one, otherwise returns None. - def get_const_value(self, func): - return None - - # Returns true if this variable is a scoreboard_var with the specified selector and objective, - # to reduce extranious copies. - def is_objective(self, func, selector, objective): - path_data = self.get_path(func) - - myselector = self.selector - name_def = func.get_name_definition(self.selector) - if name_def != None: - myselector = name_def - - if path_data == None and myselector == selector and self.objective == objective: - return True - else: - return False - - def same_as(self, func, var): - if var == None: - return False - - myselector = self.selector - name_def = func.get_name_definition(self.selector) - if name_def != None: - myselector = name_def - - return var.is_objective(func, myselector, self.objective) - - # Returns true if this varariable/expression references the specified scoreboard variable - def references_scoreboard_var(self, func, var): - return self.same_as(func, var) - - def is_fast_selector(self): - if not self.selector.startswith('@'): - return True - - if self.selector == '@s': - return True - - return False - - # Gets an assignto value for this variable if there is one. - def get_assignto(self, func): - path_data = self.get_path(func) - if path_data == None and self.is_fast_selector(): - func.register_objective(self.objective) - - return self - else: - return None - - # Copies the value from a target variable to this variable - def copy_from(self, func, var): - path_data = self.get_path(func) - - var_const = var.get_const_value(func) - - if path_data: - path, data_type, scale = path_data - - if var_const != None: - suffix = { - 'byte': 'b', - 'short': 's', - 'int': '', - 'long': 'L', - 'float': 'f', - 'double': 'd', - } - if data_type != 'float' and data_type != 'double': - val = int(var_const / scale) - else: - val = float(var_const) / float(scale) - - func.add_command(f'data modify entity {self.selector} {path} set value {val}{suffix[data_type]}') - else: - func.add_command(f'{self.set_command(func)} run {var.get_command(func)}') - else: - func.register_objective(self.objective) - - selector = self.selector - name_def = func.get_name_definition(self.selector) - if name_def != None: - selector = name_def - - if var_const != None: - func.add_command(f'scoreboard players set {selector} {self.objective} {var_const}') - elif not var.is_objective(func, selector, self.objective): - selvar = var.get_selvar(func) - - if selvar == None: - func.add_command(f'{self.set_command(func)} run {var.get_command(func)}') - else: - func.add_command(f'scoreboard players operation {selector} {self.objective} = {selvar}') - - # Returns a scoreboard_var which can be modified as needed without side effects - def get_modifiable_var(self, func, assignto): - path_data = self.get_path(func) - - if path_data: - return self.get_scoreboard_var(func, assignto) - else: - func.register_objective(self.objective) - - if self.selector == 'Global' and func.is_scratch(self.objective): - return self - elif self.same_as(func, assignto): - return self - else: - modifiable_var = scoreboard_var('Global', func.get_scratch()) - modifiable_var.copy_from(func, self) - - return modifiable_var - - # If this is a scratch variable, free it up - def free_scratch(self, func): - func.free_scratch(self.objective) - - def uses_macro(self, func): - return func.get_name_definition(self.selector) != None or "$(" in self.selector - - # Returns the selector and objective of this variable if it is a scoreboard_var, otherwise returns None - def get_selvar(self, func): - path_data = self.get_path(func) - if path_data: - return None - - func.register_objective(self.objective) - - name_def = func.get_name_definition(self.selector) - - if name_def != None: - return f'{name_def} {self.objective}' - else: - return f'{self.selector} {self.objective}' - - # This should only be used for scoreboard variables that are known to - # be Global - @property - def selvar(self): - return f'{self.selector} {self.objective}' + def __init__(self, selector, objective): + self.selector = selector + self.objective = objective + + def get_path(self, func): + if self.selector.startswith("@s"): + seldef = func.get_self_selector_definition() + else: + seldef = func.get_selector_definition(self.selector) + + if seldef != None: + if self.objective in seldef.paths: + return seldef.paths[self.objective] + + return None + + # Returns a scoreboard_var for this variable. + # If assignto isn't None, then this function may + # use the assignto objective to opimtize data flow. + def get_scoreboard_var(self, func, assignto=None): + path_data = self.get_path(func) + + if path_data: + if assignto == None: + assignto = scoreboard_var("Global", func.get_scratch()) + + assignto.copy_from(func, self) + + return assignto + else: + func.register_objective(self.objective) + + name_def = func.get_name_definition(self.selector) + if name_def != None: + return scoreboard_var(name_def, self.objective) + + return self + + def compile(self, func, assignto=None): + name_def = func.get_name_definition(self.selector) + if name_def != None: + return scoreboard_var(name_def, self.objective) + else: + return self + + # Returns a command that will get this variable's value to be used with "execute store result" + def get_command(self, func): + path_data = self.get_path(func) + if path_data: + path, data_type, scale = path_data + return f"data get entity {self.selector} {path} {scale}" + else: + func.register_objective(self.objective) + + selector = self.selector + name_def = func.get_name_definition(self.selector) + if name_def != None: + selector = name_def + + return f"scoreboard players get {selector} {self.objective}" + + # Returns an execute prefix that can be used to set this variable's value when paired with a get_command() command + def set_command(self, func): + path_data = self.get_path(func) + if path_data: + path, data_type, scale = path_data + return f"execute store result entity {self.selector} {path} {data_type} {1/float(scale)}" + else: + func.register_objective(self.objective) + + selector = self.selector + name_def = func.get_name_definition(self.selector) + if name_def != None: + selector = name_def + + return f"execute store result score {selector} {self.objective}" + + # Gets a constant integer value for this variable if there is one, otherwise returns None. + def get_const_value(self, func): + return None + + # Returns true if this variable is a scoreboard_var with the specified selector and objective, + # to reduce extranious copies. + def is_objective(self, func, selector, objective): + path_data = self.get_path(func) + + myselector = self.selector + name_def = func.get_name_definition(self.selector) + if name_def != None: + myselector = name_def + + if ( + path_data == None + and myselector == selector + and self.objective == objective + ): + return True + else: + return False + + def same_as(self, func, var): + if var == None: + return False + + myselector = self.selector + name_def = func.get_name_definition(self.selector) + if name_def != None: + myselector = name_def + + return var.is_objective(func, myselector, self.objective) + + # Returns true if this varariable/expression references the specified scoreboard variable + def references_scoreboard_var(self, func, var): + return self.same_as(func, var) + + def is_fast_selector(self): + if not self.selector.startswith("@"): + return True + + if self.selector == "@s": + return True + + return False + + # Gets an assignto value for this variable if there is one. + def get_assignto(self, func): + path_data = self.get_path(func) + if path_data == None and self.is_fast_selector(): + func.register_objective(self.objective) + + return self + else: + return None + + # Copies the value from a target variable to this variable + def copy_from(self, func, var): + path_data = self.get_path(func) + + var_const = var.get_const_value(func) + + if path_data: + path, data_type, scale = path_data + + if var_const != None: + suffix = { + "byte": "b", + "short": "s", + "int": "", + "long": "L", + "float": "f", + "double": "d", + } + if data_type != "float" and data_type != "double": + val = int(var_const / scale) + else: + val = float(var_const) / float(scale) + + func.add_command( + f"data modify entity {self.selector} {path} set value {val}{suffix[data_type]}" + ) + else: + func.add_command( + f"{self.set_command(func)} run {var.get_command(func)}" + ) + else: + func.register_objective(self.objective) + + selector = self.selector + name_def = func.get_name_definition(self.selector) + if name_def != None: + selector = name_def + + if var_const != None: + func.add_command( + f"scoreboard players set {selector} {self.objective} {var_const}" + ) + elif not var.is_objective(func, selector, self.objective): + selvar = var.get_selvar(func) + + if selvar == None: + func.add_command( + f"{self.set_command(func)} run {var.get_command(func)}" + ) + else: + func.add_command( + f"scoreboard players operation {selector} {self.objective} = {selvar}" + ) + + # Returns a scoreboard_var which can be modified as needed without side effects + def get_modifiable_var(self, func, assignto): + path_data = self.get_path(func) + + if path_data: + return self.get_scoreboard_var(func, assignto) + else: + func.register_objective(self.objective) + + if self.selector == "Global" and func.is_scratch(self.objective): + return self + elif self.same_as(func, assignto): + return self + else: + modifiable_var = scoreboard_var("Global", func.get_scratch()) + modifiable_var.copy_from(func, self) + + return modifiable_var + + # If this is a scratch variable, free it up + def free_scratch(self, func): + func.free_scratch(self.objective) + + def uses_macro(self, func): + return ( + func.get_name_definition(self.selector) != None + or "$(" in self.selector + ) + + # Returns the selector and objective of this variable if it is a scoreboard_var, otherwise returns None + def get_selvar(self, func): + path_data = self.get_path(func) + if path_data: + return None + + func.register_objective(self.objective) + + name_def = func.get_name_definition(self.selector) + + if name_def != None: + return f"{name_def} {self.objective}" + else: + return f"{self.selector} {self.objective}" + + # This should only be used for scoreboard variables that are known to + # be Global + @property + def selvar(self): + return f"{self.selector} {self.objective}" diff --git a/variable_types/selector_id_var.py b/variable_types/selector_id_var.py index 7646827..89fdbb9 100644 --- a/variable_types/selector_id_var.py +++ b/variable_types/selector_id_var.py @@ -2,45 +2,53 @@ from variable_types.scoreboard_var import scoreboard_var from CompileError import CompileError + class selector_id_var(var_base): - def __init__(self, selector): - self.selector = selector - - def initialize_id(self, func): - if not func.check_single_entity(self.selector): - raise CompileError(f'Selector "{self.selector}" does not specify an individual entity.') - - func.register_objective('_unique') - func.register_objective('_id') - func.add_command('scoreboard players add Global _unique 1') - func.add_command(f'execute unless score {self.selector} _id matches 1.. run scoreboard players operation {0} _id = Global _unique') - - # Returns a scoreboard objective for this variable. - # If assignto isn't None, then this function may - # use the assignto objective to opimtize data flow. - def get_scoreboard_var(self, func, assignto=None): - self.initialize_id(func) - return scoreboard_var(self.selector, '_id') - - # Returns a command that will get this variable's value to be used with "execute store result" - def get_command(self, func): - self.initialize_id(func) - return scoreboard_var(self.selector, '_id',).get_command(func) - - # Returns true if this variable is a scoreboard_var with the specified selector and objective, - # to reduce extranious copies. - def is_objective(self, func, selector, objective): - return selector == self.selector and objective == '_id' - - # Copies the value from a target variable to this variable - def copy_from(self, func, var): - id_scoreboard_var = scoreboard_var(self.selector, '_id') - id_scoreboard_var.copy_from(var) - - var.free_scratch(func) - - # Returns a scoreboard_var which can be modified as needed without side effects - def get_modifiable_var(self, func, assignto): - scratch_var = scoreboard_var('Global', func.get_scratch()) - scratch_var.copy_from(func, self) - return scratch_var + def __init__(self, selector): + self.selector = selector + + def initialize_id(self, func): + if not func.check_single_entity(self.selector): + raise CompileError( + f'Selector "{self.selector}" does not specify an individual entity.' + ) + + func.register_objective("_unique") + func.register_objective("_id") + func.add_command("scoreboard players add Global _unique 1") + func.add_command( + f"execute unless score {self.selector} _id matches 1.. run scoreboard players operation {0} _id = Global _unique" + ) + + # Returns a scoreboard objective for this variable. + # If assignto isn't None, then this function may + # use the assignto objective to opimtize data flow. + def get_scoreboard_var(self, func, assignto=None): + self.initialize_id(func) + return scoreboard_var(self.selector, "_id") + + # Returns a command that will get this variable's value to be used with "execute store result" + def get_command(self, func): + self.initialize_id(func) + return scoreboard_var( + self.selector, + "_id", + ).get_command(func) + + # Returns true if this variable is a scoreboard_var with the specified selector and objective, + # to reduce extranious copies. + def is_objective(self, func, selector, objective): + return selector == self.selector and objective == "_id" + + # Copies the value from a target variable to this variable + def copy_from(self, func, var): + id_scoreboard_var = scoreboard_var(self.selector, "_id") + id_scoreboard_var.copy_from(var) + + var.free_scratch(func) + + # Returns a scoreboard_var which can be modified as needed without side effects + def get_modifiable_var(self, func, assignto): + scratch_var = scoreboard_var("Global", func.get_scratch()) + scratch_var.copy_from(func, self) + return scratch_var diff --git a/variable_types/storage_path_var.py b/variable_types/storage_path_var.py index 1717ae0..a604efb 100644 --- a/variable_types/storage_path_var.py +++ b/variable_types/storage_path_var.py @@ -1,45 +1,52 @@ from variable_types.var_base import var_base from variable_types.scoreboard_var import scoreboard_var + class storage_path_var(var_base): - def __init__(self, target, path_name): - self.target = target - self.path_name = path_name - - # Returns a scoreboard objective for this variable. - # If assignto isn't None, then this function may - # use the assignto objective to opimtize data flow. - def get_scoreboard_var(self, func, assignto=None): - if assignto == None: - assignto = scoreboard_var('Global', func.get_scratch()) - - func.add_command(f'execute store result score {assignto.get_selvar(func)} run {self.get_command(func)}') - - return assignto - - def get_target(self, func): - if self.target == None: - return func.namespace - else: - return self.target - - # Returns a command that will get this variable's value to be used with "execute store result" - def get_command(self, func): - return f'data get storage {self.get_target(func)} {self.path_name} 1' - - # Copies the value from a target variable to this variable - def copy_from(self, func, var): - var_const = var.get_const_value(func) - - if var_const != None: - func.add_command(f'data modify storage {self.get_target(func)} {self.path_name} set value {var_const}') - else: - func.add_command(f'execute store result storage {self.get_target(func)} {self.path_name} int 1 run {var.get_command(func)}') - - var.free_scratch(func) - - # Returns a scoreboard_var which can be modified as needed without side effects - def get_modifiable_var(self, func, assignto): - scratch_var = scoreboard_var('Global', func.get_scratch()) - scratch_var.copy_from(func, self) - return scratch_var + def __init__(self, target, path_name): + self.target = target + self.path_name = path_name + + # Returns a scoreboard objective for this variable. + # If assignto isn't None, then this function may + # use the assignto objective to opimtize data flow. + def get_scoreboard_var(self, func, assignto=None): + if assignto == None: + assignto = scoreboard_var("Global", func.get_scratch()) + + func.add_command( + f"execute store result score {assignto.get_selvar(func)} run {self.get_command(func)}" + ) + + return assignto + + def get_target(self, func): + if self.target == None: + return func.namespace + else: + return self.target + + # Returns a command that will get this variable's value to be used with "execute store result" + def get_command(self, func): + return f"data get storage {self.get_target(func)} {self.path_name} 1" + + # Copies the value from a target variable to this variable + def copy_from(self, func, var): + var_const = var.get_const_value(func) + + if var_const != None: + func.add_command( + f"data modify storage {self.get_target(func)} {self.path_name} set value {var_const}" + ) + else: + func.add_command( + f"execute store result storage {self.get_target(func)} {self.path_name} int 1 run {var.get_command(func)}" + ) + + var.free_scratch(func) + + # Returns a scoreboard_var which can be modified as needed without side effects + def get_modifiable_var(self, func, assignto): + scratch_var = scoreboard_var("Global", func.get_scratch()) + scratch_var.copy_from(func, self) + return scratch_var diff --git a/variable_types/var_base.py b/variable_types/var_base.py index b3f60f0..6480bf3 100644 --- a/variable_types/var_base.py +++ b/variable_types/var_base.py @@ -1,52 +1,52 @@ # Base class for Minecraft variables. Each variable subclass must implement at least one of the get() functions. # If the variable is settable, it must implement set_value as well. class var_base(object): - # Returns a scoreboard objective for this variable. - # If assignto isn't None, then this function may - # use the assignto objective to opimtize data flow. - def get_scoreboard_var(self, func, assignto=None): - raise NotImplementedError() - - # Returns a command that will get this variable's value to be used with "execute store result" - def get_command(self, func): - raise NotImplementedError() - - # Gets a constant integer value for this variable if there is one, otherwise returns None. - def get_const_value(self, func): - return None - - # Returns true if this variable is a scoreboard_var with the specified selector and objective, - # to reduce extranious copies. - def is_objective(self, func, selector, objective): - return False - - # Gets an assignto value for this variable if there is one. - def get_assignto(self, func): - return None - - # Copies the value from a target variable to this variable - def copy_from(self, func, var): - raise NotImplementedError() - - # Returns a scoreboard_var which can be modified as needed without side effects - def get_modifiable_var(self, func, assignto): - raise NotImplementedError() - - # If this is a scratch variable, free it up - def free_scratch(self, func): - None - - def get_global_id(self): - return None - - # Returns the selector and objective of this variable if it is a scoreboard_var, otherwise returns None - def get_selvar(self, func): - return None - - # Returns true if this varariable/expression references the specified scoreboard variable - def references_scoreboard_var(self, func, var): - return False - - # Used to evaluate a variable as an expression - def compile(self, func, assignto=None): - return self \ No newline at end of file + # Returns a scoreboard objective for this variable. + # If assignto isn't None, then this function may + # use the assignto objective to opimtize data flow. + def get_scoreboard_var(self, func, assignto=None): + raise NotImplementedError() + + # Returns a command that will get this variable's value to be used with "execute store result" + def get_command(self, func): + raise NotImplementedError() + + # Gets a constant integer value for this variable if there is one, otherwise returns None. + def get_const_value(self, func): + return None + + # Returns true if this variable is a scoreboard_var with the specified selector and objective, + # to reduce extranious copies. + def is_objective(self, func, selector, objective): + return False + + # Gets an assignto value for this variable if there is one. + def get_assignto(self, func): + return None + + # Copies the value from a target variable to this variable + def copy_from(self, func, var): + raise NotImplementedError() + + # Returns a scoreboard_var which can be modified as needed without side effects + def get_modifiable_var(self, func, assignto): + raise NotImplementedError() + + # If this is a scratch variable, free it up + def free_scratch(self, func): + None + + def get_global_id(self): + return None + + # Returns the selector and objective of this variable if it is a scoreboard_var, otherwise returns None + def get_selvar(self, func): + return None + + # Returns true if this varariable/expression references the specified scoreboard variable + def references_scoreboard_var(self, func, var): + return False + + # Used to evaluate a variable as an expression + def compile(self, func, assignto=None): + return self diff --git a/variable_types/virtualint_var.py b/variable_types/virtualint_var.py index eb48534..43dcfd2 100644 --- a/variable_types/virtualint_var.py +++ b/variable_types/virtualint_var.py @@ -2,33 +2,36 @@ from variable_types.scoreboard_var import scoreboard_var from CompileError import CompileError + class virtualint_var(var_base): - def __init__(self, val): - self.val = val - - def get_value(self, func): - return int(func.apply_replacements(self.val)) - - # Returns a scoreboard objective for this variable. - # If assignto isn't None, then this function may - # use the assignto objective to opimtize data flow. - def get_scoreboard_var(self, func, assignto=None): - return scoreboard_var(func.add_constant(self.get_value(func)), 'Constant') - - # Returns a command that will get this variable's value to be used with "execute store result" - def get_command(self, func): - return f'scoreboard players get {func.add_constant(self.get_value(func))} Constant' - - # Gets a constant integer value for this variable if there is one, otherwise returns None. - def get_const_value(self, func): - return self.get_value(func) - - # Copies the value from a target variable to this variable - def copy_from(self, func, var): - raise CompileError('Cannot set the value of a constant.') - - # Returns a scoreboard_var which can be modified as needed without side effects - def get_modifiable_var(self, func, assignto): - scratch_var = scoreboard_var('Global', func.get_scratch()) - scratch_var.copy_from(func, self) - return scratch_var + def __init__(self, val): + self.val = val + + def get_value(self, func): + return int(func.apply_replacements(self.val)) + + # Returns a scoreboard objective for this variable. + # If assignto isn't None, then this function may + # use the assignto objective to opimtize data flow. + def get_scoreboard_var(self, func, assignto=None): + return scoreboard_var( + func.add_constant(self.get_value(func)), "Constant" + ) + + # Returns a command that will get this variable's value to be used with "execute store result" + def get_command(self, func): + return f"scoreboard players get {func.add_constant(self.get_value(func))} Constant" + + # Gets a constant integer value for this variable if there is one, otherwise returns None. + def get_const_value(self, func): + return self.get_value(func) + + # Copies the value from a target variable to this variable + def copy_from(self, func, var): + raise CompileError("Cannot set the value of a constant.") + + # Returns a scoreboard_var which can be modified as needed without side effects + def get_modifiable_var(self, func, assignto): + scratch_var = scoreboard_var("Global", func.get_scratch()) + scratch_var.copy_from(func, self) + return scratch_var diff --git a/vector_expressions/sel_vector_var_expr.py b/vector_expressions/sel_vector_var_expr.py index 921a52c..d6ecfd4 100644 --- a/vector_expressions/sel_vector_var_expr.py +++ b/vector_expressions/sel_vector_var_expr.py @@ -1,15 +1,18 @@ from variable_types.scoreboard_var import scoreboard_var + class sel_vector_var_expr(object): - def __init__(self, sel, id): - self.sel = sel - self.id = id - - def compile(self, func, assignto): - return_components = [] - for i in range(3): - return_components.append(scoreboard_var(self.sel, f'_{self.id}_{i}')) - - func.get_vector_path(self.sel, self.id) - - return return_components + def __init__(self, sel, id): + self.sel = sel + self.id = id + + def compile(self, func, assignto): + return_components = [] + for i in range(3): + return_components.append( + scoreboard_var(self.sel, f"_{self.id}_{i}") + ) + + func.get_vector_path(self.sel, self.id) + + return return_components diff --git a/vector_expressions/vector_binop_base.py b/vector_expressions/vector_binop_base.py index 28c8b0f..51bedc0 100644 --- a/vector_expressions/vector_binop_base.py +++ b/vector_expressions/vector_binop_base.py @@ -1,19 +1,23 @@ class vector_binop_base(object): - def __init__(self, lhs, op, rhs): - self.lhs = lhs - self.op = op - self.rhs = rhs - - def compile(self, func, assignto): - return_components = [] - - left_component_vars = self.lhs.compile(func, assignto) - if left_component_vars == None: - return None - - for i in range(3): - return_components.append(left_component_vars[i].get_modifiable_var(func, assignto[i] if assignto else None)) - - self.calc_op(func, return_components) - - return return_components \ No newline at end of file + def __init__(self, lhs, op, rhs): + self.lhs = lhs + self.op = op + self.rhs = rhs + + def compile(self, func, assignto): + return_components = [] + + left_component_vars = self.lhs.compile(func, assignto) + if left_component_vars == None: + return None + + for i in range(3): + return_components.append( + left_component_vars[i].get_modifiable_var( + func, assignto[i] if assignto else None + ) + ) + + self.calc_op(func, return_components) + + return return_components diff --git a/vector_expressions/vector_binop_scalar_expr.py b/vector_expressions/vector_binop_scalar_expr.py index cdb4a8f..66b246b 100644 --- a/vector_expressions/vector_binop_scalar_expr.py +++ b/vector_expressions/vector_binop_scalar_expr.py @@ -1,10 +1,13 @@ from .vector_binop_base import vector_binop_base + class vector_binop_scalar_expr(vector_binop_base): - def calc_op(self, func, return_components): - right_var = self.rhs.compile(func, None).get_scoreboard_var(func) - - for i in range(3): - func.add_command(f'scoreboard players operation {return_components[i].selector} {return_components[i].objective} {self.op}= {right_var.selector} {right_var.objective}') - - right_var.free_scratch(func) + def calc_op(self, func, return_components): + right_var = self.rhs.compile(func, None).get_scoreboard_var(func) + + for i in range(3): + func.add_command( + f"scoreboard players operation {return_components[i].selector} {return_components[i].objective} {self.op}= {right_var.selector} {right_var.objective}" + ) + + right_var.free_scratch(func) diff --git a/vector_expressions/vector_binop_vector_expr.py b/vector_expressions/vector_binop_vector_expr.py index 60cb0fc..8307274 100644 --- a/vector_expressions/vector_binop_vector_expr.py +++ b/vector_expressions/vector_binop_vector_expr.py @@ -1,14 +1,16 @@ from .vector_binop_base import vector_binop_base -from variable_types.scoreboard_var import scoreboard_var + class vector_binop_vector_expr(vector_binop_base): - def calc_op(self, func, return_components): - right_component_vars = self.rhs.compile(func, None) - - if right_component_vars == None: - return None - - for i in range(3): - right_var = right_component_vars[i].get_scoreboard_var(func) - func.add_command(f'scoreboard players operation {return_components[i].selector} {return_components[i].objective} {self.op}= {right_var.selector} {right_var.objective}') - right_component_vars[i].free_scratch(func) + def calc_op(self, func, return_components): + right_component_vars = self.rhs.compile(func, None) + + if right_component_vars == None: + return None + + for i in range(3): + right_var = right_component_vars[i].get_scoreboard_var(func) + func.add_command( + f"scoreboard players operation {return_components[i].selector} {return_components[i].objective} {self.op}= {right_var.selector} {right_var.objective}" + ) + right_component_vars[i].free_scratch(func) diff --git a/vector_expressions/vector_expr.py b/vector_expressions/vector_expr.py index c943fcb..c7a422a 100644 --- a/vector_expressions/vector_expr.py +++ b/vector_expressions/vector_expr.py @@ -1,15 +1,17 @@ class vector_expr(object): - def __init__(self, exprs): - self.exprs = exprs - - def compile(self, func, assignto): - vars = [] - for i in range(3): - var = self.exprs[i].compile(func, None if assignto == None else assignto[i]) - - if var == None: - return None - - vars.append(var) - - return vars + def __init__(self, exprs): + self.exprs = exprs + + def compile(self, func, assignto): + vars = [] + for i in range(3): + var = self.exprs[i].compile( + func, None if assignto == None else assignto[i] + ) + + if var == None: + return None + + vars.append(var) + + return vars diff --git a/vector_expressions/vector_here_expr.py b/vector_expressions/vector_here_expr.py index d98d699..eb17725 100644 --- a/vector_expressions/vector_here_expr.py +++ b/vector_expressions/vector_here_expr.py @@ -1,29 +1,34 @@ from variable_types.scoreboard_var import scoreboard_var + class vector_here_expr(object): - def __init__(self, scale): - self.scale = scale - - def compile(self, func, assignto): - if self.scale == None: - scale = func.scale - else: - scale = self.scale.get_value(func) - - func.register_objective('_age') - func.add_command('scoreboard players add @e _age 1') - func.add_command('summon area_effect_cloud') - func.add_command('scoreboard players add @e _age 1') - - return_components = [] - for i in range(3): - if assignto == None: - return_components.append(scoreboard_var('Global', func.get_scratch())) - else: - return_components.append(assignto[i]) - - func.add_command(f'execute store result score Global {return_components[i].objective} run data get entity @e[_age==1,limit=1] Pos[{i}] {scale}') - - func.add_command('/kill @e[_age==1]') - - return return_components + def __init__(self, scale): + self.scale = scale + + def compile(self, func, assignto): + if self.scale == None: + scale = func.scale + else: + scale = self.scale.get_value(func) + + func.register_objective("_age") + func.add_command("scoreboard players add @e _age 1") + func.add_command("summon area_effect_cloud") + func.add_command("scoreboard players add @e _age 1") + + return_components = [] + for i in range(3): + if assignto == None: + return_components.append( + scoreboard_var("Global", func.get_scratch()) + ) + else: + return_components.append(assignto[i]) + + func.add_command( + f"execute store result score Global {return_components[i].objective} run data get entity @e[_age==1,limit=1] Pos[{i}] {scale}" + ) + + func.add_command("/kill @e[_age==1]") + + return return_components diff --git a/vector_expressions/vector_var_const_vector.py b/vector_expressions/vector_var_const_vector.py index 2682623..976fc9a 100644 --- a/vector_expressions/vector_var_const_vector.py +++ b/vector_expressions/vector_var_const_vector.py @@ -1,18 +1,21 @@ from variable_types.virtualint_var import virtualint_var from CompileError import CompileError + class vector_var_const_vector(object): - def __init__(self, value): - self.value = value - - def compile(self, func, assignto): - components = self.value.get_value(func) - - vars = [] - try: - vars = [virtualint_var(int(components[i])) for i in range(3)] - except Exception as e: - print(e) - raise CompileError('Unable to get three components from constant vector expression.') - - return vars + def __init__(self, value): + self.value = value + + def compile(self, func, assignto): + components = self.value.get_value(func) + + vars = [] + try: + vars = [virtualint_var(int(components[i])) for i in range(3)] + except Exception as e: + print(e) + raise CompileError( + "Unable to get three components from constant vector expression." + ) + + return vars diff --git a/vector_expressions/vector_var_expr.py b/vector_expressions/vector_var_expr.py index b51eb1c..2d3b949 100644 --- a/vector_expressions/vector_var_expr.py +++ b/vector_expressions/vector_var_expr.py @@ -1,14 +1,15 @@ from variable_types.scoreboard_var import scoreboard_var + class vector_var_expr(object): - def __init__(self, vector_id): - self.vector_id = vector_id - - def compile(self, func, assignto): - return_components = [] - for i in range(3): - component_name = f'_{self.vector_id}_{i}' - return_components.append(scoreboard_var('Global', component_name)) - func.register_objective(component_name) - - return return_components + def __init__(self, vector_id): + self.vector_id = vector_id + + def compile(self, func, assignto): + return_components = [] + for i in range(3): + component_name = f"_{self.vector_id}_{i}" + return_components.append(scoreboard_var("Global", component_name)) + func.register_objective(component_name) + + return return_components