Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Messages - Toupie

Pages: [1] 2 3 ... 5
1
Programming with Blackvoxel / Re: A* pathfinding routine
« on: October 31, 2013, 10:53:12 pm »
Here is an example script that uses AStar.nut to walk a programmable robot to a point.

The goal is defined by:
Code: [Select]
DestX <- 44;
DestY <- 0;
DestZ <- 11;

You can place the robot anywhere and it will try and find it's way to that location in the shortest possible route without going through any solid blocks.

Example Code:
Code: [Select]
// Test of pathfinding

Time <- 0;

DestX <- 44;
DestY <- 0;
DestZ <- 11;
MovePath <- null;
MyAstar <- null;

function Voxel_Load()
{
  Time = GetGameTime();
  log_info("Voxel_Load()");
  dofile(GetPath(3)+GetInfo(20)+"AStar.nut",true);
  MyAstar = AStar(); // Create instance of AStar
  //MyAstar.SetMax(32); // Limit search area
  MyAstar.Set3D();  // Enable full 3D search
}

function Voxel_Step()
{
  if (GetGameTime() - Time > 0) {
    Time = GetGameTime();
  } else {
    // Fix for funky GetGameTime()
    if (GetGameTime() - Time < -60000)
      Time = GetGameTime();
    return;
  }

  if (MoveTo(DestX,DestY,DestZ)) {
    if (GetX() == DestX && GetY() == DestY && GetZ() == DestZ) {
      log_info("We have arrived!");
      Time = GetGameTime() + 10000;
    } else {
      log_err("Failed to arrive");
      Time = GetGameTime() + 10000;
    }
  }
}

function MoveTo(x, y, z)
{
  if (MovePath == null) { // We need to keep calling GetPath until we get an array back.
    MovePath = MyAstar.GetPath(Node(GetX(),GetY(),GetZ()),Node(x,y,z));
  }
  if (MovePath != null && MovePath.len()>0) {
    local d = MovePath.pop(); // Get move direction from array
    if (GetVoxelProp(Look(d),0)) {
      if (Move(d)) {
        if (MovePath.len() == 0)
          return true; // We should have arrived.
      } else {
        MovePath.push(d); // Save move direction to path again.
        log_err("Failed to move along the path! d="+d);
        Time = GetGameTime() + 5000;
      }
    } else {
      log_err("Path is obstructed. Getting new move path!");
      Time = GetGameTime() + 5000;
      MyAstar.Clear();
      MovePath = null;
    }
  } else if (typeof MovePath=="array" && MovePath.len()==0) {
    return true; // We did not arrive, but we still have to tell the caller we are done.
  }
  return false; // Not there yet.
}


function log_info(msg)
{
    local s;
    s = format("5.nut at %d,%d,%d Info: %s", GetX(), GetY(), GetZ(), msg);
    Display( s, 2000, 4, 1000);
    error(s+"\n");
}

function log_err(msg)
{
    local s;
    s = format("5.nut at %d,%d,%d Err: %s", GetX(), GetY(), GetZ(), msg);
    Display( s, 4000, 4, 4000);
    error(s+"\n");
    Time = Time + 1500;
}

It's the function MoveTo(x,y,z) that is the meat of the example.

2
Programming with Blackvoxel / A* pathfinding routine
« on: October 31, 2013, 10:41:38 pm »
Now that we have the 3D functions I thought that I could write me a path finding routine. So here it is. It's a basic A* implementation that is configurable between 2D (XZ) and 3D (XYZ).

A little warning. 3D path finding over large distances or in complex scenarios can be very slow.

I've implemented it as 2 classes.

AStar is the real code of the path finding.
Node is just a simple container for a node in the path. It is used by AStar

Node(x,y,z) creates an instance of Node for that location.

AStar() creates an instance of AStar.

