Class: McBlocky::Executor

Inherits:
DSL::Commands show all
Defined in:
lib/mcblocky/executor.rb

Constant Summary

Constants inherited from DSL::Commands

DSL::Commands::COMMANDS

Instance Attribute Summary

Attributes inherited from DSL::Commands

#commands, #kind

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from DSL::Commands

#blockdata, #command, #detect, #execute, #gamerule, #initialize, #replaceitem, #scoreboard, #setblock, #tellraw, #title, #to_nbt

Constructor Details

This class inherits a constructor from McBlocky::DSL::Commands

Class Method Details

.to_commands(context, old_context = nil) ⇒ Object



3
4
5
6
7
# File 'lib/mcblocky/executor.rb', line 3

def self.to_commands(context, old_context=nil)
  executor = Executor.new(:final)
  executor.do_context(context, old_context)
  executor.commands
end

Instance Method Details

#do_block(block, old_block = nil) ⇒ Object



83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/mcblocky/executor.rb', line 83

def do_block(block, old_block=nil)
  if old_block and !block
    setblock old_block.x, old_block.y, old_block.z, 'minecraft:air'
    return
  end

  if old_block and old_block.block_kind == block.block_kind and old_block.block_data == block.block_data
    return if old_block.nbt == block.nbt
    blockdata block.x, block.y, block.z, block.nbt unless block.nbt == {}
  else
    setblock block.x, block.y, block.z, block.block_kind, block.block_data, 'replace'
    blockdata block.x, block.y, block.z, block.nbt unless block.nbt == {}
  end
end

#do_context(context, old_context) ⇒ Object



9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/mcblocky/executor.rb', line 9

def do_context(context, old_context)
  # do cleanup first
  if old_context
    old_context.chains.select{|x|x.kind == :cleanup}.each do |c|
      self.commands += c.commands
    end
  end

  # do initial blocks
  old_initials = old_context ? old_context.chains.select{|x|x.kind == :initial} : []
  initials = context.chains.select{|x|x.kind == :initial}
  initials.each_with_index do |chain, i|
    old_chain = old_initials[i]
    if old_chain
      matches = true
      chain.commands.each_with_index do |cmd, j|
        if matches
          old_cmd = old_chain.commands[j]
          next if old_cmd == cmd
          matches = false
          command cmd
        else
          command cmd
        end
      end
    else
      chain.commands.each {|cmd| command cmd}
    end
  end

  if old_context
    old_context.areas.each do |x1, y1, z1, x2, y2, z2|
      fill x1, y1, z1, x2, y2, z2, 'minecraft:air'
    end
  end
  context.areas.each do |x1, y1, z1, x2, y2, z2|
    fill x1, y1, z1, x2, y1, z2, 'minecraft:stained_glass', '7'
    fill x1, y2, z1, x2, y2, z2, 'minecraft:stained_glass', '7'
    fill x1, y1, z1, x1, y2, z2, 'minecraft:stained_glass', '7'
    fill x2, y1, z1, x2, y2, z2, 'minecraft:stained_glass', '7'
    fill x1, y1, z1, x2, y2, z1, 'minecraft:stained_glass', '7'
    fill x1, y1, z2, x2, y2, z2, 'minecraft:stained_glass', '7'
  end

  rects = (old_context ? old_context.rects.keys : []) + context.rects.keys
  rects.uniq.each do |rect|
    old_block = old_context ? old_context.rects[rect] : nil
    block = context.rects[rect]
    if old_block and !block
      fill rect.x1, rect.y1, rect.z1, rect.x2, rect.y2, rect.z2, 'minecraft:air'
    elsif old_block and old_block != block
      fill rect.x1, rect.y1, rect.z1, rect.x2, rect.y2, rect.z2, block.block_kind, block.block_data, 'replace', old_block.block_kind, old_block.block_data
    else
      fill rect.x1, rect.y1, rect.z1, rect.x2, rect.y2, rect.z2, block.block_kind, block.block_data
    end
  end

  context.chains.select{|x|x.kind == :repeat}.each do |c|
    do_repeat context, c
  end

  locations = (old_context ? old_context.blocks.keys : []) + context.blocks.keys
  locations.uniq.each do |loc|
    old = old_context ? old_context.blocks[loc] : nil
    new = context.blocks[loc]
    do_block(new, old)
  end

  # after blocks are set
  context.chains.select{|x|x.kind == :after}.each do |c|
    self.commands += c.commands
  end
end

#do_repeat(context, chain) ⇒ Object



98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# File 'lib/mcblocky/executor.rb', line 98

def do_repeat(context, chain)
  sequence = fill_space(chain.rect)
  if chain.commands.length > sequence.length
    raise ArgumentError, "Chain is too long for the provided space"
  end
  kind = 'minecraft:repeating_command_block'
  chain.commands.each_with_index do |c,i|
    cursor = sequence[i]
    next_cursor = if i+1 < sequence.length
                    sequence[i+1]
                  else
                    Location.new(cursor.x, cursor.y+1, cursor.z)
                  end
    facing = if next_cursor.x - cursor.x == 1
               DSL::Facing::EAST
             elsif next_cursor.x - cursor.x == -1
               DSL::Facing::WEST
             elsif next_cursor.y - cursor.y == 1
               DSL::Facing::UP
             elsif next_cursor.y - cursor.y == -1
               DSL::Facing::DOWN
             elsif next_cursor.z - cursor.z == 1
               DSL::Facing::SOUTH
             elsif next_cursor.z - cursor.z == -1
               DSL::Facing::NORTH
             end
    context.blocks[cursor] = DSL::CommandBlock.new(cursor.x, cursor.y, cursor.z, facing, kind, {'auto'=>1})
    context.blocks[cursor].command c
    kind = 'minecraft:chain_command_block'
  end
end

#fill_space(rect) ⇒ Object



130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
# File 'lib/mcblocky/executor.rb', line 130

def fill_space(rect)
  path = []
  zrange = rect.z1..rect.z2
  zrange.each do |z|
    rz = z - rect.z1
    yrange = rect.y1..rect.y2
    yrange = yrange.to_a.reverse if rz % 2 != 0
    yrange.each do |y|
      ry = y - rect.y1
      xrange = rect.x1..rect.x2
      xrange = xrange.to_a.reverse if (ry+rz) % 2 != 0
      xrange.each do |x|
        path << Location.new(x, y, z)
      end
    end
  end
  path
end