0
|
1 #include <stdio.h>
|
|
2 #include <string.h>
|
|
3 #include <fcntl.h>
|
|
4 #include <sys/types.h>
|
|
5 #include <sys/mman.h>
|
|
6 #include <sys/stat.h>
|
|
7 #include <unistd.h>
|
|
8 #include "SceneGraphRoot.h"
|
|
9 #include "lindaapi.h"
|
|
10 #include "network.h"
|
|
11 #include "network_game.pb.h"
|
|
12
|
|
13 #define GET_SERIAL_ID 65535
|
|
14
|
|
15 int NetworkGame::last_player_id = 0;
|
|
16
|
|
17 Viewer *NetworkGame::sgroot;
|
|
18 linda_t NetworkGame::linda_addr = { "localhost", 10000 };
|
|
19 int NetworkGame::linda;
|
|
20 int NetworkGame::serial_id;
|
|
21 int NetworkGame::width;
|
|
22 int NetworkGame::start_x;
|
|
23 char *NetworkGame::xml_file_name;
|
|
24
|
|
25 const char *usr_help_str = "Usage: ./network -linda LINDA_SERVER_NAME\n";
|
|
26 void TMend(TaskManager *manager);
|
|
27
|
|
28 extern void task_initialize();
|
|
29 extern int init(TaskManager *manager, int argc, char *argv[]);
|
|
30 extern Application *
|
|
31 application() {
|
|
32 return new NetworkGame();
|
|
33 }
|
|
34
|
|
35 static void
|
|
36 null_move(SceneGraphPtr node, void *sgroot_, int screen_w, int screen_h)
|
|
37 {
|
|
38 }
|
|
39 static void
|
|
40 null_collision(SceneGraphPtr node, void *sgroot_, int screen_w, int screen_h, SceneGraphPtr tree)
|
|
41 {
|
|
42 }
|
|
43
|
|
44 void
|
|
45 NetworkGame::update_last_player_id() {
|
|
46 last_player_id++;
|
|
47 if (last_player_id == serial_id)
|
|
48 last_player_id++;
|
|
49 }
|
|
50
|
|
51 void
|
|
52 NetworkGame::set_position(SceneGraphPtr node, unsigned char *reply) {
|
|
53 network_game::Position *pos = new network_game::Position();
|
|
54 pos->ParseFromArray(reply + LINDA_HEADER_SIZE, psx_get_datalength(reply));
|
|
55 node->xyz[0] = pos->x();
|
|
56 node->xyz[1] = pos->y();
|
|
57 node->angle[0] = pos->angle_x();
|
|
58 node->angle[1] = pos->angle_y();
|
|
59 delete pos;
|
|
60 }
|
|
61
|
|
62 static void
|
|
63 update_position_move(SceneGraphPtr node, void *sgroot_, int screen_w, int screen_h)
|
|
64 {
|
|
65 // LindaServerから座標データを取得してオブジェクトに反映させる。
|
|
66 if (!node->resend_flag || node->seq_rd != node->seq) {
|
|
67 unsigned char *reply_rd = psx_reply(node->seq_rd);
|
|
68 if (reply_rd != NULL) {
|
|
69 NetworkGame::set_position(node, reply_rd);
|
|
70 psx_free(reply_rd);
|
|
71 return;
|
|
72 }
|
|
73 }
|
|
74 unsigned char *reply = psx_reply(node->seq);
|
|
75 if (reply != NULL) {
|
|
76 // NetworkGame::set_position(node, reply);
|
|
77 psx_free(reply);
|
|
78 node->seq = psx_wait_rd(NetworkGame::linda, node->id * 10 + 1);
|
|
79 node->resend_flag = true;
|
|
80 } else if (node->resend_flag) {
|
|
81 node->seq_rd = psx_rd(NetworkGame::linda, node->id * 10 + 1);
|
|
82 node->resend_flag = false;
|
|
83 }
|
|
84 }
|
|
85
|
|
86 SceneGraphPtr
|
|
87 create_sg(Viewer *viewer, SceneGraphPtr par, unsigned char *data, int len, int serial_id)
|
|
88 {
|
|
89 SceneGraphPtr child = viewer->sgroot->createSceneGraph();
|
|
90 viewer->sgroot->createFromXMLmemory(viewer->sgroot->tmanager, child, (char *)data, len);
|
|
91 child->set_move_collision(update_position_move, null_collision);
|
|
92 child->id = serial_id;
|
|
93 child->seq = psx_wait_rd(NetworkGame::linda, serial_id * 10 + 1);
|
|
94 child->seq_rd = psx_rd(NetworkGame::linda, serial_id * 10 + 1);
|
|
95 child->resend_flag = false;
|
|
96 par->addChild(child);
|
|
97 return child;
|
|
98 }
|
|
99
|
|
100 static void
|
|
101 check_new_player_move(SceneGraphPtr node, void *sgroot_, int screen_w, int screen_h)
|
|
102 {
|
|
103 unsigned char *reply_rd = psx_reply(node->seq_rd);
|
|
104 if (reply_rd != NULL) {
|
|
105 unsigned char *xml_data = reply_rd + LINDA_HEADER_SIZE;
|
|
106 int xml_len = psx_get_datalength(reply_rd);
|
|
107 create_sg(NetworkGame::sgroot, node, xml_data, xml_len, NetworkGame::last_player_id);
|
|
108 psx_free(reply_rd);
|
|
109 NetworkGame::update_last_player_id();
|
|
110 int tuple_id = NetworkGame::last_player_id * 10;
|
|
111 node->seq_rd = psx_rd(NetworkGame::linda, tuple_id);
|
|
112 }
|
|
113 // printf("rd id: %d\n", NetworkGame::last_player_id);
|
|
114 }
|
|
115
|
|
116 void *
|
|
117 file_map(const char *filename, int *size) {
|
|
118 int fd;
|
|
119 void *addr;
|
|
120 struct stat sb;
|
|
121
|
|
122 if ((fd = open(filename, O_RDONLY)) == -1) {
|
|
123 fprintf(stderr, "Can't open %s\n", filename);
|
|
124 perror(NULL);
|
|
125 }
|
|
126 if (fstat(fd, &sb) == -1) {
|
|
127 fprintf(stderr, "Can't fstat %s\n", filename);
|
|
128 perror(NULL);
|
|
129 }
|
|
130 *size = sb.st_size;
|
|
131 addr = mmap(NULL, *size, PROT_READ, MAP_PRIVATE, fd, 0);
|
|
132 if (addr == MAP_FAILED) {
|
|
133 perror("mmap error\n");
|
|
134 exit(EXIT_FAILURE);
|
|
135 }
|
|
136 close(fd);
|
|
137
|
|
138 return addr;
|
|
139 }
|
|
140
|
|
141 void callback_free(unsigned char *tuple, void *arg) {
|
|
142 psx_free(tuple);
|
|
143 }
|
|
144
|
|
145 void
|
|
146 NetworkGame::send_position(SceneGraphPtr node) {
|
|
147 int pos_id = serial_id * 10 + 1;
|
|
148 psx_callback_in(linda, pos_id, callback_free, NULL);
|
|
149 network_game::Position *pos = new network_game::Position();
|
|
150 pos->set_x(node->xyz[0]);
|
|
151 pos->set_y(node->xyz[1]);
|
|
152 pos->set_angle_x(node->angle[0]);
|
|
153 pos->set_angle_y(node->angle[1]);
|
|
154 int size = pos->ByteSize();
|
|
155 unsigned char *msg = (unsigned char *) sgroot->manager->allocate(sizeof(char) * size);
|
|
156 pos->SerializeToArray(msg, size); // 更新したデータを再度シリアライズ
|
|
157 delete pos;
|
|
158 psx_out(linda, pos_id, msg, size);
|
|
159 }
|
|
160
|
|
161 void
|
|
162 my_move(SceneGraphPtr node, void *sgroot_, int w, int h)
|
|
163 {
|
|
164 SceneGraphRoot *sgroot = (SceneGraphRoot *)sgroot_;
|
|
165 Pad *pad = sgroot->getController();
|
|
166 int flag = 0;
|
|
167 if (pad->right.isHold() || pad->left.isHold()) {
|
|
168 if (pad->right.isHold()) {
|
|
169 node->xyz[0] += 5.0f;
|
|
170 sgroot->camera->xyz[0] = node->xyz[0];
|
|
171 // node->angle[1] = 0.0f;
|
|
172 flag = 1;
|
|
173 } else if (pad->left.isHold()) {
|
|
174 node->xyz[0] -= 5.0f;
|
|
175 sgroot->camera->xyz[0] = node->xyz[0];
|
|
176 // node->angle[1] = 180.0f;
|
|
177 flag = 1;
|
|
178 }
|
|
179 }
|
|
180
|
|
181 if (pad->down.isHold() || pad->up.isHold() ) {
|
|
182 if (pad->down.isHold()) {
|
|
183 node->xyz[1] += 5.0f;
|
|
184 sgroot->camera->xyz[1] = node->xyz[1];
|
|
185 flag = 1;
|
|
186 } else if (pad->up.isHold()) {
|
|
187 node->xyz[1] -= 5.0f;
|
|
188 sgroot->camera->xyz[1] = node->xyz[1];
|
|
189 flag = 1;
|
|
190 }
|
|
191 }
|
|
192
|
|
193 /* ここで座標を送信 */
|
|
194 if (flag || node->resend_flag) {
|
|
195 NetworkGame::send_position(node);
|
|
196 }
|
|
197 }
|
|
198
|
|
199 void
|
|
200 NetworkGame::create_my_sg(Viewer *viewer, SceneGraphPtr par, int screen_w, int screen_h)
|
|
201 {
|
|
202 int size;
|
|
203 void *addr = file_map(xml_file_name, &size);
|
|
204 SceneGraphPtr sgp = viewer->createSceneGraph();
|
|
205 viewer->createFromXMLmemory(sgp, (char *)addr, size);
|
|
206 sgp->set_move_collision(my_move, null_collision);
|
|
207 Camera *camera = viewer->sgroot->camera;
|
|
208 camera->xyz[0] = 0.0;
|
|
209 camera->xyz[1] = 0.0;
|
|
210
|
|
211 par->addChild(sgp);
|
|
212 sgp->c_xyz[0] = 0.0f;
|
|
213 sgp->c_xyz[1] = 0.0f;
|
|
214 sgp->c_xyz[2] = 0.0f;
|
|
215
|
|
216 int xml_id = serial_id * 10;
|
|
217 psx_out(linda, xml_id, (unsigned char *)addr, size);
|
|
218 int pos_id = serial_id * 10 + 1;
|
|
219
|
|
220 network_game::Position *pos = new network_game::Position();
|
|
221 pos->set_x(0.0f);
|
|
222 pos->set_y(0.0f);
|
|
223 pos->set_angle_x(0.0f);
|
|
224 pos->set_angle_y(0.0f);
|
|
225 unsigned char *msg = (unsigned char *) viewer->manager->allocate(sizeof(unsigned char *) * size);
|
|
226 pos->SerializeToArray(msg, size);
|
|
227 psx_out(linda, pos_id, (unsigned char *)msg, pos->ByteSize());
|
|
228 delete pos;
|
|
229 sgp->seq = 0;
|
|
230 sgp->resend_flag = 0;
|
|
231 }
|
|
232
|
|
233 MainLoopPtr
|
|
234 NetworkGame::init(Viewer *sgroot, int screen_w, int screen_h)
|
|
235 {
|
|
236 this->sgroot = sgroot;
|
|
237 width = screen_w;
|
|
238 linda_connect(); // 接続に合わせて serial_id も取得
|
|
239 // update_screen_scope();
|
|
240 SceneGraphPtr parent = sgroot->createSceneGraph();
|
|
241 parent->set_move_collision(check_new_player_move, null_collision);
|
|
242
|
|
243 create_my_sg(sgroot, parent, screen_w, screen_h);
|
|
244 update_last_player_id();
|
|
245
|
|
246 int tuple_id = NetworkGame::last_player_id * 10;
|
|
247 parent->seq_rd = psx_rd(linda, tuple_id);
|
|
248 sgroot->setSceneData(parent);
|
|
249 return sgroot;
|
|
250 }
|
|
251
|
|
252 void
|
|
253 NetworkGame::linda_connect() {
|
|
254 init_linda(); // セレクタの初期化
|
|
255 linda = open_linda_java(linda_addr.hostname, linda_addr.port);
|
|
256 // serial_id の取得
|
|
257 int seq = psx_in(linda, GET_SERIAL_ID);
|
|
258 unsigned char *data = NULL;
|
|
259 do {
|
|
260 psx_sync_n();
|
|
261 data = psx_reply(seq);
|
|
262 } while (data == NULL);
|
|
263 // data[LINDA_HEADER_SIZE + psx_get_datalength(data)] = '\0';
|
|
264 serial_id = atoi((char *)data + LINDA_HEADER_SIZE);
|
|
265 psx_free(data);
|
|
266 printf("Get serial_id: %d\n", serial_id);
|
|
267 }
|
|
268
|
|
269 int
|
|
270 TMmain(TaskManager *manager, int argc, char *argv[])
|
|
271 {
|
|
272 task_initialize();
|
|
273 manager->set_TMend(TMend);
|
|
274
|
|
275 for (int i = 0; i < argc; i++) {
|
|
276 if (strcmp(argv[i],"-linda") == 0 && i + 1 <= argc) {
|
|
277 NetworkGame::linda_addr.hostname = argv[i+1];
|
|
278 } else if (strcmp(argv[i],"-port") == 0 && i + 1 <= argc) {
|
|
279 NetworkGame::linda_addr.port = atoi(argv[i+1]);
|
|
280 } else if (strcmp(argv[i],"-xml") == 0 && i + 1 <= argc) {
|
|
281 NetworkGame::xml_file_name = argv[i+1];
|
|
282 }
|
|
283 }
|
|
284 return init(manager, argc, argv);
|
|
285 }
|
|
286
|
|
287 void
|
|
288 TMend(TaskManager *manager)
|
|
289 {
|
|
290 printf("NetworkGame end\n");
|
|
291 }
|
|
292
|
|
293 /* end */
|