From 52046a296d5acd6588c2dde5918cdb6cbd26fc52 Mon Sep 17 00:00:00 2001 From: Ketmar Dark Date: Sun, 21 Jan 2018 01:10:48 +0200 Subject: [PATCH] replaced manual pool walking with nice iterator (yet one should still call `.release()` manually... T_T) --- src/game/g_grid.pas | 83 ++++++++++++++------------- src/game/g_holmes.pas | 110 ++++++++++-------------------------- src/game/g_map.pas | 111 +++++++++++------------------------- src/game/g_monsters.pas | 87 +++++++++-------------------- src/game/g_weapons.pas | 18 ++---- src/shared/mempool.pas | 121 ++++++++++++++++++++++++++++++++++++++++ 6 files changed, 261 insertions(+), 269 deletions(-) diff --git a/src/game/g_grid.pas b/src/game/g_grid.pas index 99eb0ef..ce31c63 100644 --- a/src/game/g_grid.pas +++ b/src/game/g_grid.pas @@ -49,6 +49,9 @@ type x, y: Integer; end; + CellCoordIter = specialize PoolIter; + + type TBodyProxyId = Integer; @@ -57,6 +60,8 @@ type type PITP = ^ITP; type TCellQueryCB = procedure (x, y: Integer) is nested; // top-left cell corner coords + type Iter = specialize PoolIter; + const TagDisabled = $40000000; const TagFullMask = $3fffffff; @@ -194,11 +199,11 @@ type // return number of ITP thingys put into frame pool // if `firstHit` is `true`, return on first hit (obviously) - function forEachInAABB (x, y, w, h: Integer; tagmask: Integer=-1; allowDisabled: Boolean=false; firstHit: Boolean=false): Integer; + function forEachInAABB (x, y, w, h: Integer; tagmask: Integer=-1; allowDisabled: Boolean=false; firstHit: Boolean=false): Iter; // return number of ITP thingys put into frame pool // if `firstHit` is `true`, return on first hit (obviously) - function forEachAtPoint (x, y: Integer; tagmask: Integer=-1; allowDisabled: Boolean=false; firstHit: Boolean=false): Integer; + function forEachAtPoint (x, y: Integer; tagmask: Integer=-1; allowDisabled: Boolean=false; firstHit: Boolean=false): Iter; function atCellInPoint (x, y: Integer): TAtPointEnumerator; @@ -214,7 +219,7 @@ type // trace line along the grid, put all objects from passed cells into frame pool, in no particular order // return number of ITP thingys put into frame pool - function forEachAlongLine (ax0, ay0, ax1, ay1: Integer; tagmask: Integer=-1; log: Boolean=false): Integer; + function forEachAlongLine (ax0, ay0, ax1, ay1: Integer; tagmask: Integer=-1; log: Boolean=false): Iter; // trace box with the given velocity; return object hit (if any) // `cb` is used unconvetionally here: if it returns `false`, tracer will ignore the object @@ -222,8 +227,8 @@ type function traceBox (out ex, ey: Integer; const ax0, ay0, aw, ah: Integer; const dx, dy: Integer; tagmask: Integer=-1): ITP; // debug - function forEachBodyCell (body: TBodyProxyId): Integer; // this puts `TGridCellCoord` into frame pool for each cell - function forEachInCell (x, y: Integer): Integer; // this puts `ITP` into frame pool + function forEachBodyCell (body: TBodyProxyId): CellCoordIter; // this puts `TGridCellCoord` into frame pool for each cell + function forEachInCell (x, y: Integer): Iter; // this puts `ITP` into frame pool procedure dumpStats (); public @@ -693,14 +698,14 @@ begin end; -function TBodyGridBase.forEachBodyCell (body: TBodyProxyId): Integer; +function TBodyGridBase.forEachBodyCell (body: TBodyProxyId): CellCoordIter; var g, f, ccidx: Integer; cc: PGridCell; presobj: PGridCellCoord; begin - result := 0; - if (body < 0) or (body > High(mProxies)) then exit; + result := CellCoordIter.Create(true); + if (body < 0) or (body > High(mProxies)) then begin result.finishIt(); exit; end; for g := 0 to High(mGrid) do begin ccidx := mGrid[g]; @@ -715,7 +720,6 @@ begin presobj := PGridCellCoord(framePool.alloc(sizeof(TGridCellCoord))); presobj^.x := (g mod mWidth)*mTileSize+mMinX; presobj^.y := (g div mWidth)*mTileSize+mMinY; - Inc(result); //cb((g mod mWidth)*mTileSize+mMinX, (g div mWidth)*mTileSize+mMinY); end; end; @@ -723,19 +727,20 @@ begin ccidx := cc.next; end; end; + result.finishIt(); end; -function TBodyGridBase.forEachInCell (x, y: Integer): Integer; +function TBodyGridBase.forEachInCell (x, y: Integer): Iter; var f, ccidx: Integer; cc: PGridCell; presobj: PITP; begin - result := 0; + result := Iter.Create(true); Dec(x, mMinX); Dec(y, mMinY); - if (x < 0) or (y < 0) or (x >= mWidth*mTileSize) or (y > mHeight*mTileSize) then exit; + if (x < 0) or (y < 0) or (x >= mWidth*mTileSize) or (y > mHeight*mTileSize) then begin result.finishIt(); exit; end; ccidx := mGrid[(y div mTileSize)*mWidth+(x div mTileSize)]; while (ccidx <> -1) do begin @@ -747,11 +752,11 @@ begin presobj := PITP(framePool.alloc(sizeof(ITP))); //presobj^ := mProxies[cc.bodies[f]].mObj; Move(mProxies[cc.bodies[f]].mObj, presobj^, sizeof(ITP)); - Inc(result); end; // next cell ccidx := cc.next; end; + result.finishIt(); end; @@ -1331,7 +1336,7 @@ end; // ////////////////////////////////////////////////////////////////////////// // // no callback: return `true` on the first hit -function TBodyGridBase.forEachAtPoint (x, y: Integer; tagmask: Integer=-1; allowDisabled: Boolean=false; firstHit: Boolean=false): Integer; +function TBodyGridBase.forEachAtPoint (x, y: Integer; tagmask: Integer=-1; allowDisabled: Boolean=false; firstHit: Boolean=false): Iter; var f: Integer; idx, curci: Integer; @@ -1341,9 +1346,9 @@ var ptag: Integer; presobj: PITP; begin - result := 0; + result := Iter.Create(true); tagmask := tagmask and TagFullMask; - if (tagmask = 0) then exit; + if (tagmask = 0) then begin result.finishIt(); exit; end; {$IF DEFINED(D2F_DEBUG_XXQ)} if (assigned(cb)) then e_WriteLog(Format('0: grid pointquery: (%d,%d)', [x, y]), MSG_NOTIFY); @@ -1352,7 +1357,7 @@ begin // make coords (0,0)-based Dec(x, mMinX); Dec(y, mMinY); - if (x < 0) or (y < 0) or (x >= mWidth*mTileSize) or (y >= mHeight*mTileSize) then exit; + if (x < 0) or (y < 0) or (x >= mWidth*mTileSize) or (y >= mHeight*mTileSize) then begin result.finishIt(); exit; end; curci := mGrid[(y div mTileSize)*mWidth+(x div mTileSize)]; @@ -1400,19 +1405,19 @@ begin begin presobj := PITP(framePool.alloc(sizeof(ITP))); Move(px.mObj, presobj^, sizeof(ITP)); - Inc(result); - if (firstHit) then exit; + if (firstHit) then begin result.finishIt(); exit; end; end; end; curci := cc.next; end; + result.finishIt(); end; // ////////////////////////////////////////////////////////////////////////// // // no callback: return `true` on the first hit // return number of ITP thingys put into frame pool -function TBodyGridBase.forEachInAABB (x, y, w, h: Integer; tagmask: Integer=-1; allowDisabled: Boolean=false; firstHit: Boolean=false): Integer; +function TBodyGridBase.forEachInAABB (x, y, w, h: Integer; tagmask: Integer=-1; allowDisabled: Boolean=false; firstHit: Boolean=false): Iter; var idx: Integer; gx, gy: Integer; @@ -1427,17 +1432,17 @@ var ptag: Integer; presobj: PITP; begin - result := 0; - if (w < 1) or (h < 1) then exit; - if (w = 1) and (h = 1) then begin result := forEachAtPoint(x, y, tagmask, allowDisabled, firstHit); exit; end; + result := Iter.Create(true); + if (w < 1) or (h < 1) then begin result.finishIt(); exit; end; + tagmask := tagmask and TagFullMask; - if (tagmask = 0) then exit; + if (tagmask = 0) then begin result.finishIt(); exit; end; x0 := x; y0 := y; @@ -1449,8 +1454,8 @@ begin gw := mWidth; gh := mHeight; - if (x+w <= 0) or (y+h <= 0) then exit; - if (x >= gw*mTileSize) or (y >= gh*mTileSize) then exit; + if (x+w <= 0) or (y+h <= 0) then begin result.finishIt(); exit; end; + if (x >= gw*mTileSize) or (y >= gh*mTileSize) then begin result.finishIt(); exit; end; sx := x div mTileSize; sy := y div mTileSize; @@ -1462,7 +1467,7 @@ begin if (sy < 0) then sy := 0 else if (sy >= gh) then sy := gh-1; if (ex < 0) then ex := 0 else if (ex >= gw) then ex := gw-1; if (ey < 0) then ey := 0 else if (ey >= gh) then ey := gh-1; - if (sx > ex) or (sy > ey) then exit; // just in case + if (sx > ex) or (sy > ey) then begin result.finishIt(); exit; end; // just in case // has something to do @@ -1501,18 +1506,18 @@ begin if (x0+w <= px.mX) or (y0+h <= px.mY) then continue; presobj := PITP(framePool.alloc(sizeof(ITP))); Move(px.mObj, presobj^, sizeof(ITP)); - Inc(result); - if (firstHit) then exit; + if (firstHit) then begin result.finishIt(); exit; end; end; curci := cc.next; end; end; end; + result.finishIt(); end; // ////////////////////////////////////////////////////////////////////////// // -function TBodyGridBase.forEachAlongLine (ax0, ay0, ax1, ay1: Integer; tagmask: Integer=-1; log: Boolean=false): Integer; +function TBodyGridBase.forEachAlongLine (ax0, ay0, ax1, ay1: Integer; tagmask: Integer=-1; log: Boolean=false): Iter; var lw: TLineWalker; ccidx: Integer; @@ -1528,9 +1533,9 @@ var presobj: PITP; begin log := false; - result := 0; + result := Iter.Create(true); tagmask := tagmask and TagFullMask; - if (tagmask = 0) then exit; + if (tagmask = 0) then begin result.finishIt(); exit; end; gw := mWidth; gh := mHeight; @@ -1544,7 +1549,7 @@ begin y1 := ay1-miny; lw := TLineWalker.Create(0, 0, gw*mTileSize-1, gh*mTileSize-1); - if not lw.setup(x0, y0, x1, y1) then exit; // out of screen + if not lw.setup(x0, y0, x1, y1) then begin result.finishIt(); exit; end; // out of screen // increase query counter Inc(mLastQuery); @@ -1574,7 +1579,6 @@ begin px.mQueryMark := lq; // mark as processed presobj := PITP(framePool.alloc(sizeof(ITP))); Move(px.mObj, presobj^, sizeof(ITP)); - Inc(result); end; end; // next cell @@ -1582,12 +1586,12 @@ begin end; // done processing cells, move to next tile until lw.stepToNextTile(); + result.finishIt(); end; // ////////////////////////////////////////////////////////////////////////// // // trace box with the given velocity; return object hit (if any) -// `cb` is used unconvetionally here: if it returns `false`, tracer will ignore the object function TBodyGridBase.traceBox (out ex, ey: Integer; const ax0, ay0, aw, ah: Integer; const dx, dy: Integer; tagmask: Integer=-1): ITP; var gx, gy: Integer; @@ -1701,7 +1705,7 @@ var {$IF DEFINED(D2F_DEBUG_OTR)} s: AnsiString = ''; {$ENDIF} - pmark: PoolMark; + it: Iter; begin result := false; ex := ax1; @@ -1711,9 +1715,9 @@ begin tagmask := tagmask and TagFullMask; if (tagmask = 0) then exit; - pmark := framePool.mark(); - if (forEachAtPoint(ax0, ay0, tagmask, false, true) = 0) then exit; - framePool.release(pmark); + it := forEachAtPoint(ax0, ay0, tagmask, false, true); + if (it.length = 0) then begin it.release(); exit; end; + it.release(); minx := mMinX; miny := mMinY; @@ -1828,7 +1832,6 @@ begin end; -// no callback: return `true` on the nearest hit // you are not supposed to understand this function TBodyGridBase.traceRay (out ex, ey: Integer; const ax0, ay0, ax1, ay1: Integer; tagmask: Integer=-1): ITP; var diff --git a/src/game/g_holmes.pas b/src/game/g_holmes.pas index f4fe415..d16aa60 100644 --- a/src/game/g_holmes.pas +++ b/src/game/g_holmes.pas @@ -974,21 +974,13 @@ procedure plrDebugDraw (); procedure hilightBodyCells (proxyId: Integer); var - pmark: PoolMark; - hitcount: Integer; + it: CellCoordIter; pcellxy: PGridCellCoord; begin //monsGrid.forEachBodyCell(mon.proxyId, hilightCell); - pmark := framePool.mark(); - hitcount := monsGrid.forEachBodyCell(proxyId); - pcellxy := PGridCellCoord(framePool.getPtr(pmark)); - while (hitcount > 0) do - begin - hilightCell(pcellxy^.x, pcellxy^.y); - Inc(pcellxy); - Dec(hitcount); - end; - framePool.release(pmark); + it := monsGrid.forEachBodyCell(proxyId); + for pcellxy in it do hilightCell(pcellxy^.x, pcellxy^.y); + it.release(); end; procedure hilightCell1 (cx, cy: Integer); @@ -1252,12 +1244,11 @@ procedure plrDebugDraw (); var mon: TMonster; + mit: PMonster; + it: TMonsterGrid.Iter; mx, my, mw, mh: Integer; //pan: TPanel; //ex, ey: Integer; - pmark: PoolMark; - hitcount: Integer; - pmon: PMonster; begin if (gPlayer1 = nil) then exit; @@ -1282,16 +1273,9 @@ begin if (laserSet) then begin //g_Mons_AlongLine(laserX0, laserY0, laserX1, laserY1, monsCollector, true); - pmark := framePool.mark(); - hitcount := monsGrid.forEachAlongLine(laserX0, laserY0, laserX1, laserY1, -1, true); - pmon := PMonster(framePool.getPtr(pmark)); - while (hitcount > 0) do - begin - monsCollector(pmon^); - Inc(pmon); - Dec(hitcount); - end; - framePool.release(pmark); + it := monsGrid.forEachAlongLine(laserX0, laserY0, laserX1, laserY1, -1, true); + for mit in it do monsCollector(mit^); + it.release(); end; if (monMarkedUID <> -1) then @@ -1562,9 +1546,8 @@ procedure cbAtcurSelectMonster (); var plr: TPlayer; x, y, w, h: Integer; - pmark: PoolMark; - hitcount: Integer; - pmon: PMonster; + mit: PMonster; + it: TMonsterGrid.Iter; begin monMarkedUID := -1; if (Length(gPlayers) > 0) then @@ -1580,16 +1563,9 @@ begin end; end; //e_WriteLog('===========================', MSG_NOTIFY); - pmark := framePool.mark(); - hitcount := monsGrid.forEachAtPoint(pmsCurMapX, pmsCurMapY); - pmon := PMonster(framePool.getPtr(pmark)); - while (hitcount > 0) do - begin - monsAtDump(pmon^); - Inc(pmon); - Dec(hitcount); - end; - framePool.release(pmark); + it := monsGrid.forEachAtPoint(pmsCurMapX, pmsCurMapY); + for mit in it do monsAtDump(mit^); + it.release(); //e_WriteLog('---------------------------', MSG_NOTIFY); end; @@ -1600,25 +1576,17 @@ procedure cbAtcurDumpMonsters (); e_WriteLog(Format('monster #%d (UID:%u) (proxyid:%d)', [mon.arrIdx, mon.UID, mon.proxyId]), TMsgType.Notify); end; var - pmark: PoolMark; - hitcount: Integer; - pmon: PMonster; + mit: PMonster; + it: TMonsterGrid.Iter; begin - pmark := framePool.mark(); - hitcount := monsGrid.forEachAtPoint(pmsCurMapX, pmsCurMapY); - if (hitcount > 0) then + it := monsGrid.forEachAtPoint(pmsCurMapX, pmsCurMapY); + if (it.length > 0) then begin e_WriteLog('===========================', TMsgType.Notify); - pmon := PMonster(framePool.getPtr(pmark)); - while (hitcount > 0) do - begin - monsAtDump(pmon^); - Inc(pmon); - Dec(hitcount); - end; + for mit in it do monsAtDump(mit^); e_WriteLog('---------------------------', TMsgType.Notify); end; - framePool.release(pmark); + it.release(); end; procedure cbAtcurDumpWalls (); @@ -1633,26 +1601,18 @@ var hasTrigs: Boolean = false; f: Integer; trig: PTrigger; - pmark: PoolMark; - hitcount: Integer; - ppan: PPanel; + mwit: PPanel; + it: TPanelGrid.Iter; begin platMarkedGUID := -1; - pmark := framePool.mark(); - hitcount := mapGrid.forEachAtPoint(pmsCurMapX, pmsCurMapY, (GridTagWall or GridTagDoor)); - if (hitcount > 0) then + it := mapGrid.forEachAtPoint(pmsCurMapX, pmsCurMapY, (GridTagWall or GridTagDoor)); + if (it.length > 0) then begin e_WriteLog('=== TOGGLE WALL ===', TMsgType.Notify); - ppan := PPanel(framePool.getPtr(pmark)); - while (hitcount > 0) do - begin - wallToggle(ppan^); - Inc(ppan); - Dec(hitcount); - end; + for mwit in it do wallToggle(mwit^); e_WriteLog('--- toggle wall ---', TMsgType.Notify); end; - framePool.release(pmark); + it.release(); if showTriggers then begin for f := 0 to High(gTriggers) do @@ -1676,22 +1636,14 @@ procedure cbAtcurToggleWalls (); if pan.Enabled then g_Map_DisableWallGUID(pan.guid) else g_Map_EnableWallGUID(pan.guid); end; var - pmark: PoolMark; - hitcount: Integer; - ppan: PPanel; + mwit: PPanel; + it: TPanelGrid.Iter; begin //e_WriteLog('=== TOGGLE WALL ===', MSG_NOTIFY); //e_WriteLog('--- toggle wall ---', MSG_NOTIFY); - pmark := framePool.mark(); - hitcount := mapGrid.forEachAtPoint(pmsCurMapX, pmsCurMapY, (GridTagWall or GridTagDoor)); - ppan := PPanel(framePool.getPtr(pmark)); - while (hitcount > 0) do - begin - wallToggle(ppan^); - Inc(ppan); - Dec(hitcount); - end; - framePool.release(pmark); + it := mapGrid.forEachAtPoint(pmsCurMapX, pmsCurMapY, (GridTagWall or GridTagDoor)); + for mwit in it do wallToggle(mwit^); + it.release(); end; diff --git a/src/game/g_map.pas b/src/game/g_map.pas index 4455ed9..1ddbffd 100644 --- a/src/game/g_map.pas +++ b/src/game/g_map.pas @@ -612,9 +612,8 @@ end; function g_Map_HasAnyPanelAtPoint (x, y: Integer; panelType: Word): Boolean; var tagmask: Integer = 0; - pmark: PoolMark; - hitcount: Integer; - ppan: PPanel; + mwit: PPanel; + it: TPanelGrid.Iter; begin result := false; @@ -628,39 +627,31 @@ begin if (tagmask = 0) then exit;// just in case - pmark := framePool.mark(); if ((tagmask and GridTagLift) <> 0) then begin // slow - hitcount := mapGrid.forEachAtPoint(x, y, tagmask); - ppan := PPanel(framePool.getPtr(pmark)); - while (hitcount > 0) do - begin - if (xxPanAtPointChecker(ppan^, PanelType)) then begin result := true; break; end; - Inc(ppan); - Dec(hitcount); - end; + it := mapGrid.forEachAtPoint(x, y, tagmask); + for mwit in it do if (xxPanAtPointChecker(mwit^, PanelType)) then begin result := true; break; end; end else begin // fast - result := (mapGrid.forEachAtPoint(x, y, tagmask, false, true) <> 0); // firsthit + it := mapGrid.forEachAtPoint(x, y, tagmask, false, true); + result := (it.length <> 0); // firsthit end; - framePool.release(pmark); + it.release(); end; function g_Map_PanelAtPoint (x, y: Integer; tagmask: Integer=-1): TPanel; var - pmark: PoolMark; - hitcount: Integer; + it: TPanelGrid.Iter; begin result := nil; if (tagmask = 0) then exit; - pmark := framePool.mark(); - hitcount := mapGrid.forEachAtPoint(x, y, tagmask, false, true); // firsthit - if (hitcount <> 0) then result := PPanel(framePool.getPtr(pmark))^; - framePool.release(pmark); + it := mapGrid.forEachAtPoint(x, y, tagmask, false, true); // firsthit + if (it.length <> 0) then result := it.first^; + it.release(); end; @@ -2625,43 +2616,25 @@ end; // new algo procedure g_Map_CollectDrawPanels (x0, y0, wdt, hgt: Integer); var - pmark: PoolMark; - phit: PPanel; - hitcount: Integer; + mwit: PPanel; + it: TPanelGrid.Iter; begin dplClear(); - pmark := framePool.mark(); - hitcount := mapGrid.forEachInAABB(x0, y0, wdt, hgt, GridDrawableMask); - if (hitcount = 0) then exit; - phit := PPanel(framePool.getPtr(pmark)); - while (hitcount > 0) do - begin - if (((phit^.tag and GridTagDoor) <> 0) = phit^.Door) then gDrawPanelList.insert(phit^); - Inc(phit); - Dec(hitcount); - end; - framePool.release(pmark); + it := mapGrid.forEachInAABB(x0, y0, wdt, hgt, GridDrawableMask); + for mwit in it do if (((mwit^.tag and GridTagDoor) <> 0) = mwit^.Door) then gDrawPanelList.insert(mwit^); + it.release(); // list will be rendered in `g_game.DrawPlayer()` end; procedure g_Map_DrawPanelShadowVolumes (lightX: Integer; lightY: Integer; radius: Integer); var - pmark: PoolMark; - phit: PPanel; - hitcount: Integer; + mwit: PPanel; + it: TPanelGrid.Iter; begin - pmark := framePool.mark(); - hitcount := mapGrid.forEachInAABB(lightX-radius, lightY-radius, radius*2, radius*2, (GridTagWall or GridTagDoor)); - if (hitcount = 0) then exit; - phit := PPanel(framePool.getPtr(pmark)); - while (hitcount > 0) do - begin - phit^.DrawShadowVolume(lightX, lightY, radius); - Inc(phit); - Dec(hitcount); - end; - framePool.release(pmark); + it := mapGrid.forEachInAABB(lightX-radius, lightY-radius, radius*2, radius*2, (GridTagWall or GridTagDoor)); + for mwit in it do mwit^.DrawShadowVolume(lightX, lightY, radius); + it.release(); end; @@ -2862,9 +2835,8 @@ const var tagmask: Integer = 0; - pmark: PoolMark; - phit: PPanel; - hitcount: Integer; + mwit: PPanel; + it: TPanelGrid.Iter; pan: TPanel; begin result := false; @@ -2881,15 +2853,13 @@ begin if (profMapCollision <> nil) then profMapCollision.sectionBeginAccum('*solids'); if gdbg_map_use_accel_coldet then begin - pmark := framePool.mark(); if ((tagmask and SlowMask) <> 0) then begin // slow - hitcount := mapGrid.forEachInAABB(X, Y, Width, Height, tagmask); - phit := PPanel(framePool.getPtr(pmark)); - while (hitcount > 0) do + it := mapGrid.forEachInAABB(X, Y, Width, Height, tagmask); + for mwit in it do begin - pan := phit^; + pan := mwit^; if ((pan.tag and GridTagLift) <> 0) then begin result := @@ -2909,17 +2879,15 @@ begin result := true; // i found her! end; if (result) then break; - Inc(phit); - Dec(hitcount); end; end else begin // fast - hitcount := mapGrid.forEachInAABB(X, Y, Width, Height, tagmask, false, true); // return first hit - result := (hitcount > 0); + it := mapGrid.forEachInAABB(X, Y, Width, Height, tagmask, false, true); // return first hit + result := (it.length > 0); end; - framePool.release(pmark); + it.release(); end else begin @@ -2955,27 +2923,16 @@ end; function g_Map_CollideLiquid_Texture(X, Y: Integer; Width, Height: Word): DWORD; var cctype: Integer = 3; // priority: 0: water was hit, 1: acid1 was hit, 2: acid2 was hit; 3: nothing was hit - pmark: PoolMark; - phit: PPanel; - hitcount: Integer; - pan: TPanel; + mwit: PPanel; + it: TPanelGrid.Iter; begin if (profMapCollision <> nil) then profMapCollision.sectionBeginAccum('liquids'); if gdbg_map_use_accel_coldet then begin result := LongWord(TEXTURE_NONE); - pmark := framePool.mark(); - hitcount := mapGrid.forEachInAABB(X, Y, Width, Height, (GridTagWater or GridTagAcid1 or GridTagAcid2)); - if (hitcount = 0) then exit; - phit := PPanel(framePool.getPtr(pmark)); - while (hitcount > 0) do - begin - pan := phit^; - Inc(phit); - Dec(hitcount); - if (liquidChecker(pan, result, cctype)) then break; - end; - framePool.release(pmark); + it := mapGrid.forEachInAABB(X, Y, Width, Height, (GridTagWater or GridTagAcid1 or GridTagAcid2)); + for mwit in it do if (liquidChecker(mwit^, result, cctype)) then break; + it.release(); end else begin diff --git a/src/game/g_monsters.pas b/src/game/g_monsters.pas index 018a693..bb3d293 100644 --- a/src/game/g_monsters.pas +++ b/src/game/g_monsters.pas @@ -781,10 +781,9 @@ function isCorpse (o: PObj; immediately: Boolean): Integer; var a: Integer; - mon: TMonster = nil; - pmark: PoolMark; - phit: PMonster; - hitcount: Integer; + mon: PMonster; + mres: TMonster = nil; + it: TMonsterGrid.Iter; begin result := -1; @@ -796,24 +795,19 @@ begin begin //mon := monsGrid.forEachInAABB(o.X+o.Rect.X, o.Y+o.Rect.Y, o.Rect.Width, o.Rect.Height, monsCollCheck); //if (mon <> nil) then result := mon.mArrIdx; - pmark := framePool.mark(); - hitcount := monsGrid.forEachInAABB(o.X+o.Rect.X, o.Y+o.Rect.Y, o.Rect.Width, o.Rect.Height); - if (hitcount = 0) then exit; - phit := PMonster(framePool.getPtr(pmark)); - while (hitcount > 0) do + it := monsGrid.forEachInAABB(o.X+o.Rect.X, o.Y+o.Rect.Y, o.Rect.Width, o.Rect.Height); + for mon in it do begin - mon := phit^; - Inc(phit); - Dec(hitcount); case mon.FMonsterType of // Íå âîñêðåñèòü: MONSTER_SOUL, MONSTER_PAIN, MONSTER_CYBER, MONSTER_SPIDER, - MONSTER_VILE, MONSTER_BARREL, MONSTER_ROBO: mon := nil; + MONSTER_VILE, MONSTER_BARREL, MONSTER_ROBO: begin end; // Îñòàëüíûõ ìîæíî âîñêðåñèòü + else mres := mon^; end; - if (mon <> nil) then break; + if (mres <> nil) then break; end; - framePool.release(pmark); - if (mon <> nil) then result := mon.mArrIdx; + it.release(); + if (mres <> nil) then result := mres.mArrIdx; end else begin @@ -4725,27 +4719,17 @@ function g_Mons_IsAnyAliveAt (x, y: Integer; width, height: Integer): Boolean; var idx: Integer; mon: TMonster; - pmark: PoolMark; - phit: PMonster; - hitcount: Integer; + mit: PMonster; + it: TMonsterGrid.Iter; begin result := false; if (width < 1) or (height < 1) then exit; if gmon_debug_use_sqaccel then begin //result := (monsGrid.forEachInAABB(x, y, width, height, monsCollCheck) <> nil); - pmark := framePool.mark(); - hitcount := monsGrid.forEachInAABB(x, y, width, height); - if (hitcount = 0) then exit; - phit := PMonster(framePool.getPtr(pmark)); - while (hitcount > 0) do - begin - mon := phit^; - Inc(phit); - Dec(hitcount); - if (mon.alive) then begin result := true; break; end; - end; - framePool.release(pmark); + it := monsGrid.forEachInAABB(x, y, width, height); + for mit in it do if (mit.alive) then begin result := true; break; end; + it.release(); end else begin @@ -4775,27 +4759,17 @@ function g_Mons_ForEachAt (x, y: Integer; width, height: Integer; cb: TEachMonst var idx: Integer; mon: TMonster; - pmark: PoolMark; - phit: PMonster; - hitcount: Integer; + mit: PMonster; + it: TMonsterGrid.Iter; begin result := false; if (width < 1) or (height < 1) then exit; if gmon_debug_use_sqaccel then begin //result := (monsGrid.forEachInAABB(x, y, width, height, monsCollCheck) <> nil); - pmark := framePool.mark(); - hitcount := monsGrid.forEachInAABB(x, y, width, height); - if (hitcount = 0) then exit; - phit := PMonster(framePool.getPtr(pmark)); - while (hitcount > 0) do - begin - mon := phit^; - Inc(phit); - Dec(hitcount); - if (cb(mon)) then begin result := true; break; end; - end; - framePool.release(pmark); + it := monsGrid.forEachInAABB(x, y, width, height); + for mit in it do if (cb(mit^)) then begin result := true; break; end; + it.release(); end else begin @@ -4827,9 +4801,8 @@ function g_Mons_ForEachAliveAt (x, y: Integer; width, height: Integer; cb: TEach var idx: Integer; mon: TMonster; - pmark: PoolMark; - phit: PMonster; - hitcount: Integer; + mit: PMonster; + it: TMonsterGrid.Iter; begin result := false; if (width < 1) or (height < 1) then exit; @@ -4845,21 +4818,15 @@ begin result := (monsGrid.forEachInAABB(x, y, width, height, monsCollCheck) <> nil); end; } - pmark := framePool.mark(); - hitcount := monsGrid.forEachInAABB(x, y, width, height); - if (hitcount = 0) then exit; - phit := PMonster(framePool.getPtr(pmark)); - while (hitcount > 0) do + it := monsGrid.forEachInAABB(x, y, width, height); + for mit in it do begin - mon := phit^; - Inc(phit); - Dec(hitcount); - if (mon.alive) then + if (mit^.alive) then begin - if (cb(mon)) then begin result := true; break; end; + if (cb(mit^)) then begin result := true; break; end; end; end; - framePool.release(pmark); + it.release(); end else begin diff --git a/src/game/g_weapons.pas b/src/game/g_weapons.pas index 725ab6d..3b13301 100644 --- a/src/game/g_weapons.pas +++ b/src/game/g_weapons.pas @@ -1467,9 +1467,8 @@ var {$IF DEFINED(D2F_DEBUG)} stt: UInt64; {$ENDIF} - pmark: PoolMark; - hitcount: Integer; - pmon: PMonster; + mit: PMonster; + it: TMonsterGrid.Iter; begin (* if not gwep_debug_fast_trace then @@ -1526,16 +1525,9 @@ begin // collect monsters //g_Mons_AlongLine(x, y, x2, y2, sqchecker); - pmark := framePool.mark(); - hitcount := monsGrid.forEachAlongLine(x, y, x2, y2, -1); - pmon := PMonster(framePool.getPtr(pmark)); - while (hitcount > 0) do - begin - sqchecker(pmon^); - Inc(pmon); - Dec(hitcount); - end; - framePool.release(pmark); + it := monsGrid.forEachAlongLine(x, y, x2, y2, -1); + for mit in it do sqchecker(mit^); + it.release(); // here, we collected all monsters and players in `wgunHitHeap` and `wgunHitTime` // also, if `wallWasHit` is `true`, then `wallHitX` and `wallHitY` contains spark coords diff --git a/src/shared/mempool.pas b/src/shared/mempool.pas index 1604055..ae67f03 100644 --- a/src/shared/mempool.pas +++ b/src/shared/mempool.pas @@ -90,6 +90,39 @@ type // get pointer for the given mark // WARNING! pointer can become invalid after next call to `alloc()`! function getPtr (amark: PoolMark): Pointer; inline; + function curPtr (): Pointer; inline; + end; + + +type + generic PoolIter = record + public + type Ptr = ^T; + type MyType = specialize PoolIter; + + private + mMark: PoolMark; + mCount: Integer; + mCurrent: Integer; + mFinished: Boolean; + + public + constructor Create (dummy: Boolean); // idiotic FPC doesn't support arg-less ctors for rectord + procedure startIt (); inline; // automatically called by ctor; does NO checks! + procedure finishIt (); inline; // sets count + + procedure rewind (); inline; + function length (): Integer; inline; + procedure release (); inline; // reset pool + + function moveNext (): Boolean; inline; + function getCurrent (): Ptr; inline; + function getEnumerator (): MyType; inline; + + function first (): Ptr; inline; + + public + property current: Ptr read getCurrent; end; @@ -193,6 +226,94 @@ begin end; +function TPoolMarkRelease.curPtr (): Pointer; inline; +begin + result := Pointer(PAnsiChar(mMemory)+mUsed); +end; + + + +// ////////////////////////////////////////////////////////////////////////// // +constructor PoolIter.Create (dummy: Boolean); +begin + startIt(); +end; + + +procedure PoolIter.startIt (); inline; // automatically called by ctor; does NO checks! +begin + mMark := framePool.mark(); + mCount := 0; + mCurrent := -1; + mFinished := false; +end; + + +procedure PoolIter.finishIt (); inline; // sets count +begin + if (mFinished) then raise Exception.Create('double fatality'); + if (mMark = -1) then raise Exception.Create('void fatality'); + mFinished := true; + mCount := Integer(PtrUInt(framePool.curPtr)-PtrUInt(framePool.getPtr(mMark))) div Integer(sizeof(T)); + if (mCount < 0) then raise Exception.Create('wutafu?'); +end; + + +procedure PoolIter.rewind (); inline; +begin + if (mMark = -1) then raise Exception.Create('void rewind'); + mCurrent := -1; +end; + + +function PoolIter.length (): Integer; inline; +begin + //if (mCurrent+1 >= 0) and (mCurrent+1 < mCount) then result := mCount-(mCurrent+1) else result := 0; + result := mCount; +end; + + +procedure PoolIter.release (); inline; // reset pool +begin + if (mMark = -1) then raise Exception.Create('double release'); + framePool.release(mMark); + mMark := -1; + mCount := 0; + mCurrent := -1; + mFinished := false; +end; + + +function PoolIter.moveNext (): Boolean; inline; +begin + if (mMark = -1) then raise Exception.Create('void moveNext()'); + if (not mFinished) then raise Exception.Create('moveNext() on unfinished'); + Inc(mCurrent); + result := (mCurrent < mCount); +end; + + +function PoolIter.getCurrent (): Ptr; inline; +begin + if (mCurrent < 0) or (mCurrent >= mCount) then raise Exception.Create('getCurrent() range error'); + result := Ptr(framePool.getPtr(mMark+mCurrent*Integer(sizeof(T)))); +end; + + +function PoolIter.getEnumerator (): PoolIter; inline; +begin + result := self; +end; + + +function PoolIter.first (): Ptr; inline; +begin + if (mMark = -1) then raise Exception.Create('void moveNext()'); + if (not mFinished) then raise Exception.Create('moveNext() on unfinished'); + result := Ptr(framePool.getPtr(mMark)); +end; + + // ////////////////////////////////////////////////////////////////////////// // {$IFDEF USE_MEMPOOL} uses -- 2.29.2