-
Notifications
You must be signed in to change notification settings - Fork 0
/
plot.lua
144 lines (135 loc) · 3.37 KB
/
plot.lua
1
2
3
4
5
6
7
8
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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
local strict = require("spaghetti-lite.strict")
strict.wrap_env()
local build = require("spaghetti-lite.build")
local bitx = require("spaghetti-lite.bitx")
local misc = require("spaghetti-lite.misc")
local check = require("spaghetti-lite.check")
local audited_pairs = pairs
local in_tpt = rawget(_G, "tpt") and true
local elem_mt = {}
function elem_mt:__tostring()
return ("pt.%s"):format(self.key)
end
local pt = setmetatable({}, { __index = function(tbl, key)
if in_tpt then
return elem["DEFAULT_PT_" .. key]
end
local value = setmetatable({ key = key }, elem_mt)
rawset(tbl, key, value)
return value
end })
local function apply_order(parts_in)
local parts = {}
for i = 1, #parts_in do
parts[i] = {}
for key, value in audited_pairs(parts_in[i]) do
parts[i][key] = value
end
parts[i].z = parts[i].z or i
end
table.sort(parts, function(lhs, rhs)
if lhs.y ~= rhs.y then return lhs.y < rhs.y end
if lhs.x ~= rhs.x then return lhs.x < rhs.x end
if lhs.z ~= rhs.z then return lhs.z < rhs.z end
return false
end)
for i = 1, #parts do
parts[i].z = nil
end
return parts
end
local function merge_parts(x, y, parts_out, parts_in)
return misc.user_wrap(function()
check.integer("x", x)
check.integer("y", y)
local parts = apply_order(parts_in)
for i = 1, #parts do
parts[i].x = parts[i].x + x
parts[i].y = parts[i].y + y
table.insert(parts_out, parts[i])
end
return parts_out
end)
end
local function create_parts_(x, y, parts_in, debug)
check.integer("x", x)
check.integer("y", y)
local parts = apply_order(parts_in)
for i = 1, #parts do
parts[i].x = parts[i].x + x
parts[i].y = parts[i].y + y
if parts[i].ctype_high then
parts[i].ctype = bitx.bor(parts[i].ctype, bitx.lshift(parts[i].ctype_high, sim.PMAPBITS))
end
end
do
local new_parts = {}
local parts_by_pos = {}
local function xy_key(x, y)
return y * sim.XRES + x
end
for _, part in ipairs(parts) do
local key = xy_key(part.x, part.y)
local insert = true
if parts_by_pos[key] then
if part.unstack then
insert = false
end
else
parts_by_pos[key] = part
end
if insert then
table.insert(new_parts, part)
end
end
parts = new_parts
end
local ids = {}
for i = 1, #parts do
local id = sim.partCreate(-3, 4, 4, pt.DMND)
if id == -1 then
for j = 1, i - 1 do
sim.partKill(ids[j])
end
error("out of particle ids", 2)
end
ids[i] = id
end
table.sort(ids)
local function xy_key(x, y)
return y * sim.XRES + x
end
local function xy_key_back(k)
return k % sim.XRES, math.floor(k / sim.XRES)
end
local count_at = {}
for i = 1, #parts do
if debug and parts[i].print_index then
print("layer_last", ids[i])
end
sim.partProperty(ids[i], "type", parts[i].type)
for key, value in audited_pairs(parts[i]) do
if sim["FIELD_" .. key:upper()] and key ~= "type" then
sim.partProperty(ids[i], key, value)
end
end
local key = xy_key(parts[i].x, parts[i].y)
count_at[key] = (count_at[key] or 0) + 1
end
for key, value in audited_pairs(count_at) do
if value > 5 then
local x, y = xy_key_back(key)
sim.createWalls(x, y, 1, 1, sim.walls.DEFAULT_WL_EHOLE)
end
end
end
local function create_parts(x, y, parts_in, debug)
return misc.user_wrap(function()
return create_parts_(x, y, parts_in, debug)
end)
end
return {
pt = pt,
create_parts = create_parts,
merge_parts = merge_parts,
}