Freeciv-3.2
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 i = 0;
168 struct data_in din;
169
170 dio_input_init(&din, pvalue, 4);
172
173 total_length += value_lengths[i];
174 i++;
176
177 /*
178 * Step 2: allocate memory.
179 */
180 result = fc_malloc(total_length);
181 dio_output_init(&dout, result, total_length);
182
183 /*
184 * Step 3: fill out the preamble.
185 */
189 dio_put_uint32_raw(&dout, total_length);
190
191 /*
192 * Step 4: fill out the body.
193 */
194 i = 0;
197
202
204 i++;
206
207 fc_assert(!dout.too_short);
208 fc_assert_msg(dio_output_used(&dout) == total_length,
209 "serialize_hash() total_length = %lu, actual = %lu",
210 (long unsigned)total_length,
211 (long unsigned)dio_output_used(&dout));
212
213 /*
214 * Step 5: return.
215 */
216 *pdata = result;
217 *pdata_length = total_length;
218 log_attribute("attribute.c serialize_hash() "
219 "serialized %lu entries in %lu bytes",
220 (long unsigned) entries, (long unsigned) total_length);
221 return A_SERIAL_OK;
222}
223
224/************************************************************************/
231 const void *data,
232 size_t data_length)
233{
234 int entries, i, dummy;
235 struct data_in din;
236
238
240
241 dio_get_uint32_raw(&din, &dummy);
242 if (dummy != 0) {
243 log_verbose("attribute.c unserialize_hash() preamble, uint32 %lu != 0",
244 (long unsigned) dummy);
245 return A_SERIAL_OLD;
246 }
247 dio_get_uint8_raw(&din, &dummy);
248 if (dummy != 2) {
249 log_verbose("attribute.c unserialize_hash() preamble, "
250 "uint8 %lu != 2 version", (long unsigned) dummy);
251 return A_SERIAL_OLD;
252 }
254 dio_get_uint32_raw(&din, &dummy);
255 if (dummy != data_length) {
256 log_verbose("attribute.c unserialize_hash() preamble, "
257 "uint32 %lu != %lu data_length",
258 (long unsigned) dummy, (long unsigned) data_length);
259 return A_SERIAL_FAIL;
260 }
261
262 log_attribute("attribute.c unserialize_hash() "
263 "uint32 %lu entries, %lu data_length",
264 (long unsigned) entries, (long unsigned) data_length);
265
266 for (i = 0; i < entries; i++) {
267 struct attr_key key;
268 void *pvalue;
269 int value_length;
270 struct raw_data_out dout;
271
273 log_verbose("attribute.c unserialize_hash() "
274 "uint32 value_length dio_input_too_short");
275 return A_SERIAL_FAIL;
276 }
277 log_attribute("attribute.c unserialize_hash() "
278 "uint32 %lu value_length", (long unsigned) value_length);
279
280 /* next 12 bytes */
281 if (!dio_get_uint32_raw(&din, &key.key)
282 || !dio_get_uint32_raw(&din, &key.id)
283 || !dio_get_sint16_raw(&din, &key.x)
284 || !dio_get_sint16_raw(&din, &key.y)) {
285 log_verbose("attribute.c unserialize_hash() "
286 "uint32 key dio_input_too_short");
287 return A_SERIAL_FAIL;
288 }
289 pvalue = fc_malloc(value_length + 4);
290
291 dio_output_init(&dout, pvalue, value_length + 4);
294 log_verbose("attribute.c unserialize_hash() "
295 "memory dio_input_too_short");
296 return A_SERIAL_FAIL;
297 }
298
299 if (!attribute_hash_insert(hash, &key, pvalue)) {
300 /* There are some untraceable attribute bugs caused by the CMA that
301 * can cause this to happen. I think the only safe thing to do is
302 * to delete all attributes. Another symptom of the bug is the
303 * value_length (above) is set to a random value, which can also
304 * cause a bug. */
305 free(pvalue);
307 return A_SERIAL_FAIL;
308 }
309 }
310
311 if (dio_input_remaining(&din) > 0) {
312 /* This is not an error, as old clients sent overlong serialized
313 * attributes pre gna bug #21295, and these will be hanging around
314 * in savefiles forever. */
315 log_attribute("attribute.c unserialize_hash() "
316 "ignored %lu trailing octets",
317 (long unsigned) dio_input_remaining(&din));
318 }
319
320 return A_SERIAL_OK;
321}
322
323/************************************************************************/
328{
329 struct player *pplayer = client_player();
330
331 if (!pplayer || client_is_observer() || !pplayer->is_alive) {
332 return;
333 }
334
336
338 return;
339 }
340
341 if (pplayer->attribute_block.data) {
342 free(pplayer->attribute_block.data);
343 pplayer->attribute_block.data = NULL;
344 }
345
347 &pplayer->attribute_block.length);
349}
350
351/************************************************************************/
356{
357 struct player *pplayer = client_player();
358
359 if (!pplayer) {
360 return;
361 }
362
364
366 pplayer->attribute_block.data,
367 pplayer->attribute_block.length)) {
368 case A_SERIAL_FAIL:
369 log_error(_("There has been a CMA error. "
370 "Your citizen governor settings may be broken."));
371 break;
372 case A_SERIAL_OLD:
373 log_normal(_("Old attributes detected and removed."));
374 break;
375 default:
376 break;
377 };
378}
379
380/************************************************************************/
384void attribute_set(int key, int id, int x, int y, size_t data_length,
385 const void *const data)
386{
387 struct attr_key akey = { .key = key, .id = id, .x = x, .y = y };
388
389 log_attribute("attribute_set(key = %d, id = %d, x = %d, y = %d, "
390 "data_length = %lu, data = %p)", key, id, x, y,
391 (long unsigned) data_length, data);
392
394
395 if (0 != data_length) {
396 void *pvalue = fc_malloc(data_length + 4);
397 struct raw_data_out dout;
398
399 dio_output_init(&dout, pvalue, data_length + 4);
402
404 } else {
406 }
407}
408
409/************************************************************************/
416size_t attribute_get(int key, int id, int x, int y, size_t max_data_length,
417 void *data)
418{
419 struct attr_key akey = { .key = key, .id = id, .x = x, .y = y };
420 void *pvalue;
421 int length;
422 struct data_in din;
423
424 log_attribute("attribute_get(key = %d, id = %d, x = %d, y = %d, "
425 "max_data_length = %lu, data = %p)", key, id, x, y,
426 (long unsigned) max_data_length, data);
427
429
430 if (!attribute_hash_lookup(attribute_hash, &akey, &pvalue)) {
431 log_attribute(" not found");
432 return 0;
433 }
434
435 dio_input_init(&din, pvalue, 0xffffffff);
436 dio_get_uint32_raw(&din, &length);
437
438 if (length <= max_data_length) {
439 dio_get_memory_raw(&din, data, length);
440 }
441
442 log_attribute(" found length = %d", length);
443 return length;
444}
445
446/************************************************************************/
449void attr_unit_set(enum attr_unit what, int unit_id, size_t data_length,
450 const void *const data)
451{
452 attribute_set(what, unit_id, -1, -2, data_length, data);
453}
454
455/************************************************************************/
458size_t attr_unit_get(enum attr_unit what, int unit_id, size_t max_data_length,
459 void *data)
460{
461 return attribute_get(what, unit_id, -1, -2, max_data_length, data);
462}
463
464/************************************************************************/
467void attr_unit_set_int(enum attr_unit what, int unit_id, int data)
468{
469 attr_unit_set(what, unit_id, sizeof(int), &data);
470}
471
472/************************************************************************/
475size_t attr_unit_get_int(enum attr_unit what, int unit_id, int *data)
476{
477 return attr_unit_get(what, unit_id, sizeof(int), data);
478}
479
480/************************************************************************/
483void attr_city_set(enum attr_city what, int city_id, size_t data_length,
484 const void *const data)
485{
486 attribute_set(what, city_id, -1, -1, data_length, data);
487}
488
489/************************************************************************/
492size_t attr_city_get(enum attr_city what, int city_id, size_t max_data_length,
493 void *data)
494{
495 return attribute_get(what, city_id, -1, -1, max_data_length, data);
496}
497
498/************************************************************************/
501void attr_city_set_int(enum attr_city what, int city_id, int data)
502{
503 attr_city_set(what, city_id, sizeof(int), &data);
504}
505
506/************************************************************************/
509size_t attr_city_get_int(enum attr_city what, int city_id, int *data)
510{
511 return attr_city_get(what, city_id, sizeof(int), data);
512}
513
514/************************************************************************/
517void attr_player_set(enum attr_player what, int player_id, size_t data_length,
518 const void *const data)
519{
520 attribute_set(what, player_id, -1, -1, data_length, data);
521}
522
523/************************************************************************/
526size_t attr_player_get(enum attr_player what, int player_id,
527 size_t max_data_length, void *data)
528{
529 return attribute_get(what, player_id, -1, -1, max_data_length, data);
530}
531
532/************************************************************************/
535void attr_tile_set(enum attr_tile what, int x, int y, size_t data_length,
536 const void *const data)
537{
538 attribute_set(what, -1, x, y, data_length, data);
539}
540
541/************************************************************************/
544size_t attr_tile_get(enum attr_tile what, int x, int y, size_t max_data_length,
545 void *data)
546{
547 return attribute_get(what, -1, x, y, max_data_length, data);
548}
struct @126::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:384
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:509
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:544
void attr_player_set(enum attr_player what, int player_id, size_t data_length, const void *const data)
Definition attribute.c:517
size_t attr_unit_get_int(enum attr_unit what, int unit_id, int *data)
Definition attribute.c:475
void attr_tile_set(enum attr_tile what, int x, int y, size_t data_length, const void *const data)
Definition attribute.c:535
static enum attribute_serial unserialize_hash(struct attribute_hash *hash, const void *data, size_t data_length)
Definition attribute.c:230
void attribute_flush(void)
Definition attribute.c:327
#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:416
size_t attr_city_get(enum attr_city what, int city_id, size_t max_data_length, void *data)
Definition attribute.c:492
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:355
void attr_unit_set(enum attr_unit what, int unit_id, size_t data_length, const void *const data)
Definition attribute.c:449
size_t attr_unit_get(enum attr_unit what, int unit_id, size_t max_data_length, void *data)
Definition attribute.c:458
size_t attr_player_get(enum attr_player what, int player_id, size_t max_data_length, void *data)
Definition attribute.c:526
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:467
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:501
void attr_city_set(enum attr_city what, int city_id, size_t data_length, const void *const data)
Definition attribute.c:483
#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:75
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:181
#define fc_assert_ret(condition)
Definition log.h:191
#define log_verbose(message,...)
Definition log.h:109
#define fc_assert(condition)
Definition log.h:176
#define fc_assert_ret_val(condition, val)
Definition log.h:194
#define log_normal(message,...)
Definition log.h:107
#define log_error(message,...)
Definition log.h:103
#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:266
struct attribute_block_s attribute_block
Definition player.h:305