rwmt / Multiplayer

Zetrith's Multiplayer mod for RimWorld

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Drawing of selected objects by other players has a couple of issues

SokyranTheDragon opened this issue · comments

Multiplayer selector drawing issues:

  • Doesn't decrease the size when there are multiple things in a single cell (shelves)
  • A Thing that has CustomRectForSelector will only draw the selection on the center, instead of the entire specified rect (like monument marker)
  • A pawn that is not spawned but on the map will not draw a selection (as we're checking Thing.Map instead of Thing.MapHeld against current map)
  • If current map check is done against Thing.MapHeld, it'll display the selection in an incorrect location since we don't provide any special handling for those situations

Solutions:

  • Treat as "works as intended" and leave as-is
    • Will likely be the fastest performance-wise (assuming we implement the changes in 'Additional improvements' section), as it doesn't handle all possible cases and does the least work
  • Extend the code to handle every single special handling situation
    • This will require coming back and extending it every time RimWorld adds special handling for selection drawing
    • It won't be compatible with mods that patch the vanilla methods, so they'd need to receive special patches
  • Call RimWorld's DrawSelectionBracketFor method to let the game handle it, but insert some sort of patch (transpiler) that will apply the color change
    • It will be a future-proof solution, as changes to vanilla method likely won't require changes on our side
    • Compatible with mods that patch the vanilla method (like Vehicle Framework)
  • Use Harmony's reverse patching to (basically) copy DrawSelectionBracketFor into our own method and apply a transpiler
    • It will be a future-proof solution, as changes to vanilla method likely won't require changes on our side
    • It won't be compatible with mods that patch the vanilla methods, so they'd need to receive special patches
  • Instead of doing any patches or re-implementing the method, just call DrawSelectionBracketFor but provide the overrideMat argument (and create a colored Material for each player)
    • It will be a future-proof solution, as changes to vanilla method likely won't require changes on our side
    • Compatible with mods that patch the vanilla method (like Vehicle Framework)
    • This option was likely not used in the past, as (looking at the old source code) the method did not have the overrideMat argument

Additional improvements (assuming still relevant to specific solution):

  • Change the color of MaterialPropertyBlock using the cached result from Shader.PropertyToID("_Color") instead of using the string name
  • Change the color of MaterialPropertyBlock of once per player, instead of once per draw call (4 times per Thing due to 4 corners)

Example implementation (using the last proposed solution, also assuming that the player selection Material is held by PlayerInfo):
https://gist.github.com/SokyranTheDragon/27313d910055be8b7506ecf111768a5f

Additional notes on compatibility with other mods:
Trying to add custom handling for selection drawing (like Vehicle Framework's 8-way rotation) is currently impossible without fully replacing MP's SelectionBoxPatch patch. Using the vanilla method as-is should be compatible by default, using a transpiler on vanilla method/using a reverse patch would require minor patches, while re-implementing the vanilla method (the current approach) would require extracting part of it into a separate method for improved compatibility (to allow easier patches to the MP method).

Due to multiple possible solutions to this, I'm not making a PR just yet. I'll be able to do it once we decide on the solution we want to take, assuming we decide to change how this works. @Zetrith is this something you think we should change? Any specific way you'd like this implemented?

The last solution seems like the least amount of work to make (especially since I've already included it as an example implementation earlier), as well to maintain (as we likely won't have to worry about much) - so if I were to make the choice, I'd pick that specific solution.