Skip to content

Commit cfc767d

Browse files
committed
feat(demos): add Clicker chat example; Tetris mod frames its own camera
The Tetris chat example rendered a correct board but never repositioned the host scene's Main Camera, so the game fell outside the view and looked inert. It now drops the camera in front of its board on load. Added a second ready-to-run example, Clicker (idle/clicker: click the golden cube, passive income stacks gold coins, r resets), so chat can spawn more than one playable game. Both stay parse-gated on the real Lua VM (new ClickerExample_LuaParses). Bump all CoreAI packages 6.0.0 -> 6.1.0.
1 parent 7cc0a79 commit cfc767d

9 files changed

Lines changed: 115 additions & 6 deletions

File tree

Assets/CoreAI/CHANGELOG.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,23 @@
11
# Changelog
22

3+
## [6.1.0] - 2026-07-23
4+
5+
### Added
6+
7+
- New built-in chat example **Clicker game** (`CoreAiChatExamples`): a ready-to-run Lua idle/clicker
8+
mod (left-click the golden cube to earn points, every 10 stacks a gold coin, passive income keeps it
9+
growing unattended, `r` resets) alongside the existing Tetris one. Both are "create a mod named X
10+
with this code and load it" prompts, so the Programmer agent only has to wrap the given code in a
11+
`manage_mods` call — the deterministic path that actually renders a playable game from chat. A
12+
parse-gate EditMode test (`ClickerExample_LuaParses`) validates the Lua on the real VM.
13+
14+
### Changed
15+
16+
- The Tetris chat-example mod now frames the scene itself: on load it drops the `Main Camera` straight
17+
in front of its board (`coreai_world_change('Main Camera', ...)`). WHY: the mod rendered correctly
18+
but the host scene's camera was left pointing elsewhere, so the board fell outside the view and the
19+
game looked like it "did nothing". A mod that builds a game should own the shot that shows it.
20+
321
## [6.0.0] - 2026-07-22
422

523
### Removed

Assets/CoreAI/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "com.neoxider.coreai",
3-
"version": "6.0.0",
3+
"version": "6.1.0",
44
"displayName": "CoreAI",
55
"unity": "6000.0",
66
"description": "Portable C# core for CoreAI \u2014 LLM agents that call your game code. Orchestration, function-calling tools, agent memory, AgentBuilder, SkillSet, and production resilience (retries, timeouts, rate limits), with no UnityEngine dependency. LLM and Lua are optional modules (COREAI_NO_LLM / COREAI_NO_LUA), so the core compiles without them \u2014 install only what your game uses. Unity integration ships in com.neoxider.coreaiunity.",

Assets/CoreAIBenchmark/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "com.neoxider.coreaibenchmark",
3-
"version": "6.0.0",
3+
"version": "6.1.0",
44
"displayName": "CoreAI Benchmark",
55
"unity": "6000.0",
66
"description": "LLM game-creation benchmark harness and scenarios for CoreAI: drives execute_lua and world_command through real PlayMode scenarios (G1-G8), grades tool correctness, reasoning, instruction adherence, and determinism, and reports suite/role fitness scores. Depends on com.neoxider.coreai / com.neoxider.coreaiunity / com.neoxider.coreaimods.",

Assets/CoreAIHub/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "com.neoxider.coreaihub",
3-
"version": "6.0.0",
3+
"version": "6.1.0",
44
"displayName": "CoreAI Hub (UI Toolkit)",
55
"unity": "6000.0",
66
"description": "Optional UI Toolkit window for CoreAI: a tabbed Hub that renders pages registered into CoreAI's HubPageRegistry (Chat, Settings, Statistics, Mods, and C#/Lua-authored pages). Lazy per-tab content, live tab rebuild on register/unregister, semi-transparent runtime panel, and a future path to Unity 6.5 world-space PanelRenderer. Install this package only when you want the built-in Hub window; without it CoreAI still exposes the registry so you can render pages on your own uGUI/UITK canvas via the API. Depends on com.neoxider.coreai.",

Assets/CoreAIMcp/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "com.neoxider.coreaimcp",
3-
"version": "6.0.0",
3+
"version": "6.1.0",
44
"displayName": "CoreAI MCP Server",
55
"unity": "6000.0",
66
"description": "Optional Model Context Protocol (MCP) server that runs INSIDE a live CoreAI game session (play mode or a build) so an external agent - Claude Code and any other MCP client - can drive the running game over a standard protocol. Exposes the in-game Command Bar surface (execute_lua, manage_mods, get_mod_logs, and, when present, world_command + screenshot) as MCP tools over localhost streamable HTTP. Off by default: drop a CoreAiMcpServer component into a scene (or call CoreAiMcpServer.StartServer). Localhost-only, opt-in, no auth - never expose beyond loopback. Depends on com.neoxider.coreaimods; world/screenshot tools register only when those services exist in the current composition.",

Assets/CoreAIMods/Tests/EditMode/CoreAiChatExamplesEditModeTests.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,12 @@ public void TetrisExample_LuaParses()
4949
AssertExampleLuaParses("tetris");
5050
}
5151

