Solvedagones Game Server Allocation advanced filtering: player count, state, reallocation

Dependent on #1033

(Not a detailed design ticket, just putting down the basic idea to get the conversation started)

Is your feature request related to a problem? Please describe.
In both session based games and persistent games, it would be useful to be able to do something akin to:
Just give me a GameServer that has room for 2 (or n number) players, regardless whether it is Allocated or not

Which would pass back a GameServer if it had capacity available, and if not, would Allocate a whole new one (with enough initial capacity), and return that instead.

This would be useful for:

  • Automating matchmaking backfill operations
  • matchmaking players to persistent worlds that have capacities (#1034 helps here too)

Describe the solution you'd like

Some kind of adjustment to GameServerAllocation that accounts for capacity of players that are available. Maybe a way to choose what State(s) are in the Allocation pool? (Ready or Allocated??)

This probably requires much thought, and would want to tie into #1197 so they don't conflict with each other.

Describe alternatives you've considered
Having a totally different Allocation path for player capacity based allocations -- but then we will likely end up with a huge number of paths for different types of allocations.,

Additional context
Can't think of anything else.

22 Answers

✔️Accepted Answer

Objective

Already defined above

Background

These are terms that are currently used in Player Tracking:

  • Player Capacity: Max number of players that could end up in a GameServer
  • Player Count: The number of players that are in a GameServer currently
  • Player Availability: Capacity - Count. (this is new for this ticket)

Requirements and Scale

  • Is a high throughput operation, so will need to have an implementation that allows for this.
  • Will need similar scaling characteristics to current Allocation policy.
  • Will sit behind a feature flag of “PlayerAvailableAllocation”
  • Will still need to adhere to Packing and Distributed optimisation patterns
  • Will still need to be filterable on required and preferred match labels/expressions

Design Ideas

We extend the required and preffered sections of GameServer Allocation to allow for player availability and game
server state filtering (Credit), as well as allow allocation to "re-allocate" an already Allocated GameServer.

This should be extensible to other types of allocation strategies down the line, as well as having applicability
outside of only player tracking re-allocation. This approach also doesn’t require a breaking change to the existing
allocation implementation.

For example, the current way of allocating against Ready GameServers (which would be default, and therefore backward compatible) would become:

apiVersion: "allocation.agones.dev/v1"
kind: GameServerAllocation
spec:
  required:
    matchLabels:
      agones.dev/fleet: simple-udp
  gameServerState: Ready # Allocate out of the Ready Pool (which would be default, so backward compatible)

Wherein:

  • gameServerState - is the state of the GameServers to search, limited to Ready and Allocated.
    By default this would Ready, which is the same as the current implementation.

Therefore, to attempt to find a GameServer that has room for between 2 and 10 players, that is already Allocated, and if
not found, to then find a Ready one that has the same amount or more of capacity, and move it to Allocated, this would look like the following:

apiVersion: "allocation.agones.dev/v1"
kind: GameServerAllocation
spec:
  preferred:
    - matchLabels:
        agones.dev/fleet: simple-udp
      gameServerState: Allocated # new state filter: allocate from Allocated servers
      players: # new player availability filter
          minAvailable: 2
          maxAvailable: 10
  required:
    matchLabels:
      agones.dev/fleet: simple-udp
      players: # new player availability filter
          minAvailable: 2
          maxAvailable: 10
    gameServerState: Ready # Allocate out of the Ready Pool (which would be default, so backward compatible)

Wherein:

  • players.minAvailable - is the minimum number of players to match against (default: 0)
  • players.maxAvailable - is the maximum number of players to match against (default: max(int))

This works since the preferred section would currently Allocated GameServers first, and if it failed to match, then search then would move onto the required section.

This would also need to eventually be expanded to the gRPC Allocation Service API, but the same format could be reused.

Removing GameServers from the pool on re-allocation

One concern with this design is that you could continually get the same GameServer over and over again on re-allocation, which could send way more players to a particular GameServer than may be desired.

To solve that problem, we can use already existing Agones alloction constructs to solve this: matchLabel selectors
and also being able to set annotations and labels on a GameServer at allocation time.

For example, we can extend the example above and also add a user defined label agones.dev/sdk-available to our
GameServers that indicates that there are slots available for a player to fill.

apiVersion: "allocation.agones.dev/v1"
kind: GameServerAllocation
spec:
  preferred:
    - matchLabels:
        agones.dev/fleet: simple-udp
        agones.dev/sdk-available: "true" # this is important
      gameServerState: Allocated # new state filter: allocate from Allocated servers
      players: # new player availability filter
          minAvailable: 2
          maxAvailable: 10
  required:
    matchLabels:
      agones.dev/fleet: simple-udp
    gameServerState: Ready # Allocate out of the Ready Pool (which would be default, so backward compatible)
  metadata:
    annotations:
      waitForPlayers: "2" # user defined data to pass to the game server so it know when to switch back the agones.dev/sdk-available label
    labels:
      agones.dev/sdk-available: "false" # this removes it from the pool

Upon allocation the value of agones.dev/sdk-available is set to false, thereby taking it out of the preferred
re-allocation pool. From the annotation data we're passing through (in this case, telling the game server binary to
potentially wait for 2 players to connect), the game server binary can use the SDK.SetLabel(...)

