2 @Copyright Looking Glass Studios, Inc.
3 1996,1997,1998,1999,2000 Unpublished Work.
6 // $Header: r:/t2repos/thief2/src/sim/wrloop.cpp,v 1.73 2000/03/18 15:20:54 adurant Exp $
44 // Must be last header
47 // This shouldn't be here either
48 EXTERN
int *wr_brfaces
[];
51 // Goofy Memory management
55 static struct sMemBuffer
57 uchar
* buf
; // the buffer
58 ulong size
; // The buffer size;
59 uchar
* next
; // next available byte
60 ulong overflow
; // how much we couldn't allocate
64 static void ClearMemBuf()
73 static void AllocMemBuf(ulong n
)
79 MemBuf
.buf
= new uchar
[n
];
82 MemBuf
.next
= MemBuf
.buf
;
86 #define DoMalloc(x) (new char[x])
87 #define DoFree(x) (delete [] (char*)(x))
89 static void* wrAlloc(ulong size
)
91 if (MemBuf
.next
== NULL
|| MemBuf
.buf
== NULL
)
92 return DoMalloc(size
);
93 if (MemBuf
.next
+ size
> MemBuf
.buf
+ MemBuf
.size
)
95 if (MemBuf
.overflow
== 0)
96 Warning(("wrAlloc: need %d bytes, have %d\n",size
,MemBuf
.size
- (MemBuf
.next
- MemBuf
.buf
)));
97 MemBuf
.overflow
+= size
;
98 return DoMalloc(size
);
101 void* retval
= MemBuf
.next
;
106 static void wrFree(void* ptr
)
108 if (ptr
< MemBuf
.buf
|| ptr
>= MemBuf
.buf
+ MemBuf
.size
)
113 static void wrAllocPrintOverflow(void)
115 if (MemBuf
.overflow
!= 0) {
116 mprintf("WARNING: %d bytes of worldrep not allocated from main block\n",
118 } else if (MemBuf
.next
!= MemBuf
.buf
+ MemBuf
.size
) {
119 mprintf("WARNING: %d bytes of worldrep alloc unused.\n",
120 (MemBuf
.next
- MemBuf
.buf
) + MemBuf
.size
);
125 /////////////////////////////////////////////////////////////
126 // WORLD REP LOOP CLIENT
127 ////////////////////////////////////////////////////////////
132 // These are just here to separate out boiler-plate code and leave it untouched
135 #define MY_GUID LOOPID_Wr
139 typedef void Context
;
141 // fields to this structure.
144 typedef struct _StateRecord
146 Context
* context
; // a pointer to the context data I got.
147 // State fields go here
150 ////////////////////////////////////////
151 // DATABASE MESSAGE HANDLER
154 typedef void (*PortalReadWrite
) (void *buf
, size_t elsize
, size_t nelem
);
156 void SpewCellPlanes(PortalCell
*p
)
159 mprintf("num_vertices:%d\n", p
->num_vertices
);
160 mprintf("num_polys:%d\n", p
->num_polys
);
161 mprintf("num_render_polys:%d\n", p
->num_render_polys
);
162 mprintf("num_portal_polys:%d\n", p
->num_portal_polys
);
163 for (i
= 0; i
< p
->num_planes
; i
++)
164 mprintf("plane_list[i] %g,%g,%g, %g\n", p
->plane_list
[i
].normal
.x
, p
->plane_list
[i
].normal
.y
, p
->plane_list
[i
].normal
.z
, p
->plane_list
[i
].plane_constant
);
167 void SpewCell(PortalCell
*p
)
171 mprintf("num_vertices:%d\n", p
->num_vertices
);
172 mprintf("num_polys:%d\n", p
->num_polys
);
173 mprintf("num_render_polys:%d\n", p
->num_render_polys
);
174 mprintf("num_portal_polys:%d\n", p
->num_portal_polys
);
176 mprintf("num_planes:%d\n", p
->num_planes
);
177 mprintf("medium:%d\n", p
->medium
);
178 mprintf("flags:%d\n", p
->flags
);
180 mprintf("portal_vertex_list:%d\n", p
->portal_vertex_list
);
182 //mprintf("refs:%d", p->refs);
184 mprintf("sphere_center:%g,%g,%g\n", p
->sphere_center
.x
, p
->sphere_center
.y
, p
->sphere_center
.z
);
185 mprintf("sphere_radius:%g\n", p
->sphere_radius
);
187 for (i
= 0; i
< p
->num_vertices
; i
++)
188 mprintf("vpool[i]:%g,%g,%g\n", p
->vpool
[i
].x
, p
->vpool
[i
].y
, p
->vpool
[i
].z
);
190 for (i
= 0; i
< p
->num_polys
; i
++)
192 mprintf ("poly_list[i] flags:%d\n", p
->poly_list
[i
].flags
);
193 // should be more here....
196 mprintf ("portal_poly_list[0] flags:%d\n", p
->portal_poly_list
[0]);
198 for (i
= 0; i
< p
->num_render_polys
; i
++)
200 mprintf("render_list u->raw:%g,%g,%g\n", p
->render_list
[i
].tex_u
.x
, p
->render_list
[i
].tex_u
.y
, p
->render_list
[i
].tex_u
.z
);
201 mprintf("render_list v->raw:%g,%g,%g\n", p
->render_list
[i
].tex_v
.x
, p
->render_list
[i
].tex_v
.y
, p
->render_list
[i
].tex_v
.z
);
202 mprintf("render_list u_base:%d\n", p
->render_list
[i
].u_base
);
203 mprintf("render_list v_base:%d\n", p
->render_list
[i
].v_base
);
204 mprintf("render_list texture_id:%d\n", p
->render_list
[i
].texture_id
);
205 mprintf("render_list texture_anchor:%d\n", p
->render_list
[i
].texture_anchor
);
206 mprintf("render_list cached_surface:%d\n", p
->render_list
[i
].cached_surface
);
210 for (pi
= 0; pi
< p
->num_polys
; ++pi
)
211 voff
+= p
->poly_list
[pi
].num_vertices
;
212 for (i
= 0; i
< voff
; i
++)
213 mprintf("vertex_list[i]:%d\n", p
->vertex_list
[i
]);
215 for (i
= 0; i
< p
->num_planes
; i
++)
216 mprintf("plane_list[i] normal %g,%g,%g\n", p
->plane_list
[i
].normal
.x
, p
->plane_list
[i
].normal
.y
, p
->plane_list
[i
].normal
.z
);
218 // for (i = 0; i < xxxx; i++)
219 // mprintf("render_data[i]
221 for (i
= 0; i
< p
->num_render_polys
; i
++)
223 mprintf("light_list[i] base_u:%d\n", p
->light_list
[i
].base_u
);
224 mprintf("light_list[i] base_u:%d\n", p
->light_list
[i
].base_v
);
225 mprintf("light_list[i] h:%d\n", p
->light_list
[i
].h
);
226 mprintf("light_list[i] w:%d\n", p
->light_list
[i
].w
);
227 mprintf("light_list[i] bits[0]:%d\n", p
->light_list
[i
].data
[0]);
228 mprintf("light_list[i] bits[h*w-1]:%d\n", p
->light_list
[i
].data
[p
->light_list
[i
].h
*p
->light_list
[i
].w
-1]);
231 for (i
= 0; i
< p
->light_indices
[0]; i
++)
232 mprintf("light_indices[i]:%d\n", p
->light_indices
[i
]);
235 void SpewAllCells(void)
239 for (ci
= 0; ci
< wr_num_cells
; ci
++)
240 if (wr_cell
[ci
] != NULL
)
241 SpewCell(wr_cell
[ci
]);
244 ulong
ReadWriteNonPtrPortalCell(PortalReadWrite func
, PortalCell
*p
)
247 (*func
)(&(p
->num_vertices
), sizeof(uchar
), 1);
248 (*func
)(&(p
->num_polys
), sizeof(uchar
), 1);
249 (*func
)(&(p
->num_render_polys
), sizeof(uchar
), 1);
250 (*func
)(&(p
->num_portal_polys
), sizeof(uchar
), 1);
251 retval
+= 4*sizeof(uchar
);
253 (*func
)(&(p
->num_planes
), sizeof(uchar
), 1);
254 (*func
)(&(p
->medium
), sizeof(uchar
), 1);
255 (*func
)(&(p
->flags
), sizeof(uchar
), 1);
256 retval
+= 3* sizeof(uchar
);
258 (*func
)(&(p
->portal_vertex_list
), sizeof(int), 1);
259 retval
+= sizeof(int);
261 (*func
)(&(p
->num_vlist
), sizeof(ushort
), 1);
262 (*func
)(&(p
->num_anim_lights
), sizeof(uchar
), 1);
263 (*func
)(&(p
->motion_index
), sizeof(uchar
), 1);
264 retval
+= sizeof(ushort
)+2*sizeof(uchar
);
266 (*func
)(&(p
->sphere_center
), sizeof(Vertex
), 1);
267 (*func
)(&(p
->sphere_radius
), sizeof(mxs_real
), 1);
268 retval
+= sizeof(Vertex
) + sizeof(mxs_real
) ;
274 ulong
WriteCachedVector(PortalReadWrite func
, CachedVector
*cv
)
276 (*func
)(&(cv
->raw
), sizeof(Vector
), 1);
277 return sizeof(CachedVector
);
278 // (*func)(cv->cached, sizeof(CachedData), 1);
281 void ReadAndAllocCachedVector(PortalReadWrite func
, CachedVector
**cv
)
283 *cv
= (CachedVector
*) wrAlloc(sizeof(CachedVector
));
284 (*func
)(&((**cv
).raw
), sizeof(Vector
), 1);
286 // (**cv).cached = (st_CachedData*) DoMalloc(sizeof(CachedData));
287 // (*func)((**cv).cached, sizeof(CachedData), 1);
293 // Free worldrep structures
295 // NOTE: This does NOT free wrBspTree. You must do this explicitly.
296 // The reason it doesn't is that FreeWR gets called at the
297 // beginning of each pass of the portalization, and we need
298 // to preserve wrBspTree through all passes.
300 // NOTE: FreeWR seems to be getting called twice in a row typically.
301 // Right now I'm not going to worry about it because it doesn't
302 // seem to be hurting anything, but be aware of it.
308 clear_surface_cache();
310 reset_dynamic_lights();
312 for (ci
= 0; ci
< wr_num_cells
; ci
++) {
313 if (wr_cell
[ci
] != NULL
) {
316 if (p
->vpool
!= NULL
) wrFree(p
->vpool
);
317 if (p
->poly_list
!= NULL
) wrFree(p
->poly_list
);
318 if (p
->render_list
!= NULL
) {
319 wrFree(p
->render_list
);
321 if (p
->vertex_list
!= NULL
) wrFree(p
->vertex_list
);
322 if (p
->plane_list
!= NULL
) wrFree(p
->plane_list
);
324 if (p
->render_data
!= NULL
) wrFree(p
->render_data
);
325 if (p
->anim_light_index_list
!= NULL
) wrFree(p
->anim_light_index_list
);
326 if (p
->light_list
!= NULL
) {
327 for (i
= 0; i
< p
->num_render_polys
; i
++) {
328 if (p
->light_list
[i
].data
!= NULL
) wrFree(p
->light_list
[i
].data
);
329 if (p
->light_list
[i
].dynamic_light
!= NULL
) wrFree(p
->light_list
[i
].dynamic_light
);
331 wrFree(p
->light_list
);
333 if (p
->light_indices
!= NULL
) wrFree(p
->light_indices
);
336 if (wr_brfaces
[ci
] != NULL
) wrFree(wr_brfaces
[ci
]);
342 // NOTE: doesn't free refs
352 // Given a rendered non-portal polygon in a cell, how many lightmaps?
353 // There's always the static one. Each animated animated light which
354 // reaches this polygon contributes another.
355 static int lightmap_count(PortalCell
*cell
, int polygon_index
)
358 uint bitmask
= cell
->light_list
[polygon_index
].anim_light_bitmask
;
369 ulong
WriteWR(PortalReadWrite func
)
371 int ci
, i
; // portal cell index
372 int pi
, voff
, num_light_indices
;
375 ulong alloced_bytes_written
= 0 ;
379 // write the number of portal cells to be written
380 (*func
)(&wr_num_cells
, sizeof(int), 1);
382 for (ci
= 0; ci
< wr_num_cells
; ci
++)
386 // write the portal cell
387 ReadWriteNonPtrPortalCell(func
, p
);
388 alloced_bytes_written
+= sizeof(*p
);
391 (*func
)(p
->vpool
, sizeof(Vertex
), p
->num_vertices
);
392 alloced_bytes_written
+= sizeof(Vertex
)*p
->num_vertices
;
394 // write the poly_list
395 (*func
)(p
->poly_list
, sizeof(PortalPolygonCore
), p
->num_polys
);
396 alloced_bytes_written
+= sizeof(PortalPolygonCore
)*p
->num_polys
;
399 (*func
)(p
->render_list
, sizeof(PortalPolygonRenderInfo
), p
->num_render_polys
);
400 alloced_bytes_written
+= sizeof(PortalPolygonRenderInfo
)*p
->num_render_polys
;
402 // calculate the highest index into the vertex_list used,
403 // and then write the index, and then the vertex_list array.
405 for (pi
= 0; pi
< p
->num_polys
; ++pi
)
406 voff
+= p
->poly_list
[pi
].num_vertices
;
407 (*func
)(&voff
, sizeof(int), 1);
408 (*func
)(p
->vertex_list
, sizeof(uchar
), voff
);
409 alloced_bytes_written
+= sizeof(uchar
)*voff
;
411 // write the plane_list
412 (*func
)(p
->plane_list
, sizeof(PortalPlane
), p
->num_planes
);
413 alloced_bytes_written
+= sizeof(PortalPlane
)*p
->num_planes
;
415 if (p
->num_anim_lights
)
416 (*func
)(p
->anim_light_index_list
, sizeof(ushort
), p
->num_anim_lights
);
417 alloced_bytes_written
+= sizeof(ushort
)*p
->num_anim_lights
;
419 // write the light_list and the sub field bits parameter
420 // zero out the pointers (.data, and .dynamic_light), since we
421 // zero them out on load anyway, and they are meaningless to save.
422 // If we don't, we keep getting a different WRRGB tag which sucks
424 PortalLightMap templist
;
425 for (i
= 0; i
< p
->num_render_polys
; i
++)
427 memcpy(&templist
,&(p
->light_list
[i
]),sizeof(PortalLightMap
));
429 templist
.dynamic_light
= 0;
430 (*func
)(&templist
,sizeof(PortalLightMap
),1);
432 //(*func)(p->light_list, sizeof(PortalLightMap), p->num_render_polys);
433 alloced_bytes_written
+= sizeof(PortalLightMap
) * p
->num_render_polys
;
434 for (i
= 0; i
< p
->num_render_polys
; i
++)
436 int lightmap_size
= (p
->light_list
[i
].h
)
437 * (p
->light_list
[i
].pixel_row
)
438 * sizeof(LightmapEntry
)
439 * (lightmap_count(p
, i
));
441 (*func
)(p
->light_list
[i
].data
, 1, lightmap_size
);
442 alloced_bytes_written
+= /* sizeof(LightmapEntry) * */ lightmap_size
;
445 // write the light_indices
446 num_light_indices
= p
->light_indices
[0]+1;
447 if (num_light_indices
>1024)
448 mprintf("ummm, dont take this the wrong way, but cell %d has %d light idx\n",ci
,num_light_indices
);
449 (*func
)(&num_light_indices
, sizeof(int), 1);
450 (*func
)(p
->light_indices
, sizeof(ushort
), num_light_indices
);
451 // a little silly to write out the first field twice, oh well
452 alloced_bytes_written
+= sizeof(ushort
) * (num_light_indices
);
454 // pointers in struct that are not being written to disk yet......
455 //////////////////////////////////////////////////////////////////
456 // vertex_list_dynamic
458 // decal ptr and dynamic ptr in PortalLightMap (same place as bits)
461 wrBspTreeWrite(func
);
463 return alloced_bytes_written
;
467 void ReadWR(PortalReadWrite func
)
470 int num_vertex_list
, num_light_indices
;
473 // read the number of portal cells to be read
474 (*func
)(&wr_num_cells
, sizeof(int), 1);
476 if (wr_num_cells
> 0)
478 ged_validate_level(TRUE
);
483 ged_validate_level(FALSE
);
486 for (ci
= 0; ci
< wr_num_cells
; ci
++)
488 // alloc and read the portal cell
489 wr_cell
[ci
] = (PortalCell
*) wrAlloc(sizeof(PortalCell
));
491 ReadWriteNonPtrPortalCell(func
, p
);
493 // alloc and read the vpool
494 p
->vpool
= (Vertex
*) wrAlloc(sizeof(Vertex
) * p
->num_vertices
);
495 (*func
)(p
->vpool
, sizeof(Vertex
), p
->num_vertices
);
497 // alloc and read the poly_list
498 p
->poly_list
= (PortalPolygonCore
*) wrAlloc(sizeof(PortalPolygonCore
) * p
->num_polys
);
499 (*func
)(p
->poly_list
, sizeof(PortalPolygonCore
), p
->num_polys
);
501 // alloc and read the render_list
502 p
->render_list
= (PortalPolygonRenderInfo
*) wrAlloc(sizeof(PortalPolygonRenderInfo
)* p
->num_render_polys
);
503 (*func
)(p
->render_list
, sizeof(PortalPolygonRenderInfo
), p
->num_render_polys
);
504 for (i
=0; i
< p
->num_render_polys
; ++i
)
505 p
->render_list
[i
].cached_surface
= 0;
507 // set the portal_list_ptr
508 p
->portal_poly_list
= p
->poly_list
+ p
->num_polys
- p
->num_portal_polys
;
510 // read the size of the vertex_list and then alloc and read the array
511 (*func
)(&num_vertex_list
, sizeof(int), 1);
512 p
->vertex_list
= (uchar
*) wrAlloc(sizeof(uchar
) * num_vertex_list
);
513 (*func
)(p
->vertex_list
, sizeof(uchar
), num_vertex_list
);
515 // alloc and read the plane_list, and then read in the
516 // cached vectors inside the plane_list
517 p
->plane_list
= (PortalPlane
*) wrAlloc(sizeof(PortalPlane
) * p
->num_planes
);
518 (*func
)(p
->plane_list
, sizeof(PortalPlane
), p
->num_planes
);
521 g_pMalloc
->PushCredit("WR Light Maps",0);
524 // DoMalloc and read the anim_light_index_list
525 if (p
->num_anim_lights
) {
526 p
->anim_light_index_list
527 = (ushort
*) wrAlloc(sizeof(ushort
) * p
->num_anim_lights
);
528 (*func
)(p
->anim_light_index_list
, sizeof(ushort
), p
->num_anim_lights
);
530 p
->anim_light_index_list
= NULL
;
532 // DoMalloc and read the light_list and the sub field bits pointer
533 p
->light_list
= (PortalLightMap
*) wrAlloc(sizeof(PortalLightMap
)
534 * p
->num_render_polys
);
535 (*func
)(p
->light_list
, sizeof(PortalLightMap
), p
->num_render_polys
);
537 for (i
= 0; i
< p
->num_render_polys
; i
++)
539 int lightmap_size
= (p
->light_list
[i
].h
)
540 * (p
->light_list
[i
].pixel_row
)
541 * sizeof(LightmapEntry
)
542 * (lightmap_count(p
, i
));
544 p
->light_list
[i
].data
= (LightmapEntry
*) wrAlloc(lightmap_size
);
545 (*func
)(p
->light_list
[i
].data
, 1 /* sizeof(LightmapEntry) */, lightmap_size
);
547 p
->light_list
[i
].dynamic_light
= NULL
;
550 // DoMalloc and read the light_indices
551 (*func
)(&num_light_indices
, sizeof(int), 1);
552 p
->light_indices
= (ushort
*) wrAlloc(sizeof(ushort
) * num_light_indices
);
553 (*func
)(p
->light_indices
, sizeof(ushort
), num_light_indices
);
555 // pointers in the struct which are not being read from disk yet....
556 /////////////////////////////////////////////////////////////////////
558 p
->render_data
= NULL
;
559 p
->changed_anim_light_bitmask
= 0;
560 p
->num_full_bright
= 0;
561 // and decal and dynamic in PortalLightMap
564 g_pMalloc
->PopCredit();
569 g_pMalloc
->PushCredit("WR BSP",0);
573 wrBspTreeRefCells(WRBSP_HEAD
);
576 g_pMalloc
->PopCredit();
579 wrAllocPrintOverflow();
585 //////////////////////////////////////////////////
586 // World Rep Save/Load Stuff
588 //////////////////////////////////////////////////
589 // light save/load stuff -- anim light scripts are next
591 typedef void (*LightReadWrite
) (void *buf
, size_t elsize
, size_t nelem
);
595 #define MAX_STATIC 768
597 EXTERN
int num_light
;
599 EXTERN mls_multi_light light_data
[];
600 EXTERN mls_multi_light light_this
[];
602 // @TODO: Shouldn't this be using num_light for the number of elements?
603 void ReadWriteLight(LightReadWrite func
)
606 (*func
)(&num_light
, sizeof(int), 1);
607 (*func
)(&num_dyn
, sizeof(int), 1);
608 (*func
)(light_data
, sizeof(mls_multi_light
), MAX_STATIC
);
609 (*func
)(light_this
, sizeof(mls_multi_light
), 32);
611 // mappings from animated lights to cells
612 (*func
)(&g_iCurAnimLightToCell
, sizeof(int), 1);
613 (*func
)(&g_aAnimLightToCell
[0], sizeof(sAnimLightToCell
),
614 g_iCurAnimLightToCell
);
617 // end of light save/load stuff
618 //////////////////////////////////////////////////
621 //////////////////////////////////////////////////
622 // management of PortalCellMotion structures
625 static void ReadWriteWaterMotion(PortalReadWrite func
)
627 (*func
)(portal_cell_motion
,
628 sizeof(portal_cell_motion
[0]), MAX_CELL_MOTION
);
629 (*func
)(g_aMedMoCellMotion
,
630 sizeof(g_aMedMoCellMotion
[0]), MAX_CELL_MOTION
);
634 static void ClearWaterMotion()
636 memset(&g_aMedMoCellMotion
[0], 0,
637 sizeof(g_aMedMoCellMotion
[0]) * MAX_CELL_MOTION
);
639 memset(&portal_cell_motion
[0], 0,
640 sizeof(portal_cell_motion
[0]) * MAX_CELL_MOTION
);
642 for (int i
= 0; i
< MAX_CELL_MOTION
; ++i
) {
643 portal_cell_motion
[i
].major_axis
= MEDIUM_AXIS_Z
;
644 portal_cell_motion
[i
].in_motion
= TRUE
;
649 // end of management of PortalCellMotion structures
650 //////////////////////////////////////////////////
653 //////////////////////////////////////////////////
656 static void ReadWriteFog(PortalReadWrite func
)
658 (*func
)(portal_fog_color
, sizeof(portal_fog_color
), 1);
659 (*func
)(&portal_fog_dist
, sizeof(portal_fog_dist
), 1);
662 static void ClearFog()
665 portal_fog_color
[0] = 128;
666 portal_fog_color
[1] = 128;
667 portal_fog_color
[2] = 128;
670 // end of management of fog
671 //////////////////////////////////////////////////
674 //////////////////////////////////////////////////
677 static ITagFile
* tagfile
= NULL
;
678 static void movefunc(void *buf
, size_t elsize
, size_t nelem
)
680 ITagFile_Move(tagfile
,(char*)buf
,elsize
*nelem
);
689 TagFileTag WrTag
= { "WRRGB" };
691 TagFileTag WrTag
= { "WR" };
693 TagVersion WrVersion
= { 0, 24 };
694 TagVersion AcceptWrVersion
= { 0, 24 };
696 static BOOL
setup_tagfile(ITagFile
* file
, TagFileTag
*tag
,
697 TagVersion
*version
, TagVersion
* accept
)
700 TagVersion old_version
= *version
;
703 result
= file
->OpenBlock(tag
, version
);
704 if (VersionNumsCompare(version
,accept
) < 0)
710 return SUCCEEDED(result
);
715 static void cleanup_tagfile(ITagFile
* file
)
720 //////////////////////////////////////////////////
723 //////////////////////////////////////////////////
724 // water tag file thingbobs
726 TagFileTag WaterMotionTag
= { "CELL_MOTION" };
727 TagVersion WaterMotionVersion
= { 0, 1 };
728 TagVersion AcceptWaterMotionVersion
= { 0, 1 };
733 //////////////////////////////////////////////////
734 // fog tag file thingbobs
736 static TagFileTag FogTag
= { "FOG" };
737 static TagVersion FogVersion
= { 0, 1 };
738 static TagVersion AcceptFogVersion
= { 0, 1 };
743 //////////////////////////////////////////////////
745 // @TODO: something more graceful here
748 BOOL wr_db_disabled
= FALSE
;
751 static void water_db_message(DispatchData
* msg
)
753 msgDatabaseData data
;
754 data
.raw
= msg
->data
;
756 switch (DB_MSG(msg
->subtype
))
764 if (msg
->subtype
& kDBMap
)
766 TagVersion v
= WaterMotionVersion
;
767 if (setup_tagfile(data
.save
, &WaterMotionTag
, &v
, &AcceptWaterMotionVersion
) )
769 ReadWriteWaterMotion(movefunc
);
770 cleanup_tagfile(data
.save
);
778 static void db_message(DispatchData
* msg
)
780 msgDatabaseData data
;
781 data
.raw
= msg
->data
;
786 switch (DB_MSG(msg
->subtype
))
792 wrBspTreeDeallocate();
795 free_csg_internal_database();
800 portal_cleanup_water_hack();
810 if (msg
->subtype
& kDBMap
) // Save world info into the MAP file.
812 if (!gedit_editted
&& wr_num_cells
> 0)
814 ITagFile
* file
= data
.save
;
815 TagVersion v
= WrVersion
;
816 if (setup_tagfile(file
, &WrTag
, &v
,&AcceptWrVersion
))
820 // make room for the size
821 file
->Write((char*)&size
,sizeof(size
));
823 // write the world rep
824 size
= WriteWR(movefunc
);
826 // write the light stuff
827 ReadWriteLight(movefunc
);
829 // write the csg editting stuff
831 save_csg_internal_database(movefunc
);
834 // backpatch the writen size
835 file
->Seek(0,kTagSeekFromStart
);
836 file
->Write((char*)&size
,sizeof(size
));
838 cleanup_tagfile(data
.save
);
842 TagVersion v
= FogVersion
;
843 if (setup_tagfile(data
.save
, &FogTag
, &v
, &AcceptFogVersion
))
845 ReadWriteFog(movefunc
);
846 cleanup_tagfile(data
.save
);
849 texture_Save(data
.save
);
856 if (msg
->subtype
& kDBMap
) // Load world info from the MAP file.
858 ITagFile
* file
= data
.load
;
859 TagVersion v
= WrVersion
;
860 if (setup_tagfile(file
, &WrTag
, &v
, &AcceptWrVersion
))
863 if (v
.minor
>= kSizeHeader
)
864 file
->Read((char*)&size
,sizeof(size
));
866 size
= file
->BlockSize(&WrTag
);
870 // load the world rep
873 // load the light stuff
874 ReadWriteLight(movefunc
);
876 // load the csg editting type stuff
878 load_csg_internal_database(movefunc
);
881 cleanup_tagfile(data
.load
);
883 ConfigSpew("wr_load_spew",("Wr is %d bytes, %d bytes unused\n",MemBuf
.next
- MemBuf
.buf
,MemBuf
.size
- (MemBuf
.next
- MemBuf
.buf
)));
886 ged_validate_level(FALSE
);
889 if (setup_tagfile(data
.load
, &FogTag
, &v
, &AcceptFogVersion
))
891 ReadWriteFog(movefunc
);
892 cleanup_tagfile(data
.load
);
895 texture_Load(data
.load
);
903 ////////////////////////////////////////
905 // LOOP/DISPATCH callback
906 // Here's where we do the dirty work.
909 #pragma off(unreferenced)
910 static eLoopMessageResult LGAPI
_LoopFunc(void* data
, eLoopMessage msg
, tLoopMessageData hdata
)
912 // useful stuff for most clients
913 eLoopMessageResult result
= kLoopDispatchContinue
;
914 StateRecord
* state
= (StateRecord
*)data
;
924 db_message(info
.dispatch
);
925 water_db_message(info
.dispatch
);
929 family_init(); // a reset but an init
943 ////////////////////////////////////////////////////////////
945 // Loop client factory function.
948 #pragma off(unreferenced)
949 static ILoopClient
* LGAPI
_CreateClient(sLoopClientDesc
* pDesc
, tLoopClientData data
)
952 // allocate space for our state, and fill out the fields
953 state
= (StateRecord
*)DoMalloc(sizeof(StateRecord
));
954 state
->context
= (Context
*)data
;
956 return CreateSimpleLoopClient(_LoopFunc
,state
,pDesc
);
958 #pragma on(unreferenced)
964 sLoopClientDesc WrLoopClientDesc
=
967 "World Rep Client", // NAME
968 kPriorityNormal
, // PRIORITY
969 kMsgEnd
| kMsgDatabase
| kMsgsAppOuter
, // INTERESTS
977 {kConstrainAfter
, &LOOPID_Render
, kMsgDatabase
|kMsgAppTerm
}, // for texture archetypes
978 {kNullConstraint
} // terminator