From 7ebeadc73c52eadef157665b848c6704ef8d176d Mon Sep 17 00:00:00 2001
From: Allanis <allanis@saracraft.net>
Date: Sun, 25 Aug 2013 19:34:27 +0100
Subject: [PATCH] [Change] Stage two of the lua API conversion, needs some
 heavy testing.

---
 dat/mission.xml                   |   2 +-
 dat/missions/cargo.lua            |  17 ++-
 dat/missions/emp_cargo00.lua      |   9 +-
 dat/missions/emp_collective00.lua |  23 ++--
 dat/missions/emp_collective01.lua |  10 +-
 dat/missions/emp_collective02.lua |   6 +-
 dat/missions/es_cargo.lua         |  12 +-
 snd/music.lua                     |   2 +-
 src/llua_space.c                  | 177 ++++++++++++++++++++----------
 src/llua_space.h                  |   3 +
 10 files changed, 162 insertions(+), 99 deletions(-)

diff --git a/dat/mission.xml b/dat/mission.xml
index f065ec3..d9ac6fc 100644
--- a/dat/mission.xml
+++ b/dat/mission.xml
@@ -46,7 +46,7 @@
    <unique>1</unique>
   </flags>
   <avail>
-   <cond>var.peek("es_cargo") == true and space.jumpDist("NGC-7291") &lt; 5 and player.getFaction("Empire") &gt; 5 and player.getRating() &gt; 10</cond>
+   <cond>var.peek("es_cargo") == true and space.getSystem("NGC-7291"):jumpDist() &lt; 5 and player.getFaction("Empire") &gt; 5 and player.getRating() &gt; 10</cond>
    <chance>60</chance>
    <location>Bar</location>
    <faction>Empire</faction>
diff --git a/dat/missions/cargo.lua b/dat/missions/cargo.lua
index 7a68d06..c7b1348 100644
--- a/dat/missions/cargo.lua
+++ b/dat/missions/cargo.lua
@@ -32,21 +32,20 @@ end
 
 -- Create the mission.
 function create()
-  local landed = space.getLanded()
+  local landed = space.getPlanet() -- Get landed planet.
 
    -- Target destination.
   local i = 0
   repeat
-    planet = space.getPlanet(misn.factions())
+    planet, system = space.getPlanet(misn.factions())
     i = i + 1
   until planet ~= landed or i > 10
    -- Infinite loop protection.
   if i > 10 then
     misn.finish(false)
   end
-  system = space.getSystem(planet:name())
   misn.setMarker(system) -- Mark the system.
-  misn_dist = space.jumpDist(system)
+  misn_dist = system:jumpDist()
 
   -- Mission generics.
   i = rnd.int(6)
@@ -93,21 +92,21 @@ function create()
   end
 
   if misn_type == "Cargo" then
-    misn.setDesc(string.format( misn_desc[1], planet:name(), system, carg_mass, carg_type))
+    misn.setDesc(string.format( misn_desc[1], planet:name(), system:name(), carg_mass, carg_type))
     reward = misn_dist * carg_mass * (250+rnd.int(150)) +
         carg_mass * (150+rnd.int(75)) +
         rnd.int(1500)
   elseif misn_type == "Rush" then
     misn_time = time.get() + time.units(2) +
         rnd.int(time.units(2), time.units(4)) * misn_dist
