### Start Moon Cluster ETC Service Source: https://github.com/sniper00/moon/blob/master/example/cluster/README.md Initiates the cluster ETC service to retrieve node configuration details. This command is a prerequisite for setting up communication nodes. ```shell ../../moon cluster_etc.lua node.json ``` -------------------------------- ### Lua HTTP Server with Moon Source: https://context7.com/sniper00/moon/llms.txt Sets up an HTTP server using moon.http.server, configuring header and content limits, and defining error handlers. It includes examples for GET and POST endpoints, handling query parameters, form data, and JSON bodies, along with fallback and static file serving. ```lua local moon = require("moon") local json = require("json") local http_server = require("moon.http.server") -- Configure limits http_server.header_max_len = 8192 http_server.content_max_len = 8192 -- Error handler http_server.error = function(fd, err) print("HTTP error on fd", fd, ":", err) end -- GET endpoint with query parameters http_server.on("/hello", function(request, response) local query = request:parse_query() print("Query params:", query.name, query.age) response:write_header("Content-Type", "text/plain") response:write("Hello " .. (query.name or "World")) end) -- POST endpoint with form data http_server.on("/login", function(request, response) local form = request:parse_form() print("Login:", form.username, form.password) response:write_header("Content-Type", "application/json") response:write(json.encode({ success = true, user_id = 12345, token = "abc123" })) end) -- POST endpoint with JSON body http_server.on("/api/data", function(request, response) local data = json.decode(request.body) print("Received JSON:", data.action, data.value) response:write_header("Content-Type", "application/json") response:write(json.encode({ status = "ok", result = data.value * 2 })) end) -- Fallback handler http_server.fallback(function(request, response, next) response:write_header("Content-Type", "text/plain") response:write("404 Not Found: " .. request.path) end) -- Static file server http_server.static("/www") http_server.listen("127.0.0.1", 8001) print("HTTP server listening on port 8001") ``` -------------------------------- ### Complete Node Setup and Initialization with Moon Framework Source: https://context7.com/sniper00/moon/llms.txt This Lua code demonstrates a comprehensive setup for a game server node using the Moon framework. It includes detailed initialization configurations, asynchronous creation of various services (DB, World, Chat), setting up a TCP gateway, and implementing a graceful shutdown sequence to ensure all services are properly closed before exiting. ```lua --- ---__init__--- if _G["__init__"] then local arg = ... return { thread = 8, -- 8 worker threads enable_stdout = true, -- Print to console logfile = string.format("log/game-%s.log", os.date("%Y-%m-%d-%H-%M-%S")), loglevel = "DEBUG", path = table.concat({ "./?.lua", "./?/init.lua", "../lualib/?.lua", "../service/?.lua" }, ";") } end local moon = require("moon") local socket = require("moon.socket") -- Service definitions local services = { { unique = true, name = "db", file = "redisd.lua", threadid = 2, poolsize = 5, opts = {host = "127.0.0.1", port = 6379, timeout = 1000} }, { unique = true, name = "world", file = "service_world.lua", threadid = 3 }, { unique = true, name = "chat", file = "service_chat.lua", threadid = 4 } } moon.async(function() -- Create all unique services for _, config in ipairs(services) do local service_id = moon.new_service(config) if service_id == 0 then print("Failed to create service:", config.name) moon.exit(-1) return end print("Created service:", config.name, string.format("ID=%X", service_id)) end -- Start TCP gateway local listenfd = socket.listen("0.0.0.0", 8889, moon.PTYPE_SOCKET_MOON) if listenfd == 0 then print("Failed to listen on port 8889") moon.exit(-1) return end print("Game server started on port 8889") -- Accept connections and create player services while true do local player_service = moon.new_service({ name = "player", file = "service_player.lua" }) local fd, err = socket.accept(listenfd, player_service) if not fd then print("Accept error:", err) moon.kill(player_service) else -- Initialize player service with socket moon.send("lua", player_service, "START", fd) end end end) -- Graceful shutdown moon.shutdown(function() moon.async(function() -- Shutdown services in order print("Shutting down services...") local chat_id = moon.queryservice("chat") if chat_id > 0 then moon.call("lua", chat_id, "SHUTDOWN") end local world_id = moon.queryservice("world") if world_id > 0 then moon.call("lua", world_id, "SHUTDOWN") end local db_id = moon.queryservice("db") if db_id > 0 then moon.raw_send("system", db_id, "wait_save") end -- Wait for all services to quit while true do local count = moon.server_stats("service.count") if count == 1 then -- Only bootstrap remains break end moon.sleep(200) print("Waiting for services to quit, remaining:", count) end print("All services stopped, exiting...") moon.quit() end) end) ``` -------------------------------- ### Start Moon Cluster Receiver Node Source: https://github.com/sniper00/moon/blob/master/example/cluster/README.md Starts the receiver node for the Moon cluster communication. It requires a node identifier, in this case, '2'. ```shell ../../moon node.lua 2 ``` -------------------------------- ### Start Moon Cluster Sender Node Source: https://github.com/sniper00/moon/blob/master/example/cluster/README.md Starts the sender node for the Moon cluster communication. It requires a node identifier, in this case, '1'. ```shell ../../moon node.lua 1 ``` -------------------------------- ### Moon HTTP Client: Making GET, POST, and POST requests Source: https://context7.com/sniper00/moon/llms.txt Demonstrates how to perform various HTTP requests using the Moon HTTP client. It covers GET requests with query parameters, POST requests with raw bodies, form data, and JSON data. It also shows how to include custom headers and use HTTPS with a proxy. ```lua local moon = require("moon") local httpc = require("moon.http.client") moon.async(function() -- GET request with query parameters local response = httpc.get("http://127.0.0.1:8001/hello?name=Alice&age=25") print("Status:", response.status_code) print("Body:", response.body) -- POST request with raw body local response = httpc.post("http://127.0.0.1:8001/api/message", "Hello Server") print("Response:", response.body) -- POST form data local form = { username = "alice", password = "secret123", remember = "true" } local response = httpc.post_form("http://127.0.0.1:8001/login", form) print("Login response:", response.body) -- POST JSON data local response = httpc.post_json("http://127.0.0.1:8001/api/data", { action = "calculate", value = 42 }) print("API response:", response.body) -- With custom headers and keepalive local response = httpc.get("http://api.example.com/data", { headers = { ["Authorization"] = "Bearer token123", ["User-Agent"] = "Moon/1.0" }, keepalive = 300 -- Keep connection alive for 300 seconds }) -- HTTPS with proxy moon.env("HTTPS_PROXY", "http://127.0.0.1:8443") local response = httpc.get("https://api.example.com/secure") print("Secure response:", response.body) end) ``` -------------------------------- ### Install Detour Library and Headers with CMake Source: https://github.com/sniper00/moon/blob/master/third/recastnavigation/Detour/CMakeLists.txt This snippet details the installation process for the Detour library and its associated header files using CMake. It specifies destinations for runtime binaries, archives, libraries, and header files, ensuring they are placed correctly in the build system's install paths. It also includes conditional installation of PDB files for debugging on MSVC. ```cmake install(TARGETS Detour EXPORT recastnavigation-targets RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT library INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} ${CMAKE_INSTALL_INCLUDEDIR}/recastnavigation ) file(GLOB INCLUDES Include/*.h) install(FILES ${INCLUDES} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/recastnavigation) if(MSVC) install(FILES "$/Detour-d.pdb" CONFIGURATIONS "Debug" DESTINATION "lib" OPTIONAL) endif() ``` -------------------------------- ### Node 2 Message Receiver with Moon Framework Source: https://context7.com/sniper00/moon/llms.txt This Lua code configures Node 2 as a message receiver using the Moon framework. It handles initialization, environment setup, and defines command handlers for notifications (NOTIFY) and RPC calls (ADD, GET_STATUS). It also asynchronously starts a cluster service and begins listening for connections. ```lua ---__init__--- if _G["__init__"] then local arg = ... return { thread = 4, enable_stdout = true, logfile = string.format("log/node-%s.log", arg[1]), loglevel = "DEBUG", path = "./?.lua;../lualib/?.lua;../service/?.lua" } end local moon = require("moon") local arg = ... moon.env("NODE", arg[1]) -- Node ID: 2 moon.env("CONFIG", "http://127.0.0.1:8001") local command = {} -- Handle notification from Node 1 command.NOTIFY = function(sender, session, message) print("Received notification:", message) end -- Handle RPC call from Node 1 command.ADD = function(sender, session, a, b) return a + b end command.GET_STATUS = function() return { online = true, players = 150, uptime = 3600 } end moon.dispatch("lua", function(sender, session, cmd, ...) local f = command[cmd] if f then local res = {xpcall(f, debug.traceback, sender, session, ...)} if res[1] and session > 0 then moon.response("lua", sender, session, table.unpack(res, 2)) end end end) moon.async(function() -- Create and start cluster service local cluster_service = moon.new_service({ unique = true, name = "cluster", file = "cluster.lua" }) if cluster_service == 0 then moon.exit(-1) return end -- Start listening for cluster connections moon.send("lua", cluster_service, "Listen", "127.0.0.1:42346") print("Node 2 listening on port 42346") end) ``` -------------------------------- ### CMake: Install DetourTileCache Library and Headers Source: https://github.com/sniper00/moon/blob/master/third/recastnavigation/DetourTileCache/CMakeLists.txt This section outlines the installation process for the DetourTileCache library using CMake. It specifies installation destinations for runtime files, archives, libraries, and header files. It also includes conditional installation of PDB files for MSVC debug builds. ```cmake install(TARGETS DetourTileCache EXPORT recastnavigation-targets RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT library INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} ${CMAKE_INSTALL_INCLUDEDIR}/recastnavigation ) file(GLOB INCLUDES Include/*.h) install(FILES ${INCLUDES} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/recastnavigation) if(MSVC) install(FILES "$/DetourTileCache-d.pdb" CONFIGURATIONS "Debug" DESTINATION "lib" OPTIONAL) endif() ``` -------------------------------- ### JavaScript WebSocket Client Test Source: https://github.com/sniper00/moon/blob/master/example/websocket_client.html This JavaScript code implements a client for testing WebSocket connections. It handles connection opening, message sending, receiving, and error handling. The output is displayed on an HTML element with the ID 'output'. ```javascript var wsUri = "ws://127.0.0.1:12346/"; var output; function init() { output = document.getElementById("output"); testWebSocket(); } function testWebSocket() { websocket = new WebSocket(wsUri); websocket.onopen = function(evt) { onOpen(evt) }; websocket.onclose = function(evt) { onClose(evt) }; websocket.onmessage = function(evt) { onMessage(evt) }; websocket.onerror = function(evt) { onError(evt) }; } function onOpen(evt) { writeToScreen("CONNECTED"); doSend("WebSocket rocks"); } function onClose(evt) { writeToScreen("DISCONNECTED"); } function onMessage(evt) { writeToScreen('RESPONSE: ' + evt.data + ''); websocket.close(); } function onError(evt) { writeToScreen('ERROR: ' + evt.data); } function doSend(message) { writeToScreen("SENT: " + message); websocket.send(message); } function writeToScreen(message) { var pre = document.createElement("p"); pre.style.wordWrap = "break-word"; pre.innerHTML = message; output.appendChild(pre); } window.addEventListener("load", init, false); ``` -------------------------------- ### Lua: HTTP Client GET Request Implementation Source: https://github.com/sniper00/moon/wiki/Moon-Extension-Library Provides a 'get' function for the Lua HTTP client. It constructs the request options, sets the owner and session, and uses the 'c.request' function to perform the GET request, waiting for the response. ```lua --@class HttpRequestOptions --@field headers? table --@field timeout? integer Request timeout in seconds. default 5s --@field proxy? string local client = {} --@param url string --@param opts? HttpRequestOptions --@return HttpResponse function client.get(url, opts) opts = opts or {} opts.owner = moon.id opts.session = moon.next_sequence() opts.url = url opts.method = "GET" return moon.wait(c.request(opts, protocol_type)) end ``` -------------------------------- ### Define and Configure DetourCrowd Library (CMake) Source: https://github.com/sniper00/moon/blob/master/third/recastnavigation/DetourCrowd/CMakeLists.txt This snippet defines the DetourCrowd library using source files found in 'Source/*.cpp'. It sets properties such as the debug postfix, include directories, and links the 'Detour' library. It also configures versioning (SOVERSION and VERSION) and PDB output for debugging. Finally, it defines installation rules for targets, including runtime, archive, and library destinations, along with include directories. It also installs header files and platform-specific PDB files for MSVC debug builds. ```cmake file(GLOB SOURCES Source/*.cpp) add_library(DetourCrowd ${SOURCES}) add_library(RecastNavigation::DetourCrowd ALIAS DetourCrowd) set_target_properties(DetourCrowd PROPERTIES DEBUG_POSTFIX -d) set(DetourCrowd_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/Include") target_include_directories(DetourCrowd PUBLIC "$" ) target_link_libraries(DetourCrowd Detour ) set_target_properties(DetourCrowd PROPERTIES SOVERSION ${SOVERSION} VERSION ${LIB_VERSION} COMPILE_PDB_OUTPUT_DIRECTORY . COMPILE_PDB_NAME "DetourCrowd-d" ) install(TARGETS DetourCrowd EXPORT recastnavigation-targets RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT library INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} ${CMAKE_INSTALL_INCLUDEDIR}/recastnavigation ) file(GLOB INCLUDES Include/*.h) install(FILES ${INCLUDES} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/recastnavigation) if(MSVC) install(FILES "$/DetourCrowd-d.pdb" CONFIGURATIONS "Debug" DESTINATION "lib" OPTIONAL) endif() ``` -------------------------------- ### Create, Query, and Manage Services in Lua Source: https://context7.com/sniper00/moon/llms.txt Demonstrates how to create a unique service, query it by name, send messages to it, and then kill the service. This function is essential for managing the lifecycle and communication of actors within the Moon framework. ```lua local moon = require("moon") -- Create a unique service moon.async(function() local service_id = moon.new_service({ name = "worldmap", file = "worldmap.lua", unique = true, -- Queryable by name threadid = 2, -- Optional: run on dedicated thread -- Pass custom parameters db_host = "127.0.0.1", db_port = 6379 }) if service_id == 0 then print("Service creation failed") moon.exit(-1) return end print(string.format("Service created with ID: %X", service_id)) end) -- Query unique service by name local worldmap_id = moon.queryservice("worldmap") assert(worldmap_id > 0, "Service not found") -- Send message to service moon.send("lua", worldmap_id, "UPDATE", {x=100, y=200}) -- Kill a service moon.kill(service_id) ``` -------------------------------- ### Moon Redis Client: Direct Connection and Operations Source: https://context7.com/sniper00/moon/llms.txt Illustrates how to establish a direct connection to a Redis server and perform various operations using the Moon Redis client. It covers string, hash, and set operations, as well as executing transactions and pipelines for efficiency. Pub/Sub functionality is also demonstrated. ```lua local moon = require("moon") local redis = require("moon.db.redis") moon.async(function() -- Connect to Redis local db, err = redis.connect({ host = "127.0.0.1", port = 6379, timeout = 5000 -- 5 second timeout }) if not db then print("Redis connection failed:", err) return end -- String operations db:set("user:1001:name", "Alice") db:set("user:1001:score", "9500") local name = db:get("user:1001:name") print("User name:", name) -- Output: Alice -- Hash operations db:del("player:1001") db:hset("player:1001", "level", 50) db:hset("player:1001", "gold", 10000) db:hset("player:1001", "exp", 123456) local level = db:hget("player:1001", "level") print("Player level:", level) local all_data = db:hgetall("player:1001") for k, v in pairs(all_data) do print(k, "=", v) end -- Set operations db:sadd("online_users", "user1", "user2", "user3") local is_member = db:sismember("online_users", "user1") print("User online:", is_member == 1) -- Transaction db:multi() db:set("key1", "value1") db:set("key2", "value2") db:get("key1") db:get("key2") local results = db:exec() for i, v in ipairs(results) do print("Result", i, ":", v) end -- Pipeline for better performance local res, err = db:pipeline({ {"set", "player:hp", "100"}, {"set", "player:mp", "50"}, {"get", "player:hp"}, {"get", "player:mp"}, {"incr", "player:hp"} }, {}) -- Provide empty table for results if err then print("Pipeline error:", err) else for i, v in ipairs(res) do print("Pipeline result", i, ":", v) end end -- Pub/Sub db:publish("game:events", "player_joined") db:disconnect() end) ``` -------------------------------- ### Cluster Node 1 Message Sender with Moon Source: https://context7.com/sniper00/moon/llms.txt Illustrates setting up Node 1 of a cluster using the Moon framework. It configures logging, sets environment variables for node ID and config center URL, and demonstrates sending asynchronous messages and making synchronous calls to other nodes in the cluster. Error handling for remote calls is also included. ```lua --__init__-- if _G["__init__"] then local arg = ... return { thread = 4, enable_stdout = true, logfile = string.format("log/node-%s.log", arg[1]), loglevel = "DEBUG", path = "./?.lua;../lualib/?.lua;../service/?.lua" } end local moon = require("moon") local cluster = require("moon.cluster") -- Set node ID from command line argument local arg = ... moon.env("NODE", arg[1]) -- Node ID: 1 -- Config center URL moon.env("CONFIG", "http://127.0.0.1:8001") moon.async(function() -- Create cluster service local cluster_service = moon.new_service({ unique = true, name = "cluster", file = "cluster.lua" }) if cluster_service == 0 then print("Failed to create cluster service") moon.exit(-1) return end print("Node 1 started, waiting for Node 2...") moon.sleep(3000) -- Send message to Node 2 (no response) cluster.send(2, "bootstrap", "NOTIFY", "Hello from Node 1") -- Call Node 2 and wait for response local result = cluster.call(2, "bootstrap", "ADD", 10, 20) print("Node 2 returned:", result) -- Output: 30 -- Call with error handling local success, err = cluster.call(2, "bootstrap", "GET_STATUS") if success then print("Status:", success) else print("Error:", err) end end) ``` -------------------------------- ### Redis Service Pool with Moon Source: https://context7.com/sniper00/moon/llms.txt Demonstrates creating and using a Redis service with a connection pool via the Moon framework. It shows how to send commands that don't require a response and how to call commands that do, including handling multiple operations and direct pipeline calls. The service is configured with a dedicated thread and a specific pool size. ```lua local moon = require("moon") local redisd = require("redisd") moon.async(function() -- Create Redis service with connection pool local redis_service = moon.new_service({ unique = true, name = "db", file = "redisd.lua", threadid = 2, -- Dedicated thread poolsize = 5, -- 5 connections in pool opts = { host = "127.0.0.1", port = 6379, timeout = 1000 } }) if redis_service == 0 then print("Failed to create redis service") return end -- Send command (no response needed) redisd.send(redis_service, "SET", "game:status", "running") -- Call command and wait for response local value = redisd.call(redis_service, "GET", "game:status") print("Game status:", value) -- Output: running -- Multiple operations redisd.send(redis_service, "SET", "player:1", "Alice") redisd.send(redis_service, "SET", "player:2", "Bob") redisd.send(redis_service, "SET", "player:3", "Charlie") print(redisd.call(redis_service, "GET", "player:1")) print(redisd.call(redis_service, "GET", "player:2")) print(redisd.call(redis_service, "GET", "player:3")) -- Direct pipeline call local res, err = redisd.direct(redis_service, "pipeline", { {"hset", "game:config", "max_players", "100"}, {"hset", "game:config", "map_size", "1000"}, {"hget", "game:config", "max_players"}, {"hget", "game:config", "map_size"} }, {}) if err then print("Error:", err) else print("Pipeline results:", table.unpack(res)) end end) -- Cleanup on shutdown moon.shutdown(function() moon.kill(redis_service) moon.quit() end) ``` -------------------------------- ### Bootstrap Service Template in Lua Source: https://context7.com/sniper00/moon/llms.txt This Lua script serves as a template for a Moon service. It defines how to receive configuration parameters, handle incoming commands (like UPDATE and QUIT), and register message dispatch and shutdown handlers. It utilizes `xpcall` for robust error handling during command execution. ```lua local moon = require("moon") local conf = ... -- Receive configuration parameters print("Service config:", conf.db_host, conf.db_port) local command = {} -- Define command handlers command.UPDATE = function(sender, session, data) print("Update position:", data.x, data.y) return true end command.QUIT = function() moon.quit() return true end -- Register message dispatcher moon.dispatch("lua", function(sender, session, cmd, ...) local f = command[cmd] if f then local res = {xpcall(f, debug.traceback, sender, session, ...)} if res[1] and session > 0 then moon.response("lua", sender, session, table.unpack(res, 2)) elseif not res[1] then print("Error:", res[2]) end else error(string.format("Unknown command: %s", cmd)) end end) -- Register shutdown handler moon.shutdown(function() print("Service shutting down...") moon.quit() end) ``` -------------------------------- ### Lua Timers and Coroutine Sleep with Moon Source: https://context7.com/sniper00/moon/llms.txt Demonstrates one-time timeouts, canceling timers, coroutine-based sleep with optional tags, waking up sleeping coroutines, and setting up repeating timer patterns using the moon library's timeout and async functions. ```lua local moon = require("moon") -- One-time timeout local timer_id = moon.timeout(1000, function() print("Timer fired after 1 second") end) -- Cancel timer moon.remove_timer(timer_id) -- Coroutine-based sleep moon.async(function() print("Start waiting...") moon.sleep(1000) -- Sleep for 1 second print("1 second elapsed") moon.sleep(2000, "tag1") -- Sleep with tag print("2 more seconds elapsed") end) -- Wake up sleeping coroutine local co = moon.async(function() print("Wakeup result:", moon.sleep(10000)) end) moon.async(function() moon.sleep(1000) moon.wakeup(co, "manual_wakeup") -- Wake up early end) -- Repeating timer pattern moon.async(function() while true do moon.sleep(5000) -- Execute every 5 seconds print("Periodic task executed") end end) ``` -------------------------------- ### Rust: Lua Module Initialization for HTTP Client Source: https://github.com/sniper00/moon/wiki/Moon-Extension-Library Initializes the Lua module 'rust.httpc', registering the various HTTP-related functions (request, form_urlencode, form_urldecode, decode) to be callable from Lua. ```rust #[no_mangle] #[allow(clippy::not_unsafe_ptr_arg_deref)] pub extern "C-unwind" fn luaopen_rust_httpc(state: *mut ffi::lua_State) -> c_int { let l = [ lreg!("request", lua_http_request), lreg!("form_urlencode", lua_http_form_urlencode), lreg!("form_urldecode", lua_http_form_urldecode), lreg!("decode", decode), lreg_null!(), ]; luaL_newlib!(state, l); 1 } ``` -------------------------------- ### Lua TCP Server with Moon Protocol Source: https://context7.com/sniper00/moon/llms.txt Sets up a TCP server using the moon.socket module, employing the Moon protocol (2-byte header + data). It registers event handlers for accept, message, close, and error events, configuring socket options like timeout and nodelay. ```lua local moon = require("moon") local socket = require("moon.socket") -- Start TCP server with Moon protocol local listenfd = socket.listen("0.0.0.0", 8080, moon.PTYPE_SOCKET_MOON) socket.start(listenfd) -- Auto-accept connections -- Register event handlers socket.on("accept", function(fd, msg) print("Client connected:", fd, moon.decode(msg, "Z")) socket.settimeout(fd, 60) -- 60 second timeout socket.setnodelay(fd) -- Disable Nagle's algorithm end) socket.on("message", function(fd, msg) local data = moon.decode(msg, "Z") print("Received:", data) -- Echo back to client socket.write(fd, moon.decode(msg, "Z")) end) socket.on("close", function(fd, msg) print("Client disconnected:", fd) end) socket.on("error", function(fd, msg) print("Socket error:", fd, moon.decode(msg, "Z")) end) print("Server listening on port 8080") ``` -------------------------------- ### Lua TCP Client with Moon Protocol Source: https://context7.com/sniper00/moon/llms.txt Implements a TCP client using the moon.socket module to connect to a server using the Moon protocol. It includes helper functions to send and read messages with the 2-byte length header, and demonstrates sending a message and reading the server's response. ```lua local moon = require("moon") local socket = require("moon.socket") local function send_message(fd, data) local len = #data return socket.write(fd, string.pack(">H", len) .. data) end local function read_message(fd) local header, err = socket.read(fd, 2) if not header then return false, err end local len = string.unpack(">H", header) local data, err = socket.read(fd, len) if not data then return false, err end return data end moon.async(function() local fd, err = socket.connect("127.0.0.1", 8080, moon.PTYPE_SOCKET_TCP) if not fd then print("Connect failed:", err) return end -- Send message send_message(fd, "Hello Server") -- Read response local response, err = read_message(fd) if response then print("Server replied:", response) else print("Read error:", err) end socket.close(fd) end) ``` -------------------------------- ### Rust: Make HTTP Request and Handle Errors Source: https://github.com/sniper00/moon/wiki/Moon-Extension-Library Spawns a Tokio task to perform an HTTP request. If the request fails, it sends an error message back to the owner and session associated with the request. ```rust CONTEXT.tokio_runtime.spawn(async move { let session = req.session; let owner = req.owner; if let Err(err) = http_request(req, protocol_type).await { let err_string = err.to_string(); moon_send_bytes(PTYPE_ERROR, owner, session, err_string.as_bytes()); } }); ``` -------------------------------- ### Coroutine-based Request-Response (Lua) Source: https://context7.com/sniper00/moon/llms.txt Illustrates the coroutine-based request-response pattern for inter-service communication in Moon. The sender service uses `moon.call` to send a request and wait for a response, while also demonstrating sending a message without waiting using `moon.send`. The receiver service defines handlers for ADD and LOG commands and uses `moon.response` to send back results or errors. ```lua local moon = require("moon") -- Sender service moon.async(function() -- Call remote service and wait for response local result, err = moon.call("lua", service_id, "ADD", 10, 20) if result then print("Result:", result) -- Output: 30 else print("Error:", err) end -- Send message without waiting for response moon.send("lua", service_id, "LOG", "Operation completed") end) -- Receiver service local command = {} command.ADD = function(sender, session, a, b) return a + b -- Auto-responds with result end command.LOG = function(sender, session, message) print("Log:", message) -- No return value needed end moon.dispatch("lua", function(sender, session, cmd, ...) local f = command[cmd] if f then local res = {xpcall(f, debug.traceback, sender, session, ...)} if res[1] then moon.response("lua", sender, session, table.unpack(res, 2)) else moon.response("lua", sender, session, false, res[2]) end end end) ``` -------------------------------- ### Initialize Lua Excel Library (Rust) Source: https://github.com/sniper00/moon/wiki/Moon-Extension-Library This function initializes the Rust Excel library for use within a Lua environment. It registers the `lua_excel_read` function under the name 'read' in the Lua global table. The function returns 1 upon successful initialization, indicating that the library is ready for use. ```rust /// # Safety /// /// This function is unsafe because it dereferences a raw pointer `state`. /// The caller must ensure that `state` is a valid pointer to a `lua_State` /// and that it remains valid for the duration of the function call. #[no_mangle] #[allow(clippy::not_unsafe_ptr_arg_deref)] pub unsafe extern "C-unwind" fn luaopen_rust_excel(state: *mut ffi::lua_State) -> c_int { let l = [lreg!("read", lua_excel_read), lreg_null!()]; ffi::lua_createtable(state, 0, l.len() as c_int); ffi::luaL_setfuncs(state, l.as_ptr(), 0); 1 } ``` -------------------------------- ### Configure Detour Library Build with CMake Source: https://github.com/sniper00/moon/blob/master/third/recastnavigation/Detour/CMakeLists.txt This snippet defines how the Detour library is built using CMake. It globbs C++ source files, creates a static or shared library, sets up an alias, configures include directories, and applies conditional compilation definitions based on project settings. It also sets versioning and PDB output properties. ```cmake file(GLOB SOURCES Source/*.cpp) add_library(Detour ${SOURCES}) add_library(RecastNavigation::Detour ALIAS Detour) set_target_properties(Detour PROPERTIES DEBUG_POSTFIX -d) set(Detour_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/Include") if(RECASTNAVIGATION_DT_POLYREF64) target_compile_definitions(Detour PUBLIC DT_POLYREF64) endif() if(RECASTNAVIGATION_DT_VIRTUAL_QUERYFILTER) target_compile_definitions(Detour PUBLIC DT_VIRTUAL_QUERYFILTER) endif() target_include_directories(Detour PUBLIC "$" ) set_target_properties(Detour PROPERTIES SOVERSION ${SOVERSION} VERSION ${LIB_VERSION} COMPILE_PDB_OUTPUT_DIRECTORY . COMPILE_PDB_NAME "Detour-d" ) ``` -------------------------------- ### Callback-Style Inter-Service Communication (Lua) Source: https://context7.com/sniper00/moon/llms.txt This Lua code snippet demonstrates callback-style inter-service communication. The sender service sends a request using `moon.send` and expects a specific callback handler (`ADDRESULT`) to be invoked when the operation is complete. The receiver service handles the request and uses `moon.send` to trigger the callback on the sender. ```lua -- Sender service local command = {} command.ADDRESULT = function(sender, result) print("Got result:", result) end moon.dispatch("lua", function(sender, session, cmd, ...) local f = command[cmd] if f then f(sender, ...) end end) -- Send request without waiting moon.send("lua", service_id, "ADD", 1, 2) -- Receiver service local command = {} command.ADD = function(sender, a, b) local result = a + b moon.send("lua", sender, "ADDRESULT", result) end moon.dispatch("lua", function(sender, session, cmd, ...) local f = command[cmd] if f then f(sender, ...) end end) ``` -------------------------------- ### Cluster Node Configuration Source: https://context7.com/sniper00/moon/llms.txt Defines the configuration for a distributed cluster, specifying the node ID, host, and port for each participating node. This JSON structure is used to establish communication channels between different parts of the cluster. ```json [ { "node": 1, "host": "127.0.0.1", "port": 42345 }, { "node": 2, "host": "127.0.0.1", "port": 42346 }, { "node": 3, "host": "192.168.1.100", "port": 42347 } ] ``` -------------------------------- ### Configure Recast Library Build (CMake) Source: https://github.com/sniper00/moon/blob/master/third/recastnavigation/Recast/CMakeLists.txt This snippet configures the build for the Recast library using CMake. It defines source files, creates a static library, sets up an alias for easier referencing, and specifies debug postfixes. It also configures include directories and target properties like versioning and PDB output. ```cmake file(GLOB SOURCES Source/*.cpp) add_library(Recast ${SOURCES}) add_library(RecastNavigation::Recast ALIAS Recast) set_target_properties(Recast PROPERTIES DEBUG_POSTFIX -d) set(Recast_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/Include") target_include_directories(Recast PUBLIC "$" ) set_target_properties(Recast PROPERTIES SOVERSION ${SOVERSION} VERSION ${LIB_VERSION} COMPILE_PDB_OUTPUT_DIRECTORY . COMPILE_PDB_NAME "Recast-d" ) install(TARGETS Recast EXPORT recastnavigation-targets RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT library INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} ${CMAKE_INSTALL_INCLUDEDIR}/recastnavigation ) file(GLOB INCLUDES Include/*.h) install(FILES ${INCLUDES} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/recastnavigation) if(MSVC) install(FILES "$/Recast-d.pdb" CONFIGURATIONS "Debug" DESTINATION "lib" OPTIONAL) endif() ``` -------------------------------- ### CMake: Define and Configure DetourTileCache Library Source: https://github.com/sniper00/moon/blob/master/third/recastnavigation/DetourTileCache/CMakeLists.txt This snippet defines the DetourTileCache library using source files found in 'Source/*.cpp'. It sets up properties like debug postfix, include directories, and links against the 'Detour' library. It also configures versioning and PDB output for the library. ```cmake file(GLOB SOURCES Source/*.cpp) add_library(DetourTileCache ${SOURCES}) add_library(RecastNavigation::DetourTileCache ALIAS DetourTileCache) set_target_properties(DetourTileCache PROPERTIES DEBUG_POSTFIX -d) set(DetourTileCache_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/Include") target_include_directories(DetourTileCache PUBLIC "$" ) target_link_libraries(DetourTileCache Detour ) set_target_properties(DetourTileCache PROPERTIES SOVERSION ${SOVERSION} VERSION ${LIB_VERSION} COMPILE_PDB_OUTPUT_DIRECTORY . COMPILE_PDB_NAME "DetourTileCache-d" ) ``` -------------------------------- ### Lua: Expose Rust HTTP Request Functionality Source: https://github.com/sniper00/moon/wiki/Moon-Extension-Library This Lua function registers the 'request' function from the Rust httpc module, allowing Lua scripts to initiate HTTP requests. It requires the 'moon' and 'rust.httpc' modules. ```lua local c = require "rust.httpc" local protocol_type = 21 moon.register_protocol { name = "http", PTYPE = protocol_type, pack = function(...) return ... end, unpack = function (val) return c.decode(val) -- 'val' is rust object pointer end } ``` -------------------------------- ### Rust: Form URL Decode Function for Lua Source: https://github.com/sniper00/moon/wiki/Moon-Extension-Library Implements URL decoding for a query string, parsing it into a table of key-value pairs. It takes a URL-encoded string as input and returns a Lua table containing the decoded data. ```rust extern "C-unwind" fn lua_http_form_urldecode(state: *mut ffi::lua_State) -> c_int { let query_string = laux::lua_get::<&str>(state, 1); unsafe { ffi::lua_createtable(state, 0, 8) }; let decoded: Vec<(String, String)> = form_urlencoded::parse(query_string.as_bytes()) .into_owned() .collect(); for pair in decoded { laux::lua_push(state, pair.0); laux::lua_push(state, pair.1); unsafe { ffi::lua_rawset(state, -3); } } 1 } ``` -------------------------------- ### Lua HTTP POST Request Source: https://github.com/sniper00/moon/wiki/Moon-Extension-Library Implements an HTTP POST request. It takes a URL, data payload, and optional request options. It automatically sets owner, session, URL, body, and method to 'POST'. Dependencies include the 'moon' library and a 'c' module for request execution. ```Lua ---@param url string ---@param data string ---@param opts? HttpRequestOptions ---@return HttpResponse function client.post(url, data, opts) opts = opts or {} opts.owner = moon.id opts.session = moon.next_sequence() opts.url = url opts.body = data opts.method = "POST" return moon.wait(c.request(opts, protocol_type)) end ``` -------------------------------- ### Rust: Form URL Encode Function for Lua Source: https://github.com/sniper00/moon/wiki/Moon-Extension-Library Implements URL encoding for form data, converting key-value pairs into a percent-encoded string suitable for HTTP requests. It takes a Lua table as input and returns the encoded string. ```rust extern "C-unwind" fn lua_http_form_urlencode(state: *mut ffi::lua_State) -> c_int { laux::lua_checktype(state, 1, ffi::LUA_TTABLE); laux::lua_pushnil(state); let mut result = String::new(); while laux::lua_next(state, 1) { if !result.is_empty() { result.push('&'); } let key = laux::to_string_unchecked(state, -2); let value = laux::to_string_unchecked(state, -1); result.push_str( form_urlencoded::byte_serialize(key.as_bytes()) .collect::() .as_str(), ); result.push('='); result.push_str( form_urlencoded::byte_serialize(value.as_bytes()) .collect::() .as_str(), ); laux::lua_pop(state, 1); } laux::lua_push(state, result); 1 } ``` -------------------------------- ### Lua: HTTP Client POST JSON Request Implementation Source: https://github.com/sniper00/moon/wiki/Moon-Extension-Library Implements a 'post_json' function for the Lua HTTP client. It sets the 'Content-Type' header to 'application/json', encodes the provided data as JSON, sends the request, and attempts to decode the JSON response. ```lua local json_content_type = { ["Content-Type"] = "application/json" } --@param url string --@param data table --@param opts? HttpRequestOptions --@return HttpResponse function client.post_json(url, data, opts) opts = opts or {} opts.owner = moon.id opts.session = moon.next_sequence() if not opts.headers then opts.headers = json_content_type else if not opts.headers['Content-Type'] then opts.headers['Content-Type'] = "application/json" end end opts.url = url opts.method = "POST" opts.body = json.encode(data) local res = moon.wait(c.request(opts, protocol_type)) if res.status_code == 200 then res.body = tojson(res) end return res end ```