Private Lobbies: Add kick player functionality (#1436)

## Description:
Added player management features so lobby hosts can kick players from
private games. This includes both UI changes and backend work.

### What's new:
- Hosts can now kick players from private lobbies with a simple button
- Added host badges and remove buttons to the UI
- Made sure only hosts can kick people, and hosts can't kick themselves

### How it works:
- When someone creates a private game, they automatically become the
host
- Kicking happens through WebSocket "kick-player" events
- Server checks that you're actually the host before letting you kick
anyone

<img width="1291" height="871" alt="Screenshot 2025-07-15 002114"
src="https://github.com/user-attachments/assets/ea575f83-a0f4-45d1-9cfe-7521d373f3d5"
/>



### Known Issues:
- Kicked player gets general message (same when kicked for multi tab)

### Other Issues:
- Host abandoment still existent (host clicks on x; or is closing tab)

## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced
- [x] I have read and accepted the CLA agreement (only required once).

## Please put your Discord username so you can be contacted if a bug or
regression is found:

[UN]nvm

---------

Co-authored-by: floriankilian <floriankilian@users.noreply.github.com>
This commit is contained in:
floriankilian
2025-08-01 07:01:10 +02:00
committed by GitHub
parent ee459b7410
commit bd59cd61cb
10 changed files with 211 additions and 54 deletions
+10 -1
View File
@@ -41,7 +41,9 @@ export type Intent =
| QuickChatIntent
| MoveWarshipIntent
| MarkDisconnectedIntent
| UpgradeStructureIntent;
| UpgradeStructureIntent
| KickPlayerIntent;
export type AttackIntent = z.infer<typeof AttackIntentSchema>;
export type CancelAttackIntent = z.infer<typeof CancelAttackIntentSchema>;
export type SpawnIntent = z.infer<typeof SpawnIntentSchema>;
@@ -72,6 +74,7 @@ export type MarkDisconnectedIntent = z.infer<
export type AllianceExtensionIntent = z.infer<
typeof AllianceExtensionIntentSchema
>;
export type KickPlayerIntent = z.infer<typeof KickPlayerIntentSchema>;
export type Turn = z.infer<typeof TurnSchema>;
export type GameConfig = z.infer<typeof GameConfigSchema>;
@@ -356,6 +359,11 @@ export const MarkDisconnectedIntentSchema = BaseIntentSchema.extend({
isDisconnected: z.boolean(),
});
export const KickPlayerIntentSchema = BaseIntentSchema.extend({
type: z.literal("kick_player"),
target: ID,
});
const IntentSchema = z.discriminatedUnion("type", [
AttackIntentSchema,
CancelAttackIntentSchema,
@@ -377,6 +385,7 @@ const IntentSchema = z.discriminatedUnion("type", [
MoveWarshipIntentSchema,
QuickChatIntentSchema,
AllianceExtensionIntentSchema,
KickPlayerIntentSchema,
]);
//