/* ** */ #include #include #include #include "v_cmd_gen.h" #if !defined(V_GENERATE_FUNC_MODE) #include "verse.h" #include "v_util.h" #include "vs_server.h" typedef struct { VNTag tag; VNTagType type; char tag_name[16]; } VSTag; typedef struct { VSTag *tags; unsigned int tag_count; char group_name[16]; VSSubscriptionList *subscribers; } VSTagGroup; void create_node_head(VSNodeHead *node, const char *name, unsigned int owner) { size_t len; len = strlen(name) + 1; node->name = malloc(len); v_strlcpy(node->name, name, len); node->owner = owner; node->tag_groups = NULL; node->group_count = 0; node->subscribers = vs_create_subscription_list(); } void destroy_node_head(VSNodeHead *node) { unsigned int i, j; if(node->name != NULL) free(node->name); if(node->tag_groups != NULL) { for(i = 0; i < node->group_count; i++) { for(j = 0; j < ((VSTagGroup *)node->tag_groups)[i].tag_count; j++) { if(((VSTagGroup *)node->tag_groups)[i].tags[j].type == VN_TAG_STRING) free(((VSTagGroup *)node->tag_groups)[i].tags[j].tag.vstring); if(((VSTagGroup *)node->tag_groups)[i].tags[j].type == VN_TAG_BLOB) free(((VSTagGroup *)node->tag_groups)[i].tags[j].tag.vblob.blob); } if(((VSTagGroup *)node->tag_groups)[i].tags != NULL) free(((VSTagGroup *)node->tag_groups)[i].tags); } if(node->tag_groups != NULL) free(node->tag_groups); } } void callback_send_tag_group_create(void *user, VNodeID node_id, uint16 group_id, const char *name) { VSNodeHead *node; unsigned int count, i, j, element; if((node = vs_get_node_head(node_id)) == 0) return; if(name[0] == 0) return; for(i = 0; i < node->group_count; i++) /* see if a tag group with this name alredy exists*/ { if(((VSTagGroup *)node->tag_groups)[i].group_name[0] != 0) { for(j = 0; name[j] == ((VSTagGroup *)node->tag_groups)[i].group_name[j] && name[j] != 0; j++); if(name[j] == ((VSTagGroup *)node->tag_groups)[i].group_name[j]) return; } } if(group_id < node->group_count && ((VSTagGroup *)node->tag_groups)[group_id].group_name[0] != 0) /* rename existing group */ { element = group_id; }else /* create new game group */ { for(element = 0; element < node->group_count && ((VSTagGroup *)node->tag_groups)[element].group_name[0] != 0; element++); if(element == node->group_count) { node->tag_groups = realloc(node->tag_groups, sizeof(VSTagGroup) * (node->group_count + 16)); for(i = node->group_count; i < node->group_count + 16U; i++) { ((VSTagGroup *)node->tag_groups)[i].group_name[0] = 0; ((VSTagGroup *)node->tag_groups)[i].tags = NULL; ((VSTagGroup *)node->tag_groups)[i].tag_count = 0; ((VSTagGroup *)node->tag_groups)[i].subscribers = NULL; } node->group_count += 16; } ((VSTagGroup *)node->tag_groups)[element].subscribers = vs_create_subscription_list(); } v_strlcpy(((VSTagGroup *)node->tag_groups)[element].group_name, name, sizeof ((VSTagGroup *)node->tag_groups)[element].group_name); count = vs_get_subscript_count(node->subscribers); for(i = 0; i < count; i++) { vs_set_subscript_session(node->subscribers, i); verse_send_tag_group_create(node_id, element, name); } vs_reset_subscript_session(); } static void callback_send_tag_group_destroy(void *user, VNodeID node_id, uint16 group_id) { VSNodeHead *node; unsigned int count, i; if((node = vs_get_node_head(node_id)) == 0) return; if(node->group_count <= group_id || ((VSTagGroup *)node->tag_groups)[group_id].group_name[0] == 0) return; vs_destroy_subscription_list(((VSTagGroup *)node->tag_groups)[group_id].subscribers); for(i = 0; i < ((VSTagGroup *)node->tag_groups)[group_id].tag_count; i++) { if(((VSTagGroup *)node->tag_groups)[group_id].tags[i].type == VN_TAG_STRING) free(((VSTagGroup *)node->tag_groups)[group_id].tags[i].tag.vstring); if(((VSTagGroup *)node->tag_groups)[group_id].tags[i].type == VN_TAG_BLOB) free(((VSTagGroup *)node->tag_groups)[group_id].tags[i].tag.vblob.blob); } if(((VSTagGroup *)node->tag_groups)[group_id].tags != NULL) free(((VSTagGroup *)node->tag_groups)[group_id].tags); ((VSTagGroup *)node->tag_groups)[group_id].group_name[0] = 0; ((VSTagGroup *)node->tag_groups)[group_id].tags = NULL; ((VSTagGroup *)node->tag_groups)[group_id].tag_count = 0; count = vs_get_subscript_count(node->subscribers); for(i = 0; i < count; i++) { vs_set_subscript_session(node->subscribers, i); verse_send_tag_group_destroy(node_id, group_id); } vs_reset_subscript_session(); } static void callback_send_tag_group_subscribe(void *user, VNodeID node_id, uint16 group_id) { VSNodeHead *node; unsigned int i; if((node = vs_get_node_head(node_id)) == 0) return; if(group_id < node->group_count && ((VSTagGroup *)node->tag_groups)[group_id].group_name[0] != 0) { vs_add_new_subscriptor(((VSTagGroup *)node->tag_groups)[group_id].subscribers); for(i = 0; i < ((VSTagGroup *)node->tag_groups)[group_id].tag_count; i++) { if(((VSTagGroup *)node->tag_groups)[group_id].tags[i].tag_name[0] != 0) { verse_send_tag_create(node_id, group_id, (uint16)i, ((VSTagGroup *)node->tag_groups)[group_id].tags[i].tag_name, ((VSTagGroup *)node->tag_groups)[group_id].tags[i].type, &((VSTagGroup *)node->tag_groups)[group_id].tags[i].tag); } } } } static void callback_send_tag_group_unsubscribe(void *user, VNodeID node_id, uint16 group_id) { VSNodeHead *node; if((node = vs_get_node_head(node_id)) == 0) return; if(group_id < node->group_count && ((VSTagGroup *)node->tag_groups)[group_id].group_name[0] != 0) vs_remove_subscriptor(((VSTagGroup *)node->tag_groups)[group_id].subscribers); } static void callback_send_tag_create(void *user, VNodeID node_id, uint16 group_id, uint16 tag_id, char *name, uint8 type, void *tag) { VSNodeHead *node; VSTag *t = NULL; unsigned int i, count; if((node = vs_get_node_head(node_id)) == 0) return; if(group_id >= node->group_count || ((VSTagGroup *)node->tag_groups)[group_id].group_name[0] == 0) return; /* for(i = 0; i < ((VSTagGroup *)node->tag_groups)[group_id].tag_count; i++) { if(((VSTagGroup *)node->tag_groups)[group_id].tags[i].tag_name != NULL && i != tag_id) { for(j = 0; name[j] == ((VSTagGroup *)node->tag_groups)[group_id].tags[i].tag_name[j] && name[j] != 0; j++); if(name[j] == ((VSTagGroup *)node->tag_groups)[group_id].tags[i].tag_name[j]) return; } }*/ if(tag_id < ((VSTagGroup *)node->tag_groups)[group_id].tag_count && ((VSTagGroup *)node->tag_groups)[group_id].tags[tag_id].tag_name[0] != 0) ; else { for(tag_id = 0; tag_id < ((VSTagGroup *)node->tag_groups)[group_id].tag_count && ((VSTagGroup *)node->tag_groups)[group_id].tags[tag_id].tag_name[0] != 0; tag_id++) ; if(tag_id == ((VSTagGroup *)node->tag_groups)[group_id].tag_count) { ((VSTagGroup *)node->tag_groups)[group_id].tags = realloc(((VSTagGroup *)node->tag_groups)[group_id].tags, sizeof(VSTag) * (((VSTagGroup *)node->tag_groups)[group_id].tag_count + 16)); for(i = tag_id; i < ((VSTagGroup *)node->tag_groups)[group_id].tag_count + 16; i++) ((VSTagGroup *)node->tag_groups)[group_id].tags[i].tag_name[0] = 0; ((VSTagGroup *)node->tag_groups)[group_id].tag_count += 16; } } t = &((VSTagGroup *)node->tag_groups)[group_id].tags[tag_id]; if(t->tag_name[0] != '\0') /* Old tag being re-set? */ { if(t->type == VN_TAG_STRING) free(t->tag.vstring); else if(t->type == VN_TAG_BLOB) free(t->tag.vblob.blob); } t->type = type; v_strlcpy(t->tag_name, name, sizeof t->tag_name); switch(type) { case VN_TAG_BOOLEAN : t->tag.vboolean = ((VNTag *)tag)->vboolean; break; case VN_TAG_UINT32 : t->tag.vuint32 = ((VNTag *)tag)->vuint32; break; case VN_TAG_REAL64 : t->tag.vreal64 = ((VNTag *)tag)->vreal64; break; case VN_TAG_STRING : i = strlen(((VNTag *) tag)->vstring); t->tag.vstring = malloc(i + 1); strcpy(t->tag.vstring, ((VNTag *) tag)->vstring); break; case VN_TAG_REAL64_VEC3 : t->tag.vreal64_vec3[0] = ((VNTag *)tag)->vreal64_vec3[0]; t->tag.vreal64_vec3[1] = ((VNTag *)tag)->vreal64_vec3[1]; t->tag.vreal64_vec3[2] = ((VNTag *)tag)->vreal64_vec3[2]; break; case VN_TAG_LINK : t->tag.vlink = ((VNTag *)tag)->vlink; break; case VN_TAG_ANIMATION : t->tag.vanimation.curve = ((VNTag *)tag)->vanimation.curve; t->tag.vanimation.start = ((VNTag *)tag)->vanimation.start; t->tag.vanimation.end = ((VNTag *)tag)->vanimation.end; break; case VN_TAG_BLOB : t->tag.vblob.blob = malloc(((VNTag *)tag)->vblob.size); t->tag.vblob.size = ((VNTag *)tag)->vblob.size; memcpy(t->tag.vblob.blob, ((VNTag *)tag)->vblob.blob, ((VNTag *)tag)->vblob.size); break; } count = vs_get_subscript_count(((VSTagGroup *) node->tag_groups)[group_id].subscribers); for(i = 0; i < count; i++) { vs_set_subscript_session(((VSTagGroup *) node->tag_groups)[group_id].subscribers, i); verse_send_tag_create(node_id, group_id, tag_id, name, type, tag); } vs_reset_subscript_session(); } static void callback_send_tag_destroy(void *user, VNodeID node_id, uint16 group_id, uint16 tag_id) { VSNodeHead *node; unsigned int count, i; if((node = vs_get_node_head(node_id)) == 0) return; count = vs_get_subscript_count(((VSTagGroup *) node->tag_groups)[group_id].subscribers); for(i = 0; i < count; i++) { vs_set_subscript_session(((VSTagGroup *) node->tag_groups)[group_id].subscribers, i); verse_send_tag_destroy(node_id, group_id, tag_id); } vs_reset_subscript_session(); } static void callback_send_node_name_set(void *user, VNodeID node_id, char *name) { VSNodeHead *node; unsigned int count, i; size_t len; if((node = vs_get_node_head(node_id)) == 0) return; len = strlen(name); if(len == 0) return; free(node->name); len++; node->name = malloc(len); v_strlcpy(node->name, name, len); count = vs_get_subscript_count(node->subscribers); for(i = 0; i < count; i++) { vs_set_subscript_session(node->subscribers, i); verse_send_node_name_set(node_id, name); } vs_reset_subscript_session(); } extern void vs_o_subscribe(VSNodeHead *node); extern void vs_g_subscribe(VSNodeHead *node); extern void vs_m_subscribe(VSNodeHead *node); extern void vs_b_subscribe(VSNodeHead *node); extern void vs_t_subscribe(VSNodeHead *node); extern void vs_c_subscribe(VSNodeHead *node); extern void vs_a_subscribe(VSNodeHead *node); static void callback_send_node_subscribe(void *user, VNodeID node_id) { unsigned int i; VSNodeHead *node; if((node = vs_get_node_head(node_id)) == NULL) return; switch(node->type) { case V_NT_OBJECT : vs_o_subscribe(node); break; case V_NT_GEOMETRY : vs_g_subscribe(node); break; case V_NT_MATERIAL : vs_m_subscribe(node); break; case V_NT_BITMAP : vs_b_subscribe(node); break; case V_NT_TEXT: vs_t_subscribe(node); break; case V_NT_CURVE: vs_c_subscribe(node); break; case V_NT_AUDIO: vs_a_subscribe(node); break; default: fprintf(stderr, "Not subscribing to node type %d\n", node->type); } verse_send_node_name_set(node->id, node->name); for(i = 0; i < node->group_count; i++) if(((VSTagGroup *)node->tag_groups)[i].group_name[0] != 0) verse_send_tag_group_create(node->id, (uint16)i, ((VSTagGroup *)node->tag_groups)[i].group_name); vs_add_new_subscriptor(node->subscribers); } extern void vs_o_unsubscribe(VSNodeHead *node); extern void vs_g_unsubscribe(VSNodeHead *node); extern void vs_m_unsubscribe(VSNodeHead *node); extern void vs_b_unsubscribe(VSNodeHead *node); extern void vs_t_unsubscribe(VSNodeHead *node); extern void vs_c_unsubscribe(VSNodeHead *node); extern void vs_a_unsubscribe(VSNodeHead *node); static void callback_send_node_unsubscribe(void *user, VNodeID node_id) { VSNodeHead *node; if((node = vs_get_node_head(node_id)) == NULL) return; vs_remove_subscriptor(node->subscribers); switch(node->type) { case V_NT_OBJECT : vs_o_unsubscribe(node); break; case V_NT_GEOMETRY : vs_g_unsubscribe(node); break; case V_NT_MATERIAL : vs_m_unsubscribe(node); break; case V_NT_BITMAP : vs_b_unsubscribe(node); break; case V_NT_TEXT: vs_t_unsubscribe(node); break; case V_NT_CURVE: vs_c_unsubscribe(node); break; case V_NT_AUDIO: vs_a_unsubscribe(node); break; default: fprintf(stderr, "Not unsubscribing from node type %d\n", node->type); } } void vs_h_callback_init(void) { verse_callback_set(verse_send_tag_group_create, callback_send_tag_group_create, NULL); verse_callback_set(verse_send_tag_group_destroy, callback_send_tag_group_destroy, NULL); verse_callback_set(verse_send_tag_group_subscribe, callback_send_tag_group_subscribe, NULL); verse_callback_set(verse_send_tag_group_unsubscribe, callback_send_tag_group_unsubscribe, NULL); verse_callback_set(verse_send_tag_create, callback_send_tag_create, NULL); verse_callback_set(verse_send_tag_destroy, callback_send_tag_destroy, NULL); verse_callback_set(verse_send_node_name_set, callback_send_node_name_set, NULL); verse_callback_set(verse_send_node_subscribe, callback_send_node_subscribe, NULL); verse_callback_set(verse_send_node_unsubscribe, callback_send_node_unsubscribe, NULL); } #endif