In this blog from Firebase: https://firebase.blog/posts/2020/01/google-loteria-realtime-database they are talking about matchmaking.
This blog includes:
"When a player selects “Random Match,” their player ID is written to the location /queue/. A Cloud Function is set up to trigger when a new entry is created, and it checks whether we have enough players to start a game. If so, it creates the game at /games/{gameId}, and writes the gameId to each player's entry, like so: /players/{playerId}/gameId = {gameId}
Players listen to gameId on their own database entries, so they know when to transition to the gameplay screen.
Since there are a lot of players connecting simultaneously, and the Cloud Function is asynchronous, we once again used a transaction to ensure that players are removed from the queue and placed into games atomically. Making one game at a time atomically could create a bottleneck, so instead we create as many games as possible in one transaction."
How do I check there are enough players to start a game and how to atomically create as many games as possible in one transaction?
Thank you
I use the same structure with queue, games and players.
Related
Lets say, for starters, i have a game. And in that game, I add a few places. If i were to create a datastore in the main GAME, would that transfer to all of the places automatically as well?
Yes, all subsidiary places created under the same game share datastores of the main game. If you want to send specific data to a certain place, use https://developer.roblox.com/en-us/api-reference/function/TeleportService/GetLocalPlayerTeleportData.
Keep in mind that data sent along with teleports is local and can be manipulated by the client.
For example, I would have a main lobby in my Roblox game. Then, a player gets sent into another game and collects coins. When they come back to the lobby after they get a certain amount of coins, I want it to save their all time coins.
I would share code, but I have absolutely no idea how to do this.
Roblox "Games" can hold multiple "Places". Up to 20, I believe, including the "Starting Place". The neat thing about this is that datastores are saved across the entire game. As a result, if you save someone's data in place1, then they move to place2, their data will carry over.
To learn more about Games vs. Places, you can visit the developer API documentation.
EDIT: Alternatively, if you want data to save across multiple games, you would have to look into HTTPService, and off-roblox datastores.
Let's say I have a turn based match with two players. At some point player 1 recognizes that he is about to lose the game. When it is Player 1's turn, he uses Game Center App to do a swipe to remove the match.
Issues:
A. Take turn timer never expires on Player 1. So the match's turn will not switch to Player 2 when the time expired.
B. The game also offers a view only mode so players can view the game progress while he is out of turn. But since no status was updated to indicate that Player 1 had removed the match manually. App can offers no resolution. Also, you can only end match while it is your turn.
Ideally, I want to declare Player 2 as a winner and end the match.
How do you handle in this situation?
I finally found a workaround for this.
If you delete a match, then call GKTurnBasedMatch:loadMatchesWithCompletionHandler, the deleted match doesn't appear (as expected). However, it turns out that you can still re-download the deleted match using GKTurnBasedMatch:LoadMatchWithID, if you happen to still have the deleted match's ID.
I think we can reasonably assume that The Cheater is going to play the game again; otherwise, why would they care about incurring a loss? Therefore, I implemented the following:
Maintain a table locally, on the device, of matches.
On startup, pull the list of local player's matches from Game Center and compare against my local list.
When The Cheater recognizes the situation and deletes the match using the Game Center interface, the match is removed from Game Center, but not from my local DB. When The Cheater starts my game again, I see that they have more matches locally than on Game Center.
I then call either participantQuitInTurnWithOutcome or participantQuitOutOfTurnWithOutcome, as appropriate, with an outcome of GKTurnBasedMatchOutcomeLost.
This passes the turn to the next player and records a loss for The Cheater. It won't work if the cheater never plays the game again, though. (But, if they're not playing, they're not wrecking any more matches, so the chaos is contained)
I am trying to develop a computer game. I want this game to be multiplayer playable. The game is an arcade space shooter
I plan to run the game at server level and then send updates at the clients. The problem that I am facing is object creation. Let's say if a player shots, the shots themselves are new objects. These will need to be created.
In my game I have a hierarchical structure and the shots themselves will be part of this structure. It will be something like a tree. The problem that I have is identifying objects on the clients and server.
How can I make sure that when the client receives some update then it will update the right objects?
What about new object creation. In my case the scene graph is traversed and each object is updated once it gets updates from the server. But updates which creates new object violates this principle. How should I handle them?
Also, I can't really get updates for the entire scene. I would only need to update specific objects that are visible to the player. What should I do with the rest of the objects that aren't visible? What will happen when they become visible? How can I track when objects become visible to a player?
How can I make sure that when the client receives some update then it
will update the right objects?
You can give an unique id to each object server creates. You might want to create a super Object class containing id and let all other game object classes inherit from it. Or, you can have a map to link between id and object. Or, you can mix them. To get an unique id, server can have a global 'nextID' as int and simply assign to a new object and increase it for next one.
But updates which creates new object violates this principle.
I don't really understand the principle you are talking about but if you are worried about editing your scene graph (or game object list) while traversing it, you can put the newly created objects into another list and just insert the new ones after traversing is done. They will start getting updated from next update. (You should consider how you will remove an object too)
What should I do with the rest of the objects that aren't visible?
What will happen when they become visible?
Well, you are the one who should figure it out because it really depends on your game system. My suggestion is that try to skip their updates and see what problems appear and fix them.
How can I track when objects become visible to a player?
Also, several ways to handle this. Server can detect everything for clients and send only visible object info for each client. Or, each client can detect them and send a request to server for starting to update visible ones. Or, it could be mixed way.
Try server-driven one first and see if server can perform it with maximum number of clients.To use client-driven one, remember each client still needs to update all object location regardless of their visibility but send a request for AI updates for only visible ones.
Again, there are many ways to handle this kind of problems and it really depends on your game system requirements. That's why it's hard to answer your question without knowing your game system well enough. Try to investigate how other similar multiplayer games are designed from some books or google. Good luck!
(Disclosure: I'm very new to Rails)
I am trying to make a RISK-style board-game in Rails, though this question may apply for any MVC-style framework.
I have players and games. Players can join games until the game is full. Trying to join a full game (or the same game twice) signals an error, yada yada.
Below are three pieces of game logic that I am unsure where to place, or at least where they are typically placed.
If a game is full, it should start and do things related to that (ie, messaging all players that the game has begun, randomly disperse armies across the map).
When a player executes moves during his turn it seems reasonable to have that logic in the controller. What about when his turn ends and it is time to message the next player? Would that code go in the same controller as
Suppose that a player forfeits his turn if he does not finish it within 24 hours. I'd need to periodically look at all the games in my app and see if a player started a turn more than 24 hours ago. Where would this logic go?
My question is: Where does logic for items like the above go in a Rails/MVC app?
In one sense I could stuff all of it except 3. into the controllers for the last-done-action. For instance I could place the logic for 1. in the player-joins-game controller method (check if the game is full after every player join, if it is, commence 1. related logic). This seems like it might be the wrong place, but maybe that's how it is typically done.
Rails' convention is "fat model, thin controller". so I would suggest that the state of the game should be held by the Game model.
You webapp consists of zero or more games, and each game consists of 1 or more players.
The state of "full", or the state of "game begun" are properties of the game, and should be held by that model.
So for 1) When the final player joins (or perhaps, all current players vote to start the game), the game state (a property of Game) would be set to "begun", the property that holds the currently active player would be set, and a delayed job would be queued to message all the players.
For 2, the game has a "execute move" method in the Game controller that would check that the player executing the move is the current player, then it would execute the move against the Game model. The Game model internally would know if the move is valid, what the result is, and what the next step(s) would be. It would, again, use something like a delayed job to message the next player.
For #3, again, a delayed job could be set to execute the timeout. I'm not 100% on how to schedule delayed jobs, or if there's another gem/plugin that would work better. But, the job would call a method on the Game controller to check the status of the game at the required time. If the player has not moved, then execute your forfit logic, which would, again, be a method in the Game model.
The state of each player could be held in the Player model, or in the Game model, I suppose, depending on the game, and how much interaction between Player models there might be.
In the case of a risk game, I would think the player model would be rather thin, as the state of the board is more about which player owns a country, and how many armies they have there - that's more a state of the game, then a state of each individual player. I would expect the Player model in a risk game to be more oriented towards metadata about the actual player - username, wins/losses, skill level, etc.
In a game like Supremacy, where the player has resources, nukes, etc., then there's more data to store in the Player model.