Methods of AStar
result = GetPath( start, goal )
start and goal are instances of Node(x,y,z) representing the start position and the goal of the path.
result will be an array containing the necessary move directions you need to take to get from start to goal. The moves are stored in reverse order so you can just .pop() them from back of the array. GetPath will limit it's processing time to 200ms for every call to it, and will return null until it is done. So you will have to call it several times before getting your path. In case it fails to find a path to goal it will return an empty array.

Clear()
Resets the instance of AStar for a new search. Needs to be called after you have done a search before you start a new one. Can be used instead of creating a new instance of AStar.

Set2d()
Sets the search mode to 2D (XZ), ignoring Y. This is the default.

Set3D()
Sets the search mode to full 3D. Warning, can be slow.

SetMax(value)
Sets the limits of the search to value in all directions (xyz) from the center point between start and goal. Default values are 64, which gives it an area of 128*128 or 128*128*128 in 3D that will be used when searching for a path. This is necessary, or GetPath would never give up in case there is no path between start and goal.

Members of AStar

xmax, ymax, zmax
The limits on the 3 coordinate for the search. Default value 64.

debug
How much will be printed out to stderr.txt. 0 = nothing. 1 = summary.  2 = detail information (not implemented since it slows things down to much)

AStar.nut
Code: [Select]
// A* pathfinding

class Node {
  constructor(x,y,z)
  {
    this.x = x;
    this.y = y;
    this.z = z;
  }

  // This one does not seem to work.
  function _cmp(other)
  {
    error("_cmp This.x="+x+"This.z="+z+" other.x="+other.x+" other.z="+other.z+"\n");
    if (x < other.x) return -1;
    if (y < other.y) return -1;
    if (z < other.z) return -1;
    if (x > other.x) return 1;
    if (y > other.y) return 1;
    if (z > other.z) return 1;
    return 0;
  }

  function index()
  {
    return format("%d:%d:%d",x,y,z);
  }

  x = null;  // X position
  y = null;  // Y position
  z = null;  // Z position
  d = null; // Direction to get here;
  g = 0; // Cost from start to here
  h = 0; // Estimated cost from here to goal
  f = 0; // Total estimated cost to goal
  p = null; // Came from (parent). Used to walk back from goal to get the shortest path.
}

class AStar {
  constructor()
  {
    open = {};
    closed = {};
  }

  // Private Members
  open = null; // Our open set of nodes
  closed = null; // Our close set of nodes
  checked = 0; // The number of nodes checked
  time = 0; // Total time processed
  directions = 4; // 4 = X & Z, 6 = X, Y & Z
  moveCoord = [ [0,0,1], [1,0,0], [0,0,-1], [-1,0,0], [0,1,0], [0,-1,0] ];

  // Public Members
  // A full 3D scan of an area of the size [64*2,64*2,64*2] will take up to 10 minutes
  xmax = 64;
  ymax = 64;
  zmax = 64;

  debug = 1; // 0=nothing, 1=summary, 2=full debug info

  // Private Methods
  function CostEstimate(start,goal)
  {
    return (abs(goal.x-start.x)+abs(goal.y-start.y)+abs(goal.z-start.z)) * 10;
  }

  function GetCheapest()
  {
    local m=null;
    local i,v;
    foreach (i,v in open) {
      if (m==null || v.f<m.f) {
        m = v;
      }
    }
    delete open[m.index()];
    return m;
  }

  function ReconstructPath(n)
  {
    local path = [];
    while( n.p!=null ) {
      path.append(n.d);
      n = n.p;
    }
    if (debug>0) error("PathLen="+path.len()+"\n");
    return path;
  }

  // Public Methods
  function Clear()
  {
    closed = {};
    open = {};
    checked = 0;
    time = 0;
  }

