the files
This commit is contained in:
@@ -0,0 +1,226 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Newtonsoft.Json;
|
||||
using System.Security.Principal;
|
||||
using Campus_live_rewrite.api.dbs;
|
||||
using Campus_live_rewrite.api.server.Classes.db_class;
|
||||
using static Campus_live_rewrite.api.dbs.HeartbeatDB;
|
||||
|
||||
namespace Campus_live_rewrite.api.server
|
||||
{
|
||||
public class Sessions
|
||||
{
|
||||
private static readonly Random random = new Random();
|
||||
|
||||
public static RoomInstance? CreateRoom(string roomName, string sceneName = "", bool isPrivate = false)
|
||||
{
|
||||
//const string uuidPrefix = "Campus_live_2023";
|
||||
string formattedRoomName = $"^{roomName}";
|
||||
|
||||
if (!string.IsNullOrEmpty(sceneName))
|
||||
{
|
||||
Console.WriteLine($"[Sessions]: Finding room: \"{roomName}\" with scene id: \"{sceneName}\"");
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($"[Sessions]: Finding room: \"{roomName}\"");
|
||||
}
|
||||
|
||||
long gameSessionId = random.Next(0x1000, 0x7fffffff);
|
||||
|
||||
RoomDBClasses.RoomRoot roomData = RoomDB.GetRoomByName(roomName);
|
||||
if (roomData == null)
|
||||
{
|
||||
Console.WriteLine($"[Sessions]: Room \"{roomName}\" not found.");
|
||||
return null;
|
||||
}
|
||||
|
||||
Console.WriteLine($"[Sessions]: {roomName} found! Joining...");
|
||||
|
||||
var firstSubRoom = roomData.SubRooms?.FirstOrDefault();
|
||||
string dataBlob = firstSubRoom?.CurrentSave?.DataBlob ?? string.Empty;
|
||||
long instanceNumber = random.Next(1000, 999999999);
|
||||
Guid instanceId = Guid.NewGuid();
|
||||
|
||||
// Public rooms used to get the CONSTANT "room" here. Photon groups players by
|
||||
// room NAME, so every public instance of every room shared one Photon room:
|
||||
// people in completely different rooms saw each other, could interact with
|
||||
// each other's worlds, and showed up in each other's player lists.
|
||||
//
|
||||
// The name must be unique per INSTANCE but identical for everyone in that
|
||||
// instance - that is exactly what makes two people meet. It is assigned at the
|
||||
// end of this method instead of here, because ApplyRandomPublicSubroom /
|
||||
// ApplySceneSettings can still change subRoomId below and the name has to
|
||||
// reflect the final subroom.
|
||||
string photonSuffix = isPrivate
|
||||
? $"_private-room-{instanceNumber}-{instanceId}"
|
||||
: "";
|
||||
|
||||
var session = new RoomInstance
|
||||
{
|
||||
roomInstanceId = instanceNumber,
|
||||
roomId = (long)roomData.RoomId,
|
||||
subRoomId = (long)roomData.SubRooms[0].SubRoomId,
|
||||
location = roomData.SubRooms[0].UnitySceneId,
|
||||
roomInstanceType = 0,
|
||||
name = formattedRoomName,
|
||||
maxCapacity = CapacityOf(roomData.SubRooms[0]),
|
||||
isFull = false,
|
||||
isPrivate = isPrivate,
|
||||
isInProgress = false,
|
||||
photonRoomIdYeee = photonSuffix,
|
||||
voiceServerId = null, // this not supported and game may explode when connecting to a server that dont exist
|
||||
voiceAuthId = null,
|
||||
matchmakingPolicy = 0
|
||||
};
|
||||
|
||||
if (!string.IsNullOrEmpty(sceneName))
|
||||
{
|
||||
ApplySceneSettings(session, roomData, roomName, sceneName, isPrivate);
|
||||
}
|
||||
else
|
||||
{
|
||||
ApplyRandomPublicSubroom(session, roomData, roomName, isPrivate);
|
||||
}
|
||||
|
||||
// Now that the subroom is final, give a public instance its own Photon room.
|
||||
// Room + subroom + instance: two players in the SAME instance produce the same
|
||||
// name and meet; different instances never collide.
|
||||
if (!isPrivate)
|
||||
session.photonRoomIdYeee = $"room-{session.roomId}-{session.subRoomId}-{session.roomInstanceId}";
|
||||
|
||||
return session;
|
||||
}
|
||||
|
||||
public static RoomInstance CreateDorm(ulong id, string name)
|
||||
{
|
||||
Random rng = new Random();
|
||||
|
||||
long RandomNumber = rng.Next(1000, 999999999);
|
||||
|
||||
ulong DormId = PlayerDB.GetDormId(id);
|
||||
|
||||
RoomDBClasses.RoomRoot dorm = RoomDB.GetRoom(DormId);
|
||||
if (dorm == null)
|
||||
{
|
||||
// Was: created the dorm but never re-read it, then dereferenced the
|
||||
// still-null `dorm` below at `dorm.SubRooms` - a guaranteed
|
||||
// NullReferenceException. MatchmakeToDorm swallows that in its catch,
|
||||
// so UpdatePlayerHeartbeat never ran and the player was handed a room
|
||||
// instance the server had not registered.
|
||||
Console.WriteLine($"[CreateDorm] player {id}: dorm room {DormId} missing - creating a fresh one");
|
||||
|
||||
if (!PlayerDB.CreateDormForPlayerId(id))
|
||||
{
|
||||
Console.WriteLine($"[CreateDorm] player {id}: could not create a dorm");
|
||||
return null;
|
||||
}
|
||||
|
||||
DormId = PlayerDB.GetDormId(id);
|
||||
dorm = RoomDB.GetRoom(DormId);
|
||||
|
||||
if (dorm == null)
|
||||
{
|
||||
Console.WriteLine($"[CreateDorm] player {id}: dorm {DormId} still missing after create - giving up");
|
||||
return null;
|
||||
}
|
||||
|
||||
Console.WriteLine($"[CreateDorm] player {id}: dorm rebuilt as room {DormId}");
|
||||
}
|
||||
// REUSE the dorm's live session (reference: playerDormInstance - "the owner leaving and
|
||||
// coming back lands in the same session"). Minting a fresh instance id + Photon room on
|
||||
// every dorm matchmake meant: the client's presence disagreed with the server after any
|
||||
// repeat request (it then re-matchmade, got yet another id, and looped - five new dorm
|
||||
// ids in 30 s were seen live), and a guest invited into the dorm sat in a different
|
||||
// Photon room than the owner the moment the owner re-entered. Order of preference: the
|
||||
// owner's own current instance of this dorm, anyone else's live instance of it (a guest
|
||||
// already inside), then the recently-live one from memory.
|
||||
RoomInstance? existing = null;
|
||||
var own = HeartbeatDB.GetSelfPresence(id).room;
|
||||
if (own != null && own.roomId == (long)DormId && !string.IsNullOrEmpty(own.photonRoomIdYeee)) existing = own;
|
||||
existing ??= HeartbeatDB.FindInstanceByRoomId((long)DormId);
|
||||
existing ??= HeartbeatDB.RecentInstanceOfRoomAny(DormId);
|
||||
if (existing != null && !string.IsNullOrEmpty(existing.photonRoomIdYeee))
|
||||
{
|
||||
// Refresh the scene/subroom off the room record so a dorm edit shows on the next visit.
|
||||
existing.subRoomId = (long?)dorm.SubRooms.FirstOrDefault()?.SubRoomId ?? existing.subRoomId;
|
||||
existing.name = $"@{name}'s Dorm";
|
||||
RoomDB.IncreaseRoomVisit(DormId);
|
||||
return existing;
|
||||
}
|
||||
|
||||
long instanceNumber = random.Next(1000, 999999999);
|
||||
Guid instanceId = Guid.NewGuid();
|
||||
|
||||
string photonSuffix = $"Campus-Dorm-{instanceNumber}-{instanceId}";
|
||||
var session = new RoomInstance
|
||||
{
|
||||
roomInstanceId = RandomNumber,
|
||||
roomId = (long)DormId,
|
||||
subRoomId = (long?)dorm.SubRooms.FirstOrDefault()?.SubRoomId ?? 0,
|
||||
location = "76d98498-60a1-430c-ab76-b54a29b7a163",
|
||||
roomInstanceType = 2, // RoomInstanceType.Dormroom (reference enum: Public 0, Private 1, Dormroom 2)
|
||||
name = $"@{name}'s Dorm",
|
||||
maxCapacity = CapacityOf(dorm.SubRooms.FirstOrDefault()),
|
||||
isFull = false,
|
||||
isPrivate = true,
|
||||
isInProgress = false,
|
||||
photonRoomIdYeee = photonSuffix,
|
||||
voiceServerId = null, // this not supported and game may explode when connecting to a server that dont exist
|
||||
voiceAuthId = null,
|
||||
matchmakingPolicy = 0
|
||||
};
|
||||
|
||||
RoomDB.IncreaseRoomVisit(DormId);
|
||||
|
||||
return session;
|
||||
}
|
||||
|
||||
// What the room settings show as "Max players" for that subroom; 4 when unset (reference).
|
||||
public static int CapacityOf(RoomDBClasses.SubRoom? sub) => sub != null && sub.MaxPlayers > 0 ? sub.MaxPlayers : 4;
|
||||
|
||||
private static void ApplySceneSettings(RoomInstance session, RoomDBClasses.RoomRoot roomData, string roomName, string sceneName, bool isPrivate)
|
||||
{
|
||||
foreach (var subroom in roomData.SubRooms)
|
||||
{
|
||||
if (subroom.Name.Equals(sceneName, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
session.subRoomId = (long)subroom.SubRoomId;
|
||||
session.location = subroom.UnitySceneId;
|
||||
session.maxCapacity = CapacityOf(subroom); // the cap is per SUBROOM, not SubRooms[0]'s
|
||||
|
||||
if (!isPrivate)
|
||||
{
|
||||
//session.photonRoomId = $"{roomName}-hello-room-{sceneName}";
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Console.WriteLine($"Scene \"{sceneName}\" not found in room \"{roomName}\".");
|
||||
}
|
||||
|
||||
private static void ApplyRandomPublicSubroom(RoomInstance session, RoomDBClasses.RoomRoot roomData, string roomName, bool isPrivate)
|
||||
{
|
||||
var publicSubrooms = roomData.SubRooms
|
||||
.Where(sub => sub.Accessibility == RoomDBClasses.RoomAccessibility.Public)
|
||||
.ToList();
|
||||
|
||||
if (publicSubrooms.Count == 0)
|
||||
{
|
||||
Console.WriteLine($"No public subrooms found for \"{roomName}\".");
|
||||
return;
|
||||
}
|
||||
|
||||
var selectedSubroom = publicSubrooms[random.Next(publicSubrooms.Count)];
|
||||
|
||||
session.subRoomId = (long)selectedSubroom.SubRoomId;
|
||||
session.location = selectedSubroom.UnitySceneId;
|
||||
session.maxCapacity = CapacityOf(selectedSubroom);
|
||||
|
||||
if (!isPrivate)
|
||||
{
|
||||
//session.photonRoomId = $"{roomName}-hello-room-{selectedSubroom.name}";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user