Freeciv-3.3
Loading...
Searching...
No Matches
attribute.c
Go to the documentation of this file.
1/***********************************************************************
2 Freeciv - Copyright (C) 2001 - R. Falke
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12***********************************************************************/
13
14#ifdef HAVE_CONFIG_H
15#include <fc_config.h>
16#endif
17
18/* utility */
19#include "dataio.h"
20#include "fcintl.h"
21#include "genhash.h" /* genhash_val_t */
22#include "log.h"
23#include "mem.h"
24
25/* common */
26#include "packets.h"
27
28/* client */
29#include "client_main.h"
30
31#include "attribute.h"
32
33#define log_attribute log_debug
34
40
41struct attr_key {
42 int key, id, x, y;
43};
44
45static genhash_val_t attr_key_val(const struct attr_key *pkey);
46static bool attr_key_comp(const struct attr_key *pkey1,
47 const struct attr_key *pkey2);
48static struct attr_key *attr_key_dup(const struct attr_key *pkey);
49static void attr_key_destroy(struct attr_key *pkey);
50
51/* 'struct attribute_hash' and related functions. */
52#define SPECHASH_TAG attribute
53#define SPECHASH_IKEY_TYPE struct attr_key *
54#define SPECHASH_IDATA_TYPE void *
55#define SPECHASH_IKEY_VAL attr_key_val
56#define SPECHASH_IKEY_COMP attr_key_comp
57#define SPECHASH_IKEY_COPY attr_key_dup
58#define SPECHASH_IKEY_FREE attr_key_destroy
59#define SPECHASH_IDATA_FREE free
60#include "spechash.h"
61#define attribute_hash_values_iterate(hash, pvalue) \
62 TYPED_HASH_DATA_ITERATE(void *, hash, pvalue)
63#define attribute_hash_values_iterate_end HASH_DATA_ITERATE_END
64#define attribute_hash_iterate(hash, pkey, pvalue) \
65 TYPED_HASH_ITERATE(const struct attr_key *, void *, hash, pkey, pvalue)
66#define attribute_hash_iterate_end HASH_ITERATE_END
67
68
70
71/************************************************************************/
75{
76 return (genhash_val_t) pkey->id ^ pkey->x ^ pkey->y ^ pkey->key;
77}
78
79/************************************************************************/
82static bool attr_key_comp(const struct attr_key *pkey1,
83 const struct attr_key *pkey2)
84{
85 return pkey1->key == pkey2->key
86 && pkey1->id == pkey2->id
87 && pkey1->x == pkey2->x
88 && pkey1->y == pkey2->y;
89}
90
91/************************************************************************/
94static struct attr_key *attr_key_dup(const struct attr_key *pkey)
95{
96 struct attr_key *pnew_key = fc_malloc(sizeof(*pnew_key));
97
98 *pnew_key = *pkey;
99 return pnew_key;
100}
101
102/************************************************************************/
105static void attr_key_destroy(struct attr_key *pkey)
106{
108 free(pkey);
109}
110
111/************************************************************************/
119
120/************************************************************************/
129
130/************************************************************************/
133static enum attribute_serial
135 void **pdata, int *pdata_length)
136{
137 /*
138 * Layout of version 2:
139 *
140 * struct {
141 * uint32 0; always != 0 in version 1
142 * uint8 2;
143 * uint32 entries;
144 * uint32 total_size_in_bytes;
145 * } preamble;
146 *
147 * struct {
148 * uint32 value_size;
149 * char key[], char value[];
150 * } body[entries];
151 */
152 const size_t entries = attribute_hash_size(hash);
153 int total_length, value_lengths[entries];
154 void *result;
155 struct raw_data_out dout;
156 int i;
157
158 /*
159 * Step 1: Loop through all keys and fill value_lengths and calculate
160 * the total_length.
161 */
162 /* Preamble */
163 total_length = 4 + 1 + 4 + 4;
164 /* Body */
165 total_length += entries * (4 + 4 + 4 + 2 + 2); /* value_size + key */
166
167 i = 0;
169 struct data_in din;
170
171 dio_input_init(&din, pvalue, 4);
173
174 total_length += value_lengths[i];
175 i++;
177
178 fc_assert(i == entries);
179
180 /*
181 * Step 2: Allocate memory.
182 */
183 result = fc_malloc(total_length);
184 dio_output_init(&dout, result, total_length);
185
186 /*
187 * Step 3: Fill out the preamble.
188 */
192 dio_put_uint32_raw(&dout, total_length);
193
194 /*
195 * Step 4: Fill out the body.
196 */
197 i = 0;
200
205
207 i++;
209
210 fc_assert(i == entries);
211
212 fc_assert(!dout.too_short);
213 fc_assert_msg(dio_output_used(&dout) == total_length,
214 "serialize_hash() total_length = %lu, actual = %lu",
215 (long unsigned)total_length,
216 (long unsigned)dio_output_used(&dout));
217
218 /*
219 * Step 5: Return.
220 */
221 *pdata = result;
222 *pdata_length = total_length;
223 log_attribute("attribute.c serialize_hash() "
224 "serialized %lu entries in %lu bytes",
225 (long unsigned) entries, (long unsigned) total_length);
226
227 return A_SERIAL_OK;
228}
229
230/************************************************************************/
237 const void *data,
238 size_t data_length)
239{
240 int entries, i, dummy;
241 struct data_in din;
242
244
246
247 dio_get_uint32_raw(&din, &dummy);
248 if (dummy != 0) {
249 log_verbose("attribute.c unserialize_hash() preamble, uint32 %lu != 0",
250 (long unsigned) dummy);
251 return A_SERIAL_OLD;
252 }
253 dio_get_uint8_raw(&din, &dummy);
254 if (dummy != 2) {
255 log_verbose("attribute.c unserialize_hash() preamble, "
256 "uint8 %lu != 2 version", (long unsigned) dummy);
257 return A_SERIAL_OLD;
258 }
260 dio_get_uint32_raw(&din, &dummy);
261 if (dummy != data_length) {
262 log_verbose("attribute.c unserialize_hash() preamble, "
263 "uint32 %lu != %lu data_length",
264 (long unsigned) dummy, (long unsigned) data_length);
265 return A_SERIAL_FAIL;
266 }
267
268 log_attribute("attribute.c unserialize_hash() "
269 "uint32 %lu entries, %lu data_length",
270 (long unsigned) entries, (long unsigned) data_length);
271
272 for (i = 0; i < entries; i++) {
273 struct attr_key key;
274 void *pvalue;
275 int value_length;
276 struct raw_data_out dout;
277
279 log_verbose("attribute.c unserialize_hash() "
280 "uint32 value_length dio_input_too_short");
281 return A_SERIAL_FAIL;
282 }
283 log_attribute("attribute.c unserialize_hash() "
284 "uint32 %lu value_length", (long unsigned) value_length);
285
286 /* next 12 bytes */
287 if (!dio_get_uint32_raw(&din, &key.key)
288 || !dio_get_uint32_raw(&din, &key.id)
289 || !dio_get_sint16_raw(&din, &key.x)
290 || !dio_get_sint16_raw(&din, &key.y)) {
291 log_verbose("attribute.c unserialize_hash() "
292 "uint32 key dio_input_too_short");
293 return A_SERIAL_FAIL;
294 }
295 pvalue = fc_malloc(value_length + 4);
296
297 dio_output_init(&dout, pvalue, value_length + 4);
300 log_verbose("attribute.c unserialize_hash() "
301 "memory dio_input_too_short");
302 return A_SERIAL_FAIL;
303 }
304
305 if (!attribute_hash_insert(hash, &key, pvalue)) {
306 /* There are some untraceable attribute bugs caused by the CMA that
307 * can cause this to happen. I think the only safe thing to do is
308 * to delete all attributes. Another symptom of the bug is the
309 * value_length (above) is set to a random value, which can also
310 * cause a bug. */
311 free(pvalue);
313 return A_SERIAL_FAIL;
314 }
315 }
316
317 if (dio_input_remaining(&din) > 0) {
318 /* This is not an error, as old clients sent overlong serialized
319 * attributes pre gna bug #21295, and these will be hanging around
320 * in savefiles forever. */
321 log_attribute("attribute.c unserialize_hash() "
322 "ignored %lu trailing octets",
323 (long unsigned) dio_input_remaining(&din));
324 }
325
326 return A_SERIAL_OK;
327}
328
329/************************************************************************/
334{
335 struct player *pplayer = client_player();
336
337 if (!pplayer || client_is_observer() || !pplayer->is_alive) {
338 return;
339 }
340
342
344 return;
345 }
346
347 if (pplayer->attribute_block.data) {
348 free(pplayer->attribute_block.data);
349 pplayer->attribute_block.data = NULL;
350 }
351
353 &pplayer->attribute_block.length);
355}
356
357/************************************************************************/
362{
363 struct player *pplayer = client_player();
364
365 if (!pplayer) {
366 return;
367 }
368
370
372 pplayer->attribute_block.data,
373 pplayer->attribute_block.length)) {
374 case A_SERIAL_FAIL:
375 log_error(_("There has been a CMA error. "
376 "Your citizen governor settings may be broken."));
377 break;
378 case A_SERIAL_OLD:
379 log_normal(_("Old attributes detected and removed."));
380 break;
381 default:
382 break;
383 };
384}
385
386/************************************************************************/
390void attribute_set(int key, int id, int x, int y, size_t data_length,
391 const void *const data)
392{
393 struct attr_key akey = { .key = key, .id = id, .x = x, .y = y };
394
395 log_attribute("attribute_set(key = %d, id = %d, x = %d, y = %d, "
396 "data_length = %lu, data = %p)", key, id, x, y,
397 (long unsigned) data_length, data);
398
400
401 if (0 != data_length) {
402 void *pvalue = fc_malloc(data_length + 4);
403 struct raw_data_out dout;
404
405 dio_output_init(&dout, pvalue, data_length + 4);
408
410 } else {
412 }
413}
414
415/************************************************************************/
422size_t attribute_get(int key, int id, int x, int y, size_t max_data_length,
423 void *data)
424{
425 struct attr_key akey = { .key = key, .id = id, .x = x, .y = y };
426 void *pvalue;
427 int length;
428 struct data_in din;
429
430 log_attribute("attribute_get(key = %d, id = %d, x = %d, y = %d, "
431 "max_data_length = %lu, data = %p)", key, id, x, y,
432 (long unsigned) max_data_length, data);
433
435
436 if (!attribute_hash_lookup(attribute_hash, &akey, &pvalue)) {
437 log_attribute(" not found");
438 return 0;
439 }
440
441 dio_input_init(&din, pvalue, 0xffffffff);
442 dio_get_uint32_raw(&din, &length);
443
444 if (length <= max_data_length) {
445 dio_get_memory_raw(&din, data, length);
446 }
447
448 log_attribute(" found length = %d", length);
449 return length;
450}
451
452/************************************************************************/
455void attr_unit_set(enum attr_unit what, int unit_id, size_t data_length,
456 const void *const data)
457{
458 attribute_set(what, unit_id, -1, -2, data_length, data);
459}
460
461/************************************************************************/
464size_t attr_unit_get(enum attr_unit what, int unit_id, size_t max_data_length,
465 void *data)
466{
467 return attribute_get(what, unit_id, -1, -2, max_data_length, data);
468}
469
470/************************************************************************/
473void attr_unit_set_int(enum attr_unit what, int unit_id, int data)
474{
475 attr_unit_set(what, unit_id, sizeof(int), &data);
476}
477
478/************************************************************************/
481size_t attr_unit_get_int(enum attr_unit what, int unit_id, int *data)
482{
483 return attr_unit_get(what, unit_id, sizeof(int), data);
484}
485
486/************************************************************************/
489void attr_city_set(enum attr_city what, int city_id, size_t data_length,
490 const void *const data)
491{
492 attribute_set(what, city_id, -1, -1, data_length, data);
493}
494
495/************************************************************************/
498size_t attr_city_get(enum attr_city what, int city_id, size_t max_data_length,
499 void *data)
500{
501 return attribute_get(what, city_id, -1, -1, max_data_length, data);
502}
503
504/************************************************************************/
507void attr_city_set_int(enum attr_city what, int city_id, int data)
508{
509 attr_city_set(what, city_id, sizeof(int), &data);
510}
511
512/************************************************************************/
515size_t attr_city_get_int(enum attr_city what, int city_id, int *data)
516{
517 return attr_city_get(what, city_id, sizeof(int), data);
518}
519
520/************************************************************************/
523void attr_player_set(enum attr_player what, int player_id, size_t data_length,
524 const void *const data)
525{
526 attribute_set(what, player_id, -1, -1, data_length, data);
527}
528
529/************************************************************************/
532size_t attr_player_get(enum attr_player what, int player_id,
533 size_t max_data_length, void *data)
534{
535 return attribute_get(what, player_id, -1, -1, max_data_length, data);
536}
537
538/************************************************************************/
541void attr_tile_set(enum attr_tile what, int x, int y, size_t data_length,
542 const void *const data)
543{
544 attribute_set(what, -1, x, y, data_length, data);
545}
546
547/************************************************************************/
550size_t attr_tile_get(enum attr_tile what, int x, int y, size_t max_data_length,
551 void *data)
552{
553 return attribute_get(what, -1, x, y, max_data_length, data);
554}
struct @130::my_agent entries[MAX_AGENTS]
void attribute_set(int key, int id, int x, int y, size_t data_length, const void *const data)
Definition attribute.c:390
static struct attribute_hash * attribute_hash
Definition attribute.c:69
size_t attr_city_get_int(enum attr_city what, int city_id, int *data)
Definition attribute.c:515
static void attr_key_destroy(struct attr_key *pkey)
Definition attribute.c:105
void attribute_init(void)
Definition attribute.c:114
void attribute_free(void)
Definition attribute.c:123
size_t attr_tile_get(enum attr_tile what, int x, int y, size_t max_data_length, void *data)
Definition attribute.c:550
void attr_player_set(enum attr_player what, int player_id, size_t data_length, const void *const data)
Definition attribute.c:523
size_t attr_unit_get_int(enum attr_unit what, int unit_id, int *data)
Definition attribute.c:481
void attr_tile_set(enum attr_tile what, int x, int y, size_t data_length, const void *const data)
Definition attribute.c:541
static enum attribute_serial unserialize_hash(struct attribute_hash *hash, const void *data, size_t data_length)
Definition attribute.c:236
void attribute_flush(void)
Definition attribute.c:333
#define attribute_hash_iterate_end
Definition attribute.c:66
size_t attribute_get(int key, int id, int x, int y, size_t max_data_length, void *data)
Definition attribute.c:422
size_t attr_city_get(enum attr_city what, int city_id, size_t max_data_length, void *data)
Definition attribute.c:498
static struct attr_key * attr_key_dup(const struct attr_key *pkey)
Definition attribute.c:94
#define attribute_hash_values_iterate_end
Definition attribute.c:63
static genhash_val_t attr_key_val(const struct attr_key *pkey)
Definition attribute.c:74
void attribute_restore(void)
Definition attribute.c:361
void attr_unit_set(enum attr_unit what, int unit_id, size_t data_length, const void *const data)
Definition attribute.c:455
size_t attr_unit_get(enum attr_unit what, int unit_id, size_t max_data_length, void *data)
Definition attribute.c:464
size_t attr_player_get(enum attr_player what, int player_id, size_t max_data_length, void *data)
Definition attribute.c:532
static enum attribute_serial serialize_hash(const struct attribute_hash *hash, void **pdata, int *pdata_length)
Definition attribute.c:134
attribute_serial
Definition attribute.c:35
@ A_SERIAL_OLD
Definition attribute.c:38
@ A_SERIAL_OK
Definition attribute.c:37
@ A_SERIAL_FAIL
Definition attribute.c:36
#define attribute_hash_iterate(hash, pkey, pvalue)
Definition attribute.c:64
void attr_unit_set_int(enum attr_unit what, int unit_id, int data)
Definition attribute.c:473
static bool attr_key_comp(const struct attr_key *pkey1, const struct attr_key *pkey2)
Definition attribute.c:82
void attr_city_set_int(enum attr_city what, int city_id, int data)
Definition attribute.c:507
void attr_city_set(enum attr_city what, int city_id, size_t data_length, const void *const data)
Definition attribute.c:489
#define attribute_hash_values_iterate(hash, pvalue)
Definition attribute.c:61
#define log_attribute
Definition attribute.c:33
attr_city
Definition attribute.h:37
attr_unit
Definition attribute.h:33
attr_tile
Definition attribute.h:46
attr_player
Definition attribute.h:42
bool client_is_observer(void)
struct civclient client
#define client_player()
char * incite_cost
Definition comments.c:76
int dio_put_uint8_raw(struct raw_data_out *dout, int value)
Definition dataio_raw.c:265
int dio_put_uint32_raw(struct raw_data_out *dout, int value)
Definition dataio_raw.c:309
void dio_output_init(struct raw_data_out *dout, void *destination, size_t dest_size)
Definition dataio_raw.c:171
size_t dio_input_remaining(struct data_in *din)
Definition dataio_raw.c:221
bool dio_get_uint32_raw(struct data_in *din, int *dest)
Definition dataio_raw.c:640
bool dio_get_sint16_raw(struct data_in *din, int *dest)
Definition dataio_raw.c:777
bool dio_get_memory_raw(struct data_in *din, void *dest, size_t dest_size)
Definition dataio_raw.c:816
int dio_put_memory_raw(struct raw_data_out *dout, const void *value, size_t size)
Definition dataio_raw.c:499
bool dio_get_uint8_raw(struct data_in *din, int *dest)
Definition dataio_raw.c:598
size_t dio_output_used(struct raw_data_out *dout)
Definition dataio_raw.c:184
void dio_input_init(struct data_in *din, const void *src, size_t src_size)
Definition dataio_raw.c:202
int dio_put_sint16_raw(struct raw_data_out *dout, int value)
Definition dataio_raw.c:366
int int id
Definition editgui_g.h:28
#define _(String)
Definition fcintl.h:67
unsigned int genhash_val_t
Definition genhash.h:32
static GHashTable * hash
Definition wldlg.c:322
#define fc_assert_msg(condition, message,...)
Definition log.h:182
#define fc_assert_ret(condition)
Definition log.h:192
#define log_verbose(message,...)
Definition log.h:110
#define fc_assert(condition)
Definition log.h:177
#define fc_assert_ret_val(condition, val)
Definition log.h:195
#define log_normal(message,...)
Definition log.h:108
#define log_error(message,...)
Definition log.h:104
#define fc_malloc(sz)
Definition mem.h:34
void send_attribute_block(const struct player *pplayer, struct connection *pconn)
Definition packets.c:746
#define ADD_TO_POINTER(p, n)
Definition shared.h:86
struct sprite int int y
Definition sprite_g.h:31
struct sprite int x
Definition sprite_g.h:31
int key
Definition attribute.c:42
struct connection conn
Definition client_main.h:96
bool is_alive
Definition player.h:268
struct attribute_block_s attribute_block
Definition player.h:307