52+
[Test]
53+
public void ClickerExample_LuaParses()
54+
{
55+
AssertExampleLuaParses("clicker");
56+
}
57+
5258
[Test]
5359
public void ArenaExample_LuaParses()
5460
{

Assets/CoreAIMods/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "com.neoxider.coreaimods",
3-
"version": "6.0.0",
3+
"version": "6.1.0",
44
"displayName": "CoreAI Mods (Lua)",
55
"unity": "6000.0",
66
"description": "Lua modding layer for CoreAI: the Lua-CSharp sandbox (managed, AOT-safe, WebGL/IL2CPP-ready — bundled, no external package), execute_lua and manage_mods tools, the Lua Modding skill, the mod runtime, persistent mod stores, gameplay bindings, and mod UI. Depends on com.neoxider.coreai / com.neoxider.coreaiunity. Install this package only when you want AI/player-authored Lua mods; without it CoreAI compiles Lua-free.",

Assets/CoreAiUnity/Runtime/Source/Features/Chat/CoreAiChatExamples.cs

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ public static class CoreAiChatExamples
4040
"Create a mod named tetris with this code and load it:\n" +
4141
"```lua\n" + TetrisLua + "```";
4242

43+
private const string ClickerMessage =
44+
"Create a mod named clicker with this code and load it:\n" +
45+
"```lua\n" + ClickerLua + "```";
46+
4347
private const string CastleMessage =
4448
"Build the most impressive castle you can within the -9..9 build volume (one Unity unit = one " +
4549
"meter, y is height, ground at y=0). Use the world_command tool: action='spawn', a DISTINCT " +
@@ -62,6 +66,7 @@ public static class CoreAiChatExamples
6266
private static readonly CoreAiChatExample[] Examples =
6367
{
6468
new("tetris", "Tetris mod", TetrisMessage),
69+
new("clicker", "Clicker game", ClickerMessage),
6570
new("castle", "Build a castle", CastleMessage),
6671
new("arena", "Fix the broken arena", ArenaMessage),
6772
};
@@ -200,6 +205,12 @@ local function start_game()
200205
store_set('tetris_started', '1')
201206
end
202207
208+
-- Frame the board: drop the Main Camera straight in front of the grid so the game is always on
209+
-- screen no matter where the host scene left the camera.
210+
if coreai_world_exists('Main Camera') then
211+
coreai_world_change('Main Camera', { x = 0, y = 0, z = -22, rx = 0, ry = 0, rz = 0 })
212+
end
213+
203214
spawn_grid()
204215
start_game()
205216
@@ -229,6 +240,80 @@ local function start_game()
229240
230241
render()
231242
end)
243+
";
244+
245+
// A tiny idle/clicker game: left-click the golden cube to earn points, every 10 points stacks a
246+
// gold coin into a tower, a passive +1/0.5s keeps it alive unattended, and 'r' resets. Uses only
247+
// documented globals (input_mouse_button / input_key_down, coreai_world_*, store_*, report).
248+
private const string ClickerLua =
249+
@"local BTN = 'clicker_button'
250+
local MAX_COINS = 24
251+
local score = tonumber(store_get('clicker_score')) or 0
252+
local coins = 0
253+
local pulse = 0
254+
local was_down = false
255+
256+
-- Frame the scene on the button so the game is always visible in the host scene.
257+
if coreai_world_exists('Main Camera') then
258+
coreai_world_change('Main Camera', { x = 0, y = 2, z = -12, rx = 6, ry = 0, rz = 0 })
259+
end
260+
261+
coreai_world_spawn({ prefab = 'cube', name = BTN, x = 0, y = 2, z = 0, scaleX = 1.5, scaleY = 1.5, scaleZ = 1.5 })
262+
coreai_world_set_color(BTN, '#FFC400')
263+
264+
local function coin_name(i) return 'clicker_coin_' .. i end
265+
266+
local function spawn_coin(i)
267+
if i > MAX_COINS then return end
268+
local name = coin_name(i)
269+
coreai_world_spawn({
270+
prefab = 'cube', name = name,
271+
x = -4.0, y = 0.4 + (i - 1) * 0.45, z = 0,
272+
scaleX = 0.8, scaleY = 0.35, scaleZ = 0.8,
273+
})
274+
coreai_world_set_color(name, '#FFD700')
275+
end
276+
277+
local function publish()
278+
store_set('clicker_score', tostring(score))
279+
report(string.format('SCORE=%d coins=%d', score, coins))
280+
end
281+
282+
local function add_points(n)
283+
score = score + n
284+
local want = math.min(math.floor(score / 10), MAX_COINS)
285+
while coins < want do
286+
coins = coins + 1
287+
spawn_coin(coins)
288+
end
289+
if n > 0 then pulse = 6 end
290+
publish()
291+
end
292+
293+
-- Restore the coin tower from the persisted score on load.
294+
add_points(0)
295+
296+
hooks_on('tick', function()
297+
local down = input_mouse_button(0)
298+
if down and not was_down then add_points(1) end
299+
was_down = down
300+
if input_key_down('r') then
301+
for i = 1, coins do coreai_world_destroy(coin_name(i)) end
302+
coins = 0
303+
score = 0
304+
publish()
305+
end
306+
end)
307+
308+
-- Passive income so the tower visibly grows even without a player (idle-game style).
309+
hooks_every(0.5, function() add_points(1) end)
310+
311+
-- Click feedback: the button pops on each earn and eases back to rest size.
312+
hooks_every(0.05, function()
313+
if pulse > 0 then pulse = pulse - 1 end
314+
local s = 1.5 + pulse * 0.07
315+
coreai_world_change(BTN, { scaleX = s, scaleY = s, scaleZ = s })
316+
end)
232317
";
233318

234319
// Compiles cleanly, crashes at runtime on purpose (repair-loop demo):

Assets/CoreAiUnity/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "com.neoxider.coreaiunity",
3-
"version": "6.0.0",
3+
"version": "6.1.0",
44
"displayName": "CoreAI Unity",
55
"unity": "6000.0",
66
"description": "Unity framework for LLM-powered NPCs and agents that call your game code \u2014 drop-in chat UI, function-calling tools, persistent memory, token-by-token streaming, and per-role LLM routing. Runs on a local GGUF model (via LLMUnity) or any OpenAI-compatible API; proven on a 4 GB local model. Unity layer for com.neoxider.coreai.",

0 commit comments

Comments
 (0)