Skip to content

Commit d669b9c

Browse files
committed
* Reworked Ban/Kick functionality
* Added Ban/Kick to the FishyExtension class * Improved Webserver code and added actor spwaning & kicking/banning
1 parent 99461dd commit d669b9c

8 files changed

Lines changed: 200 additions & 43 deletions

File tree

Fishy/Extensions/FishyExtension.cs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,5 +31,32 @@ public static void SendPacketToAll(FPacket packet)
3131

3232
public static void SendPacketToPlayer(FPacket packet, SteamId player)
3333
=> packet.SendPacket("single", (int)CHANNELS.GAME_STATE, player);
34+
35+
public static void SpawnActor(string actor)
36+
{
37+
switch (actor)
38+
{
39+
case "fish_spawn":
40+
Spawner.SpawnFish();
41+
break;
42+
case "fish_spawn_alien":
43+
Spawner.SpawnFish("fish_spawn_alien");
44+
break;
45+
case "raincloud":
46+
Spawner.SpawnRainCloud();
47+
break;
48+
case "metalspot":
49+
Spawner.SpawnMetalSpot();
50+
break;
51+
case "void_portal":
52+
Spawner.SpawnFish();
53+
break;
54+
}
55+
}
56+
57+
public static void KickPlayer(Player player)
58+
=> Punish.KickPlayer(player);
59+
public static void BanPlayer(Player player)
60+
=> Punish.BanPlayer(player);
3461
}
3562
}

Fishy/Plugins/Fishy.Webserver.dll

11.5 KB
Binary file not shown.

Fishy/Utils/CommandHandler.cs

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -33,21 +33,14 @@ public static void OnMessage(SteamId from, string message)
3333
Player? playerToKick = Fishy.Players.Find(p => p.Name.Equals(parameters[1]))
3434
?? Fishy.Players.Find(p => p.SteamID.Value.ToString().Equals(parameters[1]));
3535
if (playerToKick != null)
36-
new KickPacket().SendPacket("single", (int)CHANNELS.GAME_STATE, playerToKick.SteamID);
36+
Punish.KickPlayer(playerToKick);
3737
break;
3838
case "ban":
3939
if (parameters.Length < 2) return;
4040
Player? playerToBan = Fishy.Players.Find(p => p.Name.Equals(parameters[1]))
4141
?? Fishy.Players.Find(p => p.SteamID.Value.ToString().Equals(parameters[1]));
4242
if (playerToBan != null)
43-
{
44-
new BanPacket().SendPacket("single", (int)CHANNELS.GAME_STATE, playerToBan.SteamID);
45-
new ForceDisconnectPacket(playerToBan.SteamID.Value.ToString()).SendPacket("all", (int)CHANNELS.GAME_STATE);
46-
Fishy.SteamHandler.UpdateSteamBanList(playerToBan.SteamID.Value.ToString());
47-
using StreamWriter writer = new(Path.Combine(AppContext.BaseDirectory, "bans.txt"), true);
48-
writer.WriteLine(playerToBan.SteamID.Value.ToString());
49-
Fishy.BannedUsers.Add(playerToBan.SteamID.Value.ToString());
50-
}
43+
Punish.BanPlayer(playerToBan);
5144
break;
5245
case "spawn":
5346
if (parameters.Length < 2) return;

Fishy/Utils/Punish.cs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
using Fishy.Models;
7+
using Fishy.Models.Packets;
8+
9+
namespace Fishy.Utils
10+
{
11+
class Punish
12+
{
13+
internal static void BanPlayer(Player playerToBan)
14+
{
15+
new BanPacket().SendPacket("single", (int)CHANNELS.GAME_STATE, playerToBan.SteamID);
16+
new ForceDisconnectPacket(playerToBan.SteamID.Value.ToString()).SendPacket("all", (int)CHANNELS.GAME_STATE);
17+
Fishy.SteamHandler.UpdateSteamBanList(playerToBan.SteamID.Value.ToString());
18+
using StreamWriter writer = new(Path.Combine(AppContext.BaseDirectory, "bans.txt"), true);
19+
writer.WriteLine(playerToBan.SteamID.Value.ToString());
20+
Fishy.BannedUsers.Add(playerToBan.SteamID.Value.ToString());
21+
}
22+
23+
internal static void KickPlayer(Player playerToKick)
24+
=> new KickPacket().SendPacket("single", (int)CHANNELS.GAME_STATE, playerToKick.SteamID);
25+
}
26+
}