  function GetPath(start,goal)
  {
    local i,x,y,z,v;
    local time = GetGameTime();

    local midx = (goal.x-start.x)/2+start.x;
    local midy = (goal.y-start.y)/2+start.y;
    local midz = (goal.z-start.z)/2+start.z;

    if (open.len()==0) {
      start.g = 0;
      start.h = CostEstimate(start,goal);
      start.f = start.h;
      open[start.index()] <- start; // open.push(start);
    }

    while (open.len() > 0) {
      local current = GetCheapest();
      if (current.x == goal.x && current.z == goal.z && (current.y == goal.y || directions == 4)) {
        this.time += GetGameTime()-time;
        if (debug>0) error("Found path to goal after "+checked+" passes and "+(this.time)+"ms!\n");
        return ReconstructPath(current);
      }

      closed[current.index()] <- current; // closed.push(current);
      //error(format("Check %d,%d,%d g=%d h=%d",current.x,current.y,current.z,current.g,current.h));
      for (i=0; i<this.directions; i++) {
        x = current.x+moveCoord[i][0];
        y = current.y+moveCoord[i][1];
        z = current.z+moveCoord[i][2];
        if (abs(x-midx) <= xmax) {
          if (abs(y-midy) <= ymax) {
            if (abs(z-midz) <= zmax) {
              v = Look3D(x-GetX(),y-GetY(),z-GetZ());
              if (GetVoxelProp(v,0)) {
                local neighbor = Node(x, y, z);
                if (!(neighbor.index() in closed)) {
                  if (!(neighbor.index() in open)) {
                    neighbor.d = i;
                    neighbor.g = current.g + 10;
                    neighbor.h = CostEstimate(neighbor,goal);
                    neighbor.f = neighbor.g + neighbor.h;
                    neighbor.p = current;
                    //error(format(" | added %d,%d,%d g=%d h=%d",neighbor.x,neighbor.y,neighbor.z,neighbor.g,neighbor.h));
                    open[neighbor.index()] <- neighbor; // open.push(neighbor);
                  }
                }
              }
            }
          }
        }
      }
      //error("\n");
      checked++;
      if (GetGameTime()-time>=200) { // Allow max 200ms in every call.
        this.time += GetGameTime()-time;
        if (debug>0) error("Yielded after "+checked+" passes and "+(this.time)+"ms!\n");
        // Return to prevent Voxel_Step from taking to long.
        // We will continue where we left of on the next call
        return null; // Not finished yet.
      }
    }
    if (debug>0) error("Did not find a path to goal! "+checked+" passes and "+(this.time)+"ms\n");
    return []; // Not able to find a path to goal.
  }

  // Only search in X & Z. This is the default.
  function Set2D()
  {
    this.directions = 4;
  }

  // Full 3D pathfinding. CAN BE VERY SLOW!
  function Set3D()
  {
    this.directions = 6;
  }

  // Set all max limits to the same value.
  function SetMax(value)
  {
    xmax = value;
    ymax = value;
    zmax = value;
  }

} // class AStar

3
Updated to take advantage of V1.22b4.

"SaveVar.nut" goes into the Universes\nr\Scripts\Squirrel\ directory.
Code: [Select]
// SaveVar.nut

SaveName <- null;

function MakeSaveName()
{
  if (GetPath(4)!=-1) {
    SaveName = format("%s%s%d_%d.save",GetPath(4),GetInfo(20),GetInfo(22),GetRobotID());
  } else {
    throw "Needs to be called from Voxel_Step()";
  }
}

function Dump(var)
{
    local i,v;
    local s="";
    if (typeof var=="null") {
      s = "null";
    } else if (typeof var=="string") {
      s = "\""+var+"\"";
    } else if (typeof var=="array") {
      s = "[";
      foreach (v in var) {
        s += Dump(v)+",";
      }
      s += "]";
    } else if (typeof var=="table") {
      s = "{";
      foreach (i,v in var) {
        if (typeof i=="integer") {
          s += "["+i+"]="+Dump(v)+",";
        } else {
          s += i+"="+Dump(v)+",";
        }
      }
      s += "}";
    } else { // integer  bool  ??
      s = var+"";
    }
    return s;
}

