Skip to content

Commit

Permalink
Add partial support for custom GOL
Browse files Browse the repository at this point in the history
GOL colours don't sync yet. Also fix the simulation not being unpaused after a single-frame step.
  • Loading branch information
LBPHacker committed Jul 15, 2021
1 parent 6ad6932 commit 78d7240
Show file tree
Hide file tree
Showing 6 changed files with 169 additions and 41 deletions.
59 changes: 52 additions & 7 deletions tptmp/client/client.lua
Original file line number Diff line number Diff line change
Expand Up @@ -293,13 +293,7 @@ function client_i:handle_selecttool_37_()
local index = bit.rshift(tool, 14)
local xtype = bit.band(tool, 0x3FFF)
member[index_to_lrax[index]] = util.to_tool[xtype] and xtype or util.from_tool.TPTMP_PT_UNKNOWN
end

function client_i:handle_stepsim_50_()
local member = self:member_prefix_()
tpt.set_pause(1)
sim.framerender(1)
log_event(config.print_prefix .. colours.commonstr.event .. "Single-frame step from " .. member.formatted_nick)
member.last_toolslot = index
end

local simstates = {
Expand Down Expand Up @@ -464,6 +458,49 @@ function client_i:handle_rectstart_45_()
member.rect_x, member.rect_y = self:read_xy_12_()
end

function client_i:handle_custgolinfo_46_()
local member = self:member_prefix_()
local ruleset = bit.band(self:read_24be_(), 0x1FFFFF)
local primary = self:read_24be_()
local secondary = self:read_24be_()
local begin = bit.band(bit.rshift(ruleset, 8), 0x1FE)
local stay = bit.band(ruleset, 0x1FF)
local states = bit.band(bit.rshift(ruleset, 17), 0xF) + 2
local repr = {}
table.insert(repr, "B")
for i = 0, 8 do
if bit.band(bit.lshift(1, i), begin) ~= 0 then
table.insert(repr, i)
end
end
table.insert(repr, "/")
table.insert(repr, "S")
for i = 0, 8 do
if bit.band(bit.lshift(1, i), stay) ~= 0 then
table.insert(repr, i)
end
end
if states ~= 2 then
table.insert(repr, "/")
table.insert(repr, states)
end
member[index_to_lrax[member.last_toolslot]] = {
type = "cgol",
repr = table.concat(repr),
ruleset = ruleset,
primary = primary,
secondary = secondary,
elem = bit.bor(elem.DEFAULT_PT_LIFE, bit.lshift(ruleset, sim.PMAPBITS)),
}
end

function client_i:handle_stepsim_50_()
local member = self:member_prefix_()
tpt.set_pause(1)
sim.framerender(1)
log_event(config.print_prefix .. colours.commonstr.event .. "Single-frame step from " .. member.formatted_nick)
end

function client_i:handle_sparkclear_60_()
local member = self:member_prefix_()
tpt.reset_spark()
Expand Down Expand Up @@ -834,6 +871,14 @@ function client_i:send_rectstart(index, x, y)
self:write_flush_()
end

function client_i:send_custgolinfo(ruleset, primary, secondary)
self:write_("\46")
self:write_24be_(ruleset)
self:write_24be_(primary)
self:write_24be_(secondary)
self:write_flush_()
end

function client_i:send_stepsim()
self:write_flush_("\50")
end
Expand Down
7 changes: 6 additions & 1 deletion tptmp/client/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,11 @@ local function run()
[ 1 ] = " REPL",
[ 2 ] = " SDEL",
}
local function decode_rulestring(tool)
if tool.type == "cgol" then
return tool.repr
end
end
local function handle_tick()
local now = socket.gettime()
if should_reconnect_at and now >= should_reconnect_at then
Expand Down Expand Up @@ -192,7 +197,7 @@ local function run()
sx, sy = 0, 0
end
local tool = member.last_tool or member.tool_l
local tool_name = util.to_tool[tool] or "TPTMP_PT_UNKNOWN"
local tool_name = util.to_tool[tool] or decode_rulestring(tool) or "TPTMP_PT_UNKNOWN"
local tool_class = util.xid_class[tool]
if elem[tool_name] and tool ~= 0 then
local real_name = elem.property(elem[tool_name], "Name")
Expand Down
120 changes: 93 additions & 27 deletions tptmp/client/profile/vanilla.lua
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ local index_to_lrax = {
[ 2 ] = "tool_a_",
[ 3 ] = "tool_x_",
}
local index_to_lraxid = {
[ 0 ] = "tool_lid_",
[ 1 ] = "tool_rid_",
[ 2 ] = "tool_aid_",
[ 3 ] = "tool_xid_",
}
local toolwarn_tools = {
[ "DEFAULT_UI_PROPERTY" ] = "prop",
[ "DEFAULT_TOOL_CYCL" ] = "cycl",
Expand All @@ -24,14 +30,16 @@ local toolwarn_tools = {
[ "TPTMP_PT_UNKNOWN" ] = "unknown",
}
local toolwarn_messages = {
prop = "The PROP tool does not sync, you will have to use /sync",
cycl = "The CYCL tool does not sync, you will have to use /sync",
mix = "The MIX tool does not sync, you will have to use /sync",
ligh = "LIGH does not sync, you will have to use /sync",
stkm = "Stickmen do not sync, you will have to use /sync",
cbrush = "Custom brushes do not sync, you will have to use /sync",
ipcirc = "The old circle brush does not sync, you will have to use /sync",
unknown = "This custom element is not supported, please avoid using it while connected",
prop = "The PROP tool does not sync, you will have to use /sync",
cycl = "The CYCL tool does not sync, you will have to use /sync",
mix = "The MIX tool does not sync, you will have to use /sync",
ligh = "LIGH does not sync, you will have to use /sync",
stkm = "Stickmen do not sync, you will have to use /sync",
cbrush = "Custom brushes do not sync, you will have to use /sync",
ipcirc = "The old circle brush does not sync, you will have to use /sync",
unknown = "This custom element is not supported, please avoid using it while connected",
cgol = "This custom GOL type is not supported, please avoid using it while connected",
cgolcolor = "Custom GOL currently syncs without colours, use /sync to get colours across",
}

local log_event = print
Expand All @@ -44,6 +52,46 @@ while sim.signs[MAX_SIGNS + 1] do
MAX_SIGNS = MAX_SIGNS + 1
end

local function rulestring_bits(str)
local bits = 0
for i = 1, #str do
bits = bit.bor(bits, bit.lshift(1, str:byte(i) - 48))
end
return bits
end

local function get_custgolinfo(identifier)
-- * TODO[api]: add an api for this to tpt
local pref = io.open("powder.pref")
if not pref then
return
end
local pref_data = pref:read("*a")
pref:close()
local types = pref_data:match([=["Types"%s*:%s*%[([^%]]+)%]]=])
if not types then
return
end
for name, ruleset, primary, secondary in types:gmatch([["(%S+)%s+(%S+)%s+(%S+)%s+(%S+)"]]) do
if "DEFAULT_PT_LIFECUST_" .. name == identifier then
local begin, stay, states = ruleset:match("^B([1-8]+)/S([0-8]+)/([0-9]+)$")
if not begin then
begin, stay = ruleset:match("^B([1-8]+)/S([0-8]+)$")
states = "2"
end
states = tonumber(states)
states = states >= 2 and states <= 17 and states
ruleset = begin and stay and states and bit.bor(bit.lshift(rulestring_bits(begin), 8), rulestring_bits(stay), bit.lshift(states - 2, 17))
primary = tonumber(primary)
secondary = tonumber(secondary)
if ruleset and primary and secondary then
return ruleset, primary, secondary
end
break
end
end
end

