Compare commits

..

4 Commits

Author SHA1 Message Date
Kei-Luna
677e4027b9 Update version.txt 2026-05-03 13:50:50 +09:00
Kei-Luna
4dc28ae423 more House_Func 2026-05-03 13:42:09 +09:00
Kei-Luna
1fce4ca2e6 Update version.txt 2026-05-03 09:55:55 +09:00
Kei-Luna
93c59e5730 Arcade Game can play 2026-05-03 09:54:46 +09:00
7 changed files with 361 additions and 1 deletions

View File

@@ -0,0 +1,97 @@
using MikuSB.Proto;
using System.Text.Json.Nodes;
namespace MikuSB.GameServer.Server.CallGS.Handlers.House;
// ArcadeGameEnterMainUI
// Returns all girl IDs (1-25) as unlocked, and syncs TeachMode + EndlessMode attrs.
[HouseFunc("ArcadeGameEnterMainUI")]
public class ArcadeGameEnterMainUI : IHouseFuncHandler
{
private const uint ArcadeGid = 101;
private const uint EndlessModeStateSid = 18000 + 5;
private const uint TeachModeConditionSid = 18000 + 36 + 8;
public async Task Handle(Connection connection, string param)
{
var girlList = new JsonArray();
for (int i = 1; i <= 25; i++) girlList.Add(i);
var rsp = new JsonObject
{
["FuncName"] = "ArcadeGameEnterMainUI",
["tbUnlockGirlList"] = girlList
};
var player = connection.Player!;
var sync = new NtfSyncPlayer();
sync.Custom[player.ToPackedAttrKey(ArcadeGid, TeachModeConditionSid)] = 1;
sync.Custom[player.ToShiftedAttrKey(ArcadeGid, TeachModeConditionSid)] = 1;
const uint endlessAllUnlocked = 0x3FFFFFE;
sync.Custom[player.ToPackedAttrKey(ArcadeGid, EndlessModeStateSid)] = endlessAllUnlocked;
sync.Custom[player.ToShiftedAttrKey(ArcadeGid, EndlessModeStateSid)] = endlessAllUnlocked;
await CallGSRouter.SendScript(connection, "House_Request", rsp.ToJsonString(), sync);
}
}
// ArcadeGameEnter — returns a random seed for level generation.
[HouseFunc("ArcadeGameEnter")]
public class ArcadeGameEnter : IHouseFuncHandler
{
private static readonly Random Random = new();
public async Task Handle(Connection connection, string param)
{
var rsp = new JsonObject
{
["FuncName"] = "ArcadeGameEnter",
["nSeed"] = Random.Next(1, 1_000_000_000)
};
await CallGSRouter.SendScript(connection, "House_Request", rsp.ToJsonString());
}
}
// ArcadeGameSettlement — acknowledges round end; nAddExp=0 on private server.
[HouseFunc("ArcadeGameSettlement")]
public class ArcadeGameSettlement : IHouseFuncHandler
{
public async Task Handle(Connection connection, string param)
{
var rsp = new JsonObject { ["FuncName"] = "ArcadeGameSettlement", ["nAddExp"] = 0 };
await CallGSRouter.SendScript(connection, "House_Request", rsp.ToJsonString());
}
}
// ArcadeGameLogSettlement — acknowledges log upload (no client data required).
[HouseFunc("ArcadeGameLogSettlement")]
public class ArcadeGameLogSettlement : IHouseFuncHandler
{
public async Task Handle(Connection connection, string param)
{
var rsp = new JsonObject { ["FuncName"] = "ArcadeGameLogSettlement" };
await CallGSRouter.SendScript(connection, "House_Request", rsp.ToJsonString());
}
}
// ArcadeGameGetLevelReward — UI refresh only on client side.
[HouseFunc("ArcadeGameGetLevelReward")]
public class ArcadeGameGetLevelReward : IHouseFuncHandler
{
public async Task Handle(Connection connection, string param)
{
var rsp = new JsonObject { ["FuncName"] = "ArcadeGameGetLevelReward" };
await CallGSRouter.SendScript(connection, "House_Request", rsp.ToJsonString());
}
}
// ArcadeGameGetAchReward — UI refresh only on client side.
[HouseFunc("ArcadeGameGetAchReward")]
public class ArcadeGameGetAchReward : IHouseFuncHandler
{
public async Task Handle(Connection connection, string param)
{
var rsp = new JsonObject { ["FuncName"] = "ArcadeGameGetAchReward" };
await CallGSRouter.SendScript(connection, "House_Request", rsp.ToJsonString());
}
}

View File

