From 6edccfe2aa04d90352c1c0913c1bcd47157babbd Mon Sep 17 00:00:00 2001 From: Kamron Batman <3953314+kamronbatman@users.noreply.github.com> Date: Thu, 16 Jun 2022 10:19:49 -0700 Subject: [PATCH] fix: Codegens mahjong (#1070) --- .../Games/Mahjong/MahjongDealerIndicator.cs | 113 +-- .../Items/Games/Mahjong/MahjongDices.cs | 77 +- .../Items/Games/Mahjong/MahjongEnums.cs | 107 +- .../Items/Games/Mahjong/MahjongGame.cs | 583 ++++++----- .../Items/Games/Mahjong/MahjongPieceDim.cs | 75 +- .../Items/Games/Mahjong/MahjongPlayers.cs | 931 +++++++++--------- .../Items/Games/Mahjong/MahjongTile.cs | 163 ++- .../Games/Mahjong/MahjongTileTypeGenerator.cs | 43 +- .../Mahjong/MahjongWallBreakIndicator.cs | 72 +- ...nes.Mahjong.MahjongDealerIndicator.v1.json | 24 + ...erver.Engines.Mahjong.MahjongDices.v0.json | 22 + ...Server.Engines.Mahjong.MahjongGame.v1.json | 69 ++ ...ver.Engines.Mahjong.MahjongPlayers.v1.json | 53 + ...Server.Engines.Mahjong.MahjongTile.v1.json | 48 + ....Mahjong.MahjongWallBreakIndicator.v0.json | 14 + 15 files changed, 1272 insertions(+), 1122 deletions(-) create mode 100644 Projects/UOContent/Migrations/Server.Engines.Mahjong.MahjongDealerIndicator.v1.json create mode 100644 Projects/UOContent/Migrations/Server.Engines.Mahjong.MahjongDices.v0.json create mode 100644 Projects/UOContent/Migrations/Server.Engines.Mahjong.MahjongGame.v1.json create mode 100644 Projects/UOContent/Migrations/Server.Engines.Mahjong.MahjongPlayers.v1.json create mode 100644 Projects/UOContent/Migrations/Server.Engines.Mahjong.MahjongTile.v1.json create mode 100644 Projects/UOContent/Migrations/Server.Engines.Mahjong.MahjongWallBreakIndicator.v0.json diff --git a/Projects/UOContent/Items/Games/Mahjong/MahjongDealerIndicator.cs b/Projects/UOContent/Items/Games/Mahjong/MahjongDealerIndicator.cs index 2d9d694be..3b2309e83 100644 --- a/Projects/UOContent/Items/Games/Mahjong/MahjongDealerIndicator.cs +++ b/Projects/UOContent/Items/Games/Mahjong/MahjongDealerIndicator.cs @@ -1,69 +1,62 @@ -namespace Server.Engines.Mahjong +using ModernUO.Serialization; + +namespace Server.Engines.Mahjong; + +[SerializationGenerator(1, false)] +public partial class MahjongDealerIndicator { - public class MahjongDealerIndicator + [DirtyTrackingEntity] + private readonly MahjongGame _game; + + [SerializableField(0, setter: "private")] + private Point2D _position; + + [SerializableField(1, setter: "private")] + private MahjongPieceDirection _direction; + + [SerializableField(2, setter: "private")] + private MahjongWind _wind; + + public MahjongDealerIndicator(MahjongGame game) { - public MahjongDealerIndicator(MahjongGame game, Point2D position, MahjongPieceDirection direction, MahjongWind wind) + _game = game; + } + + public MahjongDealerIndicator(MahjongGame game, Point2D position, MahjongPieceDirection direction, MahjongWind wind) + { + _game = game; + _position = position; + _direction = direction; + _wind = wind; + } + + public MahjongPieceDim Dimensions => GetDimensions(_position, _direction); + + public static MahjongPieceDim GetDimensions(Point2D position, MahjongPieceDirection direction) => + direction is MahjongPieceDirection.Up or MahjongPieceDirection.Down + ? new MahjongPieceDim(position, 40, 20) + : new MahjongPieceDim(position, 20, 40); + + public void Move(Point2D position, MahjongPieceDirection direction, MahjongWind wind) + { + var dim = GetDimensions(position, direction); + + if (!dim.IsValid()) { - Game = game; - Position = position; - Direction = direction; - Wind = wind; + return; } - public MahjongDealerIndicator(MahjongGame game, IGenericReader reader) - { - Game = game; + _position = position; + _direction = direction; + _wind = wind; - var version = reader.ReadInt(); + _game.Players.SendGeneralPacket(true, true); + } - Position = reader.ReadPoint2D(); - Direction = (MahjongPieceDirection)reader.ReadInt(); - Wind = (MahjongWind)reader.ReadInt(); - } - - public MahjongGame Game { get; } - - public Point2D Position { get; private set; } - - public MahjongPieceDirection Direction { get; private set; } - - public MahjongWind Wind { get; private set; } - - public MahjongPieceDim Dimensions => GetDimensions(Position, Direction); - - public static MahjongPieceDim GetDimensions(Point2D position, MahjongPieceDirection direction) - { - if (direction is MahjongPieceDirection.Up or MahjongPieceDirection.Down) - { - return new MahjongPieceDim(position, 40, 20); - } - - return new MahjongPieceDim(position, 20, 40); - } - - public void Move(Point2D position, MahjongPieceDirection direction, MahjongWind wind) - { - var dim = GetDimensions(position, direction); - - if (!dim.IsValid()) - { - return; - } - - Position = position; - Direction = direction; - Wind = wind; - - Game.Players.SendGeneralPacket(true, true); - } - - public void Save(IGenericWriter writer) - { - writer.Write(0); // version - - writer.Write(Position); - writer.Write((int)Direction); - writer.Write((int)Wind); - } + private void Deserialize(IGenericReader reader, int version) + { + _position = reader.ReadPoint2D(); + _direction = (MahjongPieceDirection)reader.ReadInt(); + _wind = (MahjongWind)reader.ReadInt(); } } diff --git a/Projects/UOContent/Items/Games/Mahjong/MahjongDices.cs b/Projects/UOContent/Items/Games/Mahjong/MahjongDices.cs index 41666961c..80ca47512 100644 --- a/Projects/UOContent/Items/Games/Mahjong/MahjongDices.cs +++ b/Projects/UOContent/Items/Games/Mahjong/MahjongDices.cs @@ -1,52 +1,37 @@ -namespace Server.Engines.Mahjong +using ModernUO.Serialization; + +namespace Server.Engines.Mahjong; + +[SerializationGenerator(0, false)] +public partial class MahjongDices { - public class MahjongDices + [DirtyTrackingEntity] + private readonly MahjongGame _game; + + [SerializableField(0, setter: "private")] + private int _first; + + [SerializableField(1, setter: "private")] + private int _second; + + public MahjongDices(MahjongGame game) { - public MahjongDices(MahjongGame game) + _game = game; + _first = Utility.Random(1, 6); + _second = Utility.Random(1, 6); + } + + public void RollDices(Mobile from) + { + _first = Utility.Random(1, 6); + _second = Utility.Random(1, 6); + + _game.Players.SendGeneralPacket(true, true); + + if (from != null) { - Game = game; - First = Utility.Random(1, 6); - Second = Utility.Random(1, 6); - } - - public MahjongDices(MahjongGame game, IGenericReader reader) - { - Game = game; - - var version = reader.ReadInt(); - - First = reader.ReadInt(); - Second = reader.ReadInt(); - } - - public MahjongGame Game { get; } - - public int First { get; private set; } - - public int Second { get; private set; } - - public void RollDices(Mobile from) - { - First = Utility.Random(1, 6); - Second = Utility.Random(1, 6); - - Game.Players.SendGeneralPacket(true, true); - - if (from != null) - { - Game.Players.SendLocalizedMessage( - 1062695, - $"{from.Name}\t{First}\t{Second}" - ); // ~1_name~ rolls the dice and gets a ~2_number~ and a ~3_number~! - } - } - - public void Save(IGenericWriter writer) - { - writer.Write(0); // version - - writer.Write(First); - writer.Write(Second); + // ~1_name~ rolls the dice and gets a ~2_number~ and a ~3_number~! + _game.Players.SendLocalizedMessage(1062695, $"{from.Name}\t{_first}\t{_second}"); } } } diff --git a/Projects/UOContent/Items/Games/Mahjong/MahjongEnums.cs b/Projects/UOContent/Items/Games/Mahjong/MahjongEnums.cs index 4dd79a98d..32d6b3ad6 100644 --- a/Projects/UOContent/Items/Games/Mahjong/MahjongEnums.cs +++ b/Projects/UOContent/Items/Games/Mahjong/MahjongEnums.cs @@ -1,56 +1,55 @@ -namespace Server.Engines.Mahjong +namespace Server.Engines.Mahjong; + +public enum MahjongPieceDirection { - public enum MahjongPieceDirection - { - Up, - Left, - Down, - Right - } - - public enum MahjongWind - { - North, - East, - South, - West - } - - public enum MahjongTileType - { - Dagger1 = 1, - Dagger2, - Dagger3, - Dagger4, - Dagger5, - Dagger6, - Dagger7, - Dagger8, - Dagger9, - Gem1, - Gem2, - Gem3, - Gem4, - Gem5, - Gem6, - Gem7, - Gem8, - Gem9, - Number1, - Number2, - Number3, - Number4, - Number5, - Number6, - Number7, - Number8, - Number9, - North, - East, - South, - West, - Green, - Red, - White - } + Up, + Left, + Down, + Right +} + +public enum MahjongWind +{ + North, + East, + South, + West +} + +public enum MahjongTileType +{ + Dagger1 = 1, + Dagger2, + Dagger3, + Dagger4, + Dagger5, + Dagger6, + Dagger7, + Dagger8, + Dagger9, + Gem1, + Gem2, + Gem3, + Gem4, + Gem5, + Gem6, + Gem7, + Gem8, + Gem9, + Number1, + Number2, + Number3, + Number4, + Number5, + Number6, + Number7, + Number8, + Number9, + North, + East, + South, + West, + Green, + Red, + White } diff --git a/Projects/UOContent/Items/Games/Mahjong/MahjongGame.cs b/Projects/UOContent/Items/Games/Mahjong/MahjongGame.cs index 4bd778ee2..827b135cf 100644 --- a/Projects/UOContent/Items/Games/Mahjong/MahjongGame.cs +++ b/Projects/UOContent/Items/Games/Mahjong/MahjongGame.cs @@ -1,347 +1,316 @@ using System; using System.Collections.Generic; +using ModernUO.Serialization; using Server.ContextMenus; using Server.Gumps; using Server.Multis; -namespace Server.Engines.Mahjong +namespace Server.Engines.Mahjong; + +[SerializationGenerator(1, false)] +public partial class MahjongGame : Item, ISecurable { - public class MahjongGame : Item, ISecurable + public const int MaxPlayers = 4; + public const int BaseScore = 30000; + + [SerializableField(0)] + [SerializableFieldAttr("[CommandProperty(AccessLevel.GameMaster)]")] + private SecureLevel _level; + + [SerializableField(1, setter: "private")] + private MahjongTile[] _tiles; + + [SerializableField(2, setter: "private")] + private MahjongDealerIndicator _dealerIndicator; + + [SerializableField(3, setter: "private")] + private MahjongWallBreakIndicator _wallBreakIndicator; + + [SerializableField(4, setter: "private")] + private MahjongDices _dices; + + [SerializableField(5, setter: "private")] + private MahjongPlayers _players; + + // Field 6 + private bool _showScores; + + // Field 7 + private bool _spectatorVision; + + private DateTime _lastReset; + + [Constructible] + public MahjongGame() : base(0xFAA) { - public const int MaxPlayers = 4; - public const int BaseScore = 30000; - private DateTime m_LastReset; + Weight = 5.0; - private bool m_ShowScores; - private bool m_SpectatorVision; + BuildWalls(); + _dealerIndicator = + new MahjongDealerIndicator(this, new Point2D(300, 300), MahjongPieceDirection.Up, MahjongWind.North); + _wallBreakIndicator = new MahjongWallBreakIndicator(this, new Point2D(335, 335)); + _dices = new MahjongDices(this); + _players = new MahjongPlayers(this, MaxPlayers, BaseScore); + _lastReset = Core.Now; + _level = SecureLevel.CoOwners; + } - [Constructible] - public MahjongGame() : base(0xFAA) + [CommandProperty(AccessLevel.GameMaster)] + [SerializableField(6)] + public bool ShowScores + { + get => _showScores; + set { - Weight = 5.0; - - BuildWalls(); - DealerIndicator = - new MahjongDealerIndicator(this, new Point2D(300, 300), MahjongPieceDirection.Up, MahjongWind.North); - WallBreakIndicator = new MahjongWallBreakIndicator(this, new Point2D(335, 335)); - Dices = new MahjongDices(this); - Players = new MahjongPlayers(this, MaxPlayers, BaseScore); - m_LastReset = Core.Now; - Level = SecureLevel.CoOwners; - } - - public MahjongGame(Serial serial) : base(serial) - { - } - - public MahjongTile[] Tiles { get; private set; } - - public MahjongDealerIndicator DealerIndicator { get; private set; } - - public MahjongWallBreakIndicator WallBreakIndicator { get; private set; } - - public MahjongDices Dices { get; private set; } - - public MahjongPlayers Players { get; private set; } - - [CommandProperty(AccessLevel.GameMaster)] - public bool ShowScores - { - get => m_ShowScores; - set - { - if (m_ShowScores == value) - { - return; - } - - m_ShowScores = value; - - if (value) - { - Players.SendPlayersPacket(true, true); - } - - Players.SendGeneralPacket(true, true); - - Players.SendLocalizedMessage(value ? 1062777 : 1062778); // The dealer has enabled/disabled score display. - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool SpectatorVision - { - get => m_SpectatorVision; - set - { - if (m_SpectatorVision == value) - { - return; - } - - m_SpectatorVision = value; - - if (Players.IsInGamePlayer(Players.DealerPosition)) - { - Players.Dealer.NetState.SendMahjongGeneralInfo(this); - } - - Players.SendTilesPacket(false, true); - - Players.SendLocalizedMessage(value ? 1062715 : 1062716); // The dealer has enabled/disabled Spectator Vision. - - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public SecureLevel Level { get; set; } - - private void BuildHorizontalWall( - ref int index, int x, int y, int stackLevel, MahjongPieceDirection direction, - MahjongTileTypeGenerator typeGenerator - ) - { - for (var i = 0; i < 17; i++) - { - var position = new Point2D(x + i * 20, y); - Tiles[index + i] = new MahjongTile( - this, - index + i, - typeGenerator.Next(), - position, - stackLevel, - direction, - false - ); - } - - index += 17; - } - - private void BuildVerticalWall( - ref int index, int x, int y, int stackLevel, MahjongPieceDirection direction, - MahjongTileTypeGenerator typeGenerator - ) - { - for (var i = 0; i < 17; i++) - { - var position = new Point2D(x, y + i * 20); - Tiles[index + i] = new MahjongTile( - this, - index + i, - typeGenerator.Next(), - position, - stackLevel, - direction, - false - ); - } - - index += 17; - } - - private void BuildWalls() - { - Tiles = new MahjongTile[136]; - - var typeGenerator = new MahjongTileTypeGenerator(); - - var i = 0; - - BuildHorizontalWall(ref i, 165, 110, 0, MahjongPieceDirection.Up, typeGenerator); - BuildHorizontalWall(ref i, 165, 115, 1, MahjongPieceDirection.Up, typeGenerator); - - BuildVerticalWall(ref i, 530, 165, 0, MahjongPieceDirection.Left, typeGenerator); - BuildVerticalWall(ref i, 525, 165, 1, MahjongPieceDirection.Left, typeGenerator); - - BuildHorizontalWall(ref i, 165, 530, 0, MahjongPieceDirection.Down, typeGenerator); - BuildHorizontalWall(ref i, 165, 525, 1, MahjongPieceDirection.Down, typeGenerator); - - BuildVerticalWall(ref i, 110, 165, 0, MahjongPieceDirection.Right, typeGenerator); - BuildVerticalWall(ref i, 115, 165, 1, MahjongPieceDirection.Right, typeGenerator); - } - - public override void GetProperties(IPropertyList list) - { - base.GetProperties(list); - - if (m_SpectatorVision) - { - list.Add(1062717); // Spectator Vision Enabled - } - else - { - list.Add(1062718); // Spectator Vision Disabled - } - } - - public override void GetContextMenuEntries(Mobile from, List list) - { - base.GetContextMenuEntries(from, list); - - Players.CheckPlayers(); - - if (from.Alive && IsAccessibleTo(from) && Players.GetInGameMobiles(true, false).Count == 0) - { - list.Add(new ResetGameEntry(this)); - } - - SetSecureLevelEntry.AddTo(from, this, list); - } - - public override void OnDoubleClick(Mobile from) - { - Players.CheckPlayers(); - - Players.Join(from); - } - - public void ResetGame(Mobile from) - { - if (Core.Now - m_LastReset < TimeSpan.FromSeconds(5.0)) + if (_showScores == value) { return; } - m_LastReset = Core.Now; + _showScores = value; - if (from != null) + if (value) { - Players.SendLocalizedMessage(1062771, from.Name); // ~1_name~ has reset the game. + _players.SendPlayersPacket(true, true); } - Players.SendRelievePacket(true, true); - - BuildWalls(); - DealerIndicator = - new MahjongDealerIndicator(this, new Point2D(300, 300), MahjongPieceDirection.Up, MahjongWind.North); - WallBreakIndicator = new MahjongWallBreakIndicator(this, new Point2D(335, 335)); - Players = new MahjongPlayers(this, MaxPlayers, BaseScore); + _players.SendGeneralPacket(true, true); + _players.SendLocalizedMessage(value ? 1062777 : 1062778); // The dealer has enabled/disabled score display. + this.MarkDirty(); } + } - public void ResetWalls(Mobile from) + [CommandProperty(AccessLevel.GameMaster)] + [SerializableField(7)] + public bool SpectatorVision + { + get => _spectatorVision; + set { - if (Core.Now - m_LastReset < TimeSpan.FromSeconds(5.0)) + if (_spectatorVision == value) { return; } - m_LastReset = Core.Now; + _spectatorVision = value; - BuildWalls(); - - Players.SendTilesPacket(true, true); - - if (from != null) + if (_players.IsInGamePlayer(_players.DealerPosition)) { - Players.SendLocalizedMessage(1062696); // The dealer rebuilds the wall. + _players.Dealer.NetState.SendMahjongGeneralInfo(this); + } + + _players.SendTilesPacket(false, true); + _players.SendLocalizedMessage(value ? 1062715 : 1062716); // The dealer has enabled/disabled Spectator Vision. + InvalidateProperties(); + this.MarkDirty(); + } + } + + private void BuildHorizontalWall( + ref int index, int x, int y, int stackLevel, MahjongPieceDirection direction, + MahjongTileTypeGenerator typeGenerator + ) + { + for (var i = 0; i < 17; i++) + { + var position = new Point2D(x + i * 20, y); + Tiles[index + i] = new MahjongTile( + this, + index + i, + typeGenerator.Next(), + position, + stackLevel, + direction, + false + ); + } + + index += 17; + this.MarkDirty(); + } + + private void BuildVerticalWall( + ref int index, int x, int y, int stackLevel, MahjongPieceDirection direction, + MahjongTileTypeGenerator typeGenerator + ) + { + for (var i = 0; i < 17; i++) + { + var position = new Point2D(x, y + i * 20); + Tiles[index + i] = new MahjongTile( + this, + index + i, + typeGenerator.Next(), + position, + stackLevel, + direction, + false + ); + } + + index += 17; + this.MarkDirty(); + } + + private void BuildWalls() + { + Tiles = new MahjongTile[136]; + + var typeGenerator = new MahjongTileTypeGenerator(); + + var i = 0; + + BuildHorizontalWall(ref i, 165, 110, 0, MahjongPieceDirection.Up, typeGenerator); + BuildHorizontalWall(ref i, 165, 115, 1, MahjongPieceDirection.Up, typeGenerator); + + BuildVerticalWall(ref i, 530, 165, 0, MahjongPieceDirection.Left, typeGenerator); + BuildVerticalWall(ref i, 525, 165, 1, MahjongPieceDirection.Left, typeGenerator); + + BuildHorizontalWall(ref i, 165, 530, 0, MahjongPieceDirection.Down, typeGenerator); + BuildHorizontalWall(ref i, 165, 525, 1, MahjongPieceDirection.Down, typeGenerator); + + BuildVerticalWall(ref i, 110, 165, 0, MahjongPieceDirection.Right, typeGenerator); + BuildVerticalWall(ref i, 115, 165, 1, MahjongPieceDirection.Right, typeGenerator); + } + + public override void GetProperties(IPropertyList list) + { + base.GetProperties(list); + + if (_spectatorVision) + { + list.Add(1062717); // Spectator Vision Enabled + } + else + { + list.Add(1062718); // Spectator Vision Disabled + } + } + + public override void GetContextMenuEntries(Mobile from, List list) + { + base.GetContextMenuEntries(from, list); + + _players.CheckPlayers(); + + if (from.Alive && IsAccessibleTo(from) && _players.GetInGameMobiles(true, false).Count == 0) + { + list.Add(new ResetGameEntry(this)); + } + + SetSecureLevelEntry.AddTo(from, this, list); + } + + public override void OnDoubleClick(Mobile from) + { + _players.CheckPlayers(); + _players.Join(from); + } + + public void ResetGame(Mobile from) + { + if (Core.Now - _lastReset < TimeSpan.FromSeconds(5.0)) + { + return; + } + + _lastReset = Core.Now; + + if (from != null) + { + _players.SendLocalizedMessage(1062771, from.Name); // ~1_name~ has reset the game. + } + + _players.SendRelievePacket(true, true); + + BuildWalls(); + DealerIndicator = + new MahjongDealerIndicator(this, new Point2D(300, 300), MahjongPieceDirection.Up, MahjongWind.North); + WallBreakIndicator = new MahjongWallBreakIndicator(this, new Point2D(335, 335)); + Players = new MahjongPlayers(this, MaxPlayers, BaseScore); + } + + public void ResetWalls(Mobile from) + { + if (Core.Now - _lastReset < TimeSpan.FromSeconds(5.0)) + { + return; + } + + _lastReset = Core.Now; + + BuildWalls(); + + _players.SendTilesPacket(true, true); + + if (from != null) + { + _players.SendLocalizedMessage(1062696); // The dealer rebuilds the wall. + } + } + + public int GetStackLevel(MahjongPieceDim dim) + { + var level = -1; + foreach (var tile in _tiles) + { + if (tile.StackLevel > level && dim.IsOverlapping(tile.Dimensions)) + { + level = tile.StackLevel; } } - public int GetStackLevel(MahjongPieceDim dim) - { - var level = -1; - foreach (var tile in Tiles) - { - if (tile.StackLevel > level && dim.IsOverlapping(tile.Dimensions)) - { - level = tile.StackLevel; - } - } + return level; + } - return level; + private void Deserialize(IGenericReader reader, int number) + { + _level = (SecureLevel)reader.ReadInt(); + var length = reader.ReadInt(); + _tiles = new MahjongTile[length]; + + for (var i = 0; i < length; i++) + { + var tile = _tiles[i] = new MahjongTile(this); + tile.Deserialize(reader); } - public override void Serialize(IGenericWriter writer) + _dealerIndicator = new MahjongDealerIndicator(this); + _dealerIndicator.Deserialize(reader); + + _wallBreakIndicator = new MahjongWallBreakIndicator(this); + _wallBreakIndicator.Deserialize(reader); + + _dices = new MahjongDices(this); + _dices.Deserialize(reader); + + _players = new MahjongPlayers(this); + _players.Deserialize(reader); + + _showScores = reader.ReadBool(); + _spectatorVision = reader.ReadBool(); + } + + [AfterDeserialization] + private void AfterDeserialization() + { + _lastReset = Core.Now; + } + + private class ResetGameEntry : ContextMenuEntry + { + private readonly MahjongGame _game; + + public ResetGameEntry(MahjongGame game) : base(6162) => _game = game; + + public override void OnClick() { - base.Serialize(writer); + var from = Owner.From; - writer.Write(1); // version - - writer.Write((int)Level); - - writer.Write(Tiles.Length); - - for (var i = 0; i < Tiles.Length; i++) + if (from.CheckAlive() && !_game.Deleted && _game.IsAccessibleTo(from) && + _game.Players.GetInGameMobiles(true, false).Count == 0) { - Tiles[i].Save(writer); - } - - DealerIndicator.Save(writer); - - WallBreakIndicator.Save(writer); - - Dices.Save(writer); - - Players.Save(writer); - - writer.Write(m_ShowScores); - writer.Write(m_SpectatorVision); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - var version = reader.ReadInt(); - - switch (version) - { - case 1: - { - Level = (SecureLevel)reader.ReadInt(); - - goto case 0; - } - case 0: - { - if (version < 1) - { - Level = SecureLevel.CoOwners; - } - - var length = reader.ReadInt(); - Tiles = new MahjongTile[length]; - - for (var i = 0; i < length; i++) - { - Tiles[i] = new MahjongTile(this, reader); - } - - DealerIndicator = new MahjongDealerIndicator(this, reader); - - WallBreakIndicator = new MahjongWallBreakIndicator(this, reader); - - Dices = new MahjongDices(this, reader); - - Players = new MahjongPlayers(this, reader); - - m_ShowScores = reader.ReadBool(); - m_SpectatorVision = reader.ReadBool(); - - m_LastReset = Core.Now; - - break; - } - } - } - - private class ResetGameEntry : ContextMenuEntry - { - private readonly MahjongGame m_Game; - - public ResetGameEntry(MahjongGame game) : base(6162) => m_Game = game; - - public override void OnClick() - { - var from = Owner.From; - - if (from.CheckAlive() && !m_Game.Deleted && m_Game.IsAccessibleTo(from) && - m_Game.Players.GetInGameMobiles(true, false).Count == 0) - { - m_Game.ResetGame(from); - } + _game.ResetGame(from); } } } diff --git a/Projects/UOContent/Items/Games/Mahjong/MahjongPieceDim.cs b/Projects/UOContent/Items/Games/Mahjong/MahjongPieceDim.cs index 932f941b3..d93df6372 100644 --- a/Projects/UOContent/Items/Games/Mahjong/MahjongPieceDim.cs +++ b/Projects/UOContent/Items/Games/Mahjong/MahjongPieceDim.cs @@ -1,50 +1,49 @@ -namespace Server.Engines.Mahjong +namespace Server.Engines.Mahjong; + +public struct MahjongPieceDim { - public struct MahjongPieceDim + public Point2D Position { get; } + + public int Width { get; } + + public int Height { get; } + + public MahjongPieceDim(Point2D position, int width, int height) { - public Point2D Position { get; } + Position = position; + Width = width; + Height = height; + } - public int Width { get; } + public bool IsValid() => + Position.X >= 0 && Position.Y >= 0 && Position.X + Width <= 670 && Position.Y + Height <= 670; - public int Height { get; } + public bool IsOverlapping(MahjongPieceDim dim) => + Position.X < dim.Position.X + dim.Width && Position.Y < dim.Position.Y + dim.Height && + Position.X + Width > dim.Position.X && Position.Y + Height > dim.Position.Y; - public MahjongPieceDim(Point2D position, int width, int height) + public int GetHandArea() + { + if (Position.X + Width > 150 && Position.X < 520 && Position.Y < 35) { - Position = position; - Width = width; - Height = height; + return 0; } - public bool IsValid() => - Position.X >= 0 && Position.Y >= 0 && Position.X + Width <= 670 && Position.Y + Height <= 670; - - public bool IsOverlapping(MahjongPieceDim dim) => - Position.X < dim.Position.X + dim.Width && Position.Y < dim.Position.Y + dim.Height && - Position.X + Width > dim.Position.X && Position.Y + Height > dim.Position.Y; - - public int GetHandArea() + if (Position.X + Width > 635 && Position.Y + Height > 150 && Position.Y < 520) { - if (Position.X + Width > 150 && Position.X < 520 && Position.Y < 35) - { - return 0; - } - - if (Position.X + Width > 635 && Position.Y + Height > 150 && Position.Y < 520) - { - return 1; - } - - if (Position.X + Width > 150 && Position.X < 520 && Position.Y + Height > 635) - { - return 2; - } - - if (Position.X < 35 && Position.Y + Height > 150 && Position.Y < 520) - { - return 3; - } - - return -1; + return 1; } + + if (Position.X + Width > 150 && Position.X < 520 && Position.Y + Height > 635) + { + return 2; + } + + if (Position.X < 35 && Position.Y + Height > 150 && Position.Y < 520) + { + return 3; + } + + return -1; } } diff --git a/Projects/UOContent/Items/Games/Mahjong/MahjongPlayers.cs b/Projects/UOContent/Items/Games/Mahjong/MahjongPlayers.cs index 898b64009..2627ec27e 100644 --- a/Projects/UOContent/Items/Games/Mahjong/MahjongPlayers.cs +++ b/Projects/UOContent/Items/Games/Mahjong/MahjongPlayers.cs @@ -1,607 +1,604 @@ using System; using System.Collections.Generic; +using ModernUO.Serialization; using Server.Network; -namespace Server.Engines.Mahjong +namespace Server.Engines.Mahjong; + +[SerializationGenerator(1, false)] +public partial class MahjongPlayers { - public class MahjongPlayers + [SerializableField(0, setter: "private")] + private Mobile[] _players; + + [SerializableField(1, setter: "private")] + private bool[] _inGame; + + [SerializableField(2, setter: "private")] + private bool[] _publicHand; + + [SerializableField(3, setter: "private")] + private int[] _scores; + + [SerializableField(4, setter: "private")] + private int _dealerPosition; + + private List _spectators; + + [DirtyTrackingEntity] + private readonly MahjongGame _game; + + public MahjongPlayers(MahjongGame game, int maxPlayers, int baseScore) { - private readonly bool[] m_InGame; - private readonly Mobile[] m_Players; - private readonly bool[] m_PublicHand; - private readonly int[] m_Scores; - private readonly List m_Spectators; + _game = game; + _spectators = new List(); - public MahjongPlayers(MahjongGame game, int maxPlayers, int baseScore) + _players = new Mobile[maxPlayers]; + _inGame = new bool[maxPlayers]; + _publicHand = new bool[maxPlayers]; + _scores = new int[maxPlayers]; + + for (var i = 0; i < _scores.Length; i++) { - Game = game; - m_Spectators = new List(); + _scores[i] = baseScore; + } + } - m_Players = new Mobile[maxPlayers]; - m_InGame = new bool[maxPlayers]; - m_PublicHand = new bool[maxPlayers]; - m_Scores = new int[maxPlayers]; + public MahjongPlayers(MahjongGame game) + { + _game = game; + _spectators = new List(); + } - for (var i = 0; i < m_Scores.Length; i++) + private void Deserialize(IGenericReader reader, int version) + { + var seats = reader.ReadInt(); + _players = new Mobile[seats]; + _inGame = new bool[seats]; + _publicHand = new bool[seats]; + _scores = new int[seats]; + + for (var i = 0; i < seats; i++) + { + _players[i] = reader.ReadEntity(); + _publicHand[i] = reader.ReadBool(); + _scores[i] = reader.ReadInt(); + } + + _dealerPosition = reader.ReadInt(); + } + + public int Seats => _players.Length; + public Mobile Dealer => _players[DealerPosition]; + + public Mobile GetPlayer(int index) + { + if (index < 0 || index >= _players.Length) + { + return null; + } + + return _players[index]; + } + + public int GetPlayerIndex(Mobile mobile) + { + for (var i = 0; i < _players.Length; i++) + { + if (_players[i] == mobile) { - m_Scores[i] = baseScore; + return i; } } - public MahjongPlayers(MahjongGame game, IGenericReader reader) + return -1; + } + + public bool IsInGameDealer(Mobile mobile) + { + if (Dealer != mobile) { - Game = game; - m_Spectators = new List(); - - var version = reader.ReadInt(); - - var seats = reader.ReadInt(); - m_Players = new Mobile[seats]; - m_InGame = new bool[seats]; - m_PublicHand = new bool[seats]; - m_Scores = new int[seats]; - - for (var i = 0; i < seats; i++) - { - m_Players[i] = reader.ReadEntity(); - m_PublicHand[i] = reader.ReadBool(); - m_Scores[i] = reader.ReadInt(); - } - - DealerPosition = reader.ReadInt(); + return false; } - public MahjongGame Game { get; } + return _inGame[DealerPosition]; + } - public int Seats => m_Players.Length; - public Mobile Dealer => m_Players[DealerPosition]; - public int DealerPosition { get; private set; } - - public Mobile GetPlayer(int index) + public bool IsInGamePlayer(int index) + { + if (index < 0 || index >= _players.Length || _players[index] == null) { - if (index < 0 || index >= m_Players.Length) - { - return null; - } - - return m_Players[index]; + return false; } - public int GetPlayerIndex(Mobile mobile) + return _inGame[index]; + } + + public bool IsInGamePlayer(Mobile mobile) + { + var index = GetPlayerIndex(mobile); + + return IsInGamePlayer(index); + } + + public bool IsSpectator(Mobile mobile) => _spectators.Contains(mobile); + + public int GetScore(int index) + { + if (index < 0 || index >= _scores.Length) { - for (var i = 0; i < m_Players.Length; i++) + return 0; + } + + return _scores[index]; + } + + public bool IsPublic(int index) + { + if (index < 0 || index >= _publicHand.Length) + { + return false; + } + + return _publicHand[index]; + } + + public void SetPublic(int index, bool value) + { + if (index < 0 || index >= _publicHand.Length || _publicHand[index] == value) + { + return; + } + + _publicHand[index] = value; + + SendTilesPacket(true, !_game.SpectatorVision); + + if (IsInGamePlayer(index)) + { + _players[index].SendLocalizedMessage(value ? 1062775 : 1062776); // Your hand is [not] publicly viewable. + } + } + + public List GetInGameMobiles(bool players, bool spectators) + { + var list = new List(); + + if (players) + { + for (var i = 0; i < _players.Length; i++) { - if (m_Players[i] == mobile) + if (IsInGamePlayer(i)) { - return i; + list.Add(_players[i]); } } - - return -1; } - public bool IsInGameDealer(Mobile mobile) + if (spectators) { - if (Dealer != mobile) + list.AddRange(_spectators); + } + + return list; + } + + public void CheckPlayers() + { + var removed = false; + + Span relievePacket = stackalloc byte[MahjongPackets.MahjongRelievePacketLength].InitializePacket(); + + for (var i = 0; i < _players.Length; i++) + { + var player = _players[i]; + + if (player == null) { - return false; + continue; } - return m_InGame[DealerPosition]; - } - - public bool IsInGamePlayer(int index) - { - if (index < 0 || index >= m_Players.Length || m_Players[index] == null) + if (player.Deleted) { - return false; + _players[i] = null; + + SendPlayerExitMessage(player); + UpdateDealer(true); + + removed = true; } - - return m_InGame[index]; - } - - public bool IsInGamePlayer(Mobile mobile) - { - var index = GetPlayerIndex(mobile); - - return IsInGamePlayer(index); - } - - public bool IsSpectator(Mobile mobile) => m_Spectators.Contains(mobile); - - public int GetScore(int index) - { - if (index < 0 || index >= m_Scores.Length) + else if (_inGame[i]) { - return 0; - } - - return m_Scores[index]; - } - - public bool IsPublic(int index) - { - if (index < 0 || index >= m_PublicHand.Length) - { - return false; - } - - return m_PublicHand[index]; - } - - public void SetPublic(int index, bool value) - { - if (index < 0 || index >= m_PublicHand.Length || m_PublicHand[index] == value) - { - return; - } - - m_PublicHand[index] = value; - - SendTilesPacket(true, !Game.SpectatorVision); - - if (IsInGamePlayer(index)) - { - m_Players[index].SendLocalizedMessage(value ? 1062775 : 1062776); // Your hand is [not] publicly viewable. - } - } - - public List GetInGameMobiles(bool players, bool spectators) - { - var list = new List(); - - if (players) - { - for (var i = 0; i < m_Players.Length; i++) + if (player.NetState == null) { - if (IsInGamePlayer(i)) - { - list.Add(m_Players[i]); - } - } - } - - if (spectators) - { - list.AddRange(m_Spectators); - } - - return list; - } - - public void CheckPlayers() - { - var removed = false; - - Span relievePacket = stackalloc byte[MahjongPackets.MahjongRelievePacketLength].InitializePacket(); - - for (var i = 0; i < m_Players.Length; i++) - { - var player = m_Players[i]; - - if (player == null) - { - continue; - } - - if (player.Deleted) - { - m_Players[i] = null; + _inGame[i] = false; SendPlayerExitMessage(player); UpdateDealer(true); removed = true; } - else if (m_InGame[i]) + else if (!_game.IsAccessibleTo(player) || player.Map != _game.Map || + !player.InRange(_game.GetWorldLocation(), 5)) { - if (player.NetState == null) - { - m_InGame[i] = false; + _inGame[i] = false; - SendPlayerExitMessage(player); - UpdateDealer(true); + MahjongPackets.CreateMahjongRelieve(relievePacket, _game.Serial); + player.NetState?.Send(relievePacket); - removed = true; - } - else if (!Game.IsAccessibleTo(player) || player.Map != Game.Map || - !player.InRange(Game.GetWorldLocation(), 5)) - { - m_InGame[i] = false; + SendPlayerExitMessage(player); + UpdateDealer(true); - MahjongPackets.CreateMahjongRelieve(relievePacket, Game.Serial); - player.NetState?.Send(relievePacket); - - SendPlayerExitMessage(player); - UpdateDealer(true); - - removed = true; - } + removed = true; } } - - for (var i = 0; i < m_Spectators.Count;) - { - var mobile = m_Spectators[i]; - - if (mobile.NetState == null || mobile.Deleted) - { - m_Spectators.RemoveAt(i); - } - else if (!Game.IsAccessibleTo(mobile) || mobile.Map != Game.Map || - !mobile.InRange(Game.GetWorldLocation(), 5)) - { - m_Spectators.RemoveAt(i); - - MahjongPackets.CreateMahjongRelieve(relievePacket, Game.Serial); - mobile.NetState?.Send(relievePacket); - } - else - { - i++; - } - } - - if (removed && !UpdateSpectators()) - { - SendPlayersPacket(true, true); - } } - private void UpdateDealer(bool message) + for (var i = 0; i < _spectators.Count;) { - if (IsInGamePlayer(DealerPosition)) + var mobile = _spectators[i]; + + if (mobile.NetState == null || mobile.Deleted) { + _spectators.RemoveAt(i); + } + else if (!_game.IsAccessibleTo(mobile) || mobile.Map != _game.Map || + !mobile.InRange(_game.GetWorldLocation(), 5)) + { + _spectators.RemoveAt(i); + + MahjongPackets.CreateMahjongRelieve(relievePacket, _game.Serial); + mobile.NetState?.Send(relievePacket); + } + else + { + i++; + } + } + + if (removed && !UpdateSpectators()) + { + SendPlayersPacket(true, true); + } + } + + private void UpdateDealer(bool message) + { + if (IsInGamePlayer(DealerPosition)) + { + return; + } + + for (var i = DealerPosition + 1; i < _players.Length; i++) + { + if (IsInGamePlayer(i)) + { + DealerPosition = i; + + if (message) + { + SendDealerChangedMessage(); + } + return; } + } - for (var i = DealerPosition + 1; i < m_Players.Length; i++) + for (var i = 0; i < DealerPosition; i++) + { + if (IsInGamePlayer(i)) { - if (IsInGamePlayer(i)) + DealerPosition = i; + + if (message) { - DealerPosition = i; - - if (message) - { - SendDealerChangedMessage(); - } - - return; + SendDealerChangedMessage(); } + + return; } + } + } - for (var i = 0; i < DealerPosition; i++) + private int GetNextSeat() + { + for (var i = DealerPosition; i < _players.Length; i++) + { + if (_players[i] == null) { - if (IsInGamePlayer(i)) - { - DealerPosition = i; - - if (message) - { - SendDealerChangedMessage(); - } - - return; - } + return i; } } - private int GetNextSeat() + for (var i = 0; i < DealerPosition; i++) { - for (var i = DealerPosition; i < m_Players.Length; i++) + if (_players[i] == null) { - if (m_Players[i] == null) - { - return i; - } + return i; } - - for (var i = 0; i < DealerPosition; i++) - { - if (m_Players[i] == null) - { - return i; - } - } - - return -1; } - private bool UpdateSpectators() + return -1; + } + + private bool UpdateSpectators() + { + if (_spectators.Count == 0) { - if (m_Spectators.Count == 0) - { - return false; - } - - var nextSeat = GetNextSeat(); - - if (nextSeat >= 0) - { - var newPlayer = m_Spectators[0]; - - m_Spectators.RemoveAt(0); - - AddPlayer(newPlayer, nextSeat, false); - - UpdateSpectators(); - - return true; - } - return false; } - private void AddPlayer(Mobile player, int index, bool sendJoinGame) + var nextSeat = GetNextSeat(); + + if (nextSeat >= 0) { - m_Players[index] = player; - m_InGame[index] = true; + var newPlayer = _spectators[0]; - UpdateDealer(false); + _spectators.RemoveAt(0); - if (sendJoinGame) - { - player.NetState.SendMahjongJoinGame(Game.Serial); - } + AddPlayer(newPlayer, nextSeat, false); - SendPlayersPacket(true, true); + UpdateSpectators(); - player.NetState.SendMahjongGeneralInfo(Game); - player.NetState.SendMahjongTilesInfo(Game, player); - - if (DealerPosition == index) - { - SendLocalizedMessage(1062773, player.Name); // ~1_name~ has entered the game as the dealer. - } - else - { - SendLocalizedMessage(1062772, player.Name); // ~1_name~ has entered the game as a player. - } + return true; } - private void AddSpectator(Mobile mobile) - { - if (!IsSpectator(mobile)) - { - m_Spectators.Add(mobile); - } + return false; + } - mobile.NetState.SendMahjongJoinGame(Game.Serial); - mobile.NetState.SendMahjongPlayersInfo(Game, mobile); - mobile.NetState.SendMahjongGeneralInfo(Game); - mobile.NetState.SendMahjongTilesInfo(Game, mobile); + private void AddPlayer(Mobile player, int index, bool sendJoinGame) + { + _players[index] = player; + _inGame[index] = true; + + UpdateDealer(false); + + if (sendJoinGame) + { + player.NetState.SendMahjongJoinGame(_game.Serial); } - public void Join(Mobile mobile) + SendPlayersPacket(true, true); + + player.NetState.SendMahjongGeneralInfo(_game); + player.NetState.SendMahjongTilesInfo(_game, player); + + if (DealerPosition == index) { - var index = GetPlayerIndex(mobile); + SendLocalizedMessage(1062773, player.Name); // ~1_name~ has entered the game as the dealer. + } + else + { + SendLocalizedMessage(1062772, player.Name); // ~1_name~ has entered the game as a player. + } + } - if (index >= 0) - { - AddPlayer(mobile, index, true); - return; - } - - var nextSeat = GetNextSeat(); - - if (nextSeat >= 0) - { - AddPlayer(mobile, nextSeat, true); - } - else - { - AddSpectator(mobile); - } + private void AddSpectator(Mobile mobile) + { + if (!IsSpectator(mobile)) + { + _spectators.Add(mobile); } - public void LeaveGame(Mobile player) + mobile.NetState.SendMahjongJoinGame(_game.Serial); + mobile.NetState.SendMahjongPlayersInfo(_game, mobile); + mobile.NetState.SendMahjongGeneralInfo(_game); + mobile.NetState.SendMahjongTilesInfo(_game, mobile); + } + + public void Join(Mobile mobile) + { + var index = GetPlayerIndex(mobile); + + if (index >= 0) { - var index = GetPlayerIndex(player); - if (index >= 0) - { - m_InGame[index] = false; - - SendPlayerExitMessage(player); - UpdateDealer(true); - - SendPlayersPacket(true, true); - } - else - { - m_Spectators.Remove(player); - } + AddPlayer(mobile, index, true); + return; } - public void ResetScores(int value) + var nextSeat = GetNextSeat(); + + if (nextSeat >= 0) { - for (var i = 0; i < m_Scores.Length; i++) - { - m_Scores[i] = value; - } - - SendPlayersPacket(true, Game.ShowScores); - - SendLocalizedMessage(1062697); // The dealer redistributes the score sticks evenly. + AddPlayer(mobile, nextSeat, true); } - - public void TransferScore(Mobile from, int toPosition, int amount) + else { - var fromPosition = GetPlayerIndex(from); - var to = GetPlayer(toPosition); - - if (fromPosition < 0 || to == null || m_Scores[fromPosition] < amount) - { - return; - } - - m_Scores[fromPosition] -= amount; - m_Scores[toPosition] += amount; - - if (Game.ShowScores) - { - SendPlayersPacket(true, true); - } - else - { - from.NetState.SendMahjongPlayersInfo(Game, from); - to.NetState.SendMahjongPlayersInfo(Game, to); - } - - // ~1_giver~ gives ~2_receiver~ ~3_number~ points. - SendLocalizedMessage(1062774, $"{from.Name}\t{to.Name}\t{amount}"); + AddSpectator(mobile); } + } - public void OpenSeat(int index) + public void LeaveGame(Mobile player) + { + var index = GetPlayerIndex(player); + if (index >= 0) { - var player = GetPlayer(index); - if (player == null) - { - return; - } - - if (m_InGame[index]) - { - player.NetState.SendMahjongRelieve(Game.Serial); - } - - m_Players[index] = null; - - SendLocalizedMessage(1062699, player.Name); // ~1_name~ is relieved from the game by the dealer. + _inGame[index] = false; + SendPlayerExitMessage(player); UpdateDealer(true); - if (!UpdateSpectators()) - { - SendPlayersPacket(true, true); - } + SendPlayersPacket(true, true); + } + else + { + _spectators.Remove(player); + } + } + + public void ResetScores(int value) + { + for (var i = 0; i < _scores.Length; i++) + { + _scores[i] = value; } - public void AssignDealer(int index) + SendPlayersPacket(true, _game.ShowScores); + + SendLocalizedMessage(1062697); // The dealer redistributes the score sticks evenly. + } + + public void TransferScore(Mobile from, int toPosition, int amount) + { + var fromPosition = GetPlayerIndex(from); + var to = GetPlayer(toPosition); + + if (fromPosition < 0 || to == null || _scores[fromPosition] < amount) { - var to = GetPlayer(index); - - if (to == null || !m_InGame[index]) - { - return; - } - - var oldDealer = DealerPosition; - - DealerPosition = index; - - if (IsInGamePlayer(oldDealer)) - { - m_Players[oldDealer].NetState.SendMahjongPlayersInfo(Game, m_Players[oldDealer]); - } - - to.NetState.SendMahjongPlayersInfo(Game, to); - - SendDealerChangedMessage(); + return; } - private void SendDealerChangedMessage() + _scores[fromPosition] -= amount; + _scores[toPosition] += amount; + + if (_game.ShowScores) { - if (Dealer != null) - { - SendLocalizedMessage(1062698, Dealer.Name); // ~1_name~ is assigned the dealer. - } + SendPlayersPacket(true, true); + } + else + { + from.NetState.SendMahjongPlayersInfo(_game, from); + to.NetState.SendMahjongPlayersInfo(_game, to); } - private void SendPlayerExitMessage(Mobile who) + // ~1_giver~ gives ~2_receiver~ ~3_number~ points. + SendLocalizedMessage(1062774, $"{from.Name}\t{to.Name}\t{amount}"); + } + + public void OpenSeat(int index) + { + var player = GetPlayer(index); + if (player == null) { - SendLocalizedMessage(1062762, who.Name); // ~1_name~ has left the game. + return; } - public void SendPlayersPacket(bool players, bool spectators) + if (_inGame[index]) { - foreach (var mobile in GetInGameMobiles(players, spectators)) - { - mobile.NetState.SendMahjongPlayersInfo(Game, mobile); - } + player.NetState.SendMahjongRelieve(_game.Serial); } - public void SendGeneralPacket(bool players, bool spectators) + _players[index] = null; + + SendLocalizedMessage(1062699, player.Name); // ~1_name~ is relieved from the game by the dealer. + + UpdateDealer(true); + + if (!UpdateSpectators()) { - var mobiles = GetInGameMobiles(players, spectators); + SendPlayersPacket(true, true); + } + } - if (mobiles.Count == 0) - { - return; - } + public void AssignDealer(int index) + { + var to = GetPlayer(index); - Span generalInfo = stackalloc byte[MahjongPackets.MahjongGeneralInfoPacketLength].InitializePacket(); - - foreach (var mobile in mobiles) - { - MahjongPackets.CreateMahjongGeneralInfo(generalInfo, Game); - mobile.NetState?.Send(generalInfo); - } + if (to == null || !_inGame[index]) + { + return; } - public void SendTilesPacket(bool players, bool spectators) + var oldDealer = DealerPosition; + + DealerPosition = index; + + if (IsInGamePlayer(oldDealer)) { - foreach (var mobile in GetInGameMobiles(players, spectators)) - { - mobile.NetState.SendMahjongTilesInfo(Game, mobile); - } + _players[oldDealer].NetState.SendMahjongPlayersInfo(_game, _players[oldDealer]); } - public void SendTilePacket(MahjongTile tile, bool players, bool spectators) + to.NetState.SendMahjongPlayersInfo(_game, to); + + SendDealerChangedMessage(); + } + + private void SendDealerChangedMessage() + { + if (Dealer != null) { - foreach (var mobile in GetInGameMobiles(players, spectators)) - { - mobile.NetState.SendMahjongTileInfo(tile, mobile); - } + SendLocalizedMessage(1062698, Dealer.Name); // ~1_name~ is assigned the dealer. + } + } + + private void SendPlayerExitMessage(Mobile who) + { + SendLocalizedMessage(1062762, who.Name); // ~1_name~ has left the game. + } + + public void SendPlayersPacket(bool players, bool spectators) + { + foreach (var mobile in GetInGameMobiles(players, spectators)) + { + mobile.NetState.SendMahjongPlayersInfo(_game, mobile); + } + } + + public void SendGeneralPacket(bool players, bool spectators) + { + var mobiles = GetInGameMobiles(players, spectators); + + if (mobiles.Count == 0) + { + return; } - public void SendRelievePacket(bool players, bool spectators) + Span generalInfo = stackalloc byte[MahjongPackets.MahjongGeneralInfoPacketLength].InitializePacket(); + + foreach (var mobile in mobiles) { - var mobiles = GetInGameMobiles(players, spectators); + MahjongPackets.CreateMahjongGeneralInfo(generalInfo, _game); + mobile.NetState?.Send(generalInfo); + } + } - if (mobiles.Count == 0) - { - return; - } + public void SendTilesPacket(bool players, bool spectators) + { + foreach (var mobile in GetInGameMobiles(players, spectators)) + { + mobile.NetState.SendMahjongTilesInfo(_game, mobile); + } + } - Span relievePacket = stackalloc byte[MahjongPackets.MahjongRelievePacketLength].InitializePacket(); + public void SendTilePacket(MahjongTile tile, bool players, bool spectators) + { + foreach (var mobile in GetInGameMobiles(players, spectators)) + { + mobile.NetState.SendMahjongTileInfo(tile, mobile); + } + } - foreach (var mobile in mobiles) - { - MahjongPackets.CreateMahjongRelieve(relievePacket, Game.Serial); - mobile.NetState?.Send(relievePacket); - } + public void SendRelievePacket(bool players, bool spectators) + { + var mobiles = GetInGameMobiles(players, spectators); + + if (mobiles.Count == 0) + { + return; } - public void SendLocalizedMessage(int number) + Span relievePacket = stackalloc byte[MahjongPackets.MahjongRelievePacketLength].InitializePacket(); + + foreach (var mobile in mobiles) { - foreach (var mobile in GetInGameMobiles(true, true)) - { - mobile.SendLocalizedMessage(number); - } + MahjongPackets.CreateMahjongRelieve(relievePacket, _game.Serial); + mobile.NetState?.Send(relievePacket); } + } - public void SendLocalizedMessage(int number, string args) + public void SendLocalizedMessage(int number) + { + foreach (var mobile in GetInGameMobiles(true, true)) { - foreach (var mobile in GetInGameMobiles(true, true)) - { - mobile.SendLocalizedMessage(number, args); - } + mobile.SendLocalizedMessage(number); } + } - public void Save(IGenericWriter writer) + public void SendLocalizedMessage(int number, string args) + { + foreach (var mobile in GetInGameMobiles(true, true)) { - writer.Write(0); // version - - writer.Write(Seats); - - for (var i = 0; i < Seats; i++) - { - writer.Write(m_Players[i]); - writer.Write(m_PublicHand[i]); - writer.Write(m_Scores[i]); - } - - writer.Write(DealerPosition); + mobile.SendLocalizedMessage(number, args); } } } diff --git a/Projects/UOContent/Items/Games/Mahjong/MahjongTile.cs b/Projects/UOContent/Items/Games/Mahjong/MahjongTile.cs index e9d3bf628..61c684d17 100644 --- a/Projects/UOContent/Items/Games/Mahjong/MahjongTile.cs +++ b/Projects/UOContent/Items/Games/Mahjong/MahjongTile.cs @@ -1,95 +1,86 @@ -namespace Server.Engines.Mahjong +using ModernUO.Serialization; + +namespace Server.Engines.Mahjong; + +[SerializationGenerator(1, false)] +public partial class MahjongTile { - public class MahjongTile + [DirtyTrackingEntity] + private readonly MahjongGame _game; + + [SerializableField(0, setter: "private")] + private int _number; + + [SerializableField(1, setter: "private")] + private MahjongTileType _value; + + [SerializableField(2, setter: "private")] + private Point2D _position; + + [SerializableField(3, setter: "private")] + private int _stackLevel; + + [SerializableField(4, setter: "private")] + private MahjongPieceDirection _direction; + + [SerializableField(5, setter: "private")] + private bool _flipped; + + public MahjongTile(MahjongGame game) => _game = game; + + public MahjongTile( + MahjongGame game, int number, MahjongTileType value, Point2D position, int stackLevel, + MahjongPieceDirection direction, bool flipped + ) { - protected Point2D m_Position; + _game = game; + _number = number; + _value = value; + _position = position; + _stackLevel = stackLevel; + _direction = direction; + _flipped = flipped; + } - public MahjongTile( - MahjongGame game, int number, MahjongTileType value, Point2D position, int stackLevel, - MahjongPieceDirection direction, bool flipped - ) + public MahjongGame Game => _game; + + private void Deserialize(IGenericReader reader, int version) + { + _number = reader.ReadInt(); + _value = (MahjongTileType)reader.ReadInt(); + _position = reader.ReadPoint2D(); + _stackLevel = reader.ReadInt(); + _direction = (MahjongPieceDirection)reader.ReadInt(); + _flipped = reader.ReadBool(); + } + + public MahjongPieceDim Dimensions => GetDimensions(_position, _direction); + + public bool IsMovable => _game.GetStackLevel(Dimensions) <= _stackLevel; + + public static MahjongPieceDim GetDimensions(Point2D position, MahjongPieceDirection direction) => + direction is MahjongPieceDirection.Up or MahjongPieceDirection.Down + ? new MahjongPieceDim(position, 20, 30) + : new MahjongPieceDim(position, 30, 20); + + public void Move(Point2D position, MahjongPieceDirection direction, bool flip, int validHandArea) + { + var dim = GetDimensions(position, direction); + var curHandArea = Dimensions.GetHandArea(); + var newHandArea = dim.GetHandArea(); + + if (!IsMovable || !dim.IsValid() || validHandArea >= 0 && + (curHandArea >= 0 && curHandArea != validHandArea || newHandArea >= 0 && newHandArea != validHandArea)) { - Game = game; - Number = number; - Value = value; - m_Position = position; - StackLevel = stackLevel; - Direction = direction; - Flipped = flipped; + return; } - public MahjongTile(MahjongGame game, IGenericReader reader) - { - Game = game; + Position = position; + Direction = direction; + StackLevel = -1; // Avoid self interference + StackLevel = _game.GetStackLevel(dim) + 1; + Flipped = flip; - var version = reader.ReadInt(); - - Number = reader.ReadInt(); - Value = (MahjongTileType)reader.ReadInt(); - m_Position = reader.ReadPoint2D(); - StackLevel = reader.ReadInt(); - Direction = (MahjongPieceDirection)reader.ReadInt(); - Flipped = reader.ReadBool(); - } - - public MahjongGame Game { get; } - - public int Number { get; } - - public MahjongTileType Value { get; } - - public Point2D Position => m_Position; - public int StackLevel { get; private set; } - - public MahjongPieceDirection Direction { get; private set; } - - public bool Flipped { get; private set; } - - public MahjongPieceDim Dimensions => GetDimensions(m_Position, Direction); - - public bool IsMovable => Game.GetStackLevel(Dimensions) <= StackLevel; - - public static MahjongPieceDim GetDimensions(Point2D position, MahjongPieceDirection direction) - { - if (direction is MahjongPieceDirection.Up or MahjongPieceDirection.Down) - { - return new MahjongPieceDim(position, 20, 30); - } - - return new MahjongPieceDim(position, 30, 20); - } - - public void Move(Point2D position, MahjongPieceDirection direction, bool flip, int validHandArea) - { - var dim = GetDimensions(position, direction); - var curHandArea = Dimensions.GetHandArea(); - var newHandArea = dim.GetHandArea(); - - if (!IsMovable || !dim.IsValid() || validHandArea >= 0 && - (curHandArea >= 0 && curHandArea != validHandArea || newHandArea >= 0 && newHandArea != validHandArea)) - { - return; - } - - m_Position = position; - Direction = direction; - StackLevel = -1; // Avoid self interference - StackLevel = Game.GetStackLevel(dim) + 1; - Flipped = flip; - - Game.Players.SendTilePacket(this, true, true); - } - - public void Save(IGenericWriter writer) - { - writer.Write(0); // version - - writer.Write(Number); - writer.Write((int)Value); - writer.Write(m_Position); - writer.Write(StackLevel); - writer.Write((int)Direction); - writer.Write(Flipped); - } + _game.Players.SendTilePacket(this, true, true); } } diff --git a/Projects/UOContent/Items/Games/Mahjong/MahjongTileTypeGenerator.cs b/Projects/UOContent/Items/Games/Mahjong/MahjongTileTypeGenerator.cs index 099e3b610..90b260f43 100644 --- a/Projects/UOContent/Items/Games/Mahjong/MahjongTileTypeGenerator.cs +++ b/Projects/UOContent/Items/Games/Mahjong/MahjongTileTypeGenerator.cs @@ -1,31 +1,28 @@ -using System.Collections.Generic; +namespace Server.Engines.Mahjong; -namespace Server.Engines.Mahjong +public class MahjongTileTypeGenerator { - public class MahjongTileTypeGenerator + private MahjongTileType[] _leftTileTypes; + private int _nextTile; + + public MahjongTileTypeGenerator() { - public MahjongTileTypeGenerator() - { - LeftTileTypes = new List(136); + _leftTileTypes = new MahjongTileType[136]; - for (var i = 1; i <= 34; i++) - { - var tile = (MahjongTileType)i; - LeftTileTypes.Add(tile); - LeftTileTypes.Add(tile); - LeftTileTypes.Add(tile); - LeftTileTypes.Add(tile); - } + for (int i = 1, j = 0; i <= 34; i++) + { + var tile = (MahjongTileType)i; + _leftTileTypes[j++] = tile; + _leftTileTypes[j++] = tile; + _leftTileTypes[j++] = tile; + _leftTileTypes[j++] = tile; } - public List LeftTileTypes { get; } - - public MahjongTileType Next() - { - var next = LeftTileTypes.RandomElement(); - LeftTileTypes.Remove(next); - - return next; - } + _leftTileTypes.Shuffle(); + _leftTileTypes.Shuffle(); + _leftTileTypes.Shuffle(); + _leftTileTypes.Shuffle(); } + + public MahjongTileType Next() => _leftTileTypes[_nextTile++]; } diff --git a/Projects/UOContent/Items/Games/Mahjong/MahjongWallBreakIndicator.cs b/Projects/UOContent/Items/Games/Mahjong/MahjongWallBreakIndicator.cs index febd3c228..c73613aa9 100644 --- a/Projects/UOContent/Items/Games/Mahjong/MahjongWallBreakIndicator.cs +++ b/Projects/UOContent/Items/Games/Mahjong/MahjongWallBreakIndicator.cs @@ -1,49 +1,39 @@ -namespace Server.Engines.Mahjong +using ModernUO.Serialization; + +namespace Server.Engines.Mahjong; + +[SerializationGenerator(0, false)] +public partial class MahjongWallBreakIndicator { - public class MahjongWallBreakIndicator + [DirtyTrackingEntity] + private readonly MahjongGame _game; + + [SerializableField(0, setter: "private")] + private Point2D _position; + + public MahjongWallBreakIndicator(MahjongGame game) => _game = game; + + public MahjongWallBreakIndicator(MahjongGame game, Point2D position) { - public MahjongWallBreakIndicator(MahjongGame game, Point2D position) + _game = game; + _position = position; + } + + public MahjongPieceDim Dimensions => GetDimensions(_position); + + public static MahjongPieceDim GetDimensions(Point2D position) => new(position, 20, 20); + + public void Move(Point2D position) + { + var dim = GetDimensions(position); + + if (!dim.IsValid()) { - Game = game; - Position = position; + return; } - public MahjongWallBreakIndicator(MahjongGame game, IGenericReader reader) - { - Game = game; + _position = position; - var version = reader.ReadInt(); - - Position = reader.ReadPoint2D(); - } - - public MahjongGame Game { get; } - - public Point2D Position { get; private set; } - - public MahjongPieceDim Dimensions => GetDimensions(Position); - - public static MahjongPieceDim GetDimensions(Point2D position) => new(position, 20, 20); - - public void Move(Point2D position) - { - var dim = GetDimensions(position); - - if (!dim.IsValid()) - { - return; - } - - Position = position; - - Game.Players.SendGeneralPacket(true, true); - } - - public void Save(IGenericWriter writer) - { - writer.Write(0); // version - - writer.Write(Position); - } + _game.Players.SendGeneralPacket(true, true); } } diff --git a/Projects/UOContent/Migrations/Server.Engines.Mahjong.MahjongDealerIndicator.v1.json b/Projects/UOContent/Migrations/Server.Engines.Mahjong.MahjongDealerIndicator.v1.json new file mode 100644 index 000000000..967bc6e58 --- /dev/null +++ b/Projects/UOContent/Migrations/Server.Engines.Mahjong.MahjongDealerIndicator.v1.json @@ -0,0 +1,24 @@ +{ + "version": 1, + "type": "Server.Engines.Mahjong.MahjongDealerIndicator", + "properties": [ + { + "name": "Position", + "type": "Server.Point2D", + "rule": "PrimitiveUOTypeMigrationRule", + "ruleArguments": [ + "Point2D" + ] + }, + { + "name": "Direction", + "type": "Server.Engines.Mahjong.MahjongPieceDirection", + "rule": "EnumMigrationRule" + }, + { + "name": "Wind", + "type": "Server.Engines.Mahjong.MahjongWind", + "rule": "EnumMigrationRule" + } + ] +} \ No newline at end of file diff --git a/Projects/UOContent/Migrations/Server.Engines.Mahjong.MahjongDices.v0.json b/Projects/UOContent/Migrations/Server.Engines.Mahjong.MahjongDices.v0.json new file mode 100644 index 000000000..2f5945ff3 --- /dev/null +++ b/Projects/UOContent/Migrations/Server.Engines.Mahjong.MahjongDices.v0.json @@ -0,0 +1,22 @@ +{ + "version": 0, + "type": "Server.Engines.Mahjong.MahjongDices", + "properties": [ + { + "name": "First", + "type": "int", + "rule": "PrimitiveTypeMigrationRule", + "ruleArguments": [ + "" + ] + }, + { + "name": "Second", + "type": "int", + "rule": "PrimitiveTypeMigrationRule", + "ruleArguments": [ + "" + ] + } + ] +} \ No newline at end of file diff --git a/Projects/UOContent/Migrations/Server.Engines.Mahjong.MahjongGame.v1.json b/Projects/UOContent/Migrations/Server.Engines.Mahjong.MahjongGame.v1.json new file mode 100644 index 000000000..9d4348506 --- /dev/null +++ b/Projects/UOContent/Migrations/Server.Engines.Mahjong.MahjongGame.v1.json @@ -0,0 +1,69 @@ +{ + "version": 1, + "type": "Server.Engines.Mahjong.MahjongGame", + "properties": [ + { + "name": "Level", + "type": "Server.Multis.SecureLevel", + "rule": "EnumMigrationRule" + }, + { + "name": "Tiles", + "type": "Server.Engines.Mahjong.MahjongTile[]", + "rule": "ArrayMigrationRule", + "ruleArguments": [ + "Server.Engines.Mahjong.MahjongTile", + "RawSerializableMigrationRule", + "DeserializationRequiresParent" + ] + }, + { + "name": "DealerIndicator", + "type": "Server.Engines.Mahjong.MahjongDealerIndicator", + "rule": "RawSerializableMigrationRule", + "ruleArguments": [ + "DeserializationRequiresParent" + ] + }, + { + "name": "WallBreakIndicator", + "type": "Server.Engines.Mahjong.MahjongWallBreakIndicator", + "rule": "RawSerializableMigrationRule", + "ruleArguments": [ + "DeserializationRequiresParent" + ] + }, + { + "name": "Dices", + "type": "Server.Engines.Mahjong.MahjongDices", + "rule": "RawSerializableMigrationRule", + "ruleArguments": [ + "DeserializationRequiresParent" + ] + }, + { + "name": "Players", + "type": "Server.Engines.Mahjong.MahjongPlayers", + "rule": "RawSerializableMigrationRule", + "ruleArguments": [ + "DeserializationRequiresParent" + ] + }, + { + "name": "ShowScores", + "type": "bool", + "rule": "PrimitiveTypeMigrationRule", + "ruleArguments": [ + "" + ] + }, + { + "name": "SpectatorVision", + "type": "bool", + "rule": "PrimitiveTypeMigrationRule", + "ruleArguments": [ + "" + ] + } + ] +} \ No newline at end of file diff --git a/Projects/UOContent/Migrations/Server.Engines.Mahjong.MahjongPlayers.v1.json b/Projects/UOContent/Migrations/Server.Engines.Mahjong.MahjongPlayers.v1.json new file mode 100644 index 000000000..696bd989e --- /dev/null +++ b/Projects/UOContent/Migrations/Server.Engines.Mahjong.MahjongPlayers.v1.json @@ -0,0 +1,53 @@ +{ + "version": 1, + "type": "Server.Engines.Mahjong.MahjongPlayers", + "properties": [ + { + "name": "Players", + "type": "Server.Mobile[]", + "rule": "ArrayMigrationRule", + "ruleArguments": [ + "Server.Mobile", + "SerializableInterfaceMigrationRule" + ] + }, + { + "name": "InGame", + "type": "bool[]", + "rule": "ArrayMigrationRule", + "ruleArguments": [ + "bool", + "PrimitiveTypeMigrationRule", + "" + ] + }, + { + "name": "PublicHand", + "type": "bool[]", + "rule": "ArrayMigrationRule", + "ruleArguments": [ + "bool", + "PrimitiveTypeMigrationRule", + "" + ] + }, + { + "name": "Scores", + "type": "int[]", + "rule": "ArrayMigrationRule", + "ruleArguments": [ + "int", + "PrimitiveTypeMigrationRule", + "" + ] + }, + { + "name": "DealerPosition", + "type": "int", + "rule": "PrimitiveTypeMigrationRule", + "ruleArguments": [ + "" + ] + } + ] +} \ No newline at end of file diff --git a/Projects/UOContent/Migrations/Server.Engines.Mahjong.MahjongTile.v1.json b/Projects/UOContent/Migrations/Server.Engines.Mahjong.MahjongTile.v1.json new file mode 100644 index 000000000..33d13b217 --- /dev/null +++ b/Projects/UOContent/Migrations/Server.Engines.Mahjong.MahjongTile.v1.json @@ -0,0 +1,48 @@ +{ + "version": 1, + "type": "Server.Engines.Mahjong.MahjongTile", + "properties": [ + { + "name": "Number", + "type": "int", + "rule": "PrimitiveTypeMigrationRule", + "ruleArguments": [ + "" + ] + }, + { + "name": "Value", + "type": "Server.Engines.Mahjong.MahjongTileType", + "rule": "EnumMigrationRule" + }, + { + "name": "Position", + "type": "Server.Point2D", + "rule": "PrimitiveUOTypeMigrationRule", + "ruleArguments": [ + "Point2D" + ] + }, + { + "name": "StackLevel", + "type": "int", + "rule": "PrimitiveTypeMigrationRule", + "ruleArguments": [ + "" + ] + }, + { + "name": "Direction", + "type": "Server.Engines.Mahjong.MahjongPieceDirection", + "rule": "EnumMigrationRule" + }, + { + "name": "Flipped", + "type": "bool", + "rule": "PrimitiveTypeMigrationRule", + "ruleArguments": [ + "" + ] + } + ] +} \ No newline at end of file diff --git a/Projects/UOContent/Migrations/Server.Engines.Mahjong.MahjongWallBreakIndicator.v0.json b/Projects/UOContent/Migrations/Server.Engines.Mahjong.MahjongWallBreakIndicator.v0.json new file mode 100644 index 000000000..886f15a4d --- /dev/null +++ b/Projects/UOContent/Migrations/Server.Engines.Mahjong.MahjongWallBreakIndicator.v0.json @@ -0,0 +1,14 @@ +{ + "version": 0, + "type": "Server.Engines.Mahjong.MahjongWallBreakIndicator", + "properties": [ + { + "name": "Position", + "type": "Server.Point2D", + "rule": "PrimitiveUOTypeMigrationRule", + "ruleArguments": [ + "Point2D" + ] + } + ] +} \ No newline at end of file