function SaveVar(varname)
{
  local c,s;
  if (SaveName == null)
    MakeSaveName();

  s="";
  if (varname in getroottable() && typeof varname="string") {
    if (typeof (getroottable()[varname])=="table") {
      foreach (i,v in getroottable()[varname]) {
        if (typeof i=="integer") {
          s += "::"+varname+"["+i+"]<-"+Dump(v)+";\n";
        } else {
          s += "::"+varname+"."+i+"<-"+Dump(v)+";\n";
        }
      }
    } else {
      s = "::"+varname+"<-"+Dump(getroottable()[varname])+";\n";
    }

    c = compilestring(s);
    writeclosuretofile(SaveName,c);
  }
}

function LoadVar()
{
  if (SaveName==null)
    MakeSaveName();

  try {
    dofile(SaveName,false);
  } catch(e) {
    return false;
  }
/* Remove comment to have the save file removed on load
  try {
    remove(s);
  } catch(e) {}
*/
  return true;
}

result = LoadVar()
Loads the vars for this script. Put it in Voxel_Load.
Result is true if there where variables loaded, otherwise false.

SaveVar( tablename )
Save the variables in the global table named tablename. tablename is the name of the table, not the table it self.
Ex: SaveVar("Persistent");

The variables are stored in ScriptNr_robotID.save as a compiled Squirrel script in Universes\nr\Scripts\UserData directory.

And the example.
Code: [Select]
//global table with the variables that the script needs to be saved and reloaded
Persistent <- {
  StartX = 0,            // The X pos we started at
  StartZ = 0,            // The Z pos we started at
  BlockType = 0,      // The type of Block we are on top of
}


function Voxel_Load()
{
    // Include SaveVar.nut
    dofile(GetPath(3)+GetInfo(20)+"SaveVar.nut",true);
    // Load our variables
    LoadVar();
}

function Voxel_Unload()
{
  // Save Variables
  SaveVar("Persistent");  // Important, use the name of the global table, not the table it self.
}

function Voxel_Step()
{
   // Do stuff
  Display("StartX="+Persistent.StartX+" StartZ="+Persistent.StartZ+" BlockType="+Persistent.BlockType, 2000, 4, 1000);

}

4
General Discussion / Re: Area of Giant Trees
« on: October 31, 2013, 10:06:00 pm »
Yea, I've visited the Giant Tree area.
It's very pretty. Huge nice tree's.
To bad you can't go anywhere near them without being blown to pieces by those happy faces.

5
Troubleshooting & Bug Reports / Re: The v1.22 beta bug report thread!
« on: October 31, 2013, 02:11:46 am »
v1.22b4 on Windows

PickVoxel3D(x,y,z) seems to fail when z is anything but 0.

6
Updated the "include" file for saving variables to use the new features in v1.22b3.

All the variables that needs to be saved must be stored in a global table. The name of the table does not matter.

SaveVar.nut" now goes into the Universes\nr\Scripts\Squirrel\ directory.
Code: [Select]
// SaveVar.nut

SaveName <- null;

function MakeSaveName()
{
  if (GetPath(4)!=-1) {
    SaveName = format("%s%s%d_%d.save",GetPath(4),GetInfo(20),GetInfo(22),GetRobotID());
  } else {
    throw "Needs to be called from Voxel_Step()";
  }
}

function Dump(var)
{
    local i,v;
    local s="";
    if (typeof var=="null") {
      s = "null";
    } else if (typeof var=="string") {
      s = "\""+var+"\"";
    } else if (typeof var=="array") {
      s = "[";
      foreach (v in var) {
        s += Dump(v)+",";
      }
      s += "]";
    } else if (typeof var=="table") {
      s = "{";
      foreach (i,v in var) {
        if (typeof i=="integer") {
          s += "["+i+"]="+Dump(v)+",";
        } else {
          s += i+"="+Dump(v)+",";
        }
      }
      s += "}";
    } else { // integer  bool  ??
      s = var+"";
    }
    return s;
}