This strategy will need to be documented, but also have applicability outside of only allocating by player count
-- for example, it could also be used where GameServer containers host multiple instances of a GameSession.

It also allows users to utilise their own labelling names and systems that make sense for their game.

The downside here being that the onus is on the user to pass the required information down to the GameServer to know when to add the GameServer back into the pool. Long term, we could look at doing some of this automatically, but it would be best to get user feedback first on this initial implementation before going down that path.

Technical Implementation

  • Much like we keep a ready cache, we should also keep a cache of Allocated game servers that have a player availability greater than 0. This may be able to be pre-sorted based on packing rules. This should be the first place that is searched for Allocations that match the label selectors.
  • If we cannot find a previously Allocated GameServer that matches the criteria required, then we fall back to searching for a Ready GameServer - but with the additional requirement of making sure the players available of the Ready GameServer is greater than or equal to that which is requested.
  • This is likely going to require some refactoring of the ListenAndAllocate function, as it is currently optimised for only the Ready policy.
  • When allocating a GameServer, whether Ready or Allocated, an annotation of agones.dev/last-allocated with a
    timestamp of that moment will be applied. This has two pieces of functionality: (a) so that SDK.WatchGameServer() (or
    any listener to events) can see when a GameServer is re-allocated (b) we can take advantage of CRD generational
    locking so that when re -allocating we know the resource is up to date, and is still available to be re-allocated.

Alternatives Considered

New Allocation Pathway

We could implement a whole new Allocation pathway (which we discussed earlier), which seems untenable.

Allocation "policy"

Previous design used an allocation policy to switch out strategies. That was deemed too inflexible when compared to
this current design.

Related Issues:

11
agones Game Server Allocation advanced filtering: player count, state, reallocation
Objective Already defined above Background These are terms that are currently used in Player Trackin...
53
pygame Pygame not compatible with MacOS Mojave
Same issue here running python -m pygame.examples.aliens opens a window sounds and music can be hear...
37
godot Expose load/import methods for use with file from user directory
What you are trying to import isn't a resource that godot recognizes Godot version: 3.0.2 Issue desc...
34
godot ViewportTexture: Path to node is invalid
Looks like @kaadmy is correct This works without errors: The TectureRect is using the Viewport as Vi...
28
godot [TRACKER] Methods, properties and signals to consider for renaming in next planned compatibility breakage
Too tedious for me but Godspeed to whoever fixes instance as instantiate where used as a verb. ...
28
godot LanguageServer only works with VSCode
I just tested your new changes and it seems to be working great Godot version: Godot Engine v3.2.bet...
25
godot some kind of try finally (or except) block for gdscript
@salvob41 in this case you can use this: @Kotzuo this does not always work since it is not determini...
25
godot Custom-made resource types cannot be used in export statement
Games which are data-heavy (such as RPGs) would benefit immensely from better support for user-defin...
22
allegro5 Android build fails due to deprecated 'android' command
I have searched and found no replacement for the android update project command ...
21
godot Annotations in GDScript
why is gdscript's syntax being modified so heavily? it was originally designed to be simple easy to ...
20
godot Best way to avoid some warnings?
it's best to disable warnings and just code your game your code will be fine believe me 🥇 a develop...
19
godot docs Proposal: redesigning the docs for Godot 4
I'm on board :) My comments/thoughts as I come to them: Focus on documentation * Move tutorials out ...
19
godot match pattern and using _ as a wildcard
Given that there are a few nearly equally good ideas (IMO) I guess we might use some voting. ...
18
Entitas CSharp Roslyn based code generator
Wooooot! Just generated the very first time! The current code generator relies on reflection which m...
15
godot Allow AnimationPlayer to apply all its animations to multiple Nodes
I managed to make a composite sprite animation with ease Godot version: 3.0.6 3.0.7 3.1.alpha.calino...
14
godot Removing a resource from a scene makes all nodes using resources to appear in the TSCN diff
I'm currently having this problem with a team This combined with #22324 makes it impossible to merge...
14
godot Add a way to add categories to the script variables section from GDScript
As a workaround and as the inspector respects the orders of my exported variables to categorize them...
14
godot Source code documentation
I disagree with @reduz on this one Godot's comments documentation is very lacking ...
14
raylib raylib 2.6 roadmap
[rlvk] It's been long time I want to dig into Vulkan backend but the truth is that I can't find the ...
12
godot Cannot import any resource from any folder other than res://
I know this is totally off topic from this issue and I promise this is the last off-topic post I'll ...
11
godot docs 3D FPS tutorial mess
Joining after the battle and I see that all is well in the end and many good points were raised so t...
11
godot Using Viewport Texture causes "node not found" error
Just discovered that if the Viewport node is moved above the nodes that use its texture then the iss...
11
godot add dynamic linker support
I'll revive this thread with a proposal Let me know what you guys think about it ...
11
godot Add a function to find out if an instance has been freed
Can we re-open as an enhancement? This is a useful feature to have and the following code: is much m...
11
godot Add Array.last()
Note that we support array[-1] syntax just fine so this might be useless nowdays. ...
11
godot Random Number Generation class
What I'm really missing is this: var myRandom = Random.new() Yes I find Godot's random number genera...
11
godot Animations in TileMap
This will be possible in 3.1 with the new AnimatedTexture (coming soon). Part of what was mentioned ...
11
godot Cross compiling windows with ubuntu fails on etc2comp build
I found the trouble: by default mingw on ubuntu works in win32 mode (which doesn't support thread) i...
8
godot Preserve position and size of godot's editor window between sessions.
@vnen found another cool workaround like from GDScript arranges editor window exacly as i want on ev...
7
godot Idea: a method to force a condition to trigger only once
I disagree that a feature like that makes code more readable Imho it makes the code literally unread...
6
bullet3 Failed to create an OpenGL context when trying to launch a pybullet example
I am facing a similar issue and running on laptop and rebooting did not fix it for me I guess my gra...
6
godot World_vertex_coords flag required in canvas_item shaders
@clayjohn Thanks as well for the work-around! A bit of a pity that this has been dropped from 3.2 ...
6
godot Abnormal texture on Android
It seems the problem is that despite the specification saying OpenGL ES 3.0 supports fully non power...
6
pygame Building error with macOS Big Sur (11.0.1)
Also can't install on MacBook Pro M1 with Python 3.9.1 Environment: OS : macOS Big Sur 11.0.1 Build ...
6
entt Call for comments: signals on component creation/destruction
I'm trying to understand why a singleton disguised as something else should be so tempting ...
5
godot Support writing editor plugin in C#
Looks like the docs just haven't been updated yet but I figured it out Will note down for others if ...
5
godot GLES2 Batching + CPUParticles2D texture + Label = Rendering issue on iOS
Just a note that this bug has an experimental fix available in the latest 3.2.2 beta Would appreciat...
5
godot Input events are occasionally skipped (regression from input handling changes in 3.3)
bisect from 3.2.3-stable to 3.3-stable This is the commit which introduces the problem: f725d9c To c...
5
entt Serialisation Question
With everything I need for the test working here's the breakdown on the issue with code to show the ...
4
godot Replace Collision Layer/Masks with Collision Groups
Being dependent on string values to much is in my opinion is a bad idea The current way of managing ...
4
phaser Exteneded GameObject (Sprite) not fire update method, but preUpdate
Doing this.scene.on('update' this.update) for now Thank you for the reference @samme ! @kalebwalton ...
3
bullet3 Loading colors for meshes from OBJ files in URDFs fails
If you run sdf2obj over those obj files it will convert the mtl colors into the SDF materials automa...
3
godot App terminate on iOS 11 when enter to background
TEMPORARY FIX The solution in this forum post actually works for Godot as well Operating system or d...
3
godot Cannot use a ViewportTexture as PanoramaSky texture
Replace the following line: godot/drivers/gles3/rasterizer_scene_gles3.cpp Line 2365 in 3a5b25d glBi...
3
godot RichText: get_visible_line_count() returns wrong value
Did you tried waiting one idle frame before calling it? A few days ago I had a similar issue and fix...
3
godot Mono/Linux 64-bit project is 101.3MB with kbs of assets
Your executable is likely a debug build A stripped release build should be smaller than that (~35 MB...
3
godot Vulkan: Godot crashes on startup with AMD graphics driver on Linux
Nice! I'll close this as I'm fairly sure most reports here were about that same issue triggered by o...
3
godot Godot 4.0.dev editor behaves weird while using i3wm (and maybe other tilling wm's)
I did some research using i3 a while ago here's what i got from that The main issue seems related to...
3
godot transform snap yields 1px offset below and to the right of kinematicbody2d for pixel platformer
I slightly modified your project to use a single centred sprite to eliminate other sources of error:...
3
entt Please use find_package & ExternalProject for GTest
@m-waka I encountered the same error a while ago It's a GCC bug that affects just the 8.1.0 version ...