We should follow the HandBook
[tuxanci.git] / src / base / modules.c
blobeab45069f4acc33adca7d615774775dd4cab84d1
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <assert.h>
6 #include "main.h"
7 #include "list.h"
8 #include "tux.h"
9 #include "shot.h"
10 #include "modules.h"
11 #include "arena.h"
12 #include "arenaFile.h"
13 #include "proto.h"
14 #include "shareFunction.h"
16 #ifndef PUBLIC_SERVER
17 #include "interface.h"
18 #include "image.h"
19 #include "layer.h"
20 #include "configFile.h"
21 #endif /* PUBLIC_SERVER */
23 static export_fce_t export_fce = {
24 #ifndef PUBLIC_SERVER
25 .fce_addLayer = addLayer,
26 .fce_image_get = image_get,
27 #endif /* PUBLIC_SERVER */
28 .fce_module_load_dep = module_load_dep,
29 .fce_share_function_add = share_function_add,
30 .fce_share_function_get = share_function_get,
32 .fce_getValue = arena_file_get_value,
33 .fce_net_multiplayer_get_game_type = net_multiplayer_get_game_type,
34 .fce_tux_get_proportion = tux_get_proportion,
35 .fce_tux_set_proportion = tux_set_proportion,
36 .fce_tux_action = tux_action,
38 .fce_timer_get_current_time = timer_get_current_time,
40 .fce_arena_get_current = arena_get_current,
41 .fce_arena_conflict_space = arena_conflict_space,
42 .fce_arena_is_free_space = arena_is_free_space,
43 .fce_arena_find_free_space = arena_find_free_space,
45 .fce_proto_send_module_server = proto_send_module_server,
46 .fce_proto_send_del_server = proto_send_del_server,
47 #ifndef PUBLIC_SERVER
48 .fce_proto_send_module_client = proto_send_module_client,
49 #endif /* PUBLIC_SERVER */
50 .fce_shot_destroy = shot_destroy,
51 .fce_shot_bound_bombBall = shot_bound_bombBall,
52 .fce_shot_transform_lasser = shot_transform_lasser
55 static list_t *listModule;
56 static mod_reg_t mod_reglist;
58 /* register module as valid */
59 static mod_reg_t *mod_register(char *name, mod_sym_t *sym)
61 /* alloc and init context */
62 mod_reg_t *mod = (mod_reg_t *) malloc(sizeof(mod_reg_t));
64 if (!mod) {
65 return 0;
68 mod->name = strdup(name);
69 mod->sym = sym;
71 /* add entry into list */
72 mod->next = &mod_reglist;
73 mod->prev = mod_reglist.prev;
74 mod->prev->next = mod;
75 mod->next->prev = mod;
77 return mod;
80 /* free all unnecessary memory blocks from module's reglist */
81 static void mod_destroy()
83 unsigned i;
84 for (;;) {
85 i = 0;
87 mod_reg_t *mod;
88 for (mod = mod_reglist.next; mod != &mod_reglist; mod = mod->next) {
89 /* delete entry from context */
90 mod->next->prev = mod->prev;
91 mod->prev->next = mod->next;
93 free(mod->name);
94 free(mod);
96 i++;
98 break;
101 if (!i) {
102 break;
107 static mod_reg_t *mod_find(char *name)
109 mod_reg_t *mod;
110 for (mod = mod_reglist.next; mod != &mod_reglist; mod = mod->next) {
111 if (!strcmp(mod->name, name)) {
112 return mod;
116 return 0;
119 static module_t *newModule(char *name)
121 assert(name != NULL);
123 mod_reg_t *mod = mod_find(name);
125 if (!mod) {
126 error("Module [%s] is unavailable", name);
127 return 0;
130 module_t *ret = malloc(sizeof(module_t));
132 if (!ret) {
133 return 0;
136 ret->name = strdup(name);
138 if (!ret->name) {
139 free(ret);
140 return 0;
143 ret->fce_init = mod->sym->init;
144 #ifndef PUBLIC_SERVER
145 ret->fce_draw = mod->sym->draw;
146 #endif /* PUBLIC_SERVER */
147 ret->fce_event = mod->sym->event;
148 ret->fce_destroy = mod->sym->destroy;
149 ret->fce_isConflict = mod->sym->isConflict;
150 ret->fce_cmd = mod->sym->cmdArena;
151 ret->fce_recvMsg = mod->sym->recvMsg;
153 debug("Loading module [%s]", name);
155 if (ret->fce_init(&export_fce) != 0) {
156 error("Unable to load module [%s]", name);
157 free(ret->name);
158 free(ret);
159 return NULL;
162 return ret;
165 static int destroyModule(module_t *p)
167 assert(p != NULL);
169 debug("Unloading module [%s]", p->name);
171 p->fce_destroy();
173 free(p->name);
174 free(p);
176 return 0;
179 void module_init()
181 listModule = list_new();
182 share_function_init();
184 mod_reglist.next = &mod_reglist;
185 mod_reglist.prev = &mod_reglist;
187 mod_register("libmodAI", &modai_sym);
188 mod_register("libmodWall", &modwall_sym);
189 mod_register("libmodPipe", &modpipe_sym);
190 mod_register("libmodMove", &modmove_sym);
191 mod_register("libmodBasic", &modbasic_sym);
192 mod_register("libmodTeleport", &modteleport_sym);
195 int isModuleLoaded(char *name)
197 int i;
199 for (i = 0; i < listModule->count; i++) {
200 module_t *this;
202 this = (module_t *) listModule->list[i];
204 if (strcmp(this->name, name) == 0) {
205 return 1;
209 return 0;
212 int module_load(char *name)
214 module_t *module;
216 if (isModuleLoaded(name)) {
217 error("Unable to load already loaded module [%s]", name);
218 return -1;
221 module = newModule(name);
223 if (module == NULL) {
224 error("Unable to load module [%s]", name);
225 return -1;
228 list_add(listModule, module);
230 return 0;
233 int module_load_dep(char *name)
235 if (isModuleLoaded(name)) {
236 return 0;
239 return module_load(name);
242 void module_cmd(char *s)
244 int i;
246 for (i = 0; i < listModule->count; i++) {
247 module_t *this;
249 this = (module_t *) listModule->list[i];
250 this->fce_cmd(s);
254 #ifndef PUBLIC_SERVER
255 void module_draw(int x, int y, int w, int h)
257 int i;
259 for (i = 0; i < listModule->count; i++) {
260 module_t *this;
262 this = (module_t *) listModule->list[i];
263 this->fce_draw(x, y, w, h);
266 #endif /* PUBLIC_SERVER */
268 void module_event()
270 int i;
272 for (i = 0; i < listModule->count; i++) {
273 module_t *this;
275 this = (module_t *) listModule->list[i];
276 this->fce_event();
280 int module_is_conflict(int x, int y, int w, int h)
282 int i;
284 for (i = 0; i < listModule->count; i++) {
285 module_t *this;
287 this = (module_t *) listModule->list[i];
289 if (this->fce_isConflict(x, y, w, h) == 1) {
290 return 1;
294 return 0;
297 int module_recv_msg(char *msg)
299 int i;
301 for (i = 0; i < listModule->count; i++) {
302 module_t *this;
304 this = (module_t *) listModule->list[i];
305 this->fce_recvMsg(msg);
308 return 0;
311 void module_quit()
313 list_destroy_item(listModule, destroyModule);
314 share_function_quit();
316 mod_destroy();