@@ -0,0 +1,59 @@
using System.Text.Json;
using System.Text.Json.Nodes;
using System.Text.Json.Serialization;
namespace MikuSB.GameServer.Server.CallGS.Handlers.House;
[HouseFunc("ChangeNpcSuit")]
public class ChangeNpcSuit : IHouseFuncHandler
{
public async Task Handle(Connection connection, string param)
{
var req = JsonSerializer.Deserialize<NpcSuitParam>(param);
var rsp = new JsonObject
{
["FuncName"] = "ChangeNpcSuitSuccess",
["NpcId"] = req?.NpcId ?? 0,
["SuitId"] = req?.SuitId ?? 0
};
await CallGSRouter.SendScript(connection, "House_Request", rsp.ToJsonString());
}
}
[HouseFunc("ChangeNpcSuitByAreaId")]
public class ChangeNpcSuitByAreaId : IHouseFuncHandler
{
public async Task Handle(Connection connection, string param)
{
var req = JsonSerializer.Deserialize<NpcSuitParam>(param);
var rsp = new JsonObject
{
["FuncName"] = "ChangeNpcSuitByAreaIdRsp",
["NpcId"] = req?.NpcId ?? 0,
["SuitId"] = req?.SuitId ?? 0
};
await CallGSRouter.SendScript(connection, "House_Request", rsp.ToJsonString());
}
}
[HouseFunc("ChangeGirlBeachSuitId")]
public class ChangeGirlBeachSuitId : IHouseFuncHandler
{
public async Task Handle(Connection connection, string param)
{
var req = JsonSerializer.Deserialize<NpcSuitParam>(param);
var rsp = new JsonObject
{
["FuncName"] = "ChangeGirlBeachSuitIdSuccess",
["NpcId"] = req?.NpcId ?? 0,
["SuitId"] = req?.SuitId ?? 0
};
await CallGSRouter.SendScript(connection, "House_Request", rsp.ToJsonString());
}
}
internal sealed class NpcSuitParam
{
[JsonPropertyName("NpcId")] public int NpcId { get; set; }
[JsonPropertyName("SuitId")] public int SuitId { get; set; }
}

View File

@@ -0,0 +1,74 @@
using System.Text.Json.Nodes;
namespace MikuSB.GameServer.Server.CallGS.Handlers.House;
// PubGameEnter — returns nSeed for client-side game initialization.
[HouseFunc("PubGameEnter")]
public class PubGameEnter : IHouseFuncHandler
{
private static readonly Random Random = new();
public async Task Handle(Connection connection, string param)
{
var rsp = new JsonObject
{
["FuncName"] = "PubGameEnter",
["nSeed"] = Random.Next(1, 1_000_000_000),
["nModeType"] = 1,
["bIsGuide"] = false,
["bHasTry"] = false
};
await CallGSRouter.SendScript(connection, "House_Request", rsp.ToJsonString());
}
}
[HouseFunc("PubGameMulExit")]
public class PubGameMulExit : IHouseFuncHandler
{
public async Task Handle(Connection connection, string param)
{
var rsp = new JsonObject { ["FuncName"] = "PubGameMulExit" };
await CallGSRouter.SendScript(connection, "House_Request", rsp.ToJsonString());
}
}
// PubGameSettlement — nAddExp=0 on private server.
[HouseFunc("PubGameSettlement")]
public class PubGameSettlement : IHouseFuncHandler
{
public async Task Handle(Connection connection, string param)
{
var rsp = new JsonObject { ["FuncName"] = "PubGameSettlement", ["nAddExp"] = 0 };
await CallGSRouter.SendScript(connection, "House_Request", rsp.ToJsonString());
}
}
[HouseFunc("PubGameGetReward")]
public class PubGameGetReward : IHouseFuncHandler
{
public async Task Handle(Connection connection, string param)
{
var rsp = new JsonObject { ["FuncName"] = "PubGameGetReward" };
await CallGSRouter.SendScript(connection, "House_Request", rsp.ToJsonString());
}
}
[HouseFunc("PubGameGetAchReward")]
public class PubGameGetAchReward : IHouseFuncHandler
{
public async Task Handle(Connection connection, string param)
{
var rsp = new JsonObject { ["FuncName"] = "PubGameGetAchReward" };
await CallGSRouter.SendScript(connection, "House_Request", rsp.ToJsonString());
}
}
[HouseFunc("PubGameAchievementFinish")]
public class PubGameAchievementFinish : IHouseFuncHandler
{
public async Task Handle(Connection connection, string param)
{
var rsp = new JsonObject { ["FuncName"] = "PubGameAchievementFinish" };
await CallGSRouter.SendScript(connection, "House_Request", rsp.ToJsonString());
}
}

View File

@@ -0,0 +1,76 @@
using System.Text.Json.Nodes;
namespace MikuSB.GameServer.Server.CallGS.Handlers.House;
// GameEnterMainUI (Throw) — tblockGirlList empty = no blocked girls.
[HouseFunc("GameEnterMainUI")]
public class ThrowGameEnterMainUI : IHouseFuncHandler
{
public async Task Handle(Connection connection, string param)
{
var rsp = new JsonObject
{
["FuncName"] = "GameEnterMainUI",
["tblockGirlList"] = new JsonArray()
};
await CallGSRouter.SendScript(connection, "House_Request", rsp.ToJsonString());
}
}
[HouseFunc("ThrowGameTutorialFinish")]
public class ThrowGameTutorialFinish : IHouseFuncHandler
{
public async Task Handle(Connection connection, string param)
{
var rsp = new JsonObject { ["FuncName"] = "ThrowGameTutorialFinish" };
await CallGSRouter.SendScript(connection, "House_Request", rsp.ToJsonString());
}
}
// ThrowGameEnter — returns nSeed for level generation.
[HouseFunc("ThrowGameEnter")]
public class ThrowGameEnter : IHouseFuncHandler
{
private static readonly Random Random = new();
public async Task Handle(Connection connection, string param)
{
var rsp = new JsonObject
{
["FuncName"] = "ThrowGameEnter",
["nSeed"] = Random.Next(1, 1_000_000_000)
};
await CallGSRouter.SendScript(connection, "House_Request", rsp.ToJsonString());
}
}
// ThrowGameSettlement — nAddExp=0 on private server.
[HouseFunc("ThrowGameSettlement")]
public class ThrowGameSettlement : IHouseFuncHandler
{
public async Task Handle(Connection connection, string param)
{
var rsp = new JsonObject { ["FuncName"] = "ThrowGameSettlement", ["nAddExp"] = 0 };
await CallGSRouter.SendScript(connection, "House_Request", rsp.ToJsonString());
}
}
[HouseFunc("ThrowGameGetLevelReward")]
public class ThrowGameGetLevelReward : IHouseFuncHandler
{
public async Task Handle(Connection connection, string param)
{
var rsp = new JsonObject { ["FuncName"] = "ThrowGameGetLevelReward" };
await CallGSRouter.SendScript(connection, "House_Request", rsp.ToJsonString());
}
}
[HouseFunc("ThrowGameGetAchReward")]
public class ThrowGameGetAchReward : IHouseFuncHandler
{
public async Task Handle(Connection connection, string param)
{
var rsp = new JsonObject { ["FuncName"] = "ThrowGameGetAchReward" };
await CallGSRouter.SendScript(connection, "House_Request", rsp.ToJsonString());
}
}

View File

@@ -0,0 +1,12 @@
namespace MikuSB.GameServer.Server.CallGS.Handlers.House;
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public class HouseFuncAttribute(string funcName) : Attribute
{
public string FuncName { get; } = funcName;
}
public interface IHouseFuncHandler
{
Task Handle(Connection connection, string param);
}

View File

@@ -0,0 +1,42 @@
using System.Reflection;
using System.Text.Json;
using System.Text.Json.Nodes;
using System.Text.Json.Serialization;
namespace MikuSB.GameServer.Server.CallGS.Handlers.House;
[CallGSApi("House_Request")]
public class House_Request : ICallGSHandler
{
private static readonly Dictionary<string, IHouseFuncHandler> Handlers = [];
static House_Request()
{
foreach (var type in Assembly.GetExecutingAssembly().GetTypes())
{
foreach (var attr in type.GetCustomAttributes<HouseFuncAttribute>())
Handlers[attr.FuncName] = (IHouseFuncHandler)Activator.CreateInstance(type)!;
}
}
public async Task Handle(Connection connection, string param, ushort seqNo)
{
var req = JsonSerializer.Deserialize<HouseRequestParam>(param);
if (req?.FuncName == null) return;
if (Handlers.TryGetValue(req.FuncName, out var handler))
{
await handler.Handle(connection, param);
return;
}
var err = new JsonObject { ["FuncName"] = req.FuncName, ["sErr"] = "error.NotImplemented" };
await CallGSRouter.SendScript(connection, "House_Request", err.ToJsonString());
}
}
internal sealed class HouseRequestParam
{
[JsonPropertyName("FuncName")]
public string? FuncName { get; set; }
}

View File

@@ -1 +1 @@
v=1.7
v=1.9