FishyWebserver/ActionController.cs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
using Fishy.Models;
7+
using Fishy.Models.Packets;
8+
using GenHTTP.Api.Protocol;
9+
using GenHTTP.Modules.Controllers;
10+
using GenHTTP.Modules.Reflection;
11+
12+
13+
namespace Fishy.Webserver
14+
{
15+
internal class ActionController
16+
{
17+
[ControllerAction(RequestMethod.Post)]
18+
public void Spawn([FromBody] string actor_type)
19+
=> WebserverExtension.SpawnActor(actor_type);
20+
21+
[ControllerAction(RequestMethod.Post)]
22+
public void Chat([FromBody] string message)
23+
=> WebserverExtension.SendPacketToAll(new MessagePacket("Server: " + message));
24+
25+
[ControllerAction(RequestMethod.Post)]
26+
public void Kick([FromBody] string accountId)
27+
{
28+
Player? p = WebserverExtension.Players.First(p => p.SteamID.AccountId.ToString() == accountId);
29+
if (p != null)
30+
WebserverExtension.KickPlayer(p);
31+
}
32+
33+
[ControllerAction(RequestMethod.Post)]
34+
public void Ban([FromBody] string accountId)
35+
{
36+
Player? p = WebserverExtension.Players.First(p => p.SteamID.AccountId.ToString() == accountId);
37+
if (p != null)
38+
WebserverExtension.BanPlayer(p);
39+
}
40+
41+
}
42+
}

