Fawkes API  Fawkes Development Version
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
spl.cpp
1 
2 /***************************************************************************
3  * spl.cpp - Fawkes SPL refbox repeater
4  *
5  * Created: Tue Jul 08 13:50:06 2008
6  * Copyright 2008 Tim Niemueller [www.niemueller.de]
7  *
8  ****************************************************************************/
9 
10 /* This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU Library General Public License for more details.
19  *
20  * Read the full text in the LICENSE.GPL file in the doc directory.
21  */
22 
23 #include "spl.h"
24 #include <netcomm/socket/datagram.h>
25 
26 #include <cstring>
27 #include <cstdio>
28 #include <unistd.h>
29 
30 using namespace fawkes;
31 
32 static const uint32_t SPL_STRUCT_VERSION = 6;
33 
34 static const uint8_t SPL_STATE_INITIAL = 0;
35 static const uint8_t SPL_STATE_READY = 1;
36 static const uint8_t SPL_STATE_SET = 2;
37 static const uint8_t SPL_STATE_PLAYING = 3;
38 static const uint8_t SPL_STATE_FINISHED = 4;
39 
40 static const uint8_t SPL_STATE2_NORMAL = 0;
41 static const uint8_t SPL_STATE2_PENALTYSHOOT = 1;
42 
43 static const uint8_t SPL_PENALTY_NONE = 0;
44 static const uint8_t SPL_PENALTY_BALL_HOLDING = 1;
45 static const uint8_t SPL_PENALTY_GOALIE_PUSHING = 2;
46 static const uint8_t SPL_PENALTY_PLAYER_PUSHING = 3;
47 static const uint8_t SPL_PENALTY_ILLEGAL_DEFENDER = 4;
48 static const uint8_t SPL_PENALTY_ILLEGAL_DEFENSE = 5;
49 static const uint8_t SPL_PENALTY_OBSTRUCTION = 6;
50 static const uint8_t SPL_PENALTY_REQ_FOR_PICKUP = 7;
51 static const uint8_t SPL_PENALTY_LEAVING = 8;
52 static const uint8_t SPL_PENALTY_DAMAGE = 9;
53 static const uint8_t SPL_PENALTY_MANUAL = 10;
54 
55 // team numbers
56 static const uint8_t SPL_TEAM_BLUE = 0;
57 static const uint8_t SPL_TEAM_RED = 1;
58 
59 static const char SPL_GAMECONTROL_HEADER[GCHS] = {'R', 'G', 'm', 'e'};
60 
61 
62 /** @class SplRefBoxRepeater <tools/refboxrep/spl.h>
63  * SPL league refbox repeater.
64  * This class will listen to SPL refbox commands and derive matching
65  * game states from the communication stream and send this via the world info.
66  * @author Tim Niemueller
67  */
68 
69 /** Constructor.
70  * @param rss refbox state sender
71  * @param broadcast_ip Broadcast IP
72  * @param broadcast_port Broadcast port
73  * @param our_team our initial team
74  * @param our_goal our initial goal
75  */
77  const char *broadcast_ip,
78  unsigned short int broadcast_port,
81  : __rss(rss)
82 {
83  __quit = false;
84  __our_team = our_team;
85  __our_goal = our_goal;
86  __s = new DatagramSocket();
87  __s->bind(broadcast_port);
88 
89  for (unsigned int i = 0; i < MAX_NUM_PLAYERS; ++i) {
90  __penalties[i] = SPL_PENALTY_NONE;
91  }
92 }
93 
94 
95 /** Destructor. */
97 {
98  __s->close();
99  delete __s;
100 }
101 
102 
103 /** Process received struct. */
104 void
105 SplRefBoxRepeater::process_struct(spl_gamecontrol_t *msg)
106 {
107  switch (msg->state) {
108  case SPL_STATE_INITIAL:
109  __rss.set_gamestate(GS_SPL_INITIAL, TEAM_BOTH);
110  break;
111  case SPL_STATE_READY:
112  __rss.set_gamestate(GS_SPL_READY,
113  (msg->kick_off_team == SPL_TEAM_BLUE) ? TEAM_CYAN : TEAM_MAGENTA);
114  break;
115  case SPL_STATE_SET:
116  __rss.set_gamestate(GS_SPL_SET,
117  (msg->kick_off_team == SPL_TEAM_BLUE) ? TEAM_CYAN : TEAM_MAGENTA);
118  break;
119  case SPL_STATE_PLAYING:
120  __rss.set_gamestate(GS_SPL_PLAY,
121  (msg->kick_off_team == SPL_TEAM_BLUE) ? TEAM_CYAN : TEAM_MAGENTA);
122  break;
123  case SPL_STATE_FINISHED:
124  __rss.set_gamestate(GS_SPL_FINISHED, TEAM_BOTH);
125  break;
126  default:
127  __rss.set_gamestate(GS_FROZEN, TEAM_BOTH); break;
128  }
129 
130  __rss.set_half( (msg->first_half == 1) ? HALF_FIRST : HALF_SECOND);
131 
132  if (msg->teams[0].team_color == SPL_TEAM_BLUE) {
133  __rss.set_score( msg->teams[0].score, msg->teams[1].score);
134  } else {
135  __rss.set_score( msg->teams[1].score, msg->teams[0].score);
136  }
137 
138  int oti = (msg->teams[0].team_color == __our_team) ? 0 : 1;
139  for (unsigned int i = 0; i < MAX_NUM_PLAYERS; ++i) {
140  if ( (__penalties[i] != msg->teams[oti].players[i].penalty) ||
141  (msg->teams[oti].players[i].penalty != SPL_PENALTY_NONE) ) {
142  __rss.add_penalty(i, msg->teams[oti].players[i].penalty,
143  msg->teams[oti].players[i].secs_till_unpenalized);
144  }
145  }
146 
147  __rss.send();
148 }
149 
150 
151 /** Run.
152  * Reads messages from the network, processes them and calls the refbox state sender.
153  */
154 void
156 {
157  spl_gamecontrol_t ctrlmsg;
158  while ( ! __quit ) {
159  size_t bytes_read = __s->recv((void *)&ctrlmsg, sizeof(ctrlmsg));
160  if ( bytes_read == sizeof(ctrlmsg) ) {
161  if ( (strncmp(ctrlmsg.header, SPL_GAMECONTROL_HEADER, GCHS) == 0) &&
162  (ctrlmsg.version == SPL_STRUCT_VERSION) ) {
163  process_struct(&ctrlmsg);
164  } else {
165  printf("Received illegal package\n");
166  }
167  }
168  }
169 }