aboutsummaryrefslogtreecommitdiff
path: root/src/lua/modules
diff options
context:
space:
mode:
Diffstat (limited to 'src/lua/modules')
-rw-r--r--src/lua/modules/audio/luaopen_Source.cpp115
-rw-r--r--src/lua/modules/audio/luaopen_audio.cpp109
-rw-r--r--src/lua/modules/bit/luaopen_bit.cpp84
-rw-r--r--src/lua/modules/core/luaopen_core.cpp44
-rw-r--r--src/lua/modules/embed/boot.lua.h170
-rw-r--r--src/lua/modules/embed/embed.h49
-rw-r--r--src/lua/modules/embed/graphics.lua.h4
-rw-r--r--src/lua/modules/embed/keyboard.lua.h15
-rw-r--r--src/lua/modules/embed/mouse.lua.h14
-rw-r--r--src/lua/modules/embed/net.lua.h4
-rw-r--r--src/lua/modules/embed/path.lua.h14
-rw-r--r--src/lua/modules/event/luaopen_event.cpp106
-rw-r--r--src/lua/modules/filesystem/luaopen_filesystem.cpp137
-rw-r--r--src/lua/modules/graphics/luaopen_Canvas.cpp74
-rw-r--r--src/lua/modules/graphics/luaopen_Font.cpp48
-rw-r--r--src/lua/modules/graphics/luaopen_Image.cpp88
-rw-r--r--src/lua/modules/graphics/luaopen_JSL.cpp145
-rw-r--r--src/lua/modules/graphics/luaopen_graphics.cpp493
-rw-r--r--src/lua/modules/joypad/luaopen_joypad.cpp21
-rw-r--r--src/lua/modules/keyboard/luaopen_keyboard.cpp16
-rw-r--r--src/lua/modules/luaopen_jin.cpp104
-rw-r--r--src/lua/modules/luaopen_jin.h42
-rw-r--r--src/lua/modules/luax.h7
-rw-r--r--src/lua/modules/math/luaopen_math.cpp30
-rw-r--r--src/lua/modules/mouse/luaopen_mouse.cpp31
-rw-r--r--src/lua/modules/net/Buffer.h96
-rw-r--r--src/lua/modules/net/luaopen_Buffer.cpp135
-rw-r--r--src/lua/modules/net/luaopen_Socket.cpp126
-rw-r--r--src/lua/modules/net/luaopen_net.cpp86
-rw-r--r--src/lua/modules/thread/Thread.cpp14
-rw-r--r--src/lua/modules/thread/Thread.h94
-rw-r--r--src/lua/modules/thread/luaopen_thread.cpp248
-rw-r--r--src/lua/modules/time/luaopen_time.cpp38
33 files changed, 2801 insertions, 0 deletions
diff --git a/src/lua/modules/audio/luaopen_Source.cpp b/src/lua/modules/audio/luaopen_Source.cpp
new file mode 100644
index 0000000..4c98ead
--- /dev/null
+++ b/src/lua/modules/audio/luaopen_Source.cpp
@@ -0,0 +1,115 @@
+#include "libjin/jin.h"
+#include "lua/modules/luax.h"
+#include "lua/common/common.h"
+
+namespace jin
+{
+namespace lua
+{
+
+ using namespace jin::audio;
+
+ typedef Ref<Source>& SourceRef;
+
+ static inline SourceRef checkSource(lua_State* L)
+ {
+ Proxy* proxy = (Proxy*)luax_checktype(L, 1, JIN_AUDIO_SOURCE);
+ return proxy->getRef<Source>();
+ }
+
+ static int l_play(lua_State* L)
+ {
+ SourceRef ref = checkSource(L);
+ ref->play();
+ return 0;
+ }
+
+ static int l_stop(lua_State* L)
+ {
+ SourceRef ref = checkSource(L);
+ ref->stop();
+ return 0;
+ }
+
+ static int l_pause(lua_State* L)
+ {
+ SourceRef ref = checkSource(L);
+ ref->pause();
+ return 0;
+ }
+
+ static int l_rewind(lua_State* L)
+ {
+ SourceRef ref = checkSource(L);
+ ref->rewind();
+ return 0;
+ }
+
+ static int l_resume(lua_State* L)
+ {
+ SourceRef ref = checkSource(L);
+ ref->resume();
+ return 0;
+ }
+
+ static int l_isStop(lua_State* L)
+ {
+ SourceRef ref = checkSource(L);
+ bool isStop = ref->isStopped();
+ luax_pushboolean(L, isStop);
+ return 1;
+ }
+
+ static int l_isPaused(lua_State* L)
+ {
+ SourceRef ref = checkSource(L);
+ bool isPaused = ref->isPaused();
+ luax_pushboolean(L, isPaused);
+ return 1;
+ }
+
+ static int l_setVolume(lua_State* L)
+ {
+ SourceRef ref = checkSource(L);
+ float volume = luax_checknumber(L, 2);
+ ref->setVolume(volume);
+ return 0;
+ }
+
+ static int l_setLoop(lua_State* L)
+ {
+ SourceRef ref = checkSource(L);
+ bool loop = luax_checkbool(L, 2);
+ ref->setLoop(loop);
+ return 0;
+ }
+
+ static int l_gc(lua_State* L)
+ {
+ Proxy* proxy = (Proxy*)luax_checktype(L, 1, JIN_AUDIO_SOURCE);
+ proxy->release();
+ return 0;
+ }
+
+ static const luaL_Reg f[] = {
+ { "__gc", l_gc },
+ { "play", l_play },
+ { "stop", l_stop },
+ { "pause", l_pause },
+ { "resume", l_resume },
+ { "rewind", l_rewind },
+ { "isStop", l_isStop },
+ { "isPaused", l_isPaused },
+ { "setVolume", l_setVolume },
+ { "setLoop", l_setLoop },
+ { 0, 0 }
+ };
+
+ int luaopen_Source(lua_State* L)
+ {
+ luax_newtype(L, JIN_AUDIO_SOURCE, f);
+ return 0;
+ }
+
+} // lua
+} // jin \ No newline at end of file
diff --git a/src/lua/modules/audio/luaopen_audio.cpp b/src/lua/modules/audio/luaopen_audio.cpp
new file mode 100644
index 0000000..1c44374
--- /dev/null
+++ b/src/lua/modules/audio/luaopen_audio.cpp
@@ -0,0 +1,109 @@
+#include "lua/modules/luax.h"
+#include "lua/common/common.h"
+#include "libjin/jin.h"
+
+namespace jin
+{
+namespace lua
+{
+
+ using namespace jin::audio;
+ using namespace jin::filesystem;
+
+ typedef SDLAudio Audio;
+ typedef SDLSource Source;
+
+ static int l_init(lua_State* L)
+ {
+ Audio::Setting setting;
+ setting.samplerate = 44100;
+ setting.samples = 44100;
+ if (!Audio::get()->init(&setting))
+ {
+ luax_error(L, "could not init audio");
+ luax_pushboolean(L, false);
+ return 1;
+ }
+ luax_pushboolean(L, true);
+ return 1;
+ }
+
+ static int l_play(lua_State* L)
+ {
+ Audio::get()->play();
+ return 0;
+ }
+
+ static int l_stop(lua_State* L)
+ {
+ Audio::get()->stop();
+ return 0;
+ }
+
+ static int l_pause(lua_State* L)
+ {
+ Audio::get()->pause();
+ return 0;
+ }
+
+ static int l_resume(lua_State* L)
+ {
+ Audio::get()->resume();
+ return 0;
+ }
+
+ static int l_setVolume(lua_State* L)
+ {
+ float volume = luax_checknumber(L, 1);
+ Audio::get()->setVolume(volume);
+ return 0;
+ }
+
+ static int l_newSource(lua_State* L)
+ {
+ Filesystem* fs = Filesystem::get();
+ const char* f = luax_checkstring(L, 1);
+ if (!fs->exists(f))
+ {
+ printf("Error: no such image %s\n", f);
+ exit(1);
+ }
+ Buffer b;
+ fs->read(f, &b);
+ Proxy* proxy = (Proxy*)luax_newinstance(L, JIN_AUDIO_SOURCE, sizeof(Proxy));
+ Source* src = Source::createSource(b.data, b.size);
+ proxy->bind(new Ref<Source>(src, JIN_AUDIO_SOURCE));
+ return 1;
+ }
+
+ static int l_destroy(lua_State* L)
+ {
+ Audio* audio = Audio::get();
+ audio->quit();
+ return 0;
+ }
+
+ static const luaL_Reg f[] = {
+ { "init", l_init },
+ { "play", l_play },
+ { "stop", l_stop },
+ { "pause", l_pause },
+ { "resume", l_resume },
+ { "setVolume", l_setVolume },
+ { "newSource", l_newSource },
+ { "destroy", l_destroy },
+ { 0, 0 }
+ };
+
+ extern int luaopen_Source(lua_State* L);
+
+ int luaopen_audio(lua_State* L)
+ {
+ luaopen_Source(L);
+
+ luax_newlib(L, f);
+
+ return 1;
+ }
+}
+} \ No newline at end of file
diff --git a/src/lua/modules/bit/luaopen_bit.cpp b/src/lua/modules/bit/luaopen_bit.cpp
new file mode 100644
index 0000000..5b18125
--- /dev/null
+++ b/src/lua/modules/bit/luaopen_bit.cpp
@@ -0,0 +1,84 @@
+#include "lua/modules/luax.h"
+#include "libjin/jin.h"
+#include <cstdlib>
+
+namespace jin
+{
+namespace lua
+{
+
+ static int l_and(lua_State* L)
+ {
+ int a = luax_checkinteger(L, 1);
+ int b = luax_checkinteger(L, 2);
+ luax_pushinteger(L, a & b);
+ return 1;
+ }
+
+ static int l_or(lua_State* L)
+ {
+ int a = luax_checkinteger(L, 1);
+ int b = luax_checkinteger(L, 2);
+ luax_pushinteger(L, a | b);
+ return 1;
+ }
+
+ static int l_xor(lua_State* L)
+ {
+ int a = luax_checkinteger(L, 1);
+ int b = luax_checkinteger(L, 2);
+ luax_pushinteger(L, a ^ b);
+ return 1;
+ }
+
+ static int l_not(lua_State* L)
+ {
+ int n = luax_checkinteger(L, 1);
+ luax_pushinteger(L, ~n);
+ return 1;
+ }
+
+ static int l_lshift(lua_State* L)
+ {
+ int a = luax_checkinteger(L, 1);
+ int b = luax_checkinteger(L, 2);
+ luax_pushinteger(L, a << b);
+ return 1;
+ }
+
+ static int l_rshift(lua_State* L)
+ {
+ int a = luax_checkinteger(L, 1);
+ int b = luax_checkinteger(L, 2);
+ luax_pushinteger(L, a >> b);
+ return 1;
+ }
+
+ static int l_include(lua_State* L)
+ {
+ int a = luax_checkinteger(L, 1);
+ int b = luax_checkinteger(L, 2);
+ luax_pushboolean(L, (a & b) == b);
+ return 1;
+ }
+
+ static const luaL_Reg f[] = {
+ { "bAnd", l_and },
+ { "bOr" , l_or },
+ { "bXor", l_xor },
+ { "bNot", l_not },
+ { "bLs", l_lshift },
+ { "bRs", l_rshift },
+ { "bInc", l_include },
+ { 0, 0 }
+ };
+
+ int luaopen_bit(lua_State* L)
+ {
+ luax_newlib(L, f);
+
+ return 1;
+ }
+
+}
+} \ No newline at end of file
diff --git a/src/lua/modules/core/luaopen_core.cpp b/src/lua/modules/core/luaopen_core.cpp
new file mode 100644
index 0000000..0243554
--- /dev/null
+++ b/src/lua/modules/core/luaopen_core.cpp
@@ -0,0 +1,44 @@
+#include "lua/modules/luax.h"
+#include "libjin/jin.h"
+
+namespace jin
+{
+namespace lua
+{
+ using namespace jin::core;
+
+ static int l_running(lua_State* L)
+ {
+ static Game* game = Game::get();
+ bool running = game->running();
+ luax_pushboolean(L, running);
+ return 1;
+ }
+
+ static int l_stop(lua_State* L)
+ {
+ Game::get()->stop();
+ return 0;
+ }
+
+ static int l_quit(lua_State* L)
+ {
+ Game::get()->quit();
+ return 0;
+ }
+
+ static const luaL_Reg f[] = {
+ {"running", l_running },
+ {"stop", l_stop },
+ {"quit", l_quit },
+ {0, 0 }
+ };
+
+ int luaopen_core(lua_State* L)
+ {
+ luax_newlib(L, f);
+
+ return 1;
+ }
+}
+} \ No newline at end of file
diff --git a/src/lua/modules/embed/boot.lua.h b/src/lua/modules/embed/boot.lua.h
new file mode 100644
index 0000000..32d3e1d
--- /dev/null
+++ b/src/lua/modules/embed/boot.lua.h
@@ -0,0 +1,170 @@
+/* boot.lua */
+static const char* boot_lua = R"(
+jin._argv[2] = jin._argv[2] or '.'
+jin.filesystem.init()
+jin.filesystem.mount(jin._argv[2])
+
+local conf = {}
+if jin.filesystem.exist("config.lua") then
+ conf = require "config"
+end
+conf.width = conf.width or 576
+conf.height = conf.height or 448
+conf.fps = conf.fps or 60
+conf.vsync = conf.vsync or false
+conf.title = conf.title or ("jin v" .. jin.version())
+conf.resizable = conf.resizable or false
+conf.fullscreen = conf.fullscreen or false
+
+-- initialize subsystems
+jin.graphics.init(conf)
+jin.audio.init()
+
+local function call(func, ...)
+ if func then
+ return func(...)
+ end
+end
+
+jin.core.setHandler = function(handler)
+ if handler == nil then
+ return
+ end
+ jin.core.onLoad = handler.onLoad
+ jin.core.onEvent = handler.onEvent
+ jin.core.onUpdate = handler.onUpdate
+ jin.core.onDraw = handler.onDraw
+end
+
+function jin.core.run()
+ call(jin.core.onLoad)
+ local previous = jin.time.second()
+ local SEC_PER_UPDATE = 1 / conf.fps
+ local dt = SEC_PER_UPDATE
+ local running = true
+ while(jin.core.running()) do
+ for _, e in pairs(jin.event.poll()) do
+ if e.type == "keydown" then
+ jin.keyboard.set(e.key, true)
+ elseif e.type == "keyup" then
+ jin.keyboard.set(e.key, false)
+ end
+ call(jin.core.onEvent, e)
+ running = jin.core.running()
+ if not running then break end
+ end
+ if not running then break end
+
+ call(jin.core.onUpdate, dt)
+
+ jin.graphics.unbind()
+ jin.graphics.clear()
+ jin.graphics.color()
+ jin.graphics.study()
+ call(jin.core.onDraw)
+ jin.graphics.present()
+
+ local current = jin.time.second()
+ dt = current - previous
+ local wait = SEC_PER_UPDATE - dt
+ previous = previous + SEC_PER_UPDATE
+ if wait > 0 then
+ dt = SEC_PER_UPDATE
+ jin.time.sleep(wait)
+ else
+ previous = current
+ end
+ end
+end
+
+local function onError(msg)
+ local tab = ' '
+ print("Error:\n" .. msg)
+ function jin.core.onEvent(e)
+ if e.type == 'quit' then
+ jin.core.stop()
+ end
+ end
+ local ww, wh = jin.graphics.size()
+ function jin.core.onDraw()
+ jin.graphics.write("Error: ", 10, 10, 30, 3, 30)
+ jin.graphics.write(msg, 10, 50)
+ end
+end
+
+-------------------------------------------------------------------------------
+-- No game handler
+-------------------------------------------------------------------------------
+
+jin.nogame = {
+ cs = 64,
+ sw = jin.graphics.getWidth(),
+ sh = jin.graphics.getHeight(),
+ cw = 0,
+ ch = 0,
+ ww = 6,
+ ww2 = 6*2,
+ speed = 4,
+ t = 0,
+ onLoad = function()
+ local nogame = jin.nogame
+ nogame.cw = nogame.sw / nogame.cs
+ nogame.ch = nogame.sh / nogame.cs
+ nogame.t = nogame.ww - 1
+ end,
+ onEvent = function(e)
+ if e.type == 'quit' then
+ jin.core.stop()
+ end
+ end,
+ onUpdate = function(dt)
+ local nogame = jin.nogame
+ nogame.t = nogame.t + dt * nogame.speed
+ if nogame.t > nogame.ww2 then
+ nogame.t = nogame.t - nogame.ww2
+ end
+ end,
+ circle = function(x, y, r)
+ local nogame = jin.nogame
+ if r % nogame.ww2 > nogame.ww then
+ return
+ end
+ r = math.sin((r/nogame.ww)*math.pi)*nogame.cs/2
+ local fact = (x + y) / nogame.ch * nogame.cw
+ jin.graphics.color(155 + 100 * math.sin(fact), 155 + 100 * math.cos(fact), 155 + 100 * math.sin(fact * fact), 255)
+ jin.graphics.circle("fill", x*nogame.cs + nogame.cs/2, y*nogame.cs + nogame.cs/2, r)
+ end,
+ onDraw = function()
+ local nogame = jin.nogame
+ for y = 0, nogame.ch - 1 do
+ for x = 0, nogame.cw - 1 do
+ nogame.circle(x, y, nogame.t+x+y)
+ end
+ end
+ end
+}
+
+-------------------------------------------------------------------------------
+-- Boot jin
+-------------------------------------------------------------------------------
+
+local function boot()
+ if jin.filesystem.exist("main.lua") then
+ -- require main game script
+ xpcall(function() require"main" end, onError)
+ jin.core.run()
+ else
+ -- no game
+ jin.core.setHandler(jin.nogame)
+ jin.core.run()
+ end
+ -- quit subsystems
+ jin.graphics.destroy()
+ jin.audio.destroy()
+ -- exit whole game
+ jin.core.quit()
+end
+
+xpcall(boot, onError)
+
+)";
diff --git a/src/lua/modules/embed/embed.h b/src/lua/modules/embed/embed.h
new file mode 100644
index 0000000..18ed1d8
--- /dev/null
+++ b/src/lua/modules/embed/embed.h
@@ -0,0 +1,49 @@
+#ifndef __JIN_LUA_EMBED_H
+#define __JIN_LUA_EMBED_H
+#include <cstring>
+
+namespace jin
+{
+namespace embed
+{
+
+ /**
+ * embed lua script to context.
+ */
+#define embed(L, script, name)\
+ if(luax_loadbuffer(L, script, strlen(script), name) == 0)\
+ lua_call(L, 0, 0);
+
+ /**
+ * embed structure.
+ */
+ struct jin_Embed
+ {
+ const char* file, *source;
+ };
+
+ static void boot(lua_State* L)
+ {
+ // embed scripts
+ #include "graphics.lua.h" // graphics
+ #include "keyboard.lua.h" // keyboard
+ #include "mouse.lua.h" // mouse
+ #include "boot.lua.h" // boot
+
+ // embed scripts
+ const jin_Embed scripts[] = {
+ { "graphics.lua", graphics_lua },
+ { "keyboard.lua", keyboard_lua },
+ { "mouse.lua", mouse_lua },
+ { "boot.lua", boot_lua },
+ { 0, 0 }
+ };
+
+ // load all emebd lua scripts
+ for (int i = 0; scripts[i].file; ++i)
+ embed(L, scripts[i].source, scripts[i].file);
+ }
+}
+}
+
+#endif \ No newline at end of file
diff --git a/src/lua/modules/embed/graphics.lua.h b/src/lua/modules/embed/graphics.lua.h
new file mode 100644
index 0000000..1414efc
--- /dev/null
+++ b/src/lua/modules/embed/graphics.lua.h
@@ -0,0 +1,4 @@
+/* graphics.lua */
+static const char* graphics_lua = R"(
+jin.graphics = jin.graphics or {}
+)";
diff --git a/src/lua/modules/embed/keyboard.lua.h b/src/lua/modules/embed/keyboard.lua.h
new file mode 100644
index 0000000..77bf3a9
--- /dev/null
+++ b/src/lua/modules/embed/keyboard.lua.h
@@ -0,0 +1,15 @@
+
+static const char* keyboard_lua = R"(
+jin.keyboard = jin.keyboard or {}
+
+local keys = {}
+
+function jin.keyboard.isDown(k)
+ return keys[k]
+end
+
+function jin.keyboard.set(k, status)
+ keys[k] = status
+end
+
+)";
diff --git a/src/lua/modules/embed/mouse.lua.h b/src/lua/modules/embed/mouse.lua.h
new file mode 100644
index 0000000..3c222f3
--- /dev/null
+++ b/src/lua/modules/embed/mouse.lua.h
@@ -0,0 +1,14 @@
+static const char* mouse_lua = R"(
+jin.mouse = jin.mouse or {}
+
+local button = {}
+
+function jin.mouse.isDown(btn)
+ return button[btn]
+end
+
+function jin.mouse.set(btn, status)
+ button[btn] = status
+end
+
+)"; \ No newline at end of file
diff --git a/src/lua/modules/embed/net.lua.h b/src/lua/modules/embed/net.lua.h
new file mode 100644
index 0000000..4d89dc7
--- /dev/null
+++ b/src/lua/modules/embed/net.lua.h
@@ -0,0 +1,4 @@
+/* net.lua */
+static const char* net_lua = R"(
+jin.net = jin.net or {}
+)"; \ No newline at end of file
diff --git a/src/lua/modules/embed/path.lua.h b/src/lua/modules/embed/path.lua.h
new file mode 100644
index 0000000..648adf8
--- /dev/null
+++ b/src/lua/modules/embed/path.lua.h
@@ -0,0 +1,14 @@
+/* path.lua */
+static const char* path_lua = R"(
+jin.path = jin.path or {}
+
+-- game root directory
+jin._root = nil
+
+-- return full path of a given path
+function jin.path.full(path)
+ local root = jin._dir .. '/' .. jin._argv[2]
+ return root .. '/' .. path
+end
+
+)"; \ No newline at end of file
diff --git a/src/lua/modules/event/luaopen_event.cpp b/src/lua/modules/event/luaopen_event.cpp
new file mode 100644
index 0000000..af9f8fc
--- /dev/null
+++ b/src/lua/modules/event/luaopen_event.cpp
@@ -0,0 +1,106 @@
+/**
+* Event module
+*/
+#include "lua/modules/luax.h"
+#include "libjin/jin.h"
+
+namespace jin
+{
+namespace lua
+{
+
+ using namespace jin::input;
+
+ /**
+ * Load event poll, return a iterator(a table).
+ */
+ static int l_event_poll(lua_State *L)
+ {
+ // table to store events
+ luax_newtable(L);
+ static Event e;
+ int i = 1;
+ poll:
+ while (pollEvent(&e))
+ {
+ // each event is a table
+ luax_newtable(L);
+ switch (e.type)
+ {
+ case EventType::QUIT:
+ luax_setfield_string(L, "type", "quit");
+ break;
+
+ case EventType::KEY_DOWN:
+ luax_setfield_string(L, "type", "keydown");
+ luax_setfield_string(L, "key", getKeyName(e.key.keysym.sym));
+ break;
+
+ case EventType::KEY_UP:
+ luax_setfield_string(L, "type", "keyup");
+ luax_setfield_string(L, "key", getKeyName(e.key.keysym.sym));
+ break;
+
+ case EventType::MOUSE_MOTION:
+ luax_setfield_string(L, "type", "mousemotion");
+ luax_setfield_number(L, "x", e.motion.x);
+ luax_setfield_number(L, "y", e.motion.y);
+ break;
+
+ case EventType::MOUSE_BUTTON_DOWN:
+ luax_setfield_string(L, "type", "mousebuttondown");
+ luax_setfield_string(L, "button", getButtonName(e.button.button));
+ luax_setfield_number(L, "x", e.button.x);
+ luax_setfield_number(L, "y", e.button.y);
+ break;
+
+ case EventType::MOUSE_BUTTON_UP:
+ luax_setfield_string(L, "type", "mousebuttonup");
+ luax_setfield_string(L, "button", getButtonName(e.button.button));
+ luax_setfield_number(L, "x", e.button.x);
+ luax_setfield_number(L, "y", e.button.y);
+ break;
+
+ case EventType::MOUSE_WHEEL:
+ luax_setfield_string(L, "type", "wheel");
+ if(e.wheel.x == -1)
+ luax_setfield_string(L, "x", "left");
+ else if(e.wheel.x == 1)
+ luax_setfield_string(L, "x", "right");
+ else
+ luax_setfield_string(L, "x", "none");
+ if (e.wheel.y == -1)
+ luax_setfield_string(L, "y", "near");
+ else if (e.wheel.y == 1)
+ luax_setfield_string(L, "y", "far");
+ else
+ luax_setfield_string(L, "y", "none");
+ break;
+
+ default:
+ /* ignore other events */
+ luax_pop(L, 1); // pop table out
+ goto poll;
+ break;
+ }
+ luax_rawseti(L, -2, i++);
+ }
+ return 1;
+ }
+
+ static const luaL_Reg f[] = {
+ { "poll", l_event_poll },
+ { 0, 0 }
+ };
+
+ /**
+ * load event module
+ */
+ int luaopen_event(lua_State* L)
+ {
+ luax_newlib(L, f);
+ return 1;
+ }
+
+} // lua
+} // jin \ No newline at end of file
diff --git a/src/lua/modules/filesystem/luaopen_filesystem.cpp b/src/lua/modules/filesystem/luaopen_filesystem.cpp
new file mode 100644
index 0000000..55f4c06
--- /dev/null
+++ b/src/lua/modules/filesystem/luaopen_filesystem.cpp
@@ -0,0 +1,137 @@
+#include "lua/modules/luax.h"
+#include "libjin/jin.h"
+#include <string>
+
+using namespace jin::filesystem;
+
+namespace jin
+{
+namespace lua
+{
+
+ static struct
+ {
+ Filesystem* fs;
+ } context;
+
+ static int l_init(lua_State* L)
+ {
+ context.fs = Filesystem::get();
+ return 0;
+ }
+
+ /**
+ * set current game root, like
+ * C:/jin/games/tank/
+ */
+ static int l_mount(lua_State* L)
+ {
+ const char* path = luax_checkstring(L, 1);
+ context.fs->mount(path);
+ return 0;
+ }
+
+ /**
+ *
+ */
+ static int l_isDir(lua_State *L)
+ {
+ const char* path = luax_checkstring(L, 1);
+ int r = context.fs->isDir(path);
+ luax_pushboolean(L, r);
+ return 1;
+ }
+
+ /**
+ *
+ */
+ static int l_exist(lua_State * L)
+ {
+ const char* path = luax_checkstring(L, 1);
+ int r = context.fs->exists(path);
+ luax_pushboolean(L, r);
+ return 1;
+ }
+
+ static int l_isdir(lua_State* L)
+ {
+ const char* path = luax_checkstring(L, 1);
+ int r = context.fs->isDir(path);
+ luax_pushboolean(L, r);
+ return 1;
+ }
+
+ // load but dont run it
+ static int loadf(lua_State* L)
+ {
+ const char* filename = lua_tostring(L, -1);
+ Buffer bf;
+ context.fs->read(filename, &bf);
+ luax_loadbuffer(L, (const char*)bf.data, bf.size, filename);
+ return 1;
+ }
+
+ static int loader(lua_State* L)
+ {
+ const char * filename = lua_tostring(L, -1);
+
+ std::string tmp(filename);
+ tmp += ".lua";
+
+ int size = tmp.size();
+
+ for (int i = 0; i<size - 4; ++i)
+ {
+ if (tmp[i] == '.')
+ {
+ tmp[i] = '/';
+ }
+ }
+
+ if (context.fs->exists(tmp.c_str()))
+ {
+ lua_pop(L, 1);
+ lua_pushstring(L, tmp.c_str());
+ return loadf(L);
+ }
+
+ tmp = filename;
+ size = tmp.size();
+ for (int i = 0; i<size; ++i)
+ {
+ if (tmp[i] == '.')
+ tmp[i] = '/';
+ }
+
+ if (context.fs->isDir(tmp.c_str()))
+ {
+ tmp += "/init.lua";
+ if (context.fs->exists(tmp.c_str()))
+ {
+ lua_pop(L, 1);
+ lua_pushstring(L, tmp.c_str());
+ return loadf(L);
+ }
+ }
+
+ lua_pushfstring(L, "\n\tno file \"%s\" in jin game directories.\n", (tmp + ".lua").c_str());
+ return 1;
+ }
+
+ static const luaL_Reg f[] = {
+ { "init", l_init },
+ { "mount", l_mount },
+ { "isdir", l_isDir },
+ { "exist", l_exist },
+ { 0, 0 }
+ };
+
+ int luaopen_filesystem(lua_State* L)
+ {
+ luax_newlib(L, f);
+ luax_register_searcher(L, loader, 1);
+ return 0;
+ }
+
+}
+} \ No newline at end of file
diff --git a/src/lua/modules/graphics/luaopen_Canvas.cpp b/src/lua/modules/graphics/luaopen_Canvas.cpp
new file mode 100644
index 0000000..d94e578
--- /dev/null
+++ b/src/lua/modules/graphics/luaopen_Canvas.cpp
@@ -0,0 +1,74 @@
+#include "lua/modules/luax.h"
+#include "lua/common/common.h"
+#include "libjin/jin.h"
+
+namespace jin
+{
+namespace lua
+{
+
+ using namespace jin::graphics;
+
+ typedef Ref<Canvas>& CanvasRef;
+
+ static inline CanvasRef checkCanvas(lua_State* L)
+ {
+ Proxy* proxy = (Proxy*)luax_checktype(L, 1, JIN_GRAPHICS_CANVAS);
+ return proxy->getRef<Canvas>();
+ }
+
+ static int l_getWidth(lua_State* L)
+ {
+ CanvasRef ref = checkCanvas(L);
+ luax_pushnumber(L, ref->getWidth());
+ return 1;
+ }
+
+ static int l_getHeight(lua_State* L)
+ {
+ CanvasRef ref = checkCanvas(L);
+ luax_pushnumber(L, ref->getHeight());
+ return 1;
+ }
+
+ static int l_getSize(lua_State* L)
+ {
+ CanvasRef ref = checkCanvas(L);
+ luax_pushnumber(L, ref->getWidth());
+ luax_pushnumber(L, ref->getHeight());
+ return 2;
+ }
+
+ static int l_setAnchor(lua_State* L)
+ {
+ CanvasRef ref = checkCanvas(L);
+ int x = luax_checknumber(L, 1);
+ int y = luax_checknumber(L, 2);
+ ref->setAnchor(x, y);
+ return 0;
+ }
+
+ static int l_gc(lua_State* L)
+ {
+ Proxy* proxy = (Proxy*)luax_checktype(L, 1, JIN_GRAPHICS_CANVAS);
+ proxy->release();
+ return 0;
+ }
+
+ static const luaL_Reg f[] = {
+ { "__gc", l_gc },
+ { "getWidth", l_getWidth },
+ { "getHeight", l_getHeight },
+ { "getSize", l_getSize },
+ { "setAnchor", l_setAnchor },
+ { 0, 0 }
+ };
+
+ int luaopen_Canvas(lua_State* L)
+ {
+ luax_newtype(L, JIN_GRAPHICS_CANVAS, f);
+ return 0;
+ }
+
+}// lua
+}// jin \ No newline at end of file
diff --git a/src/lua/modules/graphics/luaopen_Font.cpp b/src/lua/modules/graphics/luaopen_Font.cpp
new file mode 100644
index 0000000..c5789ad
--- /dev/null
+++ b/src/lua/modules/graphics/luaopen_Font.cpp
@@ -0,0 +1,48 @@
+#include "lua/modules/luax.h"
+#include "lua/common/common.h"
+#include "libjin/jin.h"
+
+namespace jin
+{
+namespace lua
+{
+
+ using namespace jin::graphics;
+
+ static int l_gc(lua_State* L)
+ {
+ Proxy* proxy = (Proxy*)luax_checktype(L, 1, JIN_GRAPHICS_FONT);
+ proxy->release();
+ return 0;
+ }
+
+ static int l_box(lua_State* L)
+ {
+ Proxy* proxy = (Proxy*)luax_newinstance(L, JIN_GRAPHICS_FONT, sizeof(Proxy));
+ Ref<Font>& ref = proxy->getRef<Font>();
+ const char* text = luax_checkstring(L, 2);
+ int fheight = luax_checknumber(L, 3);
+ int spacing = luax_checknumber(L, 4);
+ int lheight = luax_checknumber(L, 5);
+ int w, h;
+ ref->box(text, fheight, lheight, spacing, &w, &h);
+ luax_pushnumber(L, w);
+ luax_pushnumber(L, h);
+ return 2;
+ }
+
+ static const luaL_Reg f[] = {
+ { "__gc", l_gc },
+ { "box", l_box },
+ { 0, 0 }
+ };
+
+ int luaopen_Font(lua_State* L)
+ {
+ luax_newtype(L, JIN_GRAPHICS_FONT, f);
+
+ return 0;
+ }
+
+} // lua
+} // jin \ No newline at end of file
diff --git a/src/lua/modules/graphics/luaopen_Image.cpp b/src/lua/modules/graphics/luaopen_Image.cpp
new file mode 100644
index 0000000..0f68873
--- /dev/null
+++ b/src/lua/modules/graphics/luaopen_Image.cpp
@@ -0,0 +1,88 @@
+#include "lua/modules/luax.h"
+#include "lua/common/common.h"
+#include "libjin/jin.h"
+
+namespace jin
+{
+namespace lua
+{
+
+ using namespace jin::graphics;
+
+ typedef Texture Image;
+
+ static inline Ref<Image>& checkImage(lua_State* L)
+ {
+ Proxy* proxy = (Proxy*)luax_checktype(L, 1, JIN_GRAPHICS_IMAGE);
+ return proxy->getRef<Image>();
+ }
+
+ static int l_getWidth(lua_State* L)
+ {
+ Ref<Image>& ref = checkImage(L);
+ luax_pushnumber(L, ref->getWidth());
+ return 1;
+ }
+
+ static int l_getHeight(lua_State *L)
+ {
+ Ref<Image>& ref = checkImage(L);
+ luax_pushnumber(L, ref->getHeight());
+ return 1;
+ }
+
+ static int l_getPixel(lua_State* L)
+ {
+ Ref<Image>& ref = checkImage(L);
+ int x = luax_checknumber(L, 2);
+ int y = luax_checknumber(L, 3);
+ color c = ref->getPixel(x, y);
+ luax_pushnumber(L, c.rgba.r);
+ luax_pushnumber(L, c.rgba.g);
+ luax_pushnumber(L, c.rgba.b);
+ luax_pushnumber(L, c.rgba.a);
+ return 4;
+ }
+
+ static int l_setAnchor(lua_State* L)
+ {
+ Ref<Image>& ref = checkImage(L);
+ int x = luax_checknumber(L, 2);
+ int y = luax_checknumber(L, 3);
+ ref->setAnchor(x, y);
+ return 0;
+ }
+
+ static int l_getSize(lua_State* L)
+ {
+ Ref<Image>& ref = checkImage(L);
+ luax_pushnumber(L, ref->getWidth());
+ luax_pushnumber(L, ref->getHeight());
+ return 2;
+ }
+
+ static int l_gc(lua_State* L)
+ {
+ Proxy* proxy = (Proxy*)luax_checktype(L, 1, JIN_GRAPHICS_IMAGE);
+ proxy->release();
+ return 0;
+ }
+
+ static const luaL_Reg f[] = {
+ { "__gc", l_gc },
+ { "getWidth", l_getWidth },
+ { "getHeight", l_getHeight },
+ { "getSize", l_getSize },
+ { "getPixel", l_getPixel },
+ { "setAnchor", l_setAnchor },
+ { 0, 0 }
+ };
+
+ int luaopen_Image(lua_State* L)
+ {
+ luax_newtype(L, JIN_GRAPHICS_IMAGE, f);
+ return 0;
+ }
+
+}// graphics
+}// jin \ No newline at end of file
diff --git a/src/lua/modules/graphics/luaopen_JSL.cpp b/src/lua/modules/graphics/luaopen_JSL.cpp
new file mode 100644
index 0000000..c7a257a
--- /dev/null
+++ b/src/lua/modules/graphics/luaopen_JSL.cpp
@@ -0,0 +1,145 @@
+#include "lua/modules/luax.h"
+#include "lua/common/common.h"
+#include "libjin/jin.h"
+
+namespace jin
+{
+namespace lua
+{
+
+ using namespace jin::graphics;
+
+ typedef Texture Image;
+
+ static inline Ref<JSLProgram>& checkJSLProgram(lua_State* L)
+ {
+ Proxy* proxy = (Proxy*)luax_checktype(L, 1, JIN_GRAPHICS_SHADER);
+ return proxy->getRef<JSLProgram>();
+ }
+
+ static enum VARIABLE_TYPE
+ {
+ INVALID = 0,
+
+ NUMBER,
+ IMAGE,
+ CANVAS,
+ VEC2,
+ VEC3,
+ VEC4,
+ COLOR,
+ };
+
+ static VARIABLE_TYPE strToType(const char* str)
+ {
+ std::string s = std::string(str);
+ if (s == "number") return NUMBER;
+ else if (s == "Image") return IMAGE;
+ else if (s == "Canvas") return CANVAS;
+ else if (s == "vec2") return VEC2;
+ else if (s == "vec3") return VEC3;
+ else if (s == "vec4") return VEC4;
+ else if (s == "Color") return COLOR;
+ else return INVALID;
+ }
+
+ /**
+ * Use send function send variables to JSL program.
+ */
+ static int l_send(lua_State* L)
+ {
+ Ref<JSLProgram>& ref = checkJSLProgram(L);
+ // number Image Texel
+ const char* typestr = luax_checkstring(L, 2);
+ // variable name
+ const char* variable = luax_checkstring(L, 3);
+ if (typestr != nullptr)
+ {
+ int type = strToType(typestr);
+ switch (type)
+ {
+ case NUMBER:
+ {
+ float number = luax_checknumber(L, 4);
+ ref->sendFloat(variable, number);
+ break;
+ }
+ case IMAGE:
+ {
+ Proxy* proxy = (Proxy*)luax_checktype(L, 4, JIN_GRAPHICS_IMAGE);
+ Ref<Image>& tex = proxy->getRef<Image>();
+ ref->sendTexture(variable, tex.getObject());
+ break;
+ }
+ case CANVAS:
+ {
+ Proxy* proxy = (Proxy*)luax_checktype(L, 4, JIN_GRAPHICS_CANVAS);
+ Ref<Canvas>& canvas = proxy->getRef<Canvas>();
+ ref->sendCanvas(variable, canvas.getObject());
+ break;
+ }
+ case VEC2:
+ {
+ float x = luax_checknumber(L, 4);
+ float y = luax_checknumber(L, 5);
+ ref->sendVec2(variable, x, y);
+ break;
+ }
+ case VEC3:
+ {
+ float x = luax_checknumber(L, 4);
+ float y = luax_checknumber(L, 5);
+ float z = luax_checknumber(L, 6);
+ ref->sendVec3(variable, x, y, z);
+ break;
+ }
+ case VEC4:
+ {
+ float x = luax_checknumber(L, 4);
+ float y = luax_checknumber(L, 5);
+ float z = luax_checknumber(L, 6);
+ float w = luax_checknumber(L, 7);
+ ref->sendVec4(variable, x, y, z, w);
+ break;
+ }
+ case COLOR:
+ {
+ color col;
+ col.rgba.r = luax_checkinteger(L, 4);
+ col.rgba.g = luax_checkinteger(L, 5);
+ col.rgba.b = luax_checkinteger(L, 6);
+ col.rgba.a = luax_checkinteger(L, 7);
+ ref->sendColor(variable, &col);
+ break;
+ }
+ default:
+ return 0;
+ }
+ }
+ return 1;
+ }
+
+ static int l_gc(lua_State* L)
+ {
+ Proxy* proxy = (Proxy*)luax_checktype(L, 1, JIN_GRAPHICS_SHADER);
+ proxy->release();
+ return 0;
+ }
+
+ static const luaL_Reg f[] = {
+ { "__gc", l_gc },
+ { "send", l_send },
+ { 0, 0 }
+ };
+
+ /**
+ * JSL program
+ */
+ int luaopen_JSL(lua_State* L)
+ {
+ luax_newtype(L, JIN_GRAPHICS_SHADER, f);
+ return 0;
+ }
+
+}
+} \ No newline at end of file
diff --git a/src/lua/modules/graphics/luaopen_graphics.cpp b/src/lua/modules/graphics/luaopen_graphics.cpp
new file mode 100644
index 0000000..f0a7f5b
--- /dev/null
+++ b/src/lua/modules/graphics/luaopen_graphics.cpp
@@ -0,0 +1,493 @@
+#include "lua/modules/luax.h"
+#include "libjin/jin.h"
+#include "lua/common/common.h"
+#include "lua/modules/embed/graphics.lua.h"
+
+namespace jin
+{
+namespace lua
+{
+ using namespace jin::graphics;
+ using jin::filesystem::Filesystem;
+ using jin::filesystem::Buffer;
+
+ typedef Texture Image;
+
+ static struct
+ {
+ color curRenderColor;
+ Font* curFont = nullptr;
+ Font* defaultFont = nullptr;
+ } context;
+
+ static int l_init(lua_State* L)
+ {
+ Window* wnd = Window::get();
+ Window::Setting setting;
+ setting.width = luax_getfield_integer(L, 1, "width");
+ setting.height = luax_getfield_integer(L, 1, "height");
+ setting.title = luax_getfield_string(L, 1, "title");
+ setting.vsync = luax_getfield_bool(L, 1, "vsync");
+ setting.fullscreen = luax_getfield_bool(L, 1, "fullscreen");
+ setting.resizable= luax_getfield_bool(L, 1, "resizable");
+ if (!wnd->init(&setting))
+ {
+ luax_pushboolean(L, false);
+ return 1;
+ }
+ luax_pushboolean(L, true);
+ return 1;
+ }
+
+ static int l_destroy(lua_State* L)
+ {
+ Window* wnd = Window::get();
+ wnd->quit();
+ return 0;
+ }
+
+ static int l_getSize(lua_State* L)
+ {
+ Window* wnd = Window::get();
+ luax_pushnumber(L, wnd->getW());
+ luax_pushnumber(L, wnd->getH());
+ return 2;
+ }
+
+ static int l_getWidth(lua_State* L)
+ {
+ Window* wnd = Window::get();
+ luax_pushnumber(L, wnd->getW());
+ return 1;
+ }
+
+ static int l_getHeight(lua_State* L)
+ {
+ Window* wnd = Window::get();
+ luax_pushnumber(L, wnd->getH());
+ return 1;
+ }
+
+ static int l_newImage(lua_State* L)
+ {
+ Filesystem* fs = Filesystem::get();
+ const char* f = luax_checkstring(L, 1);
+ if (!fs->exists(f))
+ {
+ printf("Error: no such image %s\n", f);
+ exit(1);
+ }
+ Buffer b;
+ fs->read(f, &b);
+
+ Proxy* proxy = (Proxy*)luax_newinstance(L, JIN_GRAPHICS_IMAGE, sizeof(Proxy));
+ Image* img = Image::createTexture(b.data, b.size);
+ proxy->bind(new Ref<Image>(img, JIN_GRAPHICS_IMAGE));
+ return 1;
+ }
+
+ static int l_newShader(lua_State* L)
+ {
+ Proxy* proxy = (Proxy*)luax_newinstance(L, JIN_GRAPHICS_SHADER, sizeof(Proxy));
+ const char* program = luax_checkstring(L, 1);
+ JSLProgram* jsl = JSLProgram::createJSLProgram(program);
+ proxy->bind(new Ref<JSLProgram>(jsl, JIN_GRAPHICS_SHADER));
+ return 1;
+ }
+
+ static int l_newCanvas(lua_State* L)
+ {
+ int w = luax_checknumber(L, 1);
+ int h = luax_checknumber(L, 2);
+ Proxy* proxy = (Proxy*)luax_newinstance(L, JIN_GRAPHICS_CANVAS, sizeof(Proxy));
+ Canvas* cvs = Canvas::createCanvas(w, h);
+ proxy->bind(new Ref<Canvas>(cvs, JIN_GRAPHICS_CANVAS));
+ return 1;
+ }
+
+ static int l_clear(lua_State* L)
+ {
+ if (luax_gettop(L) == 0)
+ {
+ glClearColor(0, 0, 0, 1);
+ }
+ else
+ {
+ int r = luax_checknumber(L, 1);
+ int g = luax_checknumber(L, 2);
+ int b = luax_checknumber(L, 3);
+ int a = luax_checknumber(L, 4);
+ glClearColor(r / 255.f, g / 255.f, b / 255.f, a / 255.f);
+ }
+ glClear(GL_COLOR_BUFFER_BIT);
+ return 0;
+ }
+
+ static int l_present(lua_State* L)
+ {
+ Window::get()->swapBuffers();
+ return 0;
+ }
+
+ static int l_draw(lua_State* L)
+ {
+ int x = luax_optnumber(L, 2, 0);
+ int y = luax_optnumber(L, 3, 0);
+ float sx = luax_optnumber(L, 4, 1);
+ float sy = luax_optnumber(L, 5, 1);
+ float r = luax_optnumber(L, 6, 0);
+ if (luax_istype(L, 1, JIN_GRAPHICS_IMAGE))
+ {
+ Proxy* proxy = (Proxy*)luax_toudata(L, 1);
+ Ref<Image>& tex = proxy->getRef<Image>();
+ tex->draw(x, y, sx, sy, r);
+ }
+ else if (luax_istype(L, 1, JIN_GRAPHICS_CANVAS))
+ {
+ Proxy* proxy = (Proxy*)luax_toudata(L, 1);
+ Ref<Canvas>& p = proxy->getRef<Canvas>();
+ p->draw(x, y, sx, sy, r);
+ }
+ else
+ {
+ /* wrong type */
+ luax_typerror(L, 1, "image or canvas");
+ }
+ return 0;
+ }
+
+ static int l_setColor(lua_State* L)
+ {
+ if (luax_gettop(L) == 0)
+ {
+ glColor4f(1, 1, 1, 1);
+ return 0;
+ }
+
+ context.curRenderColor.rgba.r = luax_checknumber(L, 1);
+ context.curRenderColor.rgba.g = luax_checknumber(L, 2);
+ context.curRenderColor.rgba.b = luax_checknumber(L, 3);
+ context.curRenderColor.rgba.a = luax_checknumber(L, 4);
+
+ glColor4f(context.curRenderColor.rgba.r / 255.f,
+ context.curRenderColor.rgba.g / 255.f,
+ context.curRenderColor.rgba.b / 255.f,
+ context.curRenderColor.rgba.a / 255.f);
+ return 0;
+ }
+
+ static int l_getColor(lua_State * L)
+ {
+ luax_pushnumber(L, context.curRenderColor.rgba.r);
+ luax_pushnumber(L, context.curRenderColor.rgba.g);
+ luax_pushnumber(L, context.curRenderColor.rgba.b);
+ luax_pushnumber(L, context.curRenderColor.rgba.a);
+ return 4;
+ }
+
+ static int l_bindCanvas(lua_State* L)
+ {
+ if (luax_gettop(L) == 0)
+ {
+ // bind to default canvas
+ Canvas::unbind();
+ return 0;
+ }
+ Proxy* proxy = (Proxy*)luax_checktype(L, 1, JIN_GRAPHICS_CANVAS);
+ Ref<Canvas>& ref = proxy->getRef<Canvas>();
+ ref->bind();
+ return 0;
+ }
+
+ static int l_unbindCanvas(lua_State* L)
+ {
+ Canvas::unbind();
+ return 0;
+ }
+
+ static int l_useShader(lua_State* L)
+ {
+ if (luax_gettop(L) == 0)
+ {
+ JSLProgram::unuse();
+ return 0;
+ }
+ if (luax_istype(L, 1, JIN_GRAPHICS_SHADER))
+ {
+ Proxy* proxy = (Proxy*)luax_toudata(L, 1);
+ Ref<JSLProgram>& jsl = proxy->getRef<JSLProgram>();
+ jsl->use();
+ }
+ else
+ {
+ luax_typerror(L, 1, "JSL shader");
+ }
+ return 0;
+ }
+
+ static int l_unuseShader(lua_State* L)
+ {
+ JSLProgram::unuse();
+ return 0;
+ }
+
+ static int l_setBlend(lua_State* L)
+ {
+
+ return 0;
+ }
+
+ static RENDER_MODE strtomode(const char* str)
+ {
+ std::string s = std::string(str);
+ if (s == "fill") return RENDER_MODE::FILL;
+ else if (s == "line") return RENDER_MODE::LINE;
+ else return RENDER_MODE::NONE;
+ }
+
+ static int l_drawpoint(lua_State* L)
+ {
+ int x = luax_checknumber(L, 1);
+ int y = luax_checknumber(L, 2);
+ jin::graphics::point(x, y);
+
+ return 0;
+ }
+
+ static int l_drawLine(lua_State* L)
+ {
+ int x1 = luax_checknumber(L, 1);
+ int y1 = luax_checknumber(L, 2);
+ int x2 = luax_checknumber(L, 3);
+ int y2 = luax_checknumber(L, 4);
+ jin::graphics::line(x1, y1, x2, y2);
+
+ return 0;
+ }
+
+ static int l_drawRect(lua_State* L)
+ {
+ const char* modestr = luax_checkstring(L, 1);
+ RENDER_MODE mode = strtomode(modestr);
+ if (mode != RENDER_MODE::NONE)
+ {
+ int x = luax_checknumber(L, 2);
+ int y = luax_checknumber(L, 3);
+ int w = luax_checknumber(L, 4);
+ int h = luax_checknumber(L, 5);
+ rect(mode, x, y, w, h);
+ }
+ else
+ {
+ luax_typerror(L, 1, "'fill' or 'line'");
+ return 1;
+ }
+
+ return 0;
+ }
+
+ static int l_drawCircle(lua_State* L)
+ {
+ const char* modestr = luax_checkstring(L, 1);
+ RENDER_MODE mode = strtomode(modestr);
+ if (mode != RENDER_MODE::NONE)
+ {
+ int x = luax_checknumber(L, 2);
+ int y = luax_checknumber(L, 3);
+ float r = luax_checknumber(L, 4);
+ circle(mode, x, y, r);
+ }
+ else
+ {
+ luax_typerror(L, 1, "'fill' or 'line'");
+ return 1;
+ }
+
+ return 0;
+ }
+
+ static int l_drawTriangle(lua_State* L)
+ {
+ const char* modestr = luax_checkstring(L, 1);
+ RENDER_MODE mode = strtomode(modestr);
+ if (mode != RENDER_MODE::NONE)
+ {
+ int x = luax_checknumber(L, 2);
+ int y = luax_checknumber(L, 3);
+
+ int x2 = luax_checknumber(L, 3);
+ int y2 = luax_checknumber(L, 4);
+
+ int x3 = luax_checknumber(L, 5);
+ int y3 = luax_checknumber(L, 6);
+
+ triangle(mode, x, y, x2, y2, x3, y3);
+ }
+ else
+ {
+ luax_typerror(L, 1, "'fill' or 'line'");
+ return 1;
+ }
+
+ return 0;
+ }
+
+ static int l_drawPolygon(lua_State* L)
+ {
+ const char* modestr = luax_checkstring(L, 1);
+ int n = luax_checknumber(L, 2);
+ RENDER_MODE mode = strtomode(modestr);
+ if (mode != RENDER_MODE::NONE)
+ {
+ if (!luax_istable(L, 3))
+ {
+ luax_typerror(L, 3, "table");
+ return 1;
+ }
+ int tn = luax_tableidxlen(L, 3);
+ if (tn != n * 2)
+ {
+ static char* emsg = \
+ "number of polygon vertices doesn't match " \
+ "provided n, expect %d numbers but get %d";
+ luax_error(L, emsg, n * 2, tn);
+ return 1;
+ }
+ float* p = new float[2 * n];
+ for (int i = 1; i <= 2 * n; ++i)
+ p[i - 1] = luax_rawgetnumber(L, 3, i);
+ polygon(mode, p, n);
+ delete[] p;
+ }
+ else
+ {
+ luax_typerror(L, 1, "'fill' or 'line'");
+ return 1;
+ }
+
+ return 0;
+ }
+
+ static int l_newFont(lua_State* L)
+ {
+ Proxy* proxy = (Proxy*)luax_newinstance(L, JIN_GRAPHICS_FONT, sizeof(Proxy));
+ Font* font = new Font();
+ {
+ const char* path = luax_checkstring(L, 1);
+ Filesystem* fs = Filesystem::get();
+ Buffer b = {};
+ if (!fs->exists(path))
+ {
+ printf("Error: no such font %s\n", path);
+ exit(1);
+ }
+ fs->read(path, &b);
+ font->loadb((const unsigned char*)b.data);
+ }
+ proxy->bind(new Ref<Font>(font, JIN_GRAPHICS_FONT));
+ return 1;
+ }
+
+ static int l_study(lua_State* L)
+ {
+ int n = luax_gettop(L);
+ if (n == 0)
+ {
+ if (context.defaultFont == 0)
+ {
+ #include "lua/resources/font.ttf.h"
+ // load default font
+ context.defaultFont = new Font();
+ context.defaultFont->loadb(font_ttf);
+ }
+ context.curFont = context.defaultFont;
+ return 0;
+ }
+ Font* font = (Font*)luax_checktype(L, 1, JIN_GRAPHICS_FONT);
+ context.curFont = font;
+ return 0;
+ }
+
+ static int l_write(lua_State* L)
+ {
+ if (context.curFont == 0)
+ return 0;
+
+ const char* text = luax_checkstring(L, 1);
+ int x = luax_checknumber(L, 2);
+ int y = luax_checknumber(L, 3);
+
+ int fh = luax_optnumber(L, 4, 15);
+ int spacing = luax_optnumber(L, 5, 1);
+ int lh = luax_optnumber(L, 6, 18);
+
+ context.curFont->render(text, x, y, fh, spacing, lh);
+
+ return 0;
+ }
+
+ static int l_box(lua_State* L)
+ {
+ const char* text = luax_checkstring(L, 1);
+ int fontheight = luax_checknumber(L, 2);
+ int spacing = luax_checknumber(L, 3);
+ int lineheight = luax_checknumber(L, 4);
+ int w, h;
+ context.curFont->box(text, fontheight, spacing, lineheight, &w, &h);
+ luax_pushnumber(L, w);
+ luax_pushnumber(L, h);
+ return 2;
+ }
+
+ static const luaL_Reg f[] = {
+ { "init", l_init },
+ { "size", l_getSize },
+ { "getWidth", l_getWidth },
+ { "getHeight", l_getHeight },
+ { "newImage", l_newImage },
+ { "newShader", l_newShader },
+ { "newCanvas", l_newCanvas },
+ { "newFont", l_newFont },
+ { "box", l_box },
+ { "write", l_write },
+ { "clear", l_clear },
+ { "draw", l_draw },
+ { "color", l_setColor },
+ { "palette", l_getColor },
+ { "present", l_present },
+ { "study", l_study },
+ { "bind", l_bindCanvas },
+ { "unbind", l_unbindCanvas },
+ { "use", l_useShader },
+ { "unuse", l_unuseShader },
+ { "point", l_drawpoint },
+ { "line", l_drawLine },
+ { "rect", l_drawRect },
+ { "circle", l_drawCircle },
+ { "triangle", l_drawTriangle },
+ { "polygon", l_drawPolygon },
+ { "destroy", l_destroy },
+ { 0, 0 }
+ };
+
+ extern int luaopen_Image(lua_State* L);
+ extern int luaopen_Font(lua_State* L);
+ extern int luaopen_Canvas(lua_State* L);
+ extern int luaopen_JSL(lua_State* L);
+
+ int luaopen_graphics(lua_State* L)
+ {
+ // register types
+ luaopen_Image(L);
+ luaopen_Canvas(L);
+ luaopen_Font(L);
+ luaopen_JSL(L);
+
+ // load whole lib
+ luax_newlib(L, f);
+
+ return 1;
+ }
+
+}// lua
+}// jin \ No newline at end of file
diff --git a/src/lua/modules/joypad/luaopen_joypad.cpp b/src/lua/modules/joypad/luaopen_joypad.cpp
new file mode 100644
index 0000000..d305878
--- /dev/null
+++ b/src/lua/modules/joypad/luaopen_joypad.cpp
@@ -0,0 +1,21 @@
+#include "libjin/jin.h"
+#include "lua/modules/luax.h"
+
+namespace jin
+{
+namespace lua
+{
+
+ static const luaL_Reg f[] = {
+ { 0, 0 }
+ };
+
+ int luaopen_joypad(lua_State* L)
+ {
+ luax_newlib(L, f);
+
+ return 1;
+ }
+
+}
+} \ No newline at end of file
diff --git a/src/lua/modules/keyboard/luaopen_keyboard.cpp b/src/lua/modules/keyboard/luaopen_keyboard.cpp
new file mode 100644
index 0000000..9d27a4f
--- /dev/null
+++ b/src/lua/modules/keyboard/luaopen_keyboard.cpp
@@ -0,0 +1,16 @@
+#include "lua/modules/luax.h"
+#include "lua/modules/embed/keyboard.lua.h"
+
+namespace jin
+{
+namespace lua
+{
+
+ int luaopen_keyboard(lua_State* L)
+ {
+ luax_newlib(L, 0);
+ return 1;
+ }
+
+}
+} \ No newline at end of file
diff --git a/src/lua/modules/luaopen_jin.cpp b/src/lua/modules/luaopen_jin.cpp
new file mode 100644
index 0000000..dbbac31
--- /dev/null
+++ b/src/lua/modules/luaopen_jin.cpp
@@ -0,0 +1,104 @@
+#include "luaopen_jin.h"
+#include "lua/modules/luax.h"
+#include "embed/embed.h"
+
+namespace jin
+{
+namespace lua
+{
+
+ extern int luaopen_core(lua_State* L);
+ extern int luaopen_graphics(lua_State* L);
+ extern int luaopen_audio(lua_State* L);
+ extern int luaopen_net(lua_State* L);
+ extern int luaopen_event(lua_State* L);
+ extern int luaopen_time(lua_State* L);
+ extern int luaopen_mouse(lua_State* L);
+ extern int luaopen_keyboard(lua_State* L);
+ extern int luaopen_filesystem(lua_State* L);
+ extern int luaopen_joypad(lua_State* L);
+ extern int luaopen_math(lua_State* L);
+ extern int luaopen_thread(lua_State* L);
+ extern int luaopen_bit(lua_State* L);
+
+ static int l_getversion(lua_State* L)
+ {
+ luax_pushstring(L, VERSION);
+ return 1;
+ }
+
+ static int l_getAuthor(lua_State* L)
+ {
+ luax_pushstring(L, AUTHOR);
+ return 1;
+ }
+
+ static int l_getOS(lua_State* L)
+ {
+ #ifdef _WIN32
+ luax_pushstring(L, "windows");
+ #elif defined __unix__
+ luax_pushstring(L, "unix");
+ #elif defined __APPLE__
+ luax_pushstring(L, "macos");
+ #endif
+ return 1;
+ }
+
+ static int l_revision(lua_State* L)
+ {
+ luax_pushnumber(L, REVISION);
+ return 1;
+ }
+
+ static const luaL_Reg f[] = {
+ { "version", l_getversion },
+ { "revision", l_revision },
+ { "author", l_getAuthor },
+ { "os", l_getOS },
+ { 0, 0 }
+ };
+
+ // submodules
+ static const luaL_Reg mods[] = {
+ { "core", luaopen_core },
+ { "event", luaopen_event },
+ { "graphics", luaopen_graphics },
+ { "time", luaopen_time },
+ { "mouse", luaopen_mouse },
+ { "keyboard", luaopen_keyboard },
+ { "filesystem", luaopen_filesystem },
+ { "net", luaopen_net },
+ { "audio", luaopen_audio },
+ { "joypad", luaopen_joypad },
+ { "math", luaopen_math },
+ { "thread", luaopen_thread },
+ { "bit", luaopen_bit },
+ { 0, 0 }
+ };
+
+ int luaopen_jin(lua_State* L)
+ {
+ // jin module is on top of the stack
+ luax_newlib(L, f);
+
+ // set to global field
+ luax_justglobal(L, -1, MODULE_NAME);
+
+ // register submodules
+ for (int i = 0; mods[i].name; ++i)
+ {
+ mods[i].func(L);
+ luax_setfield(L, -2, mods[i].name);
+ }
+
+ return 1;
+ }
+
+ void boot(lua_State* L)
+ {
+ jin::embed::boot(L);
+ }
+
+} // lua
+} // jin \ No newline at end of file
diff --git a/src/lua/modules/luaopen_jin.h b/src/lua/modules/luaopen_jin.h
new file mode 100644
index 0000000..07531b2
--- /dev/null
+++ b/src/lua/modules/luaopen_jin.h
@@ -0,0 +1,42 @@
+/**
+* Copyright (C) 2016~2018 chai
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copyof
+* this software and associated documentation files (the "Software"), to deal in
+* the Software without restriction, including without limitation the rights to use,
+* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
+* Software, and to permit persons to whom the Software is furnished to do so,
+* subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all
+* copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef __JIN_M_JIN_H
+#define __JIN_M_JIN_H
+#include "luax.h"
+
+#define MODULE_NAME "jin"
+#define VERSION "0.1.1"
+#define REVISION 101
+#define AUTHOR "chai"
+
+namespace jin
+{
+namespace lua
+{
+
+ int luaopen_jin(lua_State* L);
+ void boot(lua_State* L);
+
+} // jin
+} // lua
+
+#endif // __JIN_M_JIN_H \ No newline at end of file
diff --git a/src/lua/modules/luax.h b/src/lua/modules/luax.h
new file mode 100644
index 0000000..89e456e
--- /dev/null
+++ b/src/lua/modules/luax.h
@@ -0,0 +1,7 @@
+#ifndef __JIN_LUA_LUAX_H
+#define __JIN_LUA_LUAX_H
+
+#include "LuaJIT/lua.hpp"
+#include "lua/libraries/luax/luax.h"
+
+#endif \ No newline at end of file
diff --git a/src/lua/modules/math/luaopen_math.cpp b/src/lua/modules/math/luaopen_math.cpp
new file mode 100644
index 0000000..fa59e04
--- /dev/null
+++ b/src/lua/modules/math/luaopen_math.cpp
@@ -0,0 +1,30 @@
+#include "lua/modules/luax.h"
+#include "libjin/jin.h"
+
+namespace jin
+{
+namespace lua
+{
+
+ static int l_mod(lua_State* L)
+ {
+ int n = luax_checkinteger(L, 1);
+ int m = luax_checkinteger(L, 2);
+ int mod = n % m;
+ luax_pushinteger(L, mod);
+ return 1;
+ }
+
+ static const luaL_Reg f[] = {
+ { "mod", l_mod },
+ { 0, 0 }
+ };
+
+ int luaopen_math(lua_State* L)
+ {
+ luax_newlib(L, f);
+ return 1;
+ }
+
+}
+} \ No newline at end of file
diff --git a/src/lua/modules/mouse/luaopen_mouse.cpp b/src/lua/modules/mouse/luaopen_mouse.cpp
new file mode 100644
index 0000000..f907abb
--- /dev/null
+++ b/src/lua/modules/mouse/luaopen_mouse.cpp
@@ -0,0 +1,31 @@
+#include "lua/modules/luax.h"
+#include "libjin/jin.h"
+
+namespace jin
+{
+namespace lua
+{
+ using namespace jin::input;
+
+ static int l_pos(lua_State* L)
+ {
+ static Mouse* mouse = Mouse::get();
+ int x, y;
+ mouse->getState(&x, &y);
+ luax_pushnumber(L, x);
+ luax_pushnumber(L, y);
+ return 2;
+ }
+
+ static const luaL_Reg f[] = {
+ { "position", l_pos },
+ { 0, 0 }
+ };
+
+ int luaopen_mouse(lua_State* L)
+ {
+ luax_newlib(L, f);
+ return 1;
+ }
+}
+} \ No newline at end of file
diff --git a/src/lua/modules/net/Buffer.h b/src/lua/modules/net/Buffer.h
new file mode 100644
index 0000000..31e6df8
--- /dev/null
+++ b/src/lua/modules/net/Buffer.h
@@ -0,0 +1,96 @@
+#ifndef __JIN_LUA_NET_NETBUFFER_H
+#define __JIN_LUA_NET_NETBUFFER_H
+
+#include <cstring>
+#include <cstdlib>
+#include "lua/common/common.h"
+
+namespace jin
+{
+namespace lua
+{
+namespace net
+{
+
+ class Buffer
+ {
+ public:
+ Buffer(size_t s = 0)
+ : size(s)
+ {
+ buffer = new char[size];
+ memset(buffer, 0, size);
+ }
+
+ Buffer(const char* data, size_t s)
+ : size(s)
+ {
+ buffer = new char[size];
+ memcpy(buffer, data, size);
+ }
+
+ ~Buffer()
+ {
+ if (buffer != nullptr)
+ {
+ delete[] buffer;
+ buffer = nullptr;
+ size = 0;
+ }
+ }
+
+ void append(const void* data, size_t s)
+ {
+ if (data == nullptr)
+ return;
+ char* buf = buffer;
+ buffer = new char[size + s];
+ memcpy(buffer, buf, size);
+ memcpy(buffer + size, data, s);
+ delete[] buf;
+ size += s;
+ return;
+ }
+
+ const char* grabString(int* length, int offset = 0)
+ {
+ int l = offset;
+ for (; l < size; ++l)
+ {
+ if (buffer[l] == 0)
+ break;
+ }
+ *length = l - offset + 1;
+ char* str = (char*)malloc(*length);
+ memcpy(str, buffer + offset, *length);
+ return str;
+ }
+
+ int grabInteger(int* length, int offset = 0)
+ {
+ *length = sizeof(int);
+ return *((int*)(buffer + offset));
+ }
+
+ float grabFloat(int* length, int offset = 0)
+ {
+ *length = sizeof(float);
+ return *((float*)(buffer + offset));
+ }
+
+ bool grabBoolean(int* length, int offset = 0)
+ {
+ *length = sizeof(bool);
+ return *((bool*)(buffer + offset));
+ }
+
+ char* buffer;
+ size_t size;
+
+ };
+
+} // net
+} // lua
+} // jin
+
+#endif \ No newline at end of file
diff --git a/src/lua/modules/net/luaopen_Buffer.cpp b/src/lua/modules/net/luaopen_Buffer.cpp
new file mode 100644
index 0000000..cb5b952
--- /dev/null
+++ b/src/lua/modules/net/luaopen_Buffer.cpp
@@ -0,0 +1,135 @@
+#include "lua/modules/luax.h"
+#include "lua/common/common.h"
+#include "libjin/jin.h"
+#include "Buffer.h"
+
+namespace jin
+{
+namespace lua
+{
+namespace net
+{
+
+ static inline Ref<Buffer>& checkNetBuffer(lua_State* L)
+ {
+ Proxy* proxy = (Proxy*)luax_checktype(L, 1, JIN_NETWORK_BUFFER);
+ return proxy->getRef<Buffer>();
+ }
+
+ // net.Buffer:append(value) -> value_length
+ static int l_append(lua_State* L)
+ {
+ Ref<Buffer>& ref = checkNetBuffer(L);
+ const int vp = 2;
+ if (luax_isintegerstrict(L, vp))
+ {
+ int n = luax_checkinteger(L, vp);
+ int size = sizeof(n);
+ ref->append(&n, size);
+ luax_pushinteger(L, size);
+ return 1;
+ }
+ else if (luax_isfloatstrict(L, vp))
+ {
+ float n = luax_checknumber(L, vp);
+ int size = sizeof(n);
+ ref->append(&n, size);
+ luax_pushinteger(L, size);
+ return 1;
+ }
+ else if (luax_isbooleanstrict(L, vp))
+ {
+ bool n = luax_checkbool(L, vp);
+ int size = sizeof(n);
+ ref->append(&n, size);
+ luax_pushinteger(L, size);
+ return 1;
+ }
+ else if (luax_isstringstrict(L, vp))
+ {
+ const char* str = luax_checkstring(L, vp);
+ int size = strlen(str) + 1;
+ ref->append(str, size);
+ luax_pushinteger(L, size);
+ return 1;
+ }
+ else
+ {
+ luax_typerror(L, vp, "number, bool or string");
+ return 0;
+ }
+ }
+
+ // net.Buffer:grabString(offset) -> string, length
+ static int l_grabString(lua_State* L)
+ {
+ Ref<Buffer>& ref = checkNetBuffer(L);
+ int offset = luax_checkinteger(L, 2);
+ int len;
+ const char* str = ref->grabString(&len, offset);
+ luax_pushstring(L, str);
+ luax_pushinteger(L, len);
+ return 2;
+ }
+
+ // net.Buffer:grabInteger(offset) -> integer, length
+ static int l_grabInteger(lua_State* L)
+ {
+ Ref<Buffer>& ref = checkNetBuffer(L);
+ int offset = luax_checkinteger(L, 2);
+ int len;
+ int integer = ref->grabInteger(&len, offset);
+ luax_pushinteger(L, integer);
+ luax_pushinteger(L, len);
+ return 2;
+ }
+
+ static int l_grabFloat(lua_State* L)
+ {
+ Ref<Buffer>& ref = checkNetBuffer(L);
+ int offset = luax_checkinteger(L, 2);
+ int len;
+ float floatv = ref->grabFloat(&len, offset);
+ luax_pushnumber(L, floatv);
+ luax_pushinteger(L, len);
+ return 2;
+ }
+
+ static int l_grabBoolean(lua_State* L)
+ {
+ Ref<Buffer>& ref = checkNetBuffer(L);
+ int offset = luax_checkinteger(L, 2);
+ int len;
+ bool boolean = ref->grabBoolean(&len, offset);
+ luax_pushboolean(L, boolean);
+ luax_pushinteger(L, len);
+ return 2;
+ }
+
+ static int l_gc(lua_State* L)
+ {
+ Proxy* proxy = (Proxy*)luax_checktype(L, 1, JIN_NETWORK_BUFFER);
+ proxy->release();
+ return 0;
+ }
+
+ static const luaL_Reg netbuffer_function[] = {
+ { "__gc", l_gc },
+ { "append", l_append },
+ { "grabString", l_grabString },
+ { "grabInteger", l_grabInteger },
+ { "grabBoolean", l_grabBoolean },
+ { "grabFloat", l_grabFloat },
+ { 0, 0 }
+ };
+
+} // net
+
+ int luaopen_Buffer(lua_State* L)
+ {
+ luax_newtype(L, JIN_NETWORK_BUFFER, net::netbuffer_function);
+ return 0;
+ }
+
+} // lua
+} // jin \ No newline at end of file
diff --git a/src/lua/modules/net/luaopen_Socket.cpp b/src/lua/modules/net/luaopen_Socket.cpp
new file mode 100644
index 0000000..2e5d9f3
--- /dev/null
+++ b/src/lua/modules/net/luaopen_Socket.cpp
@@ -0,0 +1,126 @@
+#include "lua/modules/luax.h"
+#include "lua/common/common.h"
+#include "libjin/jin.h"
+#include "Buffer.h"
+
+namespace jin
+{
+namespace lua
+{
+
+ using namespace jin::net;
+ using namespace lua::net;
+
+ const int BUFFER_SIZE = 1024;
+
+ static inline Ref<Socket>& checkSocket(lua_State* L, int pos = 1)
+ {
+ Proxy* proxy = (Proxy*)luax_checktype(L, pos, JIN_NETWORK_SOCKET);
+ return proxy->getRef<Socket>();
+ }
+
+ static inline Ref<Buffer>& checkNetBuffer(lua_State* L, int pos = 1)
+ {
+ Proxy* proxy = (Proxy*)luax_checktype(L, pos, JIN_NETWORK_BUFFER);
+ return proxy->getRef<Buffer>();
+ }
+
+ // return net.Socket
+ static int l_accept(lua_State* L)
+ {
+ Ref<Socket>& socket = checkSocket(L);
+ Socket* client = socket->accept();
+ Proxy* proxy = (Proxy*)luax_newinstance(L, JIN_NETWORK_SOCKET, sizeof(Proxy));
+ proxy->bind(new Ref<Socket>(client, JIN_NETWORK_SOCKET));
+ return 1;
+ }
+
+ // return net.Buffer
+ static int l_receive(lua_State* L)
+ {
+ Ref<Socket>& socket = checkSocket(L);
+ char buffer[BUFFER_SIZE] = {0};
+ int size = socket->receive(buffer, BUFFER_SIZE);
+ Proxy* proxy = (Proxy*)luax_newinstance(L, JIN_NETWORK_BUFFER, sizeof(Proxy));
+ net::Buffer* netBuffer = new net::Buffer(buffer, size);
+ proxy->bind(new Ref<Buffer>(netBuffer, JIN_NETWORK_BUFFER));
+ return 1;
+ }
+
+ // Socket:receiveFrom(address, port)
+ static int l_receiveFrom(lua_State* L)
+ {
+ Ref<Socket>& socket = checkSocket(L);
+ int address = luax_checkinteger(L, 2);
+ int port = luax_checkinteger(L, 3);
+ char buffer[BUFFER_SIZE];
+ int size = socket->receiveFrom(buffer, BUFFER_SIZE, address, port);
+ net::Buffer* netBuffer = new net::Buffer(buffer, size);
+ Proxy* proxy = (Proxy*)luax_newinstance(L, JIN_NETWORK_BUFFER, sizeof(Proxy));
+ proxy->bind(new Ref<Buffer>(netBuffer, JIN_NETWORK_BUFFER));
+ return 1;
+ }
+
+ // Socket:send(net.Buffer) -> data_length
+ static int l_send(lua_State* L)
+ {
+ Ref<Socket>& socket = checkSocket(L);
+ Ref<Buffer>& ref = checkNetBuffer(L, 2);
+ int len = socket->send(ref->buffer, ref->size);
+ luax_pushinteger(L, len);
+ return 1;
+ }
+
+ // Socket:sendTo(address, port, net.Buffer)
+ static int l_sendTo(lua_State* L)
+ {
+ Ref<Socket>& socket = checkSocket(L);
+ int address = luax_checkinteger(L, 2);
+ int port = luax_checkinteger(L, 3);
+ Ref<Buffer>& buffer = checkNetBuffer(L, 4);
+ socket->sendTo(buffer->buffer, buffer->size, address, port);
+ return 0;
+ }
+
+ static int l_close(lua_State* L)
+ {
+ Ref<Socket>& socket = checkSocket(L);
+ socket->close();
+ return 0;
+ }
+
+ static int l_configBlocking(lua_State* L)
+ {
+ Ref<Socket>& socket = checkSocket(L);
+ bool blocking = luax_checkbool(L, 2);
+ socket->configureBlocking(blocking);
+ return 0;
+ }
+
+ static int l_gc(lua_State* L)
+ {
+ Proxy* proxy = (Proxy*)luax_checktype(L, 1, JIN_NETWORK_SOCKET);
+ proxy->release();
+ return 0;
+ }
+
+ static const luaL_Reg socket_function[] = {
+ { "__gc", l_gc },
+ { "accept", l_accept },
+ { "receive", l_receive },
+ { "receiveFrom", l_receiveFrom },
+ { "send", l_send },
+ { "sendTo", l_sendTo },
+ { "close", l_close },
+ { "configBlocking", l_configBlocking },
+ { 0, 0 }
+ };
+
+ int luaopen_Socket(lua_State* L)
+ {
+ luax_newtype(L, JIN_NETWORK_SOCKET, socket_function);
+ return 0;
+ }
+
+} // lua
+} // jin \ No newline at end of file
diff --git a/src/lua/modules/net/luaopen_net.cpp b/src/lua/modules/net/luaopen_net.cpp
new file mode 100644
index 0000000..e7e55c4
--- /dev/null
+++ b/src/lua/modules/net/luaopen_net.cpp
@@ -0,0 +1,86 @@
+#include "lua/modules/luax.h"
+#include "libjin/jin.h"
+#include "lua/common/common.h"
+#include "Buffer.h"
+
+namespace jin
+{
+namespace lua
+{
+ using namespace jin::lua::net;
+ using namespace jin::net;
+
+ static int l_initNetwork(lua_State* L)
+ {
+ jin::net::Net::get()->init();
+ return 1;
+ }
+
+ // jin.net.Socket()
+ static int l_Socket(lua_State* L)
+ {
+ SocketInformation info = { 0 };
+ {
+ const char* socketType = luax_checkstring(L, 1);
+ if (strcmp(socketType, "TCP") == 0)
+ info.type = SocketType::TCP;
+ else if (strcmp(socketType, "UDP") == 0)
+ info.type = SocketType::UDP;
+ else
+ {
+ luax_error(L, "jin.net.Socket() first paramter wrong, must be TCP or UDP");
+ return 0;
+ }
+ // type, port
+ if (luax_gettop(L) == 2)
+ {
+ info.port = luax_checkinteger(L, 2);
+ }
+ // type, address, port
+ else if (luax_gettop(L) == 3)
+ {
+ if (luax_isstringstrict(L, 2))
+ info.address = tk_strtohl(luax_checkstring(L, 2));
+ else if (luax_isintegerstrict(L, 2))
+ info.address = luax_checkinteger(L, 2);
+ info.port = luax_checkinteger(L, 3);
+ }
+ }
+ Socket* socket = new Socket(info);
+ Proxy* proxy = (Proxy*)luax_newinstance(L, JIN_NETWORK_SOCKET, sizeof(Proxy));
+ proxy->bind(new Ref<Socket>(socket, JIN_NETWORK_SOCKET));
+ return 1;
+ }
+
+ // jin.net.Buffer()
+ static int l_Buffer(lua_State* L)
+ {
+ int size = luax_checkinteger(L, 1);
+ Proxy* proxy = (Proxy*)luax_newinstance(L, JIN_NETWORK_BUFFER, sizeof(Proxy));
+ net::Buffer* buffer = new net::Buffer(size);
+ proxy->bind(new Ref<Buffer>(buffer, JIN_NETWORK_BUFFER));
+ return 1;
+ }
+
+ static const luaL_Reg f[] = {
+ { "init", l_initNetwork },
+ { "newSocket", l_Socket },
+ { "newBuffer", l_Buffer },
+ { 0, 0 }
+ };
+
+ extern int luaopen_Socket(lua_State* L);
+ extern int luaopen_Buffer(lua_State* L);
+
+ int luaopen_net(lua_State* L)
+ {
+ luaopen_Socket(L);
+ luaopen_Buffer(L);
+
+ luax_newlib(L, f);
+
+ return 1;
+ }
+
+} // lua
+} // jin \ No newline at end of file
diff --git a/src/lua/modules/thread/Thread.cpp b/src/lua/modules/thread/Thread.cpp
new file mode 100644
index 0000000..8df3255
--- /dev/null
+++ b/src/lua/modules/thread/Thread.cpp
@@ -0,0 +1,14 @@
+#include "Thread.h"
+
+namespace jin
+{
+namespace lua
+{
+namespace thread
+{
+
+
+
+} // thread
+} // lua
+} // jin \ No newline at end of file
diff --git a/src/lua/modules/thread/Thread.h b/src/lua/modules/thread/Thread.h
new file mode 100644
index 0000000..645d4a1
--- /dev/null
+++ b/src/lua/modules/thread/Thread.h
@@ -0,0 +1,94 @@
+#include "libjin/jin.h"
+#include "lua/common/common.h"
+
+namespace jin
+{
+namespace lua
+{
+namespace thread
+{
+
+ class Thread
+ {
+ public:
+ typedef jin::thread::Thread::Variant Variant;
+ typedef jin::thread::Thread::ThreadRunner ThreadRunner;
+
+ Thread(std::string _name, std::string _code, ThreadRunner runner)
+ : name(_name)
+ , code(_code)
+ {
+ thread = new jin::thread::Thread(_name, runner);
+ }
+
+ ~Thread()
+ {
+ delete thread;
+ }
+
+ bool start(void* p)
+ {
+ return thread->start(p);
+ }
+
+ void wait()
+ {
+ thread->wait();
+ }
+
+ void send(int slot, const Variant& value)
+ {
+ thread->send(slot, value);
+ }
+
+ bool receive(int slot)
+ {
+ return thread->receive(slot);
+ }
+
+ Variant fetch(int slot)
+ {
+ return thread->fetch(slot);
+ }
+
+ Variant demand(int slot)
+ {
+ return thread->demand(slot);
+ }
+
+ void remove(int slot)
+ {
+ thread->remove(slot);
+ }
+
+ const char* getName()
+ {
+ return name.c_str();
+ }
+
+ bool isRunning()
+ {
+ return thread->isRunning();
+ }
+
+ void lock()
+ {
+ thread->lock();
+ }
+
+ void unlock()
+ {
+ thread->unlock();
+ }
+
+ const std::string name;
+ const std::string code;
+
+ private:
+ jin::thread::Thread* thread;
+
+ };
+
+} // thread
+} // lua
+} // jin \ No newline at end of file
diff --git a/src/lua/modules/thread/luaopen_thread.cpp b/src/lua/modules/thread/luaopen_thread.cpp
new file mode 100644
index 0000000..65a7c29
--- /dev/null
+++ b/src/lua/modules/thread/luaopen_thread.cpp
@@ -0,0 +1,248 @@
+#include "lua/modules/luax.h"
+#include "libjin/jin.h"
+#include "lua/modules/luaopen_jin.h"
+#include "lua/common/common.h"
+#include "Thread.h"
+
+namespace jin
+{
+namespace lua
+{
+
+ using thread::Thread;
+
+ int luaopen_thread(lua_State* L);
+
+ static inline Ref<Thread>& checkThread(lua_State* L)
+ {
+ Proxy* proxy = (Proxy*)luax_checktype(L, 1, JIN_THREAD_THREAD);
+ return proxy->getRef<Thread>();
+ }
+
+ static int threadRunner(void* t)
+ {
+ Ref<Thread>& ref = *(Ref<Thread>*)t;
+ lua_State* L = lua_open();
+ luax_openlibs(L);
+ luaopen_jin(L);
+ luax_getglobal(L, MODULE_NAME);
+ Proxy* proxy = (Proxy*)luax_newinstance(L, JIN_THREAD_THREAD, sizeof(Proxy));
+ ref.retain();
+ proxy->bind(&ref);
+ luax_setfield(L, -2, "_curThread");
+ luax_dostring(L, ref->code.c_str());
+ luax_close(L);
+ return 0;
+ }
+
+ static int l_thread_gc(lua_State* L)
+ {
+ Proxy* proxy = (Proxy*)luax_checktype(L, 1, JIN_THREAD_THREAD);
+ proxy->release();
+ return 0;
+ }
+
+ static int l_start(lua_State* L)
+ {
+ Ref<Thread>& ref = checkThread(L);
+ bool result = ref->start(&ref);
+ luax_pushboolean(L, result);
+ return 1;
+ }
+
+ static int l_wait(lua_State* L)
+ {
+ Ref<Thread>& ref = checkThread(L);
+ ref->wait();
+ return 0;
+ }
+
+ static int l_send(lua_State* L)
+ {
+ Ref<Thread>& ref = checkThread(L);
+ int slot = luax_checkinteger(L, 2);
+ const int vp = 3;
+ if (luax_isnumberstrict(L, vp))
+ {
+ float real = luax_checknumber(L, vp);
+ ref->send(slot, real);
+ }
+ else if (luax_isbooleanstrict(L, vp))
+ {
+ bool bol = luax_checkbool(L, vp);
+ ref->send(slot, bol);
+ }
+ else if (luax_isstringstrict(L, vp))
+ {
+ const char* str = luax_checkstring(L, vp);
+ ref->send(slot, str);
+ }
+ else if (luax_isuserdata(L, vp))
+ {
+ void* p = luax_touserdata(L, vp);
+ ref->send(slot, p);
+ }
+ else if (luax_islightuserdata(L, vp))
+ {
+ void* p = luax_tolightuserdata(L, vp);
+ ref->send(slot, p);
+ }
+ return 0;
+ }
+
+ static int l_receive(lua_State* L)
+ {
+ Ref<Thread>& ref = checkThread(L);
+ int slot = luax_checkinteger(L, 2);
+ bool result = ref->receive(slot);
+ luax_pushboolean(L, result);
+ return 1;
+ }
+
+ static int l_fetch(lua_State* L)
+ {
+ Ref<Thread>& ref = checkThread(L);
+ int slot = luax_checkinteger(L, 2);
+ Thread::Variant v = ref->fetch(slot);
+ switch (v.type)
+ {
+ case thread::Thread::Variant::INTERGER:
+ luax_pushinteger(L, v.integer);
+ break;
+
+ case thread::Thread::Variant::BOOLEAN:
+ luax_pushboolean(L, v.boolean);
+ break;
+
+ case thread::Thread::Variant::CSTRING:
+ luax_pushstring(L, v.cstring);
+ break;
+
+ case thread::Thread::Variant::REAL:
+ luax_pushnumber(L, v.real);
+ break;
+
+ case thread::Thread::Variant::POINTER:
+ Proxy* p = (Proxy*)v.pointer;
+ Proxy* proxy = (Proxy*)luax_newinstance(L, p->getObjectType(), sizeof(Proxy));
+ p->reference->retain();
+ proxy->bind(p->reference);
+ break;
+
+ }
+ return 1;
+ }
+
+ static int l_demand(lua_State* L)
+ {
+ Ref<Thread>& ref = checkThread(L);
+ int slot = luax_checkinteger(L, 2);
+ Thread::Variant v = ref->demand(slot);
+ switch (v.type)
+ {
+ case thread::Thread::Variant::INTERGER:
+ luax_pushinteger(L, v.integer);
+ break;
+
+ case thread::Thread::Variant::BOOLEAN:
+ luax_pushboolean(L, v.boolean);
+ break;
+
+ case thread::Thread::Variant::CSTRING:
+ luax_pushstring(L, v.cstring);
+ break;
+
+ case thread::Thread::Variant::REAL:
+ luax_pushnumber(L, v.real);
+ break;
+
+ case thread::Thread::Variant::POINTER:
+ Proxy* p = (Proxy*)v.pointer;
+ Proxy* proxy = (Proxy*)luax_newinstance(L, p->getObjectType(), sizeof(Proxy));
+ p->reference->retain();
+ proxy->bind(p->reference);
+ break;
+
+ }
+ return 1;
+ }
+
+ static int l_remove(lua_State* L)
+ {
+ Ref<Thread>& ref = checkThread(L);
+ int slot = luax_checkinteger(L, 2);
+ ref->remove(slot);
+ return 0;
+ }
+
+ static int l_getName(lua_State* L)
+ {
+ Ref<Thread>& ref = checkThread(L);
+ const char* name = ref->getName();
+ luax_pushstring(L, name);
+ return 1;
+ }
+
+ static int l_isRunning(lua_State* L)
+ {
+ Ref<Thread>& ref = checkThread(L);
+ bool running = ref->isRunning();
+ luax_pushboolean(L, running);
+ return 1;
+ }
+
+ static const luaL_Reg thread_function[] = {
+ { "__gc", l_thread_gc },
+ { "start", l_start },
+ { "wait", l_wait },
+ { "send", l_send },
+ { "receive", l_receive },
+ { "fetch", l_fetch },
+ { "demand", l_demand },
+ { "remove", l_remove },
+ { "getName", l_getName },
+ { "isRunning", l_isRunning },
+ { 0, 0 }
+ };
+
+ static int luaopen_Thread(lua_State* L)
+ {
+ luax_newtype(L, JIN_THREAD_THREAD, thread_function);
+
+ return 0;
+ }
+
+ static int l_newThread(lua_State* L)
+ {
+ const char* name = luax_checkstring(L, 1);
+ const char* code = luax_checkstring(L, 2);
+ Proxy* proxy = (Proxy*)luax_newinstance(L, JIN_THREAD_THREAD, sizeof(Proxy));
+ Thread* thread = new Thread(name, code, threadRunner);
+ proxy->bind(new Ref<Thread>(thread, JIN_THREAD_THREAD));
+ return 1;
+ }
+
+ static int l_getThread(lua_State* L)
+ {
+ luax_getglobal(L, MODULE_NAME);
+ luax_getfield(L, -1, "_curThread");
+ return 1;
+ }
+
+ static const luaL_Reg f[] = {
+ { "newThread", l_newThread },
+ { "getThread", l_getThread },
+ { 0, 0 }
+ };
+
+ int luaopen_thread(lua_State* L)
+ {
+ luaopen_Thread(L);
+
+ luax_newlib(L, f);
+
+ return 1;
+ }
+
+} // lua
+} // jin \ No newline at end of file
diff --git a/src/lua/modules/time/luaopen_time.cpp b/src/lua/modules/time/luaopen_time.cpp
new file mode 100644
index 0000000..39743b4
--- /dev/null
+++ b/src/lua/modules/time/luaopen_time.cpp
@@ -0,0 +1,38 @@
+#include "lua/modules/luax.h"
+#include <SDL2/SDL.h>
+#include "libjin/jin.h"
+
+namespace jin
+{
+namespace lua
+{
+
+ using namespace jin::time;
+
+ static int l_sec(lua_State* L)
+ {
+ luax_pushnumber(L, getSecond());
+ return 1;
+ }
+
+ static int l_sleep(lua_State* L)
+ {
+ double sec = luax_checknumber(L, 1);
+ sleep(sec * 1000.0f);
+ return 0;
+ }
+
+ static const luaL_Reg f[] = {
+ { "second", l_sec },
+ { "sleep", l_sleep },
+ { 0, 0 },
+ };
+
+ int luaopen_time(lua_State* L)
+ {
+ luax_newlib(L, f);
+ return 1;
+ }
+
+} // lua
+} // jin \ No newline at end of file