jespertheend / splix

MIT License
24 stars 6 forks source link

fix(gs): Update scores when someone steals some of your tiles #140

Open abhishek-exists opened 11 months ago

abhishek-exists commented 11 months ago

Fixes #135

I've left a case when player is still moving (have trailVertices) as in this case player will either die or capture their block which will update their scores.

jespertheend commented 11 months ago

This runs the flood fill algorithm for every player, every time someone returns to their captured area. I'm worried this won't run very efficiently once there are a handful of players in game. If I'm not mistaken, the old server didn't have this either for the same reason.

I think the fix would be to keep track of whose land was taken, and then only update the score of those players.

Another option would be to run a timer and only update the score every few minutes or so. But I'm not sure what the ideal frequency should be, and I reckon it would have to be pretty low for it to be meaningful.

abhishek-exists commented 11 months ago

Yeah, you're right.

I think the fix would be to keep track of whose land was taken and then only update the score of those players.

This should be the optimal solution. I'm thinking of returning playerIDs from the FillRect() method inside utils.js. The only thing that bothers me is that, possibly not the best way to write things, I have to propagate back the PlayerIDs to the Game.js.

Lmk, this is ok

splixcord commented 11 months ago

For info: the old server recalculates your own score whenever you finish a trail or every one minute

jespertheend commented 11 months ago

I think you might be able to collect the player ids in the if (testFillNode(node)) { statement in updateCapturedArea.js The signature of Arena.updateCapturedArea() would have to be changed a bit to return an object instead of just the new score. Player.updateCapturedArea() can then use the object to both update its own score, and provide this.game with a list of players that need to be updated.

abhishek-exists commented 10 months ago

I think you might be able to collect the player ids in the if (testFillNode(node)) { statement in updateCapturedArea.js The signature of Arena.updateCapturedArea() would have to be changed a bit to return an object instead of just the new score. Player.updateCapturedArea() can then use the object to both update its own score, and provide this.game with a list of players that need to be updated.

I tried this logic, and the only issue I found was that it returned all nearby players whose boundary was adjacent to the current player. So, even if he captures blocks outside the window,. testnode() will return the player ID of those players

image

Code snippet

function testFillNode(coord) {
    if (coord.x < bounds.min.x || coord.y < bounds.min.y) return false;
    if (coord.x >= bounds.max.x || coord.y >= bounds.max.y) return false;

    const alreadyFilled = floodFillMask[coord.x][coord.y];
    // We've already seen this node, so we can skip it.
    if (alreadyFilled) return false;

    // append player Id's
    if (arenaValue !== playerId && arenaValue !== 0 && arenaValue !== -1) {
      capturedPlayers.add(arenaValue);
    }
    return arenaValue != playerId;
  }
jespertheend commented 10 months ago

Hmm that seems fine by me. Although I do wonder why that is the case because judging from the code snippet you sent I'm not really sure why that would happen.

abhishek-exists commented 10 months ago

Its happening because in the updateCapturedArea() method, you have created a padding mask of 1 block around the player's old bound area, and while iterating over the entire captured area, we'll check all nodes, which leads to the addition of this. How can I check the only area that the player has currently captured?

UpdateCaptureArea-File

jespertheend commented 10 months ago

Ah I see, that makes sense. I think the problem here lies in that testFillNode is fired for every tile within the bounds, but not necessarily on all the tiles that will be replaced. I think what you'll want to do is to do is perform the check within the callback of compressTiles at the very end.