local function get_sign_data()
local sign_data = {}
for i = 1, MAX_SIGNS do
Expand All @@ -60,13 +108,6 @@ local function get_sign_data()
return sign_data
end

local function tool_lrax()
return util.from_tool[tpt.selectedl ] or util.from_tool.TPTMP_PT_UNKNOWN,
util.from_tool[tpt.selectedr ] or util.from_tool.TPTMP_PT_UNKNOWN,
util.from_tool[tpt.selecteda ] or util.from_tool.TPTMP_PT_UNKNOWN,
util.from_tool[tpt.selectedreplace] or util.from_tool.TPTMP_PT_UNKNOWN
end

local function perfect_circle()
return sim.brush(1, 1, 1, 1, 0)() == 0
end
Expand Down Expand Up @@ -319,6 +360,17 @@ end
function profile_i:report_tool_(index)
if self.client then
self.client:send_selecttool(index, self[index_to_lrax[index]])
local identifier = self[index_to_lraxid[index]]
if identifier:find("^DEFAULT_PT_LIFECUST_") then
local ruleset, primary, secondary = get_custgolinfo(identifier)
if ruleset then
self.client:send_custgolinfo(ruleset, primary, secondary)
-- * TODO[api]: add an api for setting gol colour
self.display_toolwarn_["cgolcolor"] = true
else
self.display_toolwarn_["cgol"] = true
end
end
end
end

