pick a name when you join
[mudd.git] / mud.php
1 <?php
2
3 abstract class model {
4
5 private $config_file = '/etc/mud.ini';
6 private $db;
7
8 public function __construct() {
9 $config = parse_ini_file($this->config_file, true);
10 $this->db = new mysqli(
11 $config['database']['domain'],
12 $config['database']['user'],
13 $config['database']['password'],
14 $config['database']['database']);
15 if (mysqli_connect_errno()) {
16 echo "Problem connecting to database: ";
17 echo mysqli_connect_error();
18 exit();
19 }
20 }
21
22 public function query() {
23 $args = func_get_args();
24 $statement = $this->db->prepare(array_shift($args));
25 if ($args) call_user_func_array(array($statement, 'bind_param'), &$args);
26 $statement->execute();
27 $statement->store_result();
28 $statement->store_result();
29 $data = $statement->result_metadata();
30 $return = $row = $fields = array();
31 $fields[0] = &$statement;
32 while($field = $data->fetch_field())
33 $fields[] = &$row[$field->name];
34 call_user_func_array("mysqli_stmt_bind_result", $fields);
35 $i = 0;
36 while ($statement->fetch()) {
37 foreach ($row as $key=>$value) $return[$i][$key] = $value;
38 $i++;
39 }
40 $statement->free_result();
41 return $return;
42 }
43
44 public function insert() {
45 $args = func_get_args();
46 $statement = $this->db->prepare(array_shift($args));
47 call_user_func_array(array($statement, 'bind_param'), &$args);
48 $statement->execute();
49 return $this->db->insert_id;
50 }
51
52 public function update() {
53 $args = func_get_args();
54 $statement = $this->db->prepare(array_shift($args));
55 call_user_func_array(array($statement, 'bind_param'), &$args);
56 $statement->execute();
57 return $this->db->insert_id;
58 }
59
60 }
61
62 class universe {
63 public $rows = 30;
64 public $columns = 30;
65 public $rooms = array();
66
67 public function __construct($db) {
68 $rooms = $db->query("SELECT id,x,y,state FROM rooms");
69 if ($rooms) {
70 foreach ($rooms as $room) {
71 $this->rooms[$room['x']][$room['y']] =
72 array('id' => $room['id'], 'state' => $room['state']);
73 }
74 } else {
75 $sql = 'INSERT INTO rooms (x,y,state) VALUES(?,?,?)';
76 $types = 'iii';
77 for ($x = 0; $x < $this->columns; $x++) {
78 $column = array();
79 for ($y = 0; $y < $this->rows; $y++) {
80 $state = (rand(0, 9) < 2 ? true : false);
81 $id = $db->insert($sql, $types, $x, $y, $state);
82 $this->rooms[$x][$y] =
83 array('id' => $id, 'state' => $state);
84 }
85 }
86 }
87 }
88
89 public function serialize() {
90 $serial = array();
91 for ($x = 0; $x < $this->columns; $x++) {
92 for ($y = 0; $y < $this->rows; $y++) {
93 $serial[$x][$y] = $this->rooms[$x][$y]['state'];
94 }
95 }
96 return $serial;
97 }
98
99 }
100
101 class player {
102
103 public $id;
104 public $name;
105 public $room;
106 public $x;
107 public $y;
108
109 public function __construct($db) {
110 $player = $db->query(
111 'SELECT players.id, players.name, players.room, rooms.x, rooms.y'
112 . ' FROM players LEFT JOIN rooms ON players.room = rooms.id'
113 . ' WHERE players.id = ?',
114 'i', $_SESSION['id']
115 );
116 $player = $player[0];
117 $this->id = $player['id'];
118 $this->name = $player['name'];
119 $this->room = $player['room'];
120 $this->x = $player['x'];
121 $this->y = $player['y'];
122 }
123
124 }
125
126 class mud extends model {
127
128 private $universe;
129
130 public function __construct() {
131 parent::__construct();
132 session_start();
133 $this->universe = new universe($this);
134 }
135
136 private function join() {
137 $x = $y = 0;
138 do {
139 $x = rand(0, count($this->universe->rooms)-1);
140 $y = rand(0, count($this->universe->rooms[0])-1);
141 } while ($this->universe->rooms[$x][$y]['state']);
142 $id = $this->insert('INSERT INTO players (name,room) VALUES(?,?)',
143 'si', $_GET['name'], $this->universe->rooms[$x][$y]['id']);
144 $_SESSION['id'] = $id;
145 //$others = $this->query('SELECT id, room FROM players WHERE id != ?', 'i', $this->player->id);
146 return array('x' => $x, 'y' => $y, 'id' => $id, 'name' => $name);
147 }
148
149 private function yell($msg) {
150 $this->insert(
151 'INSERT INTO messages (message,type,room,source) VALUES(?,?,?,?)',
152 'ssii', $msg, 'yell', $this->player->room, $this->player->id);
153 }
154
155 private function say($msg) {
156 $this->insert(
157 'INSERT INTO messages (message,type,room,source) VALUES(?,?,?,?)',
158 'ssii', $msg, 'say', $this->player->room, $this->player->id);
159 }
160
161 private function move() {
162 }
163
164 private function poll() {
165 $time = isset($_SESSION['last_polled']) ? $_SESSION['last_polled'] : 0;
166 $messages = $this->query(
167 'SELECT message, type, name, sent, players.id FROM messages LEFT JOIN players'
168 . ' ON destination = players.id'
169 . ' OR source = players.id'
170 . ' WHERE TIMESTAMPDIFF(MINUTE, sent, NOW()) < 5'
171 . ' AND UNIX_TIMESTAMP(sent) >= ?'
172 . ' AND (type = "yell"'
173 . ' OR (type = "tell" AND destination = ?)'
174 . ' OR (type = "say" AND messages.room = ?))',
175 'iii', $time, $this->player->id, $this->player->room);
176 $_SESSION['last_polled'] = time();
177 return $messages;
178 }
179
180 public function response($content) {
181 header('Content-Type: application/json');
182 echo json_encode($content);
183 }
184
185 public function command($cmd) {
186 if (!$_GET['cmd'])
187 $this->error(400, 'Missing command: expected `cmd` field');
188 if ($_GET['cmd'] != 'join' && $_GET['cmd'] != 'start' && !isset($_SESSION['id']))
189 $this->error(401, 'Missing user ID: please join first');
190 if (isset($_SESSION['id'])) $this->player = new player($this);
191 switch ($cmd) {
192 case 'start':
193 $this->response($this->universe->serialize());
194 break;
195 case 'join':
196 $this->response($this->join());
197 break;
198 case 'move':
199 $this->response(array('valid' => $this->move()));
200 break;
201 case 'tell':
202 $this->tell();
203 break;
204 case 'yell':
205 $this->yell($_GET['msg']);
206 break;
207 case 'say':
208 $this->say();
209 break;
210 case 'tell':
211 $this->tell();
212 break;
213 case 'poll':
214 echo json_encode($this->poll());
215 break;
216 default:
217 $this->error(400, 'Unknown command');
218 }
219 }
220
221 private function error($status, $msg) {
222 header("HTTP/1.0 $status");
223 echo $msg;
224 }
225
226 }
227
228 $mud = new mud();
229 $mud->command($_GET['cmd']);
230
231 ?>