function SaveVar(varname)
{
  local c,s;
  if (SaveName == null)
    throw "Need to call LoadVar() or MakeSaveName() from Voxel_Step() before calling SaveVar()";

  s="";
  if (varname in getroottable() && typeof varname="string") {
    if (typeof (getroottable()[varname])=="table") {
      foreach (i,v in getroottable()[varname]) {
        if (typeof i=="integer") {
          s += "::"+varname+"["+i+"]<-"+Dump(v)+";\n";
        } else {
          s += "::"+varname+"."+i+"<-"+Dump(v)+";\n";
        }
      }
    } else {
      s = "::"+varname+"<-"+Dump(getroottable()[varname])+";\n";
    }

    error(s);

    c = compilestring(s);
    writeclosuretofile(SaveName,c);
  }
}

function LoadVar()
{
  if (SaveName==null)
    MakeSaveName();

  try {
    dofile(SaveName,false);
  } catch(e) {
    return false;
  }
/* Remove comment to have the save file removed on load
  try {
    remove(s);
  } catch(e) {}
*/
  return true;
}

result = LoadVar()
Loads the vars for this script. Must be called from Voxel_Step since the GetPath and GetInfo is not available in Voxel_Load.
Result is true if there where variables loaded, otherwise false.

SaveVar( tablename )
Save the variables in the global table named tablename. tablename is the name of the table, not the table it self.
You need to call LoadVar() or MakeSaveName() from Voxel_Step before a call to SaveVar() can be made in Voxel_Unload.
Ex: SaveVar("Persistent");

The variables are stored as ScriptNr_robotID.save in a compiled Squirrel script in Universes\nr\Scripts\UserData directory.

Example script that uses SaveVar.nut for saving and loading variables

Code: [Select]
NeedInit <- true;

//global table with the variables that the script needs to be saved and reloaded
Persistent <- {
  StartX = 0,            // The X pos we started at
  StartZ = 0,            // The Z pos we started at
  BlockType = 0,      // The type of Block we are on top of
}

function Voxel_Unload()
{
  // Save Variables
  SaveVar("Persistent");  // Important, use the name of the global table, not the table it self.
}

function Voxel_Step()
{
  // Load our variables if needed
  if (NeedInit)
        NeedInit = false;  // Need to take care of the Init our self now
        // Include SaveVar.nut
        dofile(GetPath(3)+GetInfo(20)+"SaveVar.nut",true);
        // Load our variables
        LoadVar();
  }

   // Do stuff
  Display("StartX="+Persistent.StartX+" StartZ="+Persistent.StartZ+" BlockType="+Persistent.BlockType, 2000, 4, 1000);

}

7
Troubleshooting & Bug Reports / Re: The v1.22 beta bug report thread!
« on: October 28, 2013, 01:04:55 pm »
V1.22b3 on Windows

GetPath(), GetInfo() and GetInfoName all just return -1 when called in Voxel_Load or Voxel_Unload where we really need them.

GetPath(0) return 3 instead of 4 as said in the release notes, but GetPath(4) returns the correct result.

8
Programming with Blackvoxel / Re: Include file for saving variables.
« on: October 28, 2013, 11:38:22 am »
I had my reasons for saving just the variables in one table.

I have settings variables that tells the script how to perform it's work that I want to be able to change "mid run". This way I can change those variables in the script, and just restart the script on the robot. I will then save the variables I want it to save, restart the script with the new "settings" variables, then load the saved variables (without overriding the settings since they are not in the table that are save) and continue it's work.

So for just a little bit more code in my script I get added functionality, instead of it having it save the entire roottable just to save some "annoyances" in the code.