Expand Down Expand Up @@ -659,27 +711,37 @@ function profile_i:update_shape_()
end

function profile_i:update_tools_()
local tl, tr, ta, tx = tool_lrax()
if self.tool_l_ ~= tl then
self.tool_l_ = tl
local tlid = tpt.selectedl
local trid = tpt.selectedr
local taid = tpt.selecteda
local txid = tpt.selectedreplace
if self.tool_lid_ ~= tlid then
self.tool_l_ = util.from_tool[tlid] or util.from_tool.TPTMP_PT_UNKNOWN
self.tool_lid_ = tlid
self:report_tool_(0)
end
if self.tool_r_ ~= tr then
self.tool_r_ = tr
if self.tool_rid_ ~= trid then
self.tool_r_ = util.from_tool[trid] or util.from_tool.TPTMP_PT_UNKNOWN
self.tool_rid_ = trid
self:report_tool_(1)
end
if self.tool_a_ ~= ta then
self.tool_a_ = ta
if self.tool_aid_ ~= taid then
self.tool_a_ = util.from_tool[taid] or util.from_tool.TPTMP_PT_UNKNOWN
self.tool_aid_ = taid
self:report_tool_(2)
end
if self.tool_x_ ~= tx then
self.tool_x_ = tx
if self.tool_xid_ ~= txid then
self.tool_x_ = util.from_tool[txid] or util.from_tool.TPTMP_PT_UNKNOWN
self.tool_xid_ = txid
self:report_tool_(3)
end
local new_tool = util.to_tool[self[index_to_lrax[self.last_toolslot_]]]
local new_tool_id = self[index_to_lraxid[self.last_toolslot_]]
if self.last_tool_ ~= new_tool then
if toolwarn_tools[new_tool] then
self.display_toolwarn_[toolwarn_tools[new_tool]] = true
if not new_tool_id:find("^DEFAULT_PT_LIFECUST_") then
if toolwarn_tools[new_tool] then
self.display_toolwarn_[toolwarn_tools[new_tool]] = true
end
end
self.last_tool_ = new_tool
end
Expand Down Expand Up @@ -1154,6 +1216,7 @@ function profile_i:handle_keypress(key, scan, rep, shift, ctrl, alt)
end
end
self:report_framestep_()
self.simstate_invalid_ = true
elseif scan == sdl.SDL_SCANCODE_B and not ctrl then
self.simstate_invalid_ = true
elseif scan == sdl.SDL_SCANCODE_Y then
Expand Down Expand Up @@ -1311,7 +1374,10 @@ local function new(params)
clear = { x = gfx.WIDTH - 159, y = gfx.HEIGHT - 16, w = 17, h = 15 },
},
}, profile_m)
prof.tool_l_, prof.tool_r_, prof.tool_a_, prof.tool_x_ = tool_lrax()
prof.tool_l_ = util.from_tool.TPTMP_PT_UNKNOWN
prof.tool_r_ = util.from_tool.TPTMP_PT_UNKNOWN
prof.tool_a_ = util.from_tool.TPTMP_PT_UNKNOWN
prof.tool_x_ = util.from_tool.TPTMP_PT_UNKNOWN
prof.last_tool_ = prof.tool_l_
prof.deco_ = sim.decoColour()
prof:update_pos_(tpt.mousex, tpt.mousey)
Expand Down
21 changes: 16 additions & 5 deletions tptmp/client/util.lua
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ do
end

