mirror of
https://github.com/magefree/mage.git
synced 2025-12-25 13:02:06 -08:00
[WIP] Consumable JSON game logs
As discussed in https://github.com/magefree/mage/issues/4515 This exposes a JSON log of game interactions that can be analyzed. This is just a first pass, to get up to speed with how the messaging works. It'd like to trim down the messages much further so they don't include redundant information in each message. Also gson supports much more advances serialization options; such as using the @Expose annotation. We should probably use that, but I ran into some issues (I'm not a java developer, so still learning). TODO: These currently only exist on the client side; ideally we'd submit this logs back up to a central server after the games completion; thinking this could be simple via an S3 file drop, and a Lambda function to process and expose the logs; maybe via a kafka stream. Examples of log messages are below: ``` { "gameId": "2cede8c5-ff8e-4f8c-b9ac-66af53c0a254", "sessionId": "5c4o149-678483-je42ycva-1-je42ycw2-4", "type": "GAME_SELECT", "value": { "gameView": { "priorityTime": 3000, "players": [ { "name": "computer", "life": 20, "counters": {} }, { "name": "hooptie", "life": 20, "counters": {} } ], "hand": { "425d774f-ee0c-4a9b-8516-c98f886943f0": { "name": "Springleaf Drum", "power": "0", "toughness": "0", "loyalty": "", "manaCost": [ "{1}" ], "convertedManaCost": 1, "type": 0, "paid": false, "id": "425d774f-ee0c-4a9b-8516-c98f886943f0" }, "dd41bb4b-7fc3-4a3c-a69c-d18e281a1bff": { "name": "Blade of the Bloodchief", "power": "0", "toughness": "0", "loyalty": "", "manaCost": [ "{1}" ], "convertedManaCost": 1, "type": 0, "paid": false, "id": "dd41bb4b-7fc3-4a3c-a69c-d18e281a1bff" }, "06eb0a6c-1e70-4dc0-bd1c-93b6ea444806": { "name": "Ornithopter", "power": "0", "toughness": "2", "loyalty": "", "manaCost": [ "{0}" ], "convertedManaCost": 0, "type": 0, "paid": false, "id": "06eb0a6c-1e70-4dc0-bd1c-93b6ea444806" }, "a2f9cc13-e71a-4c9c-96aa-5424ea1a6b64": { "name": "Springleaf Drum", "power": "0", "toughness": "0", "loyalty": "", "manaCost": [ "{1}" ], "convertedManaCost": 1, "type": 0, "paid": false, "id": "a2f9cc13-e71a-4c9c-96aa-5424ea1a6b64" }, "91239f4f-9003-4c48-8ca1-4c318f892489": { "name": "Cranial Plating", "power": "0", "toughness": "0", "loyalty": "", "manaCost": [ "{2}" ], "convertedManaCost": 2, "type": 0, "paid": false, "id": "91239f4f-9003-4c48-8ca1-4c318f892489" }, "feb268d8-0535-4a9c-8915-83dd92a08c4c": { "name": "Arcbound Ravager", "power": "0", "toughness": "0", "loyalty": "", "manaCost": [ "{2}" ], "convertedManaCost": 2, "type": 0, "paid": false, "id": "feb268d8-0535-4a9c-8915-83dd92a08c4c" } }, "canPlayInHand": [ "06eb0a6c-1e70-4dc0-bd1c-93b6ea444806" ], "stack": {}, "combat": [], "phase": "PRECOMBAT_MAIN", "step": "PRECOMBAT_MAIN" }, "message": "Play spells and abilities.", "options": { "queryType": "SELECT" } } } { "gameId": "2cede8c5-ff8e-4f8c-b9ac-66af53c0a254", "sessionId": "5c4o149-678483-je42ycva-1-je42ycw2-4", "type": "SEND_PLAYER_UUID", "value": "06eb0a6c-1e70-4dc0-bd1c-93b6ea444806" } { "gameId": "2cede8c5-ff8e-4f8c-b9ac-66af53c0a254", "sessionId": "5c4o149-678483-je42ycva-1-je42ycw2-4", "type": "GAME_CHOOSE_PILE", "value": { "choices": { "1ecf8671-be4c-4060-a76b-af614235a5b7": "Cast Ornithopter" } } } { "gameId": "2cede8c5-ff8e-4f8c-b9ac-66af53c0a254", "sessionId": "5c4o149-3v2cj2-je43178o-1-je43179f-4", "type": "GAME_INIT", "value": { "priorityTime": 3000, "players": [ { "name": "computer", "life": 20, "counters": {} }, { "name": "hooptie", "life": 20, "counters": {} } ], "hand": { "425d774f-ee0c-4a9b-8516-c98f886943f0": { "name": "Springleaf Drum", "power": "0", "toughness": "0", "loyalty": "", "manaCost": [ "{1}" ], "convertedManaCost": 1, "type": 0, "paid": false, "id": "425d774f-ee0c-4a9b-8516-c98f886943f0" }, "dd41bb4b-7fc3-4a3c-a69c-d18e281a1bff": { "name": "Blade of the Bloodchief", "power": "0", "toughness": "0", "loyalty": "", "manaCost": [ "{1}" ], "convertedManaCost": 1, "type": 0, "paid": false, "id": "dd41bb4b-7fc3-4a3c-a69c-d18e281a1bff" }, "06eb0a6c-1e70-4dc0-bd1c-93b6ea444806": { "name": "Ornithopter", "power": "0", "toughness": "2", "loyalty": "", "manaCost": [ "{0}" ], "convertedManaCost": 0, "type": 0, "paid": false, "id": "06eb0a6c-1e70-4dc0-bd1c-93b6ea444806" }, "a2f9cc13-e71a-4c9c-96aa-5424ea1a6b64": { "name": "Springleaf Drum", "power": "0", "toughness": "0", "loyalty": "", "manaCost": [ "{1}" ], "convertedManaCost": 1, "type": 0, "paid": false, "id": "a2f9cc13-e71a-4c9c-96aa-5424ea1a6b64" }, "91239f4f-9003-4c48-8ca1-4c318f892489": { "name": "Cranial Plating", "power": "0", "toughness": "0", "loyalty": "", "manaCost": [ "{2}" ], "convertedManaCost": 2, "type": 0, "paid": false, "id": "91239f4f-9003-4c48-8ca1-4c318f892489" }, "feb268d8-0535-4a9c-8915-83dd92a08c4c": { "name": "Arcbound Ravager", "power": "0", "toughness": "0", "loyalty": "", "manaCost": [ "{2}" ], "convertedManaCost": 2, "type": 0, "paid": false, "id": "feb268d8-0535-4a9c-8915-83dd92a08c4c" } }, "canPlayInHand": [ "06eb0a6c-1e70-4dc0-bd1c-93b6ea444806" ], "stack": {}, "combat": [], "phase": "PRECOMBAT_MAIN", "step": "PRECOMBAT_MAIN" } } { "gameId": "2cede8c5-ff8e-4f8c-b9ac-66af53c0a254", "sessionId": "5c4o149-3v2cj2-je43178o-1-je43179f-4", "type": "GAME_SELECT", "value": { "gameView": { "priorityTime": 3000, "players": [ { "name": "computer", "life": 20, "counters": {} }, { "name": "hooptie", "life": 20, "counters": {} } ], "hand": { "425d774f-ee0c-4a9b-8516-c98f886943f0": { "name": "Springleaf Drum", "power": "0", "toughness": "0", "loyalty": "", "manaCost": [ "{1}" ], "convertedManaCost": 1, "type": 0, "paid": false, "id": "425d774f-ee0c-4a9b-8516-c98f886943f0" }, "dd41bb4b-7fc3-4a3c-a69c-d18e281a1bff": { "name": "Blade of the Bloodchief", "power": "0", "toughness": "0", "loyalty": "", "manaCost": [ "{1}" ], "convertedManaCost": 1, "type": 0, "paid": false, "id": "dd41bb4b-7fc3-4a3c-a69c-d18e281a1bff" }, "06eb0a6c-1e70-4dc0-bd1c-93b6ea444806": { "name": "Ornithopter", "power": "0", "toughness": "2", "loyalty": "", "manaCost": [ "{0}" ], "convertedManaCost": 0, "type": 0, "paid": false, "id": "06eb0a6c-1e70-4dc0-bd1c-93b6ea444806" }, "a2f9cc13-e71a-4c9c-96aa-5424ea1a6b64": { "name": "Springleaf Drum", "power": "0", "toughness": "0", "loyalty": "", "manaCost": [ "{1}" ], "convertedManaCost": 1, "type": 0, "paid": false, "id": "a2f9cc13-e71a-4c9c-96aa-5424ea1a6b64" }, "91239f4f-9003-4c48-8ca1-4c318f892489": { "name": "Cranial Plating", "power": "0", "toughness": "0", "loyalty": "", "manaCost": [ "{2}" ], "convertedManaCost": 2, "type": 0, "paid": false, "id": "91239f4f-9003-4c48-8ca1-4c318f892489" }, "feb268d8-0535-4a9c-8915-83dd92a08c4c": { "name": "Arcbound Ravager", "power": "0", "toughness": "0", "loyalty": "", "manaCost": [ "{2}" ], "convertedManaCost": 2, "type": 0, "paid": false, "id": "feb268d8-0535-4a9c-8915-83dd92a08c4c" } }, "canPlayInHand": [ "06eb0a6c-1e70-4dc0-bd1c-93b6ea444806" ], "stack": {}, "combat": [], "phase": "PRECOMBAT_MAIN", "step": "PRECOMBAT_MAIN" }, "message": "Play spells and abilities.", "options": { "queryType": "SELECT" } } } { "gameId": "2cede8c5-ff8e-4f8c-b9ac-66af53c0a254", "sessionId": "5c4o149-678483-je42ycva-1-je42ycw2-4", "type": "SEND_PLAYER_UUID", "value": "1ecf8671-be4c-4060-a76b-af614235a5b7" } ```
This commit is contained in:
parent
871b035bb4
commit
6aeb3c7c3a
7 changed files with 239 additions and 5 deletions
|
|
@ -31,6 +31,9 @@ import java.awt.event.KeyEvent;
|
|||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import javax.swing.*;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import mage.cards.decks.Deck;
|
||||
import mage.client.MageFrame;
|
||||
import mage.client.SessionHandler;
|
||||
|
|
@ -47,6 +50,9 @@ import mage.client.util.audio.AudioManager;
|
|||
import mage.client.util.object.SaveObjectUtil;
|
||||
import mage.interfaces.callback.CallbackClient;
|
||||
import mage.interfaces.callback.ClientCallback;
|
||||
import mage.remote.ActionData;
|
||||
import mage.remote.Session;
|
||||
import mage.remote.SessionImpl;
|
||||
import mage.utils.CompressUtil;
|
||||
import mage.view.*;
|
||||
import mage.view.ChatMessage.MessageType;
|
||||
|
|
@ -102,7 +108,6 @@ public class CallbackClientImpl implements CallbackClient {
|
|||
break;
|
||||
case CHATMESSAGE: {
|
||||
ChatMessage message = (ChatMessage) callback.getData();
|
||||
|
||||
// Drop messages from ignored users
|
||||
if (message.getUsername() != null && IgnoreList.IGNORED_MESSAGE_TYPES.contains(message.getMessageType())) {
|
||||
final String serverAddress = SessionHandler.getSession().getServerHostname().orElseGet(() -> "");
|
||||
|
|
@ -183,6 +188,7 @@ public class CallbackClientImpl implements CallbackClient {
|
|||
case GAME_INIT: {
|
||||
GamePanel panel = MageFrame.getGame(callback.getObjectId());
|
||||
if (panel != null) {
|
||||
appendJsonEvent("GAME_INIT", callback.getObjectId(), (GameView) callback.getData());
|
||||
panel.init((GameView) callback.getData());
|
||||
}
|
||||
break;
|
||||
|
|
@ -190,6 +196,7 @@ public class CallbackClientImpl implements CallbackClient {
|
|||
case GAME_OVER: {
|
||||
GamePanel panel = MageFrame.getGame(callback.getObjectId());
|
||||
if (panel != null) {
|
||||
appendJsonEvent("GAME_OVER", callback.getObjectId(), callback.getData());
|
||||
panel.endMessage((String) callback.getData(), callback.getMessageId());
|
||||
}
|
||||
break;
|
||||
|
|
@ -201,6 +208,7 @@ public class CallbackClientImpl implements CallbackClient {
|
|||
GameClientMessage message = (GameClientMessage) callback.getData();
|
||||
GamePanel panel = MageFrame.getGame(callback.getObjectId());
|
||||
if (panel != null) {
|
||||
appendJsonEvent("GAME_ASK", callback.getObjectId(), message);
|
||||
panel.ask(message.getMessage(), message.getGameView(), callback.getMessageId(), message.getOptions());
|
||||
}
|
||||
break;
|
||||
|
|
@ -208,8 +216,10 @@ public class CallbackClientImpl implements CallbackClient {
|
|||
case GAME_TARGET: // e.g. Pick triggered ability
|
||||
{
|
||||
GameClientMessage message = (GameClientMessage) callback.getData();
|
||||
|
||||
GamePanel panel = MageFrame.getGame(callback.getObjectId());
|
||||
if (panel != null) {
|
||||
appendJsonEvent("GAME_TARGET", callback.getObjectId(), message);
|
||||
panel.pickTarget(message.getMessage(), message.getCardsView(), message.getGameView(),
|
||||
message.getTargets(), message.isFlag(), message.getOptions(), callback.getMessageId());
|
||||
}
|
||||
|
|
@ -217,8 +227,10 @@ public class CallbackClientImpl implements CallbackClient {
|
|||
}
|
||||
case GAME_SELECT: {
|
||||
GameClientMessage message = (GameClientMessage) callback.getData();
|
||||
|
||||
GamePanel panel = MageFrame.getGame(callback.getObjectId());
|
||||
if (panel != null) {
|
||||
appendJsonEvent("GAME_SELECT", callback.getObjectId(), message);
|
||||
panel.select(message.getMessage(), message.getGameView(), callback.getMessageId(), message.getOptions());
|
||||
}
|
||||
break;
|
||||
|
|
@ -226,6 +238,7 @@ public class CallbackClientImpl implements CallbackClient {
|
|||
case GAME_CHOOSE_ABILITY: {
|
||||
GamePanel panel = MageFrame.getGame(callback.getObjectId());
|
||||
if (panel != null) {
|
||||
appendJsonEvent("GAME_CHOOSE_PILE", callback.getObjectId(), callback.getData());
|
||||
panel.pickAbility((AbilityPickerView) callback.getData());
|
||||
}
|
||||
break;
|
||||
|
|
@ -234,15 +247,18 @@ public class CallbackClientImpl implements CallbackClient {
|
|||
GameClientMessage message = (GameClientMessage) callback.getData();
|
||||
GamePanel panel = MageFrame.getGame(callback.getObjectId());
|
||||
if (panel != null) {
|
||||
appendJsonEvent("GAME_CHOOSE_PILE", callback.getObjectId(), message);
|
||||
panel.pickPile(message.getMessage(), message.getPile1(), message.getPile2());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GAME_CHOOSE_CHOICE: {
|
||||
GameClientMessage message = (GameClientMessage) callback.getData();
|
||||
|
||||
GamePanel panel = MageFrame.getGame(callback.getObjectId());
|
||||
|
||||
if (panel != null) {
|
||||
appendJsonEvent("GAME_CHOOSE_CHOICE", callback.getObjectId(), message);
|
||||
panel.getChoice(message.getChoice(), callback.getObjectId());
|
||||
}
|
||||
break;
|
||||
|
|
@ -251,34 +267,44 @@ public class CallbackClientImpl implements CallbackClient {
|
|||
GameClientMessage message = (GameClientMessage) callback.getData();
|
||||
GamePanel panel = MageFrame.getGame(callback.getObjectId());
|
||||
if (panel != null) {
|
||||
appendJsonEvent("GAME_PLAY_MANA", callback.getObjectId(), message);
|
||||
panel.playMana(message.getMessage(), message.getGameView(), message.getOptions(), callback.getMessageId());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GAME_PLAY_XMANA: {
|
||||
GameClientMessage message = (GameClientMessage) callback.getData();
|
||||
|
||||
GamePanel panel = MageFrame.getGame(callback.getObjectId());
|
||||
if (panel != null) {
|
||||
appendJsonEvent("GAME_PLAY_XMANA", callback.getObjectId(), message);
|
||||
panel.playXMana(message.getMessage(), message.getGameView(), callback.getMessageId());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GAME_GET_AMOUNT: {
|
||||
GameClientMessage message = (GameClientMessage) callback.getData();
|
||||
|
||||
GamePanel panel = MageFrame.getGame(callback.getObjectId());
|
||||
if (panel != null) {
|
||||
appendJsonEvent("GAME_GET_AMOUNT", callback.getObjectId(), message);
|
||||
|
||||
panel.getAmount(message.getMin(), message.getMax(), message.getMessage());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GAME_UPDATE: {
|
||||
GamePanel panel = MageFrame.getGame(callback.getObjectId());
|
||||
|
||||
if (panel != null) {
|
||||
appendJsonEvent("GAME_UPDATE", callback.getObjectId(), callback.getData());
|
||||
|
||||
panel.updateGame((GameView) callback.getData());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case END_GAME_INFO:
|
||||
appendJsonEvent("GAME_OVER", callback.getObjectId(), callback.getData());
|
||||
MageFrame.getInstance().showGameEndDialog((GameEndView) callback.getData());
|
||||
break;
|
||||
case SHOW_USERMESSAGE:
|
||||
|
|
@ -293,6 +319,7 @@ public class CallbackClientImpl implements CallbackClient {
|
|||
GameClientMessage message = (GameClientMessage) callback.getData();
|
||||
GamePanel panel = MageFrame.getGame(callback.getObjectId());
|
||||
if (panel != null) {
|
||||
appendJsonEvent("GAME_INFORM", callback.getObjectId(), message);
|
||||
panel.inform(message.getMessage(), message.getGameView(), callback.getMessageId());
|
||||
}
|
||||
}
|
||||
|
|
@ -375,7 +402,12 @@ public class CallbackClientImpl implements CallbackClient {
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void appendJsonEvent(String name, UUID gameId, Object value) {
|
||||
Session session = SessionHandler.getSession();
|
||||
ActionData actionData = new ActionData(name, gameId);
|
||||
actionData.value = value;
|
||||
session.appendJsonLog(actionData);
|
||||
}
|
||||
private void createChatStartMessage(ChatPanelBasic chatPanel) {
|
||||
chatPanel.setStartMessageDone(true);
|
||||
ChatPanelBasic usedPanel = chatPanel;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue