Rename Project To 'ReboundEmulator'
Add Partial Support For Boardwalk Seaball
This commit is contained in:
parent
7f46ebc215
commit
d6d643ec02
@ -18,7 +18,7 @@ using System.Collections;
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace NotPogo.Amf;
|
namespace ReboundEmulator.Amf;
|
||||||
|
|
||||||
public sealed record AmfHeader(string Name, bool MustUnderstand, object? Value);
|
public sealed record AmfHeader(string Name, bool MustUnderstand, object? Value);
|
||||||
public sealed record AmfMessage(string Target, string Response, object? Body);
|
public sealed record AmfMessage(string Target, string Response, object? Body);
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using NotPogo.Core;
|
using ReboundEmulator.Core.Rooms;
|
||||||
using NotPogo.Core.Rooms;
|
using ReboundEmulator.Core;
|
||||||
|
|
||||||
namespace NotPogo.Controllers
|
namespace ReboundEmulator.Controllers
|
||||||
{
|
{
|
||||||
public class CDLController : Controller
|
public class CDLController : Controller
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,12 +1,12 @@
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using NotPogo.Core;
|
using ReboundEmulator.Core;
|
||||||
using NotPogo.Model;
|
using ReboundEmulator.Model;
|
||||||
using System.IO.Compression;
|
using System.IO.Compression;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Reflection.Metadata.Ecma335;
|
using System.Reflection.Metadata.Ecma335;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace NotPogo.Controllers
|
namespace ReboundEmulator.Controllers
|
||||||
{
|
{
|
||||||
[Route("/")]
|
[Route("/")]
|
||||||
public class ConfigAndAssetsController(ILogger<ConfigAndAssetsController> logger) : Controller
|
public class ConfigAndAssetsController(ILogger<ConfigAndAssetsController> logger) : Controller
|
||||||
@ -27,7 +27,6 @@ namespace NotPogo.Controllers
|
|||||||
string appletClass,
|
string appletClass,
|
||||||
string site,
|
string site,
|
||||||
string locale,
|
string locale,
|
||||||
string hostedGameClass,
|
|
||||||
string scrn = null!, // user will get a username assigned if screenName is not set
|
string scrn = null!, // user will get a username assigned if screenName is not set
|
||||||
bool isSingleApplet = true)
|
bool isSingleApplet = true)
|
||||||
{
|
{
|
||||||
@ -55,7 +54,6 @@ namespace NotPogo.Controllers
|
|||||||
Parameters = new()
|
Parameters = new()
|
||||||
{
|
{
|
||||||
{ "name", game },
|
{ "name", game },
|
||||||
{ "hosted.game.class", hostedGameClass ?? "" },
|
|
||||||
{ "standalone", "false" },
|
{ "standalone", "false" },
|
||||||
{ "type", game },
|
{ "type", game },
|
||||||
{ "config", $"client-props.jsp?game={game}" },
|
{ "config", $"client-props.jsp?game={game}" },
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using System.Reflection.Metadata.Ecma335;
|
using System.Reflection.Metadata.Ecma335;
|
||||||
|
|
||||||
namespace NotPogo.Core
|
namespace ReboundEmulator.Core
|
||||||
{
|
{
|
||||||
public class BowlingGame
|
public class BowlingGame
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,7 +1,8 @@
|
|||||||
using NotPogo.Core.Rooms;
|
using ReboundEmulator;
|
||||||
|
using ReboundEmulator.Core.Rooms;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
|
|
||||||
namespace NotPogo.Core
|
namespace ReboundEmulator.Core
|
||||||
{
|
{
|
||||||
public sealed class Player
|
public sealed class Player
|
||||||
{
|
{
|
||||||
@ -15,6 +16,8 @@ namespace NotPogo.Core
|
|||||||
public Room? Room { get; set; }
|
public Room? Room { get; set; }
|
||||||
public DateTime? LastSeen { get; set; }
|
public DateTime? LastSeen { get; set; }
|
||||||
|
|
||||||
|
public ILogger? Log { get; set; }
|
||||||
|
|
||||||
readonly NetworkStream _stream;
|
readonly NetworkStream _stream;
|
||||||
readonly SemaphoreSlim _writeLock = new(1, 1);
|
readonly SemaphoreSlim _writeLock = new(1, 1);
|
||||||
|
|
||||||
@ -27,7 +30,7 @@ namespace NotPogo.Core
|
|||||||
await SendAsync(msg);
|
await SendAsync(msg);
|
||||||
|
|
||||||
msg.TryGetValue("msg.op", out var op);
|
msg.TryGetValue("msg.op", out var op);
|
||||||
Console.WriteLine($"[GameServer] [plid {Id}] <- {op} {string.Join(" ", msg.Where(kv => kv.Key != "msg.op").Select(kv => $"{kv.Key}='{kv.Value}'"))}");
|
Log?.LogInformation("[plid {Id}] -> {Op} {Msg}", Id, op, string.Join(" ", msg.Where(kv => kv.Key != "msg.op").Select(kv => $"{kv.Key}='{kv.Value}'")));
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task SendAsync(Dictionary<string, string> msg)
|
public async Task SendAsync(Dictionary<string, string> msg)
|
||||||
|
|||||||
@ -1,8 +1,9 @@
|
|||||||
namespace NotPogo.Core.Rooms
|
namespace ReboundEmulator.Core.Rooms
|
||||||
{
|
{
|
||||||
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
|
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
|
||||||
public sealed class GameRoomAttribute(string gameCode) : Attribute
|
public sealed class GameRoomAttribute(string gameCode, string? opPrefix = null) : Attribute
|
||||||
{
|
{
|
||||||
public string GameCode { get; } = gameCode;
|
public string GameCode { get; } = gameCode;
|
||||||
|
public string? OpPrefix { get; init; } = opPrefix;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,4 +1,6 @@
|
|||||||
namespace NotPogo.Core.Rooms.GameRooms
|
using ReboundEmulator;
|
||||||
|
|
||||||
|
namespace ReboundEmulator.Core.Rooms.GameRooms
|
||||||
{
|
{
|
||||||
[GameRoom("lottso2")]
|
[GameRoom("lottso2")]
|
||||||
public class Lottso2Room : IGameRoom
|
public class Lottso2Room : IGameRoom
|
||||||
|
|||||||
38
Core/Rooms/GameRooms/SkeeballRoom.cs
Normal file
38
Core/Rooms/GameRooms/SkeeballRoom.cs
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
namespace ReboundEmulator.Core.Rooms.GameRooms
|
||||||
|
{
|
||||||
|
[GameRoom("seaball", "sb.")]
|
||||||
|
public class SkeeballRoom : IGameRoom
|
||||||
|
{
|
||||||
|
public Task OnGameJoinAsync(Room room, Player player) => Task.CompletedTask;
|
||||||
|
|
||||||
|
public Task<bool> OnMessageAsync(Room room, Player player, string op, Dictionary<string, string> msg)
|
||||||
|
{
|
||||||
|
return op switch
|
||||||
|
{
|
||||||
|
"sb.redy" => StartGame(room, player),
|
||||||
|
_ => Task.FromResult(false),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async Task<bool> StartGame(Room room, Player player)
|
||||||
|
{
|
||||||
|
string roundString = $"0;f;c;0;0;0;0,0,0,0,0~0,0,0,0,0~0,0,0,0,0~0,0,0,0,0~0,0,0,0,0~0~0,0,0,0,0~-~-~-~-~-~f,f,f,f,f~0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0~0,0,0,0~0,0,0,0~0,0,0,0~-~-1~0~t~0~1000,1000,1000,1000~0~0~t~-1~0~-~;-;-;-;0;0;0;{player.ScreenName};-;0;0.1~5~10~1,2,3,3,2,1~1,2,3,3,2,1~1,2,3,3,2,1~2,4,6,6,4,2~10,20,30,30,20,10~20,40,60,60,40,20~-~100~1000~500~1,2,3,4,5~100~10,20,30,40,50~200~10~50~50~500~100,200,300~200,300,500~-100,-50~100,200,300~100~1000~5~5000~-1~;";
|
||||||
|
|
||||||
|
await player.SendAsync(("msg.op", "sb.state"), ("gs", roundString));
|
||||||
|
|
||||||
|
await Task.Delay(TimeSpan.FromSeconds(15));
|
||||||
|
|
||||||
|
await player.SendAsync(("msg.op", "sb.prep"), ("id", "1"), ("rnd", "0"), ("mode", "0"), ("opac", "1.0"), ("dur", "5000"));
|
||||||
|
|
||||||
|
await Task.Delay(TimeSpan.FromSeconds(5));
|
||||||
|
|
||||||
|
await player.SendAsync(("msg.op", "sb.play"), ("id", "1"), ("dur", "25000"));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task OnPlayerJoinedAsync(Room room, Player player) => Task.CompletedTask;
|
||||||
|
|
||||||
|
public Task OnPlayerLeftAsync(Room room, Player player) => Task.CompletedTask;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,7 +1,8 @@
|
|||||||
namespace NotPogo.Core.Rooms
|
namespace ReboundEmulator.Core.Rooms
|
||||||
{
|
{
|
||||||
public interface IGameRoom
|
public interface IGameRoom
|
||||||
{
|
{
|
||||||
|
string? OpPrefix => null;
|
||||||
Task OnPlayerJoinedAsync(Room room, Player player);
|
Task OnPlayerJoinedAsync(Room room, Player player);
|
||||||
Task OnPlayerLeftAsync(Room room, Player player);
|
Task OnPlayerLeftAsync(Room room, Player player);
|
||||||
Task<bool> OnMessageAsync(Room room, Player player, string op, Dictionary<string, string> msg);
|
Task<bool> OnMessageAsync(Room room, Player player, string op, Dictionary<string, string> msg);
|
||||||
|
|||||||
@ -1,13 +1,19 @@
|
|||||||
using Microsoft.AspNetCore.StaticFiles;
|
using Microsoft.AspNetCore.StaticFiles;
|
||||||
using System.Runtime.InteropServices.Marshalling;
|
using System.Runtime.InteropServices.Marshalling;
|
||||||
|
using System.Reflection;
|
||||||
|
using ReboundEmulator.Core;
|
||||||
|
|
||||||
namespace NotPogo.Core.Rooms
|
namespace ReboundEmulator.Core.Rooms
|
||||||
{
|
{
|
||||||
public sealed class Room
|
public sealed class Room
|
||||||
{
|
{
|
||||||
public string Key { get; }
|
public string Key { get; }
|
||||||
public string HumanName { get; }
|
public string HumanName { get; }
|
||||||
public string GameCode { get; }
|
public string GameCode { get; }
|
||||||
|
public string OpPrefix =>
|
||||||
|
Game.GetType().GetCustomAttributes<GameRoomAttribute>()
|
||||||
|
.FirstOrDefault(a => string.Equals(a.GameCode, GameCode, StringComparison.OrdinalIgnoreCase))
|
||||||
|
?.OpPrefix ?? GameCode + ".";
|
||||||
public string RuleId { get; }
|
public string RuleId { get; }
|
||||||
public int SoftCapacity { get; }
|
public int SoftCapacity { get; }
|
||||||
public int TabId { get; }
|
public int TabId { get; }
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
|
|
||||||
namespace NotPogo.Core.Rooms
|
namespace ReboundEmulator.Core.Rooms
|
||||||
{
|
{
|
||||||
public static class RoomManager
|
public static class RoomManager
|
||||||
{
|
{
|
||||||
@ -10,7 +10,7 @@ namespace NotPogo.Core.Rooms
|
|||||||
|
|
||||||
static readonly Dictionary<string, Func<string, IGameRoom>> Factories = BuildFactories();
|
static readonly Dictionary<string, Func<string, IGameRoom>> Factories = BuildFactories();
|
||||||
|
|
||||||
public sealed record RoomDef(string Key, string Name, string Rule, int Capacity = 50);
|
public sealed record RoomDef(string Key, string Name, string OpCode, string Rule, int Capacity = 50);
|
||||||
|
|
||||||
public static void LoadFromFile(string path)
|
public static void LoadFromFile(string path)
|
||||||
{
|
{
|
||||||
@ -44,8 +44,15 @@ namespace NotPogo.Core.Rooms
|
|||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
static IGameRoom CreateGame(string gameCode, string ruleId) =>
|
static IGameRoom CreateGame(string gameCode, string ruleId)
|
||||||
Factories.TryGetValue(gameCode, out var create) ? create(ruleId) : new ChatOnlyRoom();
|
{
|
||||||
|
var gameRoom = Factories.TryGetValue(gameCode, out var create) ? create(ruleId) : new ChatOnlyRoom();
|
||||||
|
|
||||||
|
if (gameRoom is ChatOnlyRoom)
|
||||||
|
Console.WriteLine($"[RoomManager] Game Logic For Game {gameCode} Doesn't Exist. Fell Back To Chat Only...");
|
||||||
|
|
||||||
|
return gameRoom;
|
||||||
|
}
|
||||||
|
|
||||||
public static Room Define(string key, string humanName, string gameCode, string ruleId, bool isLive, int softCapacity = 50, int tabId = 1) =>
|
public static Room Define(string key, string humanName, string gameCode, string ruleId, bool isLive, int softCapacity = 50, int tabId = 1) =>
|
||||||
Rooms.GetOrAdd(key, _ => new Room(key, humanName, gameCode, ruleId, softCapacity, tabId, isLive, CreateGame(gameCode, ruleId)));
|
Rooms.GetOrAdd(key, _ => new Room(key, humanName, gameCode, ruleId, softCapacity, tabId, isLive, CreateGame(gameCode, ruleId)));
|
||||||
|
|||||||
@ -3,7 +3,7 @@ using System.Collections.Concurrent;
|
|||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace NotPogo.Core
|
namespace ReboundEmulator.Core
|
||||||
{
|
{
|
||||||
public sealed class Account
|
public sealed class Account
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,11 +1,9 @@
|
|||||||
// /flashservices/gateway endpoint for roomsel.swf (com.pogo.roomsel.RoomTabs).
|
// /flashservices/gateway endpoint for roomsel.swf (com.pogo.roomsel.RoomTabs).
|
||||||
// Register in Program.cs: app.MapFlashGateway();
|
// Register in Program.cs: app.MapFlashGateway();
|
||||||
using NotPogo.Amf;
|
using ReboundEmulator.Core.Rooms;
|
||||||
|
using ReboundEmulator.Amf;
|
||||||
|
|
||||||
using NotPogo;
|
namespace ReboundEmulator;
|
||||||
using NotPogo.Core.Rooms;
|
|
||||||
|
|
||||||
namespace NotPogo;
|
|
||||||
|
|
||||||
public static class FlashGateway
|
public static class FlashGateway
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||||
|
|
||||||
namespace NotPogo.Model
|
namespace ReboundEmulator.Model
|
||||||
{
|
{
|
||||||
public class AppletDefinition
|
public class AppletDefinition
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,3 +0,0 @@
|
|||||||
<Solution>
|
|
||||||
<Project Path="NotPogo.csproj" />
|
|
||||||
</Solution>
|
|
||||||
@ -1,9 +1,9 @@
|
|||||||
using Microsoft.AspNetCore.StaticFiles;
|
using Microsoft.AspNetCore.StaticFiles;
|
||||||
using Microsoft.Extensions.FileProviders;
|
using Microsoft.Extensions.FileProviders;
|
||||||
using NotPogo.Core;
|
using ReboundEmulator.Core;
|
||||||
using NotPogo.Core.Rooms;
|
using ReboundEmulator.Core.Rooms;
|
||||||
|
|
||||||
namespace NotPogo
|
namespace ReboundEmulator
|
||||||
{
|
{
|
||||||
public class Program
|
public class Program
|
||||||
{
|
{
|
||||||
|
|||||||
3
ReboundEmulator.slnx
Normal file
3
ReboundEmulator.slnx
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<Solution>
|
||||||
|
<Project Path="ReboundEmulator.csproj" />
|
||||||
|
</Solution>
|
||||||
@ -1,9 +1,9 @@
|
|||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using NotPogo.Core;
|
using ReboundEmulator.Core;
|
||||||
using NotPogo.Core.Rooms;
|
using ReboundEmulator.Core.Rooms;
|
||||||
|
|
||||||
namespace NotPogo
|
namespace ReboundEmulator
|
||||||
{
|
{
|
||||||
public class TCPGameServer(ILogger<TCPGameServer> logger, IConfiguration configuration) : BackgroundService
|
public class TCPGameServer(ILogger<TCPGameServer> logger, IConfiguration configuration) : BackgroundService
|
||||||
{
|
{
|
||||||
@ -73,7 +73,7 @@ namespace NotPogo
|
|||||||
{
|
{
|
||||||
player.LastSeen = DateTime.UtcNow;
|
player.LastSeen = DateTime.UtcNow;
|
||||||
}
|
}
|
||||||
else if (player.Room is not null && (RoomOps.Contains(op) || op.StartsWith(player.Room.GameCode + ".")))
|
else if (player.Room is not null && (RoomOps.Contains(op) || op.StartsWith(player.Room.OpPrefix)))
|
||||||
{
|
{
|
||||||
await player.Room.HandleAsync(player, op, received);
|
await player.Room.HandleAsync(player, op, received);
|
||||||
}
|
}
|
||||||
@ -104,6 +104,7 @@ namespace NotPogo
|
|||||||
// populate player information
|
// populate player information
|
||||||
player.Account = accnt;
|
player.Account = accnt;
|
||||||
player.ScreenName = accnt?.ScreenName ?? $"Guest_{player.Id}";
|
player.ScreenName = accnt?.ScreenName ?? $"Guest_{player.Id}";
|
||||||
|
player.Log = _logger;
|
||||||
|
|
||||||
// get game code and rule id
|
// get game code and rule id
|
||||||
string game = logn.GetValueOrDefault("game", "");
|
string game = logn.GetValueOrDefault("game", "");
|
||||||
|
|||||||
@ -3,7 +3,7 @@ using Microsoft.AspNetCore.Server.HttpSys;
|
|||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace NotPogo
|
namespace ReboundEmulator
|
||||||
{
|
{
|
||||||
public static class TCPProtocol
|
public static class TCPProtocol
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
@model NotPogo.Model.GamePage
|
@model ReboundEmulator.Model.GamePage
|
||||||
|
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user