local tools = {
-- * TODO[api]: Could do something about custom GOL; would probably need an API for it first though.
"DEFAULT_PT_LIFE_GOL",
"DEFAULT_PT_LIFE_HLIF",
"DEFAULT_PT_LIFE_ASIM",
Expand Down Expand Up @@ -314,7 +313,10 @@ local function create_parts_any(x, y, rx, ry, xtype, brush, member)
sim.decoBrush(x, y, rx, ry, member.deco_r, member.deco_g, member.deco_b, member.deco_a, xtype - xid_first.DECOR, brush)
return
elseif class == "PT_LIFE" then
xtype = elem.DEFAULT_PT_LIFE + bit.lshift(xtype - xid_first.PT_LIFE, PMAPBITS)
xtype = bit.bor(elem.DEFAULT_PT_LIFE, bit.lshift(xtype - xid_first.PT_LIFE, PMAPBITS))
elseif type(xtype) == "table" and xtype.type == "cgol" then
-- * TODO[api]: add an api for setting gol colour
xtype = xtype.elem
end
local ov = create_override[xtype]
if ov then
Expand Down Expand Up @@ -410,7 +412,10 @@ local function create_line_any(x1, y1, x2, y2, rx, ry, xtype, brush, member, con
sim.decoLine(x1, y1, x2, y2, rx, ry, member.deco_r, member.deco_g, member.deco_b, member.deco_a, xtype - xid_first.DECOR, brush)
return
elseif class == "PT_LIFE" then
xtype = elem.DEFAULT_PT_LIFE + bit.lshift(xtype - xid_first.PT_LIFE, PMAPBITS)
xtype = bit.bor(elem.DEFAULT_PT_LIFE, bit.lshift(xtype - xid_first.PT_LIFE, PMAPBITS))
elseif type(xtype) == "table" and xtype.type == "cgol" then
-- * TODO[api]: add an api for setting gol colour
xtype = xtype.elem
end
local ov = create_override[xtype]
if ov then
Expand Down Expand Up @@ -442,7 +447,10 @@ local function create_box_any(x1, y1, x2, y2, xtype, member)
sim.decoBox(x1, y1, x2, y2, member.deco_r, member.deco_g, member.deco_b, member.deco_a, xtype - xid_first.DECOR)
return
elseif class == "PT_LIFE" then
xtype = elem.DEFAULT_PT_LIFE + bit.lshift(xtype - xid_first.PT_LIFE, PMAPBITS)
xtype = bit.bor(elem.DEFAULT_PT_LIFE, bit.lshift(xtype - xid_first.PT_LIFE, PMAPBITS))
elseif type(xtype) == "table" and xtype.type == "cgol" then
-- * TODO[api]: add an api for setting gol colour
xtype = xtype.elem
end
local _
local ov = create_override[xtype]
Expand Down Expand Up @@ -471,7 +479,10 @@ local function flood_any(x, y, xtype, part_flood_hint, wall_flood_hint, member)
elseif class == "DECOR" or class == "TOOL" then
return
elseif class == "PT_LIFE" then
xtype = elem.DEFAULT_PT_LIFE + bit.lshift(xtype - xid_first.PT_LIFE, PMAPBITS)
xtype = bit.bor(elem.DEFAULT_PT_LIFE, bit.lshift(xtype - xid_first.PT_LIFE, PMAPBITS))
elseif type(xtype) == "table" and xtype.type == "cgol" then
-- * TODO[api]: add an api for setting gol colour
xtype = xtype.elem
end
local _
local ov = create_override[xtype]
Expand Down
2 changes: 1 addition & 1 deletion tptmp/common/config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ return {
-- ***********************************************************************

-- * Protocol version, between 0 and 254. 255 is reserved for future use.
version = 19, -- * TODO[fin]: Give this a bump.
version = 20, -- * TODO[fin]: Give this a bump.

-- * Client-to-server message size limit, between 0 and 255, the latter
-- limit being imposted by the protocol.
Expand Down
1 change: 1 addition & 0 deletions tptmp/server/client.lua
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,7 @@ forward_to_room( "pointsstart", 42, 4)
forward_to_room( "pointscont", 43, 3)
forward_to_room( "linestart", 44, 4)
forward_to_room( "rectstart", 45, 4)
forward_to_room( "custgolinfo", 46, 9)
forward_to_room( "stepsim", 50, 0)
forward_to_room( "sparkclear", 60, 0)
forward_to_room( "airclear", 61, 0)
Expand Down

0 comments on commit 78d7240

Please sign in to comment.