1 /**
2  * \file game-event.c
3  * \brief Allows the registering of handlers to be told about game events.
4  *
5  * Copyright (c) 2007 Antony Sidwell
6  *
7  * This work is free software; you can redistribute it and/or modify it
8  * under the terms of either:
9  *
10  * a) the GNU General Public License as published by the Free Software
11  *    Foundation, version 2, or
12  *
13  * b) the "Angband licence":
14  *    This software may be copied and distributed for educational, research,
15  *    and not for profit purposes provided that this copyright and statement
16  *    are included in all such copies.  Other copyrights may also apply.
17  */
18 
19 #include <assert.h>
20 #include "game-event.h"
21 #include "object.h"
22 #include "z-virt.h"
23 
24 struct event_handler_entry
25 {
26 	struct event_handler_entry *next;
27 	game_event_handler *fn;
28 	void *user;
29 };
30 
31 static struct event_handler_entry *event_handlers[N_GAME_EVENTS];
32 
game_event_dispatch(game_event_type type,game_event_data * data)33 static void game_event_dispatch(game_event_type type, game_event_data *data)
34 {
35 	struct event_handler_entry *this = event_handlers[type];
36 
37 	/*
38 	 * Send the word out to all interested event handlers.
39 	 */
40 	while (this)
41 	{
42 		/* Call the handler with the relevant data */
43 		this->fn(type, data, this->user);
44 		this = this->next;
45 	}
46 }
47 
event_add_handler(game_event_type type,game_event_handler * fn,void * user)48 void event_add_handler(game_event_type type, game_event_handler *fn, void *user)
49 {
50 	struct event_handler_entry *new;
51 
52 	assert(fn != NULL);
53 
54 	/* Make a new entry */
55 	new = mem_alloc(sizeof *new);
56 	new->fn = fn;
57 	new->user = user;
58 
59 	/* Add it to the head of the appropriate list */
60 	new->next = event_handlers[type];
61 	event_handlers[type] = new;
62 }
63 
event_remove_handler(game_event_type type,game_event_handler * fn,void * user)64 void event_remove_handler(game_event_type type, game_event_handler *fn, void *user)
65 {
66 	struct event_handler_entry *prev = NULL;
67 	struct event_handler_entry *this = event_handlers[type];
68 
69 	/* Look for the entry in the list */
70 	while (this)
71 	{
72 		/* Check if this is the entry we want to remove */
73 		if (this->fn == fn && this->user == user)
74 		{
75 			if (!prev)
76 			{
77 				event_handlers[type] = this->next;
78 			}
79 			else
80 			{
81 				prev->next = this->next;
82 			}
83 
84 			mem_free(this);
85 			return;
86 		}
87 
88 		prev = this;
89 		this = this->next;
90 	}
91 }
92 
event_remove_handler_type(game_event_type type)93 void event_remove_handler_type(game_event_type type)
94 {
95 	struct event_handler_entry *handler = event_handlers[type];
96 
97 	while (handler) {
98 		struct event_handler_entry *next = handler->next;
99 		mem_free(handler);
100 		handler = next;
101 	}
102 	event_handlers[type] = NULL;
103 }
104 
event_remove_all_handlers(void)105 void event_remove_all_handlers(void)
106 {
107 	int type;
108 	struct event_handler_entry *handler, *next;
109 
110 	for (type = 0; type < N_GAME_EVENTS; type++) {
111 		handler = event_handlers[type];
112 		while (handler) {
113 			next = handler->next;
114 			mem_free(handler);
115 			handler = next;
116 		}
117 		event_handlers[type] = NULL;
118 	}
119 }
120 
event_add_handler_set(game_event_type * type,size_t n_types,game_event_handler * fn,void * user)121 void event_add_handler_set(game_event_type *type, size_t n_types, game_event_handler *fn, void *user)
122 {
123 	size_t i;
124 
125 	for (i = 0; i < n_types; i++)
126 		event_add_handler(type[i], fn, user);
127 }
128 
event_remove_handler_set(game_event_type * type,size_t n_types,game_event_handler * fn,void * user)129 void event_remove_handler_set(game_event_type *type, size_t n_types, game_event_handler *fn, void *user)
130 {
131 	size_t i;
132 
133 	for (i = 0; i < n_types; i++)
134 		event_remove_handler(type[i], fn, user);
135 }
136 
137 
138 
139 
event_signal(game_event_type type)140 void event_signal(game_event_type type)
141 {
142 	game_event_dispatch(type, NULL);
143 }
144 
event_signal_flag(game_event_type type,bool flag)145 void event_signal_flag(game_event_type type, bool flag)
146 {
147 	game_event_data data;
148 	data.flag = flag;
149 
150 	game_event_dispatch(type, &data);
151 }
152 
153 
event_signal_point(game_event_type type,int x,int y)154 void event_signal_point(game_event_type type, int x, int y)
155 {
156 	game_event_data data;
157 	data.point.x = x;
158 	data.point.y = y;
159 
160 	game_event_dispatch(type, &data);
161 }
162 
163 
event_signal_string(game_event_type type,const char * s)164 void event_signal_string(game_event_type type, const char *s)
165 {
166 	game_event_data data;
167 	data.string = s;
168 
169 	game_event_dispatch(type, &data);
170 }
171 
event_signal_message(game_event_type type,int t,const char * s)172 void event_signal_message(game_event_type type, int t, const char *s)
173 {
174 	game_event_data data;
175 	memset(&data, 0, sizeof data);
176 
177 	data.message.type = t;
178 	data.message.msg = s;
179 
180 	game_event_dispatch(type, &data);
181 }
182 
event_signal_birthpoints(int stats[6],int remaining)183 void event_signal_birthpoints(int stats[6], int remaining)
184 {
185 	game_event_data data;
186 
187 	data.birthstats.stats = stats;
188 	data.birthstats.remaining = remaining;
189 
190 	game_event_dispatch(EVENT_BIRTHPOINTS, &data);
191 }
192 
event_signal_blast(game_event_type type,int proj_type,int num_grids,int * distance_to_grid,bool drawing,bool * player_sees_grid,struct loc * blast_grid,struct loc centre)193 void event_signal_blast(game_event_type type,
194 						int proj_type,
195 						int num_grids,
196 						int *distance_to_grid,
197 						bool drawing,
198 						bool *player_sees_grid,
199 						struct loc *blast_grid,
200 						struct loc centre)
201 {
202 	game_event_data data;
203 	data.explosion.proj_type = proj_type;
204 	data.explosion.num_grids = num_grids;
205 	data.explosion.distance_to_grid = distance_to_grid;
206 	data.explosion.drawing = drawing;
207 	data.explosion.player_sees_grid = player_sees_grid;
208 	data.explosion.blast_grid = blast_grid;
209 	data.explosion.centre = centre;
210 
211 	game_event_dispatch(type, &data);
212 }
213 
event_signal_bolt(game_event_type type,int proj_type,bool drawing,bool seen,bool beam,int oy,int ox,int y,int x)214 void event_signal_bolt(game_event_type type,
215 					   int proj_type,
216 					   bool drawing,
217 					   bool seen,
218 					   bool beam,
219 					   int oy,
220 					   int ox,
221 					   int y,
222 					   int x)
223 {
224 	game_event_data data;
225 	data.bolt.proj_type = proj_type;
226 	data.bolt.drawing = drawing;
227 	data.bolt.seen = seen;
228 	data.bolt.beam = beam;
229 	data.bolt.oy = oy;
230 	data.bolt.ox = ox;
231 	data.bolt.y = y;
232 	data.bolt.x = x;
233 
234 	game_event_dispatch(type, &data);
235 }
236 
event_signal_missile(game_event_type type,struct object * obj,bool seen,int y,int x)237 void event_signal_missile(game_event_type type,
238 						  struct object *obj,
239 						  bool seen,
240 						  int y,
241 						  int x)
242 {
243 	game_event_data data;
244 	data.missile.obj = obj;
245 	data.missile.seen = seen;
246 	data.missile.y = y;
247 	data.missile.x = x;
248 
249 	game_event_dispatch(type, &data);
250 }
251