I don't know how long it will wait for Voxel_Step to finish.
Quote from: From the Voxel Manual on the Programmable Robot
You must take care to don't take excessive execution time to avoid blocking or slowing down the Voxel Dynamic Reaction Engine (for Voxel_Step() ) or the Voxel Loader (for Voxel_Load() and Voxel_Unload() ).
It's clearly never intended that you should do excessive work on one call of Voxel_Step.

But now we have a Robot ID. So I probably don't need to use the X,Y,Z to identify the robot.

9
Troubleshooting & Bug Reports / Re: The v1.22 beta bug report thread!
« on: October 27, 2013, 10:46:10 am »
v1.22b2
Got this message when I switched program on a programmable robot. Switched from one small script that has run without problems to another small script that has run without problems. The only thing special is that the game and the robot had been running for 12+ hours.

Code: [Select]
Assertion failed: _gc_chain==NULL, file /home/laurent/workspace/blackvoxel/src/sc_Squirrel3/squirrel/sqstate.cpp, line 204

This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.

10
Programming with Blackvoxel / Re: Include file for saving variables.
« on: October 27, 2013, 10:41:40 am »
Yes. Having the robot moved by a conveyer belt will possible break the script. But that's hardly a normal scenario. That would probably mess up any script that isn't designed to especially for it.

My testings show that unless you put an endless loop in Voxel_Step the game will let it run to end before calling Voxel_Unload.
That seems to be true for ending the game, having the robot unloaded from the world and picking it up.

I didn't save the entire roottable since everything is in it. All your functions, classes and squirrel stuff are in there. I modeled the save routine from the one use by alot of games that use LUA as scripting language. There you set up one table to be saved and loaded. There is no reason to save everything. But no one is stopping you from writing your own save routine that saves everything.

Quote
you qan forget about all the annoyances of having to read/set all variables back and forth to a table in every step.
Why would you read/set variable back and forth to a table? Just access them with tablename.variable.

11
Troubleshooting & Bug Reports / Re: The v1.22 beta bug report thread!
« on: October 27, 2013, 01:02:10 am »
The result from GetGameTime() seems to start over from 0 at an odd time. I've seem the value go as high as 1271305784 before starting from 0. But 1271305784 isn't even near max value for a 32 bit integer. And the value also seems to start very high.

If I did the math correctly there should take 49 days before the value would overflow in an unsigned 32 bit integer, half that if it's signed and only positive numbers are used. But I've seen it start over from 0 several times in one day.

12
Programming with Blackvoxel / Re: Include file for saving variables.
« on: October 27, 2013, 12:57:24 am »
If you always call SavePos() the last thing you do in Voxel_Step(), the robot can't move between that and the call to Voxel_Unload(). It seems the game always allows the Voxel_Step() run to the end before calling Voxel_Unload(), no async calls to scripts.
 
One "bug" i've found is that if you quit the game without letting it save (alt-F4) the next time you load, the world will have rolled-back and the saved variables file will be deleted since it gets deleted when loaded. To fix this just delete the "remove(s);" from the LoadVar(). But that will have the result that the game directory will be filled with left over save files.

13
Programming with Blackvoxel / Include file for saving variables.
« on: October 26, 2013, 01:34:22 pm »
I made a "include" file for scripts that needs to have there variables saved and loaded when they go out of scope (game reload or outside of the loaded world).
All the variables that needs to be saved must be stored in a global table. The name of the table does not matter.

"SaveVar.nut" must be saved in the games directory, not the script directory.
Code: [Select]
// SaveVar.nut

NeedLoad <- true;
Pos <- [0,0,0];

function Dump(var)
{
    local i,v;
    local s="";
    if (typeof var=="null") {
      s = "null";
    } else if (typeof var=="string") {
      s = "\""+var+"\"";
    } else if (typeof var=="array") {
      s = "[";
      foreach (v in var) {
        s += Dump(v)+",";
      }
      s += "]";
    } else if (typeof var=="table") {
      s = "{";
      foreach (i,v in var) {
        if (typeof i=="integer") {
          s += "["+i+"]="+Dump(v)+",";
        } else {
          s += i+"="+Dump(v)+",";
        }
      }
      s += "}";
    } else { // integer  bool  ??
      s = var+"";
    }
    return s;
}

function SaveVar(varname)
{
  local c,s,filename;
  s="";
  filename = format("%d_%d_%d.save",Pos[0],Pos[1],Pos[2]);
  if (varname in getroottable() && typeof varname="string") {
    if (typeof (getroottable()[varname])=="table") {
      foreach (i,v in getroottable()[varname]) {
        if (typeof i=="integer") {
          s += "::"+varname+"["+i+"]<-"+Dump(v)+";\n";
        } else {
          s += "::"+varname+"."+i+"<-"+Dump(v)+";\n";
        }
      }
    } else {
      s = "::"+varname+"<-"+Dump(getroottable()[varname])+";\n";
    }

    c = compilestring(s);
    writeclosuretofile(filename,c);
  }
}

function LoadVar()
{
  local s;
  s = format("%d_%d_%d.save",GetX(),GetY(),GetZ());
  NeedLoad = false;
  try {
    dofile(s);
  } catch(e) {
    return false;
  }
  try {
    remove(s);
  } catch(e) {}
  return true;
}

function SavePos()
{
  Pos[0]=GetX();
  Pos[1]=GetY();
  Pos[2]=GetZ();
}

result = LoadVar()
Loads the vars for this script.
Result is true if there where variables loaded, otherwise false.

SaveVar( tablename )
Save the variables in the global table named tablename. tablename is the name of the table, not the table it self.
Ex: SaveVar("Persistent");

SavePos()
Stores the robots position for use by SaveVar in Voxel_Unload() since we don't have access to the robots position in Voxel_Unload(). Needs to be called after every time we have moved.

The variables are stored as X_Y_Z.save in a compiled Squirrel script in the games directory. If you have the game installed in "/Program Files" you will need to give your self write access to the game directory, or it will not work.

WARNING! This script does not know what Universe you are in so problems may occur if you play several universes.

Example script that uses SaveVar.nut for saving and loading variables
Code: [Select]
//global table with the variables that the script needs to be saved and reloaded
Persistent <- {
  StartX = 0,            // The X pos we started at
  StartZ = 0,            // The Z pos we started at
  BlockType = 0,      // The type of Block we are on top of
}

function Voxel_Load()
{
  // "Include" SaveVar.nut
  dofile("SaveVar.nut");
}

function Voxel_Unload()
{
  // Save Variables
  SaveVar("Persistent");  // Important, use the name of the global table, not the table it self.
}

function Voxel_Step()
{
  // Load our variables if needed
  if (NeedLoad)
        LoadVar();


   // Do stuff
  Display("StartX="+Persistent.StartX+" StartZ="+Persistent.StartZ+" BlockType="+Persistent.BlockType, 2000, 4, 1000);


  // Last thing in the Voxel_Step
  SavePos();
}

Edit: Oops. Forgot to support "null", "true" and "false". Updated SaveVar.nut

14
General Discussion / Re: The tips & tricks thread.
« on: October 26, 2013, 01:00:07 pm »
To change the world view distance you can change these parameters in Settings_Hardware.dat.

RenderingDistance_Horizontal = 8             Unit is 2x16 blocks horizontal
RenderingDistance_Vertical = 3                 Unit is 2x64 blocks vertical

Setting them to high will cause the game to crash. The windows version is currently very limited since it only has access to 2G of memory. (Will be 3.5GB soon.) On the Linux 64 bit version you can do a lot more.

15
Suggestions / Re: Windows 64 bit or Large Address Aware
« on: October 26, 2013, 12:48:16 pm »
Great. Thank you

Pages: [1] 2 3 ... 5