Gameplay scripter on Jet Simulator, a pets and progression simulator. Building server-authoritative systems on a Knit + ProfileStore stack: the nametag system, startup resilience and error handling, and anti-exploit hardening across the codebase.
I design and ship across the stack: 3D and product visuals in Blender, fast interactive web, and game systems that hold up under load. Architecture, motion and craft, verified end to end.
Most people ship features. I build interfaces, 3D, and systems that are crafted, performant, and tested until they cannot break.
Not isolated scripts. Cohesive systems with clean boundaries, deterministic tests, and zero trust in the client.
Active scripting roles on live Roblox games with real players and deadlines, not just personal builds. Server-authoritative systems, shipped on a team.
Gameplay scripter on Jet Simulator, a pets and progression simulator. Building server-authoritative systems on a Knit + ProfileStore stack: the nametag system, startup resilience and error handling, and anti-exploit hardening across the codebase.
Programmer on Team C inside Playverse, a large multi-game Roblox group. Building and maintaining gameplay systems across the team's live titles, including Guess My Brainrot, Guess My Anime and Hack a Hive.
Server authority, determinism, persistence and tooling. Built the way a studio ships, not the way a tutorial teaches.
Procedurally generated, fully self-playing. Simulation core decoupled from rendering, so the same logic drives a headless test or a live 3D view.
Server-authoritative combat. The client may only request; the server validates everything and stays exploit-proof.
OOP inventory framework with a full item hierarchy, stacking and weight rules, and clean serialization.
Production persistence with session locking, so two servers can never corrupt the same save.
A component library built for responsiveness and disciplined cleanup, scaling to any screen.
A self-cleaning effects library on TweenService: the feedback layer a game needs.
A tower-defense engine built from scratch where the simulation core is fully decoupled from rendering, so the exact same logic drives a headless CI test and a live 3D match. The goal was to prove a Roblox game can be engineered like real software: deterministic, tested and observable.
Roblox gameplay code usually tangles simulation with rendering, so it cannot be unit tested and balance regressions ship silently. I wanted a game I could prove correct, not play once and hope.
The core is pure Luau with no Instance or rendering access: grid, enemies, towers, economy and waves are plain data and classes. Maps generate from a seed, towers are polymorphic (splash, slow, burn, execute), enemies carry armor and resistances, and an AI commander plays the whole match headlessly.
The same core runs in a headless harness and behind the live 3D view. 25 of 25 self-play matches finish with zero runtime errors, so a balance change is re-validated before it reaches a player. Determinism made the bugs reproducible and the design tunable.
An open-source uptime and status monitoring platform, built solo in Next.js and TypeScript. Scheduled health checks, automatic incident tracking, response-time charts, and shareable public status pages, live and deployed with green CI.
Monitors websites and APIs on a schedule, records status code and response time on every check, opens and resolves incidents automatically, and serves shareable public status pages. Secure session auth, a Postgres data layer via Prisma, and a cron-driven check engine. Open source under AGPL, with CI on every push.
Game logic is Luau; the web stack is TypeScript end to end. A few representative slices: client/server reconciliation, a typed and validated API boundary, and an optimistic React data hook.
-- Client predicts locally, then reconciles to the server snapshot,
-- replaying un-acked inputs so a correction never feels like a snap.
local RING = 128 -- input history ring buffer
local function reconcile(serverSnap, pending)
local state = clone(serverSnap) -- authoritative truth
local drift = distance(state.pos, render.pos)
if drift > HARD_SNAP then render = clone(state) end -- teleport / respawn
for _, cmd in ipairs(pending) do -- inputs not yet acked
if cmd.seq > serverSnap.lastSeq then
state = step(state, cmd, FIXED_DT) -- deterministic re-sim
end
end
local a = math.min(1, dt / FIXED_DT)
render = lerp(render, state, a) -- smooth, no rubber-banding
return render
end
-- Pack a world delta into BITS, not bytes. A position + id costs ~5B.
function BitBuffer:writeUInt(value, bits)
for _ = 1, bits do
self.acc = bit32.bor(self.acc, bit32.lshift(value % 2, self.n))
value, self.n = value // 2, self.n + 1
if self.n == 8 then self.bytes[#self.bytes+1], self.acc, self.n = self.acc, 0, 0 end
end
end
function BitBuffer:writeVarInt(v) -- 7 bits + continue flag
repeat local b = v % 128; v = v // 128; self:writeUInt(v > 0 and b+128 or b, 8) until v == 0
end
-- Archetype ECS: entities grouped by component signature for
-- cache-friendly iteration. A query is a bitmask test, not a lookup.
local mask = Component.Position | Component.Velocity
for _, arch in ipairs(world.archetypes) do
if bit32.band(arch.signature, mask) == mask then
local pos, vel = arch.cols.Position, arch.cols.Velocity
for i = 1, arch.count do
pos[i] = pos[i] + vel[i] * dt -- tight contiguous loop
end
end
end
-- Server rewinds every player to the shooter's render time,
-- so a hit that looked true on the client is validated fairly.
local function validateShot(shooter, origin, dir, clientTime)
local t = clamp(clientTime, now - MAX_REWIND, now)
for _, target in ipairs(candidates(origin, dir)) do
local box = rewindHitbox(target, t) -- historical position
local hit, dist = rayBox(origin, dir, box)
if hit and dist <= weapon.range then
if not lineOfSight(origin, box.center) then continue end
local dmg = falloff(weapon, dist) * zoneMul(box.part)
return { ok = true, id = target.id, dmg = dmg }
end
end
return { ok = false } -- reject; never trust the client
end
// POST /api/match/:id/score - typed, validated, authenticated.
// One DB transaction: never half-write a leaderboard row.
const Body = z.object({ score: z.number().int().min(0), runId: z.string().uuid() });
export const submitScore: Handler = async (req, reply) => {
const user = await requireUser(req); // 401 if no valid session
const body = Body.parse(req.body); // 400 on bad shape
const match = await db.match.findUnique({ where: { id: req.params.id } });
if (!match || match.ownerId !== user.id) return reply.code(403).send();
return db.$transaction(async (tx) => {
await tx.score.upsert({
where: { runId: body.runId }, // idempotent on retry
create: { runId: body.runId, userId: user.id, value: body.score },
update: { value: body.score },
});
const rank = await tx.score.count({ where: { value: { gt: body.score } } });
return reply.send({ ok: true, rank: rank + 1 });
});
};
// Optimistic React hook: paint the guess instantly, reconcile to the
// server, and roll back cleanly if the socket rejects the write.
export function useLiveQuery<T>(key: string, initial: T) {
const [data, setData] = useState<T>(initial);
const socket = useSocket();
useEffect(() => socket.subscribe(key, setData), [key]); // server is truth
const mutate = useCallback(async (next: T) => {
const prev = data;
setData(next); // optimistic paint
try {
await socket.send(key, next); // await server ack
} catch {
setData(prev); // rollback on reject
}
}, [key, data]);
return [data, mutate] as const;
}
Seven buildings on a shared downtown block, modeled from primitives with distinct PBR materials (warm concrete, sandstone, red brick and tinted curtain-wall glass), recessed windows and rooftop plant, lit by a low golden-hour sun. Rendered in Blender (Cycles).
BLENDER · CYCLES


Nine weapons modeled from scratch with real proportions and beveled edges, in PBR steel, gunmetal, brass, leather and wood, rendered top-down in Cycles as a clean inventory sheet. Hover any name to inspect it, or click the frame for the full set.
Double-edged steel blade, brass crossguard and pommel, leather-wrapped grip.
Server-authoritative Luau built for scale, area-of-interest replication, flow-field pathfinding for thousands of agents, and a deterministic procedural dungeon generator. The fortress below is key art for that world, modeled and lit in Blender (Cycles).

One Dijkstra pass per goal feeds an O(1) per-agent lookup, so thousands of units share a single field instead of each running A*.
-- Thousands of agents, ONE
-- shared field. Dijkstra from
-- the goal; each agent just
-- reads the downhill slope.
while #heap > 0 do
local i, c = pop()
for _, n in ipairs(DIRS) do
local nc = c + cost[n] * n.w
if nc < integ[n] then
integ[n] = nc
push(n, nc)
end
end
end
Entities live only on the server. Each player gets spawn / despawn / delta updates for what is inside their interest radius, via a spatial hash.
-- Relevancy is ~O(nearby),
-- never O(all entities).
for dx = -span, span do
for dz = -span, span do
local b = cells[key(cx+dx, cz+dz)]
if b then
for id in pairs(b) do
if within(id, p) then
now[id] = true
end
end
end
end
end
A seedable LCG rebuilds the exact same dungeon on the server and every client. Rooms are linked by an MST of L-shaped corridors.
-- One seed, same dungeon
-- everywhere (Park-Miller).
local rand = rng(opts.seed)
for _ = 1, maxRooms * 6 do
local r = randomRoom(rand)
if not overlaps(r, rooms) then
carve(grid, r)
rooms[#rooms+1] = r
end
end
connectMST(rooms, grid)
Hand-built Canvas 2D particle system, no library. The cursor repels the field and weaves cyan links to nearby nodes in real time.
Raw requestAnimationFrame · mouse-reactive · 60fps