-    misn.setDesc(string.format( misn_desc[11], planet:name(), system,
+    misn.setDesc(string.format( misn_desc[11], planet:name(), system:name(),
         carg_mass, carg_type,
         time.str(misn_time), time.str(misn_time-time.get())))
     reward = misn_dist * carg_mass * (450+rnd.int(250)) +
         carg_mass * (250+rnd.int(125)) +
         rnd.int(2500)
   else -- People.
-    misn.setDesc(string.format(misn_desc[21], carg_type, planet:name(), system))
+    misn.setDesc(string.format(misn_desc[21], carg_type, planet:name(), system:name()))
     reward = misn_dist * (1000 + rnd.int(500)) + rnd.int(2000)
   end
   misn.setReward(string.format(misn_reward, reward))
@@ -141,7 +140,7 @@ end
 
 -- Land hook.
 function land()
-  local landed = space.getLanded()
+  local landed = space.getPlanet()
   if landed == planet then
     if player.rmCargo(carg_id) then
       player.pay( reward )
@@ -171,7 +170,7 @@ function timeup()
     player.msg(misn_time_msg)
     misn.finish(false)
   end
-  misn.setDesc(string.format( misn_desc[21], planet:name(), system,
+  misn.setDesc(string.format( misn_desc[21], planet:name(), system:name(),
       carg_mass, carg_type,
       time.str(misn_time), time.str(misn_time-time.get())))
 end
diff --git a/dat/missions/emp_cargo00.lua b/dat/missions/emp_cargo00.lua
index 711cd45..4841b0f 100644
--- a/dat/missions/emp_cargo00.lua
+++ b/dat/missions/emp_cargo00.lua
@@ -20,19 +20,18 @@ You aren't too sure of what to make of your encounter with the Empire, only time
 end
 
 function create()
-  local landed = space.getLanded()
+  local landed = space.getPlanet()
 
   -- Target destination.
   local i = 0
   repeat
-    dest = space.getPlanet(misn.factions())
+    dest,system = space.getPlanet(misn.factions())
     i = i+1
   until dest ~= landed or i > 10
   -- Infinate loop protection.
   if i > 10 then
     misn.finish(false)
   end
-  system = space.getSystem(dest:name())
   misn.setMarker(system)
 
   -- Intro text.
@@ -45,7 +44,7 @@ function create()
     reward = 3000
     misn.setTitle(misn_title)
     misn.setReward(string.format(misn_reward, reward))
-    misn.setDesc(string.format(misn_desc, dest:name(), system))
+    misn.setDesc(string.format(misn_desc, dest:name(), system:name()))
 
     -- Flavour text and mini-briefing.
     tk.msg(title[2], string.format( text[3], dest:name()))
@@ -57,7 +56,7 @@ function create()
 end
 
 function land()
-  local landed = space.getLanded()
+  local landed = space.getPlanet()
   if landed == dest then
     if player.rmCargo(parcels) then
       player.pay(reward)
diff --git a/dat/missions/emp_collective00.lua b/dat/missions/emp_collective00.lua
index 1661859..b4db065 100644
--- a/dat/missions/emp_collective00.lua
+++ b/dat/missions/emp_collective00.lua
@@ -29,19 +29,20 @@ function create()
     misn.accept()
 
     misn_stage    = 0
-    misn_nearby   = "Coriolis"
-    misn_target   = "Dune"
-    misn_base     = space.getPlanet("Omega Station")
+    misn_nearby   = space.getSystem("Coriolis")
+    misn_target   = space.getSystem("Dune")
+    misn_base,misn_base_sys = space.getPlanet("Omega Station")
     misn_base_sys = "NGC-7291"
     misn.setMarker(misn_nearby) -- Not exact target.
 
     -- Mission details.
     misn.setTitle(misn_title)
     misn.setReward(misn_reward)
-    misn.setDesc(string.format(misn_desc[1],misn_nearby))
+    misn.setDesc(string.format(misn_desc[1],misn_nearby:name()))
 
     -- Flavour text and mini-briefing.
-    tk.msg(title[2], string.format(text[2], misn_nearby, misn_base:name(), misn_base_sys))
+    tk.msg(title[2], string.format(text[2], misn_nearby:name(),
+        misn_base:name(), misn_base_sys:name()))
 
     hook.enter("enter")
     hook.land("land")
@@ -49,10 +50,10 @@ function create()
 end
 
 function enter()
-  sys = space.system()
+  sys = space.getSystem()
 
   -- Additional fleets.
-  if sys == "NGC-7291" then -- Increase action for realism.
+  if sys:name() == "NGC-7291" then -- Increase action for realism.
     pilot.add("Empire Sml Defense")
     pilot.add("Collective Sml Swarm")
   elseif sys == misn_target then
@@ -64,17 +65,17 @@ function enter()
 
   -- update mission.
   if misn_stage == 0 and sys == misn_target then
-    misn.setDesc(string.format(misn_desc[2], misn_base:name() ,misn_base_sys))
+    misn.setDesc(string.format(misn_desc[2], misn_base:name() ,misn_base_sys:name()))
     misn_stage = 1
-    misn.setMarker(misn_base_sys) -- Now we mark return to base.
+    misn.setMarker(misn_base_sys:name()) -- Now we mark return to base.
   end
 end
 
 function land()
-  planet = space.getLanded()
+  planet = space.getPlanet()
 
   if misn_stage == 1 and  planet == misn_base then
-    tk.msg(title[3], string.format(text[3],misn_target))
+    tk.msg(title[3], string.format(text[3],misn_target:name()))
     player.modFaction("Empire", 5)
     misn.finish(true)
   end
diff --git a/dat/missions/emp_collective01.lua b/dat/missions/emp_collective01.lua
index 00a8de0..8757d75 100644
--- a/dat/missions/emp_collective01.lua
+++ b/dat/missions/emp_collective01.lua
@@ -26,8 +26,7 @@ function create()
 
     misn_stage = 0
     systems_visited = 0 -- Number of Collective systems visited.
-    misn_base = space.getPlanet("Omega Station")
-    misn_base_sys = space.getSystem(misn_base:name())
+    misn_base,misn_base_sys = space.getPlanet("Omega Station")
 
     -- Mission details.
     misn.setTitle(misn_title)
@@ -41,7 +40,8 @@ function create()
 end
 
 function enter()
-  factions = space.faction()
+  local sys = space.getSystem()
+  local factions = sys:faction()
 
   -- Increment system visited count.
   if misn_stage == 0 and factions["Collective"] then
@@ -50,7 +50,7 @@ function enter()
     -- Visited enough systems.
     if misn_stage == 0 and systems_visited >= 2 then
       misn.setDesc(string.format(misn_desc[2],
-        misn_base:name(), space.getSystem(misn_base)))
+        misn_base:name(), misn_base_sys:name()))
       misn_stage = 1
       misn.setMarker(misn_base_sys) -- Now we mark return to base.
       hook.land("land")
@@ -59,7 +59,7 @@ function enter()
 end
 
 function land()
-  planet = space.getLanded()
+  local planet = space.getPlanet()
 
   if misn_stage == 1 and planet == misn_base then
     tk.msg(title[3], text[3])
diff --git a/dat/missions/emp_collective02.lua b/dat/missions/emp_collective02.lua
index b996f40..62c8bd5 100644
--- a/dat/missions/emp_collective02.lua
+++ b/dat/missions/emp_collective02.lua
@@ -36,17 +36,17 @@ function create()
     -- Mission details.
     misn.setTitle(misn_title)
     misn.setReward(misn_reward)
-    misn.setDesc(string.format(misn_desc[1], misn_target:name(), misn_target_sys))
+    misn.setDesc(string.format(misn_desc[1], misn_target:name(), misn_target_sys:name()))
 
     tk.msg(title[1], string.format(text[2], misn_target:name()))
-    tk.msg(title[1], string.format(text[3]. misn_target:name(), misn_target_sys))
+    tk.msg(title[1], string.format(text[3]. misn_target:name(), misn_target_sys:name()))
 
     hook.enter("land")
   end
 end
 
 function land()
-  planet = space.getLanded()
+  planet = space.getPlanet()
 
   -- First mission part is landing on the planet.
   if misn_stage == 0 and planet == misn_target then
diff --git a/dat/missions/es_cargo.lua b/dat/missions/es_cargo.lua
index 6c96b13..eb264a6 100644
--- a/dat/missions/es_cargo.lua
+++ b/dat/missions/es_cargo.lua
@@ -27,7 +27,7 @@ end
 function create()
    -- Target destination.
   local i = 0
-  local landed = space.getLanded()
+  local landed = space.getPlanet()
   repeat
     planet, system = space.getPlanet(misn.factions())
     i = i + 1
@@ -37,7 +37,7 @@ function create()
     misn.finish(false)
   end
   misn.setMarker(system) -- Set system marker.
-  misn_dist = space.jumpDist(system)
+  misn_dist = system:jumpDist()
 
   -- Mission generics.
   misn_type = "Cargo"
@@ -61,7 +61,8 @@ function create()
 
   misn_time = time.get() + time.units(5) +
       rnd.int(time.units(5), time.units(8)) * misn_dist
-  misn.setDesc(string.format( misn_desc, carg_mass, carg_type, planet:name(),, system,
+  misn.setDesc(string.format( misn_desc, carg_mass, carg_type,
+      planet:name(),, system:name(),
       time.str(misn_time), time.str(misn_time-time.get())))
   reward = misn_dist * carg_mass * (500+rnd.int(250)) +
       carg_mass * (250+rnd.int(150)) +
@@ -87,7 +88,7 @@ end
 
 -- Land hook.
 function land()
-  local landed = space.getLanded()
+  local landed = space.getPlanet()
   if landed == planet then
     if player.rmCargo(carg_id) then
       player.pay(reward)
@@ -119,7 +120,8 @@ function timeup()
     player.msg(miss_timeup)
     misn.finish(false)
   end
-  misn.setDesc(string.format( misn_desc, carg_mass, carg_type, planet:name(), system,
+  misn.setDesc(string.format( misn_desc, carg_mass, carg_type,
+      planet:name(), system:name(),
       time.str(misn_time), time.str(misn_time-time.get())))
 end
 
diff --git a/snd/music.lua b/snd/music.lua
index 6d3ea5c..799ea02 100644
--- a/snd/music.lua
+++ b/snd/music.lua
@@ -14,7 +14,7 @@ function choose(str)
     music.play()
 
   elseif str == "land" then
-    planet = space.getLanded()
+    planet = space.getPlanet()
     class = planet:class()
 
     if class == "M" then
diff --git a/src/llua_space.c b/src/llua_space.c
index 9310957..268a4f8 100644
--- a/src/llua_space.c
+++ b/src/llua_space.c
@@ -9,9 +9,6 @@
 #include "map.h"
 #include "llua_space.h"
 
-#define PLANET_METATABLE  "Planet"
-#define SYSTEM_METATABLE  "System"
-
 /* Lua wrappers. */
 typedef struct LuaPlanet_ {
   Planet* p;
@@ -22,24 +19,20 @@ typedef struct LuaSystem_ {
 } LuaSystem;
 
 static int planetL_createmetatable(lua_State* L);
+static int systemL_createmetatable(lua_State* L);
 
 /* Space. */
 static int planetL_get(lua_State* L);
-static int space_getSystem(lua_State* L);
-static int spaceL_getLanded(lua_State* L);
-static int space_systemName(lua_State* L);
-static int space_jumpDist(lua_State* L);
-static int space_faction(lua_State* L);
+static int systemL_get(lua_State* L);
 static const luaL_reg space_methods[] = {
-  { "getPlanet",  planetL_get       },
-  { "getSystem",  space_getSystem   },
-  { "getLanded",  spaceL_getLanded  },
-  { "system",     space_systemName  },
-  { "jumpDist",   space_jumpDist    },
-  { "faction",    space_faction     },
+  { "getPlanet",  planetL_get },
+  { "getSystem",  systemL_get },
   { 0, 0 }
 };
 
+/* Internal planet methods. */
+static LuaPlanet* lua_toplanet(lua_State* L, int ind);
+static LuaPlanet* lua_pushplanet(lua_State* L, LuaPlanet planet);
 /* Planet metatable methods. */
 static int planetL_eq(lua_State* L);
 static int planetL_name(lua_State* L);
@@ -56,6 +49,23 @@ static const luaL_reg planet_methods[] = {
   { 0, 0 } 
 };
 
+/* Internal system methods. */
+static LuaSystem* lua_tosystem(lua_State* L, int ind);
+static LuaSystem* lua_pushsystem(lua_State* L, LuaSystem sys);
+/* System metatable methods. */
+static int systemL_eq(lua_State* L);
+static int systemL_name(lua_State* L);
+static int systemL_faction(lua_State* L);
+static int systemL_jumpdistance(lua_State* L);
+static const luaL_reg system_methods[] = {
+  { "__eq",       systemL_eq            },
+  { "__tostring", systemL_name          },
+  { "name",       systemL_name          },
+  { "faction",    systemL_faction       },
+  { "jumpDist",   systemL_jumpdistance  },
+  { 0, 0 }
+};
+
 /* Load the space library. */
 int lua_loadSpace(lua_State* L, int readonly) {
   (void)readonly;
@@ -65,6 +75,7 @@ int lua_loadSpace(lua_State* L, int readonly) {
 
   /* Register the metatables. */
   planetL_createmetatable(L);
+  systemL_createmetatable(L);
 
   return 0;
 }
@@ -86,6 +97,21 @@ static int planetL_createmetatable(lua_State* L) {
   return 0; /* No error. */
 }
 
+/* Register the system metatable. */
+static int systemL_createmetatable(lua_State* L) {
+  /* Create the metatable. */
+  luaL_newmetatable(L, SYSTEM_METATABLE);
+
+  /* Create the access table. */
+  lua_pushvalue(L, -1);
+  lua_setfield(L, -2, "__index");
+
+  /* Register the values. */
+  luaL_register(L, NULL, system_methods);
+
+  return 0; /* No error. */
+}
+
 /* -- PLANET -- */
 
 /* Get planet at index. */
@@ -117,13 +143,21 @@ static int planetL_get(lua_State* L) {
   int       nplanets;
   char*     rndplanet;
   LuaPlanet planet;
+  LuaSystem sys;
 
   rndplanet = NULL;
   nplanets = 0;
 
-  /* Get a random planet. */
+  /* Get the landed planet. */
   if(lua_gettop(L) == 0) {
-    rndplanet = space_getRndPlanet();
+    if(land_planet != NULL) {
+      planet.p = land_planet;
+      lua_pushplanet(L, planet);
+      sys.s = system_get(planet_getSystem(land_planet->name));
+      lua_pushsystem(L, sys);
+      return 2;
+    }
+    return 0; /* Not landed. */
   }
 
   /* Get a planet by faction */
@@ -172,7 +206,8 @@ static int planetL_get(lua_State* L) {
   /* Push the planet. */
   planet.p = planet_get(rndplanet); /* The real planet. */
   lua_pushplanet(L, planet);
-  lua_pushstring(L, planet_getSystem(rndplanet));
+  sys.s = system_get(planet_getSystem(rndplanet));
+  lua_pushsystem(L, sys);
   return 2;
 }
 
@@ -200,7 +235,7 @@ static int planetL_name(lua_State* L) {
 static int planetL_faction(lua_State* L) {
   LuaPlanet* p;
   p = lua_toplanet(L, 1);
-  lua_pushnumber(L, p->p->faction);
+  lua_pushstring(L, faction_name(p->p->faction));
   return 1;
 }
 
@@ -215,6 +250,7 @@ static int planetL_class(lua_State* L) {
   return 1;
 }
 
+/* Get planet services. */
 static int planetL_services(lua_State* L) {
   LuaPlanet* p;
   p = lua_toplanet(L, 1);
@@ -222,44 +258,92 @@ static int planetL_services(lua_State* L) {
   return 1;
 }
 
+/* -- SYSTEM -- */
+
+/* Get system at index. */
+static LuaSystem* lua_tosystem(lua_State* L, int ind) {
+  if(lua_isuserdata(L, ind)) {
+    return (LuaSystem*) lua_touserdata(L,ind);
+  }
+  luaL_typerror(L, ind, SYSTEM_METATABLE);
+  return NULL;
+}
+
+/* Pushes a system on the stack. */
+static LuaSystem* lua_pushsystem(lua_State* L, LuaSystem sys) {
+  LuaSystem* s;
+  s = (LuaSystem*) lua_newuserdata(L, sizeof(LuaSystem));
+  *s = sys;
+  luaL_getmetatable(L, SYSTEM_METATABLE);
+  lua_setmetatable(L, -2);
+  return s;
+}
+
 /* Get a system. */
-static int space_getSystem(lua_State* L) {
+static int systemL_get(lua_State* L) {
   LLUA_MIN_ARGS(1);
+  LuaSystem sys;
   char* planetname, *sysname;
 
   if(lua_isstring(L, 1)) planetname = (char*)lua_tostring(L, 1);
+  else if(lua_isuserdata(L, 1)) {}
   else LLUA_INVALID_PARAMETER();
 
+  /* Return the system. */
   sysname = planet_getSystem(planetname);
-  lua_pushstring(L, sysname);
+  sys.s = system_get(sysname);
+  lua_pushsystem(L, sys);
   return 1;
 }
 
-static int spaceL_getLanded(lua_State* L) {
-  LuaPlanet planet;
+/* Check system for equality. */
+static int systemL_eq(lua_State* L) {
+  LuaSystem* a, *b;
+  a = lua_tosystem(L, 1);
+  b = lua_tosystem(L, 2);
+  if(a->s == b->s)
+    lua_pushboolean(L, 1);
+  else
+    lua_pushboolean(L, 0);
 
-  if(landed) {
-    planet.p = land_planet;
-    lua_pushplanet(L, planet);
-    return 1;
+  return 1;
+}
+
+/* Return the systems name. */
+static int systemL_name(lua_State* L) {
+  LuaSystem* sys;
+  sys = lua_tosystem(L, 1);
+  lua_pushstring(L, sys->s->name);
+  return 1;
+}
+
+/* Get system factions. */
+static int systemL_faction(lua_State* L) {
+  int i;
+  LuaSystem* sys;
+  sys = lua_tosystem(L, 1);
+
+  /* Return result in table. */
+  lua_newtable(L);
+  for(i = 0; i < sys->s->nplanets; i++) {
+    lua_pushboolean(L, 1); /* Value. */
+    lua_setfield(L, -2, faction_name(sys->s->planets[i].faction)); /* Key. */
+    /* Allows syntax foo = space.faction("foo"); if foo["bar"] then ... end */
   }
-  return 0;
-}
 
-static int space_systemName(lua_State* L) {
-  lua_pushstring(L, cur_system->name);
   return 1;
 }
 
-static int space_jumpDist(lua_State* L) {
+/* Get jump distance for current system, or to another. */
+static int systemL_jumpdistance(lua_State* L) {
   LLUA_MIN_ARGS(1);
+  LuaSystem* sys;
   StarSystem** s;
   int jumps;
   char* start, *goal;
 
-  if(lua_isstring(L, 1))
-    start = (char*)lua_tostring(L, 1);
-  else LLUA_INVALID_PARAMETER();
+  sys = lua_tosystem(L, 1);
+  start = sys->s->name;
 
   if((lua_gettop(L) > 1) && lua_isstring(L, 2))
     goal = (char*)lua_tostring(L, 2);
@@ -273,28 +357,3 @@ static int space_jumpDist(lua_State* L) {
   return 1;
 }
 
-static int space_faction(lua_State* L) {
-  int i;
-  StarSystem* s;
-
-  /* Get system. */
-  if(lua_isstring(L, 1))
-    s = system_get(lua_tostring(L, 1));
-  else s = cur_system;
-
-  /* Check if valid. */
-  if(s == NULL) {
-    LLUA_DEBUG("Invalid system!");
-    return 0;
-  }
-
-  /* Return result in table. */
-  lua_newtable(L);
-  for(i = 0; i < s->nplanets; i++) {
-    lua_pushboolean(L, 1); /* Value. */
-    lua_setfield(L, -2, faction_name(s->planets[i].faction)); /* Key. */
-    /* Allows syntax foo = space.faction("foo"); if foo["bar"] then ... end */
-  }
-  return 1;
-}
-
diff --git a/src/llua_space.h b/src/llua_space.h
index a1b911e..85a2a39 100644
--- a/src/llua_space.h
+++ b/src/llua_space.h
@@ -1,6 +1,9 @@
 #pragma once
 #include "lua.h"
 
+#define PLANET_METATABLE    "Planet"
+#define SYSTEM_METATABLE    "System"
+
 /* Load the space library. */
 int lua_loadSpace(lua_State* L, int readonly);