Bladeren bron

support info_landmark_entry/exit entities, fix #46

Ivan Avdeev 6 jaren geleden
bovenliggende
commit
d6904887c3
3 gewijzigde bestanden met toevoegingen van 75 en 16 verwijderingen
  1. 21 6
      src/OpenSource.c
  2. 50 9
      src/bsp.c
  3. 4 1
      src/bsp.h

+ 21 - 6
src/OpenSource.c

@@ -45,7 +45,7 @@ typedef struct Map {
 	struct AVec3f offset;
 	struct AVec3f debug_offset;
 	struct BSPModel model;
-	struct Map *next;
+	struct Map *prev, *next;
 	const struct Map *parent;
 	struct AVec3f parent_offset;
 } Map;
@@ -102,8 +102,10 @@ static Map *opensrcAllocMap(StringView name) {
 
 	if (!g.maps_end)
 		g.maps_begin = map;
-	else
+	else {
 		g.maps_end->next = map;
+		map->prev = g.maps_end;
+	}
 
 	g.maps_end = map;
 
@@ -125,15 +127,28 @@ static void mapUpdatePosition(Map *map) {
 		map->offset.x, map->offset.y, map->offset.z);
 }
 
-static enum BSPLoadResult loadMap(struct Map *map, struct ICollection *collection) {
-	struct BSPLoadModelContext loadctx = {
+static enum BSPLoadResult loadMap(Map *map, ICollection *collection) {
+	BSPLoadModelContext loadctx = {
 		.collection = collection,
 		.persistent = &stack_persistent,
 		.tmp = &stack_temp,
-		.model = &map->model
+		.model = &map->model,
+		.name = { .str = map->name, .length = strlen(map->name) },
+		.prev_map_name = { .str = NULL, .length = 0 },
+		.next_map_name = { .str = NULL, .length = 0 },
 	};
 
-	const enum BSPLoadResult result = bspLoadWorldspawn(loadctx, map->name);
+	if (map->prev) {
+		loadctx.prev_map_name.str = map->prev->name;
+		loadctx.prev_map_name.length = strlen(map->prev->name);
+	}
+
+	if (map->next) {
+		loadctx.next_map_name.str = map->next->name;
+		loadctx.next_map_name.length = strlen(map->next->name);
+	}
+
+	const enum BSPLoadResult result = bspLoadWorldspawn(loadctx);
 	if (result != BSPLoadResult_Success) {
 		PRINTF("Cannot load map \"%s\": %d", map->name, result);
 		return result;

+ 50 - 9
src/bsp.c

@@ -782,9 +782,7 @@ typedef struct {
 
 typedef BSPLoadResult (*BspProcessEntityProc)(BSPLoadModelContext *ctx, const Entity *entity);
 
-BSPLoadResult bspProcessEntityInfoLandmark(BSPLoadModelContext *ctx, const Entity *entity) {
-	const StringView target_name = entity->props[EntityPropIndex_TargetName].value;
-	const StringView origin = entity->props[EntityPropIndex_Origin].value;
+BSPLoadResult bspReadAndAddLandmark(BSPLoadModelContext *ctx, StringView target_name, StringView origin) {
 
 	struct BSPModel *model = ctx->model;
 	if (model->landmarks_count == BSP_MAX_LANDMARKS) {
@@ -817,13 +815,54 @@ BSPLoadResult bspProcessEntityInfoLandmark(BSPLoadModelContext *ctx, const Entit
 	return BSPLoadResult_Success;
 }
 
-BSPLoadResult bspProcessEntityTriggerChangelevel(struct BSPLoadModelContext *ctx, const Entity *entity) {
+static BSPLoadResult bspProcessEntityInfoLandmark(BSPLoadModelContext *ctx, const Entity *entity) {
+	const StringView target_name = entity->props[EntityPropIndex_TargetName].value;
+	const StringView origin = entity->props[EntityPropIndex_Origin].value;
+
+	return bspReadAndAddLandmark(ctx, target_name, origin);
+}
+
+static BSPLoadResult bspProcessEntityInfoLandmarkEntry(BSPLoadModelContext *ctx, const Entity *entity) {
+	const int landmark_name_length = ctx->prev_map_name.length + ctx->name.length + 5;
+	char *landmark_name_buf = stackAlloc(ctx->tmp, landmark_name_length);
+	memcpy(landmark_name_buf, ctx->prev_map_name.str, ctx->prev_map_name.length);
+	memcpy(landmark_name_buf + ctx->prev_map_name.length, "_to_", 4);
+	memcpy(landmark_name_buf + ctx->prev_map_name.length + 4, ctx->name.str, ctx->name.length);
+	landmark_name_buf[landmark_name_length-1] = '\0';
+
+	const StringView target_name = { .str = landmark_name_buf, .length = landmark_name_length };
+	const StringView origin = entity->props[EntityPropIndex_Origin].value;
+
+	const BSPLoadResult result = bspReadAndAddLandmark(ctx, target_name, origin);
+	stackFreeUpToPosition(ctx->tmp, landmark_name_buf);
+
+	return result;
+}
+
+static BSPLoadResult bspProcessEntityInfoLandmarkExit(BSPLoadModelContext *ctx, const Entity *entity) {
+	const int landmark_name_length = ctx->next_map_name.length + ctx->name.length + 5;
+	char *landmark_name_buf = stackAlloc(ctx->tmp, landmark_name_length);
+	memcpy(landmark_name_buf, ctx->name.str, ctx->name.length);
+	memcpy(landmark_name_buf + ctx->name.length, "_to_", 4);
+	memcpy(landmark_name_buf + ctx->name.length + 4, ctx->next_map_name.str, ctx->next_map_name.length);
+	landmark_name_buf[landmark_name_length-1] = '\0';
+
+	const StringView target_name = { .str = landmark_name_buf, .length = landmark_name_length };
+	const StringView origin = entity->props[EntityPropIndex_Origin].value;
+
+	const BSPLoadResult result = bspReadAndAddLandmark(ctx, target_name, origin);
+	stackFreeUpToPosition(ctx->tmp, landmark_name_buf);
+
+	return result;
+}
+
+static BSPLoadResult bspProcessEntityTriggerChangelevel(struct BSPLoadModelContext *ctx, const Entity *entity) {
 	(void)ctx;
 	openSourceAddMap(entity->props[EntityPropIndex_Map].value);
 	return BSPLoadResult_Success;
 }
 
-BSPLoadResult bspProcessEntityWorldspawn(struct BSPLoadModelContext *ctx, const Entity *entity) {
+static BSPLoadResult bspProcessEntityWorldspawn(struct BSPLoadModelContext *ctx, const Entity *entity) {
 	(void)ctx;
 	const StringView skyname = entity->props[EntityPropIndex_SkyName].value;
 
@@ -840,6 +879,8 @@ static struct {
 	BspProcessEntityProc proc;
 } entity_procs[] = {
 	{"info_landmark", bspProcessEntityInfoLandmark},
+	{"info_landmark_entry", bspProcessEntityInfoLandmarkEntry},
+	{"info_landmark_exit", bspProcessEntityInfoLandmarkExit},
 	{"trigger_changelevel", bspProcessEntityTriggerChangelevel},
 	{"worldspawn", bspProcessEntityWorldspawn},
 };
@@ -925,11 +966,11 @@ static int lumpRead(const char *name, const struct VBSPLumpHeader *header,
 	return 1;
 }
 
-enum BSPLoadResult bspLoadWorldspawn(struct BSPLoadModelContext context, const char *mapname) {
+enum BSPLoadResult bspLoadWorldspawn(BSPLoadModelContext context) {
 	enum BSPLoadResult result = BSPLoadResult_Success;
 	struct IFile *file = 0;
 	if (CollectionOpen_Success !=
-			collectionChainOpen(context.collection, mapname, File_Map, &file)) {
+			collectionChainOpen(context.collection, context.name.str /* FIXME assumes null-terminated string */, File_Map, &file)) {
 		return BSPLoadResult_ErrorFileOpen;
 	}
 
@@ -952,8 +993,8 @@ enum BSPLoadResult bspLoadWorldspawn(struct BSPLoadModelContext context, const c
 		goto exit;
 	}
 
-	if (vbsp_header.version != 19 && vbsp_header.version != 20) {
-		PRINTF("Error: invalid version: %d != 19 or 20", vbsp_header.version);
+	if (vbsp_header.version < 19 && vbsp_header.version > 21) {
+		PRINTF("Error: invalid version: %d != 19 or 20 or 21", vbsp_header.version);
 		result = BSPLoadResult_ErrorFileFormat;
 		goto exit;
 	}

+ 4 - 1
src/bsp.h

@@ -70,6 +70,9 @@ typedef struct BSPLoadModelContext {
 
 	/* allocated by caller, populated by callee */
 	struct BSPModel *model;
+
+	StringView name;
+	StringView prev_map_name, next_map_name;
 } BSPLoadModelContext;
 
 typedef enum BSPLoadResult {
@@ -84,6 +87,6 @@ typedef enum BSPLoadResult {
 /* should be called AFTER renderInit() */
 void bspInit();
 
-enum BSPLoadResult bspLoadWorldspawn(struct BSPLoadModelContext context, const char *mapname);
+enum BSPLoadResult bspLoadWorldspawn(BSPLoadModelContext context);
 
 void openSourceAddMap(StringView name);