fix: Codegens mahjong (#1070)

This commit is contained in:
Kamron Batman 2022-06-16 10:19:49 -07:00 committed by GitHub
parent 800f864335
commit 6edccfe2aa
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 1272 additions and 1122 deletions

View file

@ -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();
}
}

View file

@ -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}");
}
}
}

View file

@ -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
}

View file

@ -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<ContextMenuEntry> 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<ContextMenuEntry> 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);
}
}
}

View file

@ -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;
}
}

File diff suppressed because it is too large Load diff

View file

@ -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);
}
}

View file

@ -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<MahjongTileType>(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<MahjongTileType> 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++];
}

View file

@ -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);
}
}

View file

@ -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"
}
]
}

View file

@ -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": [
""
]
}
]
}

View file

@ -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": [
""
]
}
]
}

View file

@ -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": [
""
]
}
]
}

View file

@ -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": [
""
]
}
]
}

View file

@ -0,0 +1,14 @@
{
"version": 0,
"type": "Server.Engines.Mahjong.MahjongWallBreakIndicator",
"properties": [
{
"name": "Position",
"type": "Server.Point2D",
"rule": "PrimitiveUOTypeMigrationRule",
"ruleArguments": [
"Point2D"
]
}
]
}