FishyWebserver/Dashboard.cs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
using Fishy.Models;
1+
using System.Text.Json;
2+
using Fishy.Models;
23
using Fishy.Models.Packets;
34
using Fishy.Utils;
45
using GenHTTP.Engine.Internal;
56
using GenHTTP.Modules.Authentication;
7+
using GenHTTP.Modules.Controllers;
68
using GenHTTP.Modules.Functional;
79
using GenHTTP.Modules.IO;
810
using GenHTTP.Modules.Layouting;
@@ -20,25 +22,25 @@ public void Initalize()
2022
{
2123
var mainPage = Content.From(Resource.FromAssembly("index.html"));
2224
var syncEvent = EventSource.Create().Generator(SyncStats);
23-
var chatService = Inline.Create().Post(([FromBody] string message) => WebserverExtension.SendPacketToAll(new MessagePacket("Server: " + message)));
2425

2526
var app = Layout.Create()
2627
.Index(mainPage)
2728
.Add("status", syncEvent)
28-
.Add("chat", chatService)
29+
.AddController<ActionController>("action")
2930
.Authentication(Authentication.Auth);
3031

3132
Host.Create()
3233
.Defaults()
3334
.Handler(app)
3435
.RunAsync();
3536
}
36-
37+
38+
3739
async ValueTask SyncStats(IEventConnection connection)
3840
{
3941
// Resync data on reload
4042
foreach (Player p in WebserverExtension.Players)
41-
await connection.DataAsync(p.Name, "join");
43+
await connection.DataAsync(JsonSerializer.Serialize(p), "join");
4244

4345
foreach (ChatMessage m in WebserverExtension.ChatLog)
4446
await connection.DataAsync(m.ToString(), "message");
@@ -63,7 +65,7 @@ async ValueTask SyncStats(IEventConnection connection)
6365
{
6466
foreach (KeyValuePair<Player, string> p in PlayersToSync.ToDictionary())
6567
{
66-
await connection.DataAsync(p.Key.Name, p.Value);
68+
await connection.DataAsync(JsonSerializer.Serialize(p.Key), p.Value);
6769
PlayersToSync.Remove(p.Key);
6870
}
6971
}

FishyWebserver/Fishy.Webserver.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
</PackageReference>
3535
<PackageReference Include="GenHTTP.Core" Version="9.1.0" />
3636
<PackageReference Include="GenHTTP.Modules.Authentication" Version="9.1.0" />
37+
<PackageReference Include="GenHTTP.Modules.Controllers" Version="9.1.0" />
3738
<PackageReference Include="GenHTTP.Modules.Functional" Version="9.1.0" />
3839
<PackageReference Include="GenHTTP.Modules.ServerSentEvents" Version="9.1.0" />
3940
<PackageReference Include="GenHTTP.Modules.SinglePageApplications" Version="9.1.0" />

FishyWebserver/index.html

Lines changed: 94 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,13 @@ <h5 class="card-title">There are <span id="actors">0</span> actors loaded</h5>
5151
</div>
5252
</div>
5353
</div>
54-
<!--<div class="btn-group" role="group" aria-label="Basic outlined example">
55-
<button type="button" class="btn btn-outline-primary opacity-75">Spawn Meteor</button>
56-
<button type="button" class="btn btn-outline-primary opacity-75">Spawn Raincloud</button>
57-
<button type="button" class="btn btn-outline-primary opacity-75">Spawn MetalSpot</button>
58-
<button type="button" class="btn btn-outline-primary opacity-75">Spawn Fish/Ripple</button>
59-
</div>-->
54+
<div class="btn-group" role="group" aria-label="Basic outlined example">
55+
<button id="fish_spawn_alien" type="button" class="btn btn-outline-primary opacity-75 spawn">Spawn Meteor</button>
56+
<button id="raincloud" type="button" class="btn btn-outline-primary opacity-75 spawn">Spawn Raincloud</button>
57+
<button id="metalspot" type="button" class="btn btn-outline-primary opacity-75 spawn">Spawn MetalSpot</button>
58+
<button id="fish_spawn" type="button" class="btn btn-outline-primary opacity-75 spawn">Spawn Fish/Ripple</button>
59+
<button id="void_portal" type="button" class="btn btn-outline-primary opacity-75 spawn">Spawn Void Portal</button>
60+
</div>
6061
</div>
6162
<div class="col-4">
6263
<div class="card mb-4">
@@ -72,19 +73,41 @@ <h5 class="card-title">There are <span id="actors">0</span> actors loaded</h5>
7273
</main>
7374
<script>
7475
const eventSource = new EventSource('/status');
76+
7577
const chat = document.getElementById('chat');
7678
const playerList = document.getElementById('playerlist');
7779
const message = document.getElementById('message');
7880
const sendButton = document.getElementById('send_message');
7981

82+
83+
// Add a eventlistener for the different stats that are being sent
84+
const stats = ['players', 'banned', 'actors']
85+
stats.forEach(stat => {
86+
eventSource.addEventListener(stat, event => {
87+
update(stat, event.data);
88+
});
89+
});
90+
91+
// Update the stats at the top
92+
function update(name, data) {
93+
let element = document.getElementById(name);
94+
element.innerHTML = `${data}`;
95+
}
96+
97+
eventSource.onerror = function () {
98+
console.error('Connection to the server lost.');
99+
};
100+
101+
// Add the eventlistener for sending messages
80102
sendButton.addEventListener('click', (e) => sendMessage(message.value));
81103
message.addEventListener('keypress', (e) => {
82104
if (e.key === "Enter") sendMessage(message.value);
83105
});
84106

107+
// Send a message to all players
85108
function sendMessage(msg) {
86109
message.value = "";
87-
fetch("chat", {
110+
fetch("action/chat/", {
88111
method: "POST",
89112
body: msg,
90113
headers: {
@@ -93,43 +116,86 @@ <h5 class="card-title">There are <span id="actors">0</span> actors loaded</h5>
93116
});
94117
}
95118

96-
function update(name, data) {
97-
let element = document.getElementById(name);
98-
element.innerHTML = `${data}`;
99-
}
100-
101-
const stats = ['players', 'banned', 'actors']
102-
stats.forEach(stat => {
103-
eventSource.addEventListener(stat, event => {
104-
update(stat, event.data);
105-
});
106-
});
107-
119+
// Append messages to list
108120
eventSource.addEventListener('message', event => {
109-
110121
let chatElement = document.createElement('li');
111122
chatElement.className = "list-group-item";
112123
chatElement.innerHTML = event.data;
113124
chat.appendChild(chatElement)
114125
chat.scrollTop = chat.scrollHeight;
115126
});
116127

128+
129+
// Add the eventlistener for spawning actors
130+
Array.from(document.getElementsByClassName('spawn')).forEach(function (element) {
131+
element.addEventListener('click', (e) => spawnActor(element.id));
132+
});
133+
134+
// Spawn the actor of the given type
135+
function spawnActor(actor) {
136+
fetch('action/spawn/', {
137+
method: "POST",
138+
body: actor,
139+
headers: {
140+
"Content-type": "text/plain; charset=UTF-8"
141+
}
142+
});
143+
}
144+
145+
// Add the player to the list when they join
117146
eventSource.addEventListener('join', event => {
118-
let playerElement = document.createElement('li');
119-
playerElement.className = "list-group-item";
120-
playerElement.id = event.data;
121-
playerElement.innerHTML = event.data;
147+
let eventPlayer = JSON.parse(event.data);
148+
let playerElement = createPlayerItem(eventPlayer);
122149
playerList.appendChild(playerElement)
123150
});
124151

152+
// Create a list item with the player name and kick/ban buttons
153+
function createPlayerItem(data) {
154+
let listElement = document.createElement('li');
155+
listElement.className = 'list-group-item d-flex align-items-center';
156+
listElement.id = data.SteamID.AccountId;
157+
158+
// Player Name
159+
let playerName = document.createElement('span');
160+
playerName.className = 'me-auto';
161+
playerName.innerHTML = data.Name;
162+
listElement.appendChild(playerName);
163+
164+
// Kick Button
165+
let kickButton = document.createElement('button');
166+
kickButton.className = 'btn btn-sm btn-primary';
167+
kickButton.innerHTML = 'Kick';
168+
kickButton.addEventListener('click', (e) => punishPlayer('kick', data.SteamID.AccountId))
169+
listElement.appendChild(kickButton);
170+
171+
// Ban Button
172+
let banButton = document.createElement('button');
173+
banButton.className = 'btn btn-sm btn-danger ms-1';
174+
banButton.innerHTML = 'Ban';
175+
banButton.addEventListener('click', (e) => punishPlayer('ban', data.SteamID.AccountId))
176+
listElement.appendChild(banButton);
177+
178+
return listElement;
179+
}
180+
181+
// Kick / Ban the player
182+
function punishPlayer(type, player) {
183+
fetch('action/'+ type +'/', {
184+
method: "POST",
185+
body: player,
186+
headers: {
187+
"Content-type": "text/plain; charset=UTF-8"
188+
}
189+
});
190+
}
191+
192+
// Remove the player from the list when they leave
125193
eventSource.addEventListener('leave', event => {
126-
let playerElement = document.getElementById(event.data);
194+
let eventPlayer = JSON.parse(event.data);
195+
let playerElement = document.getElementById(eventPlayer.SteamID.AccountId);
127196
playerList.removeChild(playerElement)
128197
});
129198

130-
eventSource.onerror = function () {
131-
console.error('Connection to the server lost.');
132-
};
133199
</script>
134200
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script>
135201
</body>

0 commit comments

Comments
 (0)