Page MenuHomeCode

No OneTemporary

diff --git a/README b/README
--- a/README
+++ b/README
@@ -1,126 +1,128 @@
ZzzzzzZ zz
Z z z The spatial gallery / social network / lounge
z z (c) 2010, Dereckson, some rights reserved.
z zzzzz zzzzz
z z z z z 0.1 alpha technical preview
z zzzzzzz z z
z z z z Last update hypership time: 5.096
z Z z z z z
ZzzzzzZ zzzzz zzzzzz
===========
LOCATIONS
===========
* Global location is a 9 letters code
<B,S> <body or spaceship id> <place where you are in this body/spaceship>
zerofilled 5 digits zerofilled 3 digits
You can also find 6 digits expressions e.g. B00001 is the hypership
* Local location varies of the place.
- On hypership core (B00001002): Sector C<0-8> Level <z> Zone <x-y>
- 0 is the gravity center
- 1-8 the 8 cubes surrounding it: 1-4 below, 5-8 above
- On the ship tower (B00001001): Sector T<z> Couloir <1-6>
- z is the level
- couloir depends of your x, y position (polar coordinates could help)
=================
HYPERSHIP TIME?
=================
* the amount of days since hypership launch, January 25th 2010 00:00 UTC
* So the decimal part is like internet time, but in GMT and not CET/CEST
===============
SIDE PROJECTS
===============
* A pazaak game, to have something to play
* Will be an Arzakon client
=================
I WANT TO HELP!
=================
* You can create new SmartLine commands
* You can translate it in a new language
Start point: http://zed.dereckson.be/lang/en/core.conf
* You can code a bit of adventure, places description, stuff to do
as long you don't transform it in ogame clone (we're building a community
who want or don't want to play, but not a mechanic game)
and as long no money is involved (if you ask why, read Iain M. Banks novels)
in the hypership (in far asteroids, orbitals, planets you do what you want)
============
KNOWN BUGS
============
* Javascript get_hypership_time will returns 5.94 instead 5.094
Some %03d to add in /js/misc.js
* All URLs outside homepage will return Unknown URL
Well... only the home controller is coded.
* The floater rendering adds a black line under Opera
dojox.layout.floatingPane bug, need to check with last dojo version
* API /location query will break indent on location->body->location
beautify XML code to improve
+ * do.php allows any local location move, discarding FrL status
+
=======================
API - General methods
=======================
* /api.php/time
Returns hypership time
Public access
* /api.php/perso/<perso_id>
Returns perso object
Created only to test extensively recursivity of api xml output
It's disabled since 10.811 on zed.dereckson.be, if you need an alternative,
open a bug report with the fields you need. Ship API should be able to manage
inventory if user is on. Ship API must also be able to get/set custom flags.
Requires a key
* /api.php/location/<location code or name>
Returns location object
Tip: to get the full name, use string eg /api.php/location/Zeta?format=string
Requires a key
* GET/POST API parameters
- key
API key, ask it at zed at dereckson be, object [DEV] api key request
- format
- preview print_r representation, so you've an idea of the object
- json json_encode() output
- php serialize() output
- wddx WDDX were an early universal serialization attempt
- xml XML document
- string output "as is" (or if it's an object, calls __toString())
============
API - Ship
=============
* /api.php/ship/authenticate/<perso nickname>
=================
ACKNOWLEDGEMENT
=================
Elfix, to have let me figure a regexp correction, instead to throw away regexp
validation for places local location.
diff --git a/content/travel.dat b/content/travel.dat
deleted file mode 100644
--- a/content/travel.dat
+++ /dev/null
@@ -1,26 +0,0 @@
-#
-# The [Places] section lists allowed global travel moves.
-# FrL = Can the perso moves freely locally?
-#
-
-[Places]
-#Place FrL Other reachable places
-B00001001 1 B0001002,B0001003
-B00001002 0 B0001001,B0001003
-B00001003 0 B0001001,B0001002
-B00002001 0
-B00003001 0
-
-#
-# Now we add some local travel exceptions
-# = denotes an alias
-#
-[B00001002]
-=C1 "Secteur C1" (-10, 6, -4)
-=C2 "Secteur C2" (10, 6, -4)
-=C3 "Secteur C3" (-10, -6, -4)
-=C4 "Secteur C4" (10, -6, -4)
-=C5 "Secteur C5" (-10, 6, 4)
-=C6 "Secteur C6" (10, 6, 4)
-=C7 "Secteur C7" (-10, -6, 4)
-=C8 "Secteur C8" (10, -6, 4)
\ No newline at end of file
diff --git a/content/travel.xml b/content/travel.xml
new file mode 100644
--- /dev/null
+++ b/content/travel.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ This document contains travel rules.
+
+ By default, travel inside a place is restricted and should be handled
+ by /explore mechanisms.
+
+ To allow wheter a local move, wheter a move to another place, you've
+ to add an TravelPlace entry.
+
+ When you need regular behavior, without any exception, you don't need
+ to list the place here.
+-->
+<Travel>
+ <TravelPlace code="B00001001" freeLocalMove="true">
+ <!--
+ HyperShip tower allows free movement, at least in corridors.
+ For other locations, we should trust /explore mechanism to
+ implement a security kick, if the perso have no access.
+
+ Then, we allow travel to core and bays
+ -->
+ <GlobalTravelTo code="B00001002" />
+ <GlobalTravelTo code="B00001003" />
+ </TravelPlace>
+
+ <TravelPlace code="B00001002">
+ <!-- From the HyperShip core, perso can travel to tower and bays -->
+ <GlobalTravelTo code="B00001001" />
+ <GlobalTravelTo code="B00001003" />
+
+ <!-- And we add local travel exceptions allowing limited usage
+ to free travel movements to reach the 8 core cubes.
+ -->
+ <LocalMove local_location="(-10, 6, -4)" alias="C1" name="Secteur C1" />
+ <LocalMove local_location="(10, 6, -4)" alias="C2" name="Secteur C2" />
+ <LocalMove local_location="(-10, -6, -4)" alias="C3" name="Secteur C3" />
+ <LocalMove local_location="(10, -6, -4)" alias="C4" name="Secteur C4" />
+ <LocalMove local_location="(-10, 6, 4)" alias="C5" name="Secteur C5" />
+ <LocalMove local_location="(10, 6, 4)" alias="C6" name="Secteur C6" />
+ <LocalMove local_location="(-10, -6, 4)" alias="C7" name="Secteur C7" />
+ <LocalMove local_location="(10, -6, 4)" alias="C8" name="Secteur C8" />
+ </TravelPlace>
+
+ <TravelPlace code="B00001003">
+ <!-- From the HyperShip core, perso can travel to core and tower -->
+ <GlobalTravelTo code="B00001001" />
+ <GlobalTravelTo code="B00001002" />
+ </TravelPlace>
+</Travel>
\ No newline at end of file
diff --git a/dev/quux.php b/dev/quux.php
--- a/dev/quux.php
+++ b/dev/quux.php
@@ -1,70 +1,87 @@
<?php
require_once('includes/objects/ship.php');
require_once('includes/objects/port.php');
require_once('includes/objects/application.php');
require_once('includes/objects/content.php');
require_once('includes/objects/message.php');
require_once('includes/objects/invite.php');
+ require_once('includes/cache/cache.php');
include('controllers/header.php');
- $case = 'perso.create.notify';
+ $case = 'travel';
switch ($case) {
+ case 'travel':
+ require_once('includes/travel/travel.php');
+ require_once('includes/travel/place.php');
+
+ $cache = Cache::load();
+ $travel = $cache->get('zed_travel');
+ if ($travel == '') {
+ $travel_nocached = new Travel();
+ $travel_nocached->load_xml("content/travel.xml");
+ $cache->set('zed_travel', serialize($travel_nocached));
+ } else {
+ $travel = unserialize($travel);
+ }
+ dieprint_r($travel);
+ break;
+
case 'perso.create.notify':
$testperso = Perso::get(4733);
$message = new Message();
$message->from = 0;
$message->to = invite::who_invited(4733);
$url = get_server_url() . get_url('who', $testperso->nickname);
$message->text = sprintf(lang_get('InvitePersoCreated'), $testperso->name, $url);
$message->send();
dieprint_r($message);
break;
case 'pushdata';
echo '
<h2>/api.php/app/pushdata</h2>
<form method="post" action="/api.php/app/pushdata?mode=file&key=37d839ba-f9fc-42ca-a3e8-28053e979b90" enctype="multipart/form-data">
<input type="file" name="datafile" /><br />
<input type="submit" value="Send file" />
</form>
';
break;
case 'thumbnail':
$content = new Content(1);
dprint_r($content);
$content->generate_thumbnail();
break;
case 'port':
echo '<h2>Port::from_location test</h2>';
$locations = array("B00002", "B00002123", "B00001001", "xyz: [800, 42, 220]");
foreach ($locations as $location) {
dprint_r(Port::from_location($location));
}
break;
case 'ext':
$file = 'dev/foo.tar';
echo "<h2>$file</h2>";
echo "<h3>.tar.bz2</h3>";
echo ereg('\.tar\.bz2$', $file);
echo "<h3>.tar</h3>";
echo ereg('\.tar$', $file);
break;
case 'app':
echo Application::from_api_key("37d839ba-f9fc-42ca-a3e8-28053e979b90")->generate_userkey();
break;
case '':
dieprint_r("No case currently selected.");
break;
}
include('controllers/footer.php');
?>
\ No newline at end of file
diff --git a/includes/SmartLine/ZedCommands.php b/includes/SmartLine/ZedCommands.php
--- a/includes/SmartLine/ZedCommands.php
+++ b/includes/SmartLine/ZedCommands.php
@@ -1,371 +1,382 @@
<?php
/*
* Zed
* (c) 2010, Dereckson, some rights reserved
* Released under BSD license
*
* SmartLine
*
* TODO: SettingsSmartLineCommand - understand why dojo floating pane isn't
* rendered if we est $controller instead to redirect
*/
///
/// Register commands
///
$smartLine->register_object('goto', 'GotoSmartLineCommand');
$smartLine->register_object('guid', 'GUIDSmartLineCommand');
$smartLine->register_object('invite', 'InviteSmartLineCommand');
$smartLine->register_object('invites', 'InviteSmartLineCommand');
$smartLine->register_object('list', 'ListSmartLineCommand');
$smartLine->register_object('requests', 'RequestsSmartLineCommand');
$smartLine->register_object('settings', 'SettingsSmartLineCommand');
$smartLine->register_object('unixtime', 'UnixTimeSmartLineCommand');
$smartLine->register_object('version', 'VersionSmartLineCommand');
$smartLine->register_object('whereami', 'WhereAmISmartLineCommand');
///
/// Help (todo: move $lang array in lang folder)
///
$lang['Help']['goto'] = "Go to a location";
$lang['Help']['guid'] = "Generate a GUID";
$lang['Help']['invite'] = "Generate an invite. To see the generated invites, invite list.";
$lang['Help']['list'] = "Lists specified objects (bodies, locations or places)";
$lang['Help']['requests'] = "Checks if there are waiting requests";
$lang['Help']['unixtime'] = "Prints current unixtime (seconds elapsed since 1970-01-01 00:00, UTC) or the specified unixtime date.";
$lang['Help']['version'] = "Gets Zed's software version info (Mercurial repository version, node id and if you're on the dev or prod site)";
$lang['Help']['whereami'] = "Where am I?";
///
/*
* Zed
* (c) 2010, Dereckson, some rights reserved
* Released under BSD license
*
* SmartLine
*
* TODO: SettingsSmartLineCommand - understand why dojo floating pane isn't
* rendered if we est $controller instead to redirect
*/
///
/// Register commands
///
$smartLine->register_object('goto', 'GotoSmartLineCommand');
$smartLine->register_object('guid', 'GUIDSmartLineCommand');
$smartLine->register_object('invite', 'InviteSmartLineCommand');
$smartLine->register_object('invites', 'InviteSmartLineCommand');
$smartLine->register_object('list', 'ListSmartLineCommand');
$smartLine->register_object('requests', 'RequestsSmartLineCommand');
$smartLine->register_object('settings', 'SettingsSmartLineCommand');
$smartLine->register_object('unixtime', 'UnixTimeSmartLineCommand');
$smartLine->register_object('version', 'VersionSmartLineCommand');
$smartLine->register_object('whereami', 'WhereAmISmartLineCommand');
///
/// Help (todo: move $lang array in lang folder)
///
$lang['Help']['goto'] = "Go to a location";
$lang['Help']['guid'] = "Generate a GUID";
$lang['Help']['invite'] = "Generate an invite. To see the generated invites, invite list.";
$lang['Help']['list'] = "Lists specified objects (bodies, locations or places)";
$lang['Help']['requests'] = "Checks if there are waiting requests";
$lang['Help']['unixtime'] = "Prints current unixtime (seconds elapsed since 1970-01-01 00:00, UTC) or the specified unixtime date.";
$lang['Help']['version'] = "Gets Zed's software version info (Mercurial repository version, node id and if you're on the dev or prod site)";
$lang['Help']['whereami'] = "Where am I?";
///
/// goto
///
class GotoSmartLineCommand extends SmartLineCommand {
public function run ($argv, $argc) {
global $CurrentPerso;
if ($argc == 1) {
$this->SmartLine->puts("Where do you want to go?", STDERR);
return;
}
require_once("includes/geo/location.php");
$here = new GeoLocation($CurrentPerso->location_global, $CurrentPerso->location_local);
try {
$place = new GeoLocation($argv[1]);
if ($place->equals($CurrentPerso->location_global)) {
$this->SmartLine->puts("You're already there.");
return;
}
} catch (Exception $ex) {
//Global location failed, trying local location
try {
$place = new GeoLocation($CurrentPerso->location_global, $argv[1]);
} catch (Exception $ex) {
$this->SmartLine->puts($ex->getMessage(), STDERR);
return;
}
if ($place->equals($here)) {
$this->SmartLine->puts("You're already there.");
return;
}
}
+ //Determines if the place exists
if (!$place->exists()) {
$this->SmartLine->puts("This place doesn't seem to exist.");
return;
}
- $this->SmartLine->puts("TODO: code travel assistant");
+ //Could we really go there?
+ require_once("includes/travel/travel.php");
+ $travel = Travel::load();
+ if (!$travel->can_travel($here, $place)) {
+ $this->SmartLine->puts("You can't reach that location.");
+ return;
+ }
+
+ $CurrentPerso->move_to($place->global, $place->local);
+ $this->SmartLine->puts("You travel to that location.");
+ return;
}
}
///
/// GUID
///
class GUIDSmartLineCommand extends SmartLineCommand {
public function run ($argv, $argc) {
if ($argc > 1 && is_numeric($argv[1])) {
for ($i = 0 ; $i < $argv[1] ; $i++) {
$this->SmartLine->puts(new_guid());
}
return;
}
$this->SmartLine->puts(new_guid());
}
}
///
/// invite
///
class InviteSmartLineCommand extends SmartLineCommand {
public function run ($argv, $argc) {
require_once('includes/objects/invite.php');
global $CurrentUser, $CurrentPerso;
$command = ($argc > 1) ? strtolower($argv[1]) : '';
switch ($command) {
case 'list':
$codes = Invite::get_invites_from($CurrentPerso->id);
if (!count($codes)) {
$this->SmartLine->puts("No invite code.");
} else {
foreach ($codes as $code) {
$this->SmartLine->puts($code);
}
}
break;
case 'add':
case '':
$code = Invite::create($CurrentUser->id, $CurrentPerso->id);
$url = get_server_url() . get_url('invite', $code);
$this->SmartLine->puts("New invite code created: $code<br />Invite URL: $url");
break;
case 'del':
$code = $argv[2];
if (!preg_match("/^([A-Z]){3}([0-9]){3}$/i", $code)) {
$this->SmartLine->puts("Invalid code format. Use invite list to get all your invite codes.", STDERR);
} else {
$invite = new Invite($code);
if ($CurrentPerso->id == $invite->from_perso_id) {
$invite->delete();
$this->SmartLine->puts("Deleted");
} else {
$this->SmartLine->puts("Invalid code. Use invite list to get all your invite codes.", STDERR);
}
}
break;
default:
$this->SmartLine->puts("Usage: invite [add|list|del <code>]", STDERR);
break;
}
}
}
///
/// list
///
class ListSmartLineCommand extends SmartLineCommand {
public function run ($argv, $argc) {
if ($argc == 1) {
$this->SmartLine->puts("Available lists: bodies, locations, places");
return;
}
switch ($objects = $argv[1]) {
case 'bodies':
$list = $this->get_list(TABLE_BODIES, "CONCAT('B', body_code)", "body_name");
$this->SmartLine->puts($list);
break;
case 'locations':
$list = $this->get_list(TABLE_LOCATIONS, "location_code", "location_name");
$this->SmartLine->puts($list);
break;
case 'places':
if ($argv[2] == "-a" || $argv[2] == "--all") {
//Global bodies places list
$list = $this->get_list(TABLE_PLACES, "CONCAT('B', body_code, place_code)", "place_name");
} else {
//Local places (or equivalent) list
global $CurrentPerso;
switch ($CurrentPerso->location_global[0]) {
case 'B':
$body_code = substr($CurrentPerso->location_global, 1, 5);
$list = $this->get_list(TABLE_PLACES, "CONCAT('B', body_code, place_code)", "place_name", "body_code = $body_code");
break;
case 'S':
$this->SmartLine->puts("I don't have a map of the spaceship.", STDERR);
return;
default:
$this->SmartLine->puts("Unknown location type. Can only handle B or S.", STDERR);
return;
}
}
$this->SmartLine->puts($list);
break;
default:
$this->SmartLine->puts("Unknown objects to list: $objects", STDERR);
}
}
public function get_list ($table, $key, $value, $where = null) {
global $db;
$sql = "SELECT $key as `key`, $value as value FROM $table ";
if ($where) $sql .= "WHERE $where ";
$sql .= "ORDER BY `key` ASC";
if (!$result = $db->sql_query($sql)) {
message_die(SQL_ERROR, "Unable to fetch list", '', __LINE__, __FILE__, $sql);
}
while ($row = $db->sql_fetchrow($result)) {
$rows .= "<tr><td>$row[key]</td><td>$row[value]</td></tr>";
}
$this->SmartLine->truncate(STDERR);
return "<table cellspacing=\"8\"><thead style=\"color: white\" scope=\"row\"><tr><th>Key</th><th>Value</th></thead><tbody>$rows</tbody></table>";
}
}
///
/// Requests
///
class RequestsSmartLineCommand extends SmartLineCommand {
public function run ($argv, $argc) {
global $CurrentPerso;
$force = ($argc > 1) && ($argv[1] == "-f" || $argv[1] == "--force");
if ($force || (array_key_exists('site.requests', $CurrentPerso->flags) && $CurrentPerso->flags['site.requests'])) {
global $controller;
$controller = 'controllers/persorequest.php';
} else {
$this->SmartLine->puts("No request waiting.");
}
}
}
///
/// Settings
///
class SettingsSmartLineCommand extends SmartLineCommand {
public function run ($argv, $argc) {
if (headers_sent()) {
global $controller;
$controller = 'controllers/settings.php';
} else {
header('location: ' . get_url('settings'));
}
}
}
///
/// unixtime
///
class UnixTimeSmartLineCommand extends SmartLineCommand {
public function run ($argv, $argc) {
date_default_timezone_set('UTC');
if ($argc == 1) {
$this->SmartLine->puts(time());
} elseif ($argc == 2 && is_numeric($argv[1])) {
$this->SmartLine->puts(strftime("%Y-%m-%d %X", $argv[1]));
$this->SmartLine->puts(get_hypership_time($argv[1]));
} else {
array_shift($argv);
$date = implode(' ', $argv);
if ($time = strtotime($date) !== false) {
$this->SmartLine->puts("Unixtime from $date: <span class=\"highlight\">$time</span>");
} else {
$this->SmartLine->puts("$date isn't a unixtime nor a valid date strtotime is able to parse.", STDERR);
}
}
}
}
///
/// version
///
class VersionSmartLineCommand extends SmartLineCommand {
public function run ($argv, $argc) {
//Gets .hg revision
if (file_exists('.hg/tags.cache')) {
$content = file_get_contents('.hg/tags.cache');
$info = explode(' ', $content, 2);
$info[] = "development environment";
} else if (file_exists('.hg_archival.txt')) {
$content = file('.hg_archival.txt');
foreach ($content as $line) {
$items = explode(' ', $line, 2);
if ($items[0] == 'node:') $info[1] = trim($items[1]);
if ($items[0] == 'latesttagdistance:') $info[0] = trim($items[1]);
$info[2] = 'production environment';
}
} else {
$this->SmartLine->puts("No version information available.", STDERR);
return false;
}
$this->SmartLine->puts("r$info[0] ($info[2])");
$this->SmartLine->puts("Hash: $info[1]");
}
}
///
/// whereami
///
class WhereAmISmartLineCommand extends SmartLineCommand {
public function run ($argv, $argc) {
global $CurrentPerso;
require_once("includes/geo/location.php");
$place = new GeoLocation($CurrentPerso->location_global);
$this->SmartLine->puts($CurrentPerso->location_global . ' - ' . $place);
}
}
?>
\ No newline at end of file
diff --git a/includes/geo/location.php b/includes/geo/location.php
--- a/includes/geo/location.php
+++ b/includes/geo/location.php
@@ -1,367 +1,368 @@
<?php
require_once('body.php');
require_once('place.php');
require_once('point3D.php');
require_once('includes/objects/ship.php');
/*
* Geo location class
*
* 0.1 2010-01-28 18:52 DcK
*
* @package Zed
* @subpackage Geo
* @copyright Copyright (c) 2010, Dereckson
* @license Released under BSD license
* @version 0.1
*
* @todo initializes $point3D from $body or $ship own locations;
*
*/
class GeoLocation {
private $data;
/*
* @var GeoBody a body object
*/
public $body = null;
/*
* @var GeoPlace a place object
*/
public $place = null;
/*
* @var GeoPoint3D a point identified by x, y, z coordinates
*/
public $point3D = null;
/*
* @var Ship a ship object
*/
public $ship = null;
function __construct ($global = null, $local = null) {
if (!$global) {
$this->data = array();
} elseif (preg_match("/[BS][0-9]{5}[0-9]{3}/", $global)) {
$this->data[0] = $global;
} elseif (preg_match("/[BS][0-9]{5}/", $global)) {
$this->data[0] = $global;
} elseif (preg_match("/^xyz\:/", $global)) {
$coords = sscanf($global, "xyz: [%d, %d, %d]");
if (count($coords) == 3) {
$this->data[0] = $global;
} else {
throw new Exception("Invalid expression: $global");
}
} else {
global $db;
$name = $db->sql_escape($global);
$sql = "SELECT location_code FROM " . TABLE_LOCATIONS . " WHERE location_name LIKE '$name'";
$code = $db->sql_query_express($sql);
if ($code) {
$this->data[0] = $code;
return;
}
throw new Exception("Invalid expression: $global");
}
//TODO: handle $local in a better way: from the global location, gets
//a local location handler. Or a some inheriance, like a class
//HypershipGeoLocation extending GeoLocation.
if ($local !== null) $this->data[1] = $local;
$this->load_classes();
}
/*
* Gets $place, $body and $ship instances if they're needed
*/
function load_classes () {
//No data, no class to load
if (!count($this->data))
return;
//Loads global classes
$global = $this->data[0];
$code = substr($global, 1, 5);
switch ($global[0]) {
case 'B':
switch (strlen($global)) {
case 9:
$this->place = GeoPlace::from_code($global);
case 6:
$this->body = new GeoBody($code);
break;
}
break;
case 'S':
$this->ship = new Ship($code);
break;
case 'x':
$coords = sscanf($global, "xyz: [%d, %d, %d]");
if (count($coords) == 3) {
$this->point3D = new GeoPoint3D($coords[0], $coords[1], $coords[2]);
}
break;
}
}
/*
* Magic method called when a unknown property is get.
* Handles $global, $local, $type, $body_code, $ship_code, $place_code,
* $body_kind, $containsGlobalLocation, $containsLocalLocation.
*/
function __get ($variable) {
switch ($variable) {
/* main variables */
case 'global':
return $this->data[0];
break;
case 'local':
return $this->data[1];
break;
/* global location */
case 'type':
return $this->data[0][0];
case 'body_code':
if ($this->data[0][0] == 'B') {
return substr($this->data[0], 1, 5);
}
return null;
case 'place_code':
if ($this->data[0][0] == 'B') {
return substr($this->data[0], 6, 3);
}
return null;
case 'ship_code':
if ($this->data[0][0] == 'S') {
return substr($this->data[0], 1, 5);
}
return null;
case 'body_kind':
if ($this->data[0][0] == 'B' && $this->body != null) {
if ($kind = $this->body->kind()) {
return $kind;
}
} elseif ($this->data[0][0] == 'S') {
return 'ship';
}
return 'place';
case 'containsGlobalLocation':
return count($this->data) > 0;
case 'containsLocalLocation':
return count($this->data) > 1;
default:
throw new Exception("Unknown variable: $variable");
break;
}
}
/*
* Checks if the place exists
*
* @return boolean true if the place exists ; false otherwise
+ * @todo handles alias
*/
function exists () {
$n = count($this->data);
//If not defined, it doesn't exist
if ($n == 0) return false;
//Checks global location
switch ($this->data[0][0]) {
case 'B':
switch (strlen($this->data[0])) {
case 9:
if (!$place = GeoPlace::from_code($this->data[0]))
return false;
break;
case 6:
$body = new GeoBody(substr($this->data[0], 1));
if ($body->lastError) return false;
break;
default:
message_die(GENERAL_ERROR, "Invalid global location expression size: " . $this->data[0], "GeoLocation exists method", __LINE__, __FILE__);
}
break;
case 'S':
$ship = new Ship(substr($this->data[0], 1));
if ($body->lastError) return false;
break;
default:
message_die(GENERAL_ERROR, "Invalid global location expression size: " . $this->data[0], "GeoLocation exists method", __LINE__, __FILE__);
return false;
}
if ($n > 1) {
if (!isset($place)) {
message_die(GENERAL_ERROR, "Can't check if a local place exists for the following location: " . $this->data[0], "GeoLocation exists method", __LINE__, __FILE__);
}
if (!$place->is_valid_local_location($this->data[1])) {
return false;
}
}
return true;
}
/*
* Checks if the place is equals at the specified expression or place
*
* @return boolean true if the places are equals ; otherwise, false
*/
function equals ($expression) {
//Are global location equals?
//TODO: creates a better set of rules to define when 2 locations are equa l.
if (is_a($expression, 'GeoLocation')) {
if (!$this->equals($expression->data[0])) {
return false;
}
if (count($expression->data) + count($this->data) > 2) {
return $expression->data[1] == $this->data[1];
}
}
if ($expression == $this->data[0]) return true;
$n1 = strlen($expression);
$n2 = strlen($this->data[0]);
if ($n1 > $n2) {
return substr($expression, 0, $n2) == $this->data[0];
}
return false;
}
/*
* Represents the current location instance as a string
*
* @return string a string representing the current location
*/
function __toString () {
if (!$this->data[0])
return "";
switch ($this->data[0][0]) {
case 'S':
$ship = new Ship($this->ship_code);
$location[] = $ship->name;
break;
case 'B':
$body = new GeoBody($this->body_code);
$location[] = $body->name ? $body->name : lang_get('UnknownBody');
if (strlen($this->data[0]) == 9) {
$place = GeoPlace::from_code($this->data[0]);
$location[] = $place->name ? $place->name : lang_get('UnknownPlace');
}
break;
default:
message_die(GENERAL_ERROR, "Unknown location identifier: $type.<br />Expected: B or S.");
}
return implode(", ", array_reverse($location));
}
/*
* Magic method called when a unknown property is set.
* Handles $global, $local, $type, $body_code, $ship_code, $place_code
*/
function __set ($variable, $value) {
switch ($variable) {
/* main variables */
case 'global':
$this->data[0] = $value;
break;
case 'local':
$this->data[1] = $value;
break;
/* global location */
case 'type':
if ($value == 'B' || $value == 'S') {
if (!$this->data[0]) {
$this->data[0] = $value;
} else {
$this->data[0][0] = $value;
}
}
break;
case 'body_code':
if (preg_match("/[0-9]{1,5}/", $value)) {
$value = sprintf("%05d", $value);
if (!$this->data[0]) {
$this->data[0] = "B" . $value;
return;
} elseif ($this->data[0][0] == 'B') {
$this->data[0] = "B" . $value . substr($this->data[0], 6);
return;
}
throw new Exception("Global location isn't a body.");
}
throw new Exception("$value isn't a valid body code");
case 'ship_code':
if (preg_match("/[0-9]{1,5}/", $value)) {
$value = sprintf("%05d", $value);
if (!$this->data[0]) {
$this->data[0] = "S" . $value;
return;
} elseif ($this->data[0][0] == 'S') {
$this->data[0] = "S" . $value . substr($this->data[0], 6);
return;
}
throw new Exception("Global location isn't a ship.");
}
throw new Exception("$value isn't a valid ship code");
case 'place_code':
if (!preg_match("/[0-9]{1,3}/", $value)) {
throw new Exception("$value isn't a valid place code");
}
$value = sprintf("%03d", $value);
if ($this->data[0][0] == 'B') {
$this->data[0] = substr($this->data[0], 0, 6) . $value;
}
throw new Exception("Global location isn't a body.");
default:
throw new Exception("Unknown variable: $variable");
break;
}
}
}
?>
diff --git a/includes/travel/place.php b/includes/travel/place.php
new file mode 100644
--- /dev/null
+++ b/includes/travel/place.php
@@ -0,0 +1,86 @@
+<?php
+
+/*
+ * TravelPlace class
+ *
+ * 0.1 2010-07-19 22:10 DcK
+ *
+ * @package Zed
+ * @subpackage Travel
+ * @copyright Copyright (c) 2010, Dereckson
+ * @license Released under BSD license
+ * @version 0.1
+ *
+ */
+class TravelPlace {
+ /*
+ * @var string the place code
+ */
+ public $code;
+
+ /*
+ * @var boolean determines if any local location move is valid
+ */
+ public $freeLocalMove = false;
+
+ /*
+ * @var Array array of strings, each item another place reachable
+ */
+ public $globalTravelTo = array();
+
+ /*
+ * @var Array array of array, containing [location, alias, name] entries
+ */
+ public $localMoves = array();
+
+ static function from_xml ($xml) {
+ $travelPlace = new TravelPlace();
+
+ //Reads attributes: <TravelPlace code="B00001001" freeLocalMove="true">
+ foreach ($xml->attributes() as $key => $value) {
+ switch ($key) {
+ case 'code':
+ $travelPlace->code = (string)$value;
+ break;
+
+ case 'freeLocalMove':
+ $travelPlace->freeLocalMove = (boolean)$value;
+ break;
+ }
+ }
+
+ //<GlobalTravelTo code="B00001002" />
+ foreach ($xml->GlobalTravelTo as $globalTravelToXml) {
+ foreach ($globalTravelToXml->attributes() as $key => $value) {
+ if ($key == "code") {
+ $travelPlace->globalTravelTo[] = (string)$value;
+ }
+ }
+ }
+
+ //<LocalMove local_location="(0, 0, 0)" alias="C0" name="Core" />
+ foreach ($xml->LocalMove as $localMoveXml) {
+ $localMove = array(null, null, null);
+ foreach ($localMoveXml->attributes() as $key => $value) {
+ switch ($key) {
+ case 'local_location':
+ $localMove[0] = (string)$value;
+ break;
+
+ case 'alias':
+ $localMove[1] = (string)$value;
+ break;
+
+ case 'name':
+ $localMove[2] = (string)$value;
+ break;
+ }
+ }
+ $travelPlace->localMoves[] = $localMove;
+ }
+
+ return $travelPlace;
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/includes/travel/travel.php b/includes/travel/travel.php
new file mode 100644
--- /dev/null
+++ b/includes/travel/travel.php
@@ -0,0 +1,106 @@
+<?php
+
+/*
+ * Travel helper class
+ *
+ * 0.1 2010-07-18 22:05 DcK
+ *
+ * @package Zed
+ * @subpackage Travel
+ * @copyright Copyright (c) 2010, Dereckson
+ * @license Released under BSD license
+ * @version 0.1
+ *
+ * This class implements a singleton pattern.
+ *
+ */
+class Travel {
+ /*
+ * @var Array array of TravelPlace, each one a custom travel rule
+ * This array is indeed by TravelPlace code.
+ */
+ public $globalTravelTo = array();
+
+
+ /*
+ * Gets and initializes if needed the Travel instance
+ */
+ static function load () {
+ require_once('../cache/cache.php');
+ $cache = Cache::load();
+
+ if (!$travel = $cache->get('zed_travel')) {
+ //Initializes resource and caches it
+ $travel = new Travel();
+ $travel>load_xml("content/travel.xml");
+ $cache->set('zed_travel', serialize($travel));
+ return $travel;
+ }
+
+ return unserialize($travel);
+ }
+
+ /*
+ * Loads a travel configuration XML file
+ * @param string the path to the travel XML file
+ */
+ function load_xml ($file) {
+ require_once('place.php');
+
+ $xml = simplexml_load_file($file);
+ foreach ($xml->TravelPlace as $travelPlaceXml) {
+ $travelPlace = TravelPlace::from_xml($travelPlaceXml);
+ $this->globalTravelTo[$travelPlace->code] = $travelPlace;
+ }
+ }
+
+ /*
+ * Determines if a perso can travel from $from to $to
+ * If an alias have been used for $to local location, set correct location.
+ *
+ * @param GeoLocation the location where the perso is
+ * @param GeoLocation the location where the perso wants to go
+ * @return true if the travel move is valid ; otherwise, false.
+ */
+ function can_travel ($from, &$to) {
+ require_once('../geo/location.php');
+
+ if ($from->global != $to->global) {
+ //Checks if we can locally from $from to $to place
+ if (!array_key_exists($from->global, $this->globalTravelTo)) {
+ return false;
+ }
+ $travelPlace = $this->globalTravelTo[$from->global];
+ if (!in_array($to->global, $travelPlace->globalTravelTo)) {
+ return false;
+ }
+ }
+
+ if ($to->containsLocalLocation) {
+ //Determines if we've custom rules about local moves in $to
+ if (!array_key_exists($to->global, $this->globalTravelTo)) {
+ return false;
+ }
+ $travelPlace = $this->globalTravelTo[$to->global];
+
+ //Is it's an especially allowed movement?
+ foreach ($travelPlace->localMoves as $move) {
+ //move is a [location, alias, name] array
+ //If any of those 3 parameters matches $to->local, it's okay
+ if (in_array($to->local, $move)) {
+ $to->local = $move[0];
+ return true;
+ }
+ }
+
+ if ($travelPlace->freeLocalMove) {
+ //We can move freely, perfect
+ return true;
+ }
+ }
+
+ return false;
+ }
+}
+
+?>
\ No newline at end of file

File Metadata

Mime Type
text/x-diff
Expires
Sun, Nov 24, 16:36 (3 h, 52 m ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
20798
Default Alt Text
(41 KB)

Event Timeline