about summary refs log tree commit diff
path: root/src/game/server/gameworld.cpp
diff options
context:
space:
mode:
authorMagnus Auvinen <magnus.auvinen@gmail.com>2008-08-14 18:42:47 +0000
committerMagnus Auvinen <magnus.auvinen@gmail.com>2008-08-14 18:42:47 +0000
commit78c089c0eae503822c7f1025aefcf02529b13723 (patch)
tree10c8767ef1006a09c9ca228770f1ce86b45cbccb /src/game/server/gameworld.cpp
parenta420eb543f8206730aebb80e60a625f7204694e4 (diff)
downloadzcatch-78c089c0eae503822c7f1025aefcf02529b13723.tar.gz
zcatch-78c089c0eae503822c7f1025aefcf02529b13723.zip
last of the game server clean up. now it's done
Diffstat (limited to 'src/game/server/gameworld.cpp')
-rw-r--r--src/game/server/gameworld.cpp215
1 files changed, 215 insertions, 0 deletions
diff --git a/src/game/server/gameworld.cpp b/src/game/server/gameworld.cpp
new file mode 100644
index 00000000..60b276d3
--- /dev/null
+++ b/src/game/server/gameworld.cpp
@@ -0,0 +1,215 @@
+
+#include "gameworld.hpp"
+#include "entity.hpp"
+#include "gamecontext.hpp"
+
+//////////////////////////////////////////////////
+// game world
+//////////////////////////////////////////////////
+GAMEWORLD::GAMEWORLD()
+{
+	paused = false;
+	reset_requested = false;
+	first_entity = 0x0;
+	for(int i = 0; i < NUM_ENT_TYPES; i++)
+		first_entity_types[i] = 0;
+}
+
+GAMEWORLD::~GAMEWORLD()
+{
+	// delete all entities
+	while(first_entity)
+		delete first_entity;
+}
+
+ENTITY *GAMEWORLD::find_first(int type)
+{
+	return first_entity_types[type];
+}
+
+
+int GAMEWORLD::find_entities(vec2 pos, float radius, ENTITY **ents, int max, int type)
+{
+	int num = 0;
+	for(ENTITY *ent = (type<0) ? first_entity : first_entity_types[type];
+		ent; ent = (type<0) ? ent->next_entity : ent->next_type_entity)
+	{
+		if(distance(ent->pos, pos) < radius+ent->proximity_radius)
+		{
+			ents[num] = ent;
+			num++;
+			if(num == max)
+				break;
+		}
+	}
+
+	return num;
+}
+
+void GAMEWORLD::insert_entity(ENTITY *ent)
+{
+	ENTITY *cur = first_entity;
+	while(cur)
+	{
+		dbg_assert(cur != ent, "err");
+		cur = cur->next_entity;
+	}
+
+	// insert it
+	if(first_entity)
+		first_entity->prev_entity = ent;
+	ent->next_entity = first_entity;
+	ent->prev_entity = 0x0;
+	first_entity = ent;
+
+	// into typelist aswell
+	if(first_entity_types[ent->objtype])
+		first_entity_types[ent->objtype]->prev_type_entity = ent;
+	ent->next_type_entity = first_entity_types[ent->objtype];
+	ent->prev_type_entity = 0x0;
+	first_entity_types[ent->objtype] = ent;
+}
+
+void GAMEWORLD::destroy_entity(ENTITY *ent)
+{
+	ent->marked_for_destroy = true;
+}
+
+void GAMEWORLD::remove_entity(ENTITY *ent)
+{
+	// not in the list
+	if(!ent->next_entity && !ent->prev_entity && first_entity != ent)
+		return;
+
+	// remove
+	if(ent->prev_entity)
+		ent->prev_entity->next_entity = ent->next_entity;
+	else
+		first_entity = ent->next_entity;
+	if(ent->next_entity)
+		ent->next_entity->prev_entity = ent->prev_entity;
+
+	if(ent->prev_type_entity)
+		ent->prev_type_entity->next_type_entity = ent->next_type_entity;
+	else
+		first_entity_types[ent->objtype] = ent->next_type_entity;
+	if(ent->next_type_entity)
+		ent->next_type_entity->prev_type_entity = ent->prev_type_entity;
+
+	ent->next_entity = 0;
+	ent->prev_entity = 0;
+	ent->next_type_entity = 0;
+	ent->prev_type_entity = 0;
+}
+
+//
+void GAMEWORLD::snap(int snapping_client)
+{
+	for(ENTITY *ent = first_entity; ent; ent = ent->next_entity)
+		ent->snap(snapping_client);
+}
+
+void GAMEWORLD::reset()
+{
+	// reset all entities
+	for(ENTITY *ent = first_entity; ent; ent = ent->next_entity)
+		ent->reset();
+	remove_entities();
+
+	game.controller->post_reset();
+	remove_entities();
+
+	reset_requested = false;
+}
+
+void GAMEWORLD::remove_entities()
+{
+	// destroy objects marked for destruction
+	ENTITY *ent = first_entity;
+	while(ent)
+	{
+		ENTITY *next = ent->next_entity;
+		if(ent->marked_for_destroy)
+		{
+			remove_entity(ent);
+			ent->destroy();
+		}
+		ent = next;
+	}
+}
+
+void GAMEWORLD::tick()
+{
+	if(reset_requested)
+		reset();
+
+	if(!paused)
+	{
+		// update all objects
+		for(ENTITY *ent = first_entity; ent; ent = ent->next_entity)
+			ent->tick();
+		
+		for(ENTITY *ent = first_entity; ent; ent = ent->next_entity)
+			ent->tick_defered();
+	}
+
+	remove_entities();
+}
+
+
+// TODO: should be more general
+CHARACTER *GAMEWORLD::intersect_character(vec2 pos0, vec2 pos1, float radius, vec2& new_pos, ENTITY *notthis)
+{
+	// Find other players
+	float closest_len = distance(pos0, pos1) * 100.0f;
+	vec2 line_dir = normalize(pos1-pos0);
+	CHARACTER *closest = 0;
+
+	CHARACTER *p = (CHARACTER *)game.world.find_first(NETOBJTYPE_CHARACTER);
+	for(; p; p = (CHARACTER *)p->typenext())
+ 	{
+		if(p == notthis)
+			continue;
+			
+		vec2 intersect_pos = closest_point_on_line(pos0, pos1, p->pos);
+		float len = distance(p->pos, intersect_pos);
+		if(len < CHARACTER::phys_size+radius)
+		{
+			if(len < closest_len)
+			{
+				new_pos = intersect_pos;
+				closest_len = len;
+				closest = p;
+			}
+		}
+	}
+	
+	return closest;
+}
+
+
+CHARACTER *GAMEWORLD::closest_character(vec2 pos, float radius, ENTITY *notthis)
+{
+	// Find other players
+	float closest_range = radius*2;
+	CHARACTER *closest = 0;
+		
+	CHARACTER *p = (CHARACTER *)game.world.find_first(NETOBJTYPE_CHARACTER);
+	for(; p; p = (CHARACTER *)p->typenext())
+ 	{
+		if(p == notthis)
+			continue;
+			
+		float len = distance(pos, p->pos);
+		if(len < CHARACTER::phys_size+radius)
+		{
+			if(len < closest_range)
+			{
+				closest_range = len;
+				closest = p;
+			}
+		}
+	}
+	
+	return closest;
+}