Adds style cop (#109)
This commit is contained in:
parent
3e715bcb60
commit
556a17aba8
1725 changed files with 33831 additions and 38046 deletions
|
|
@ -27,7 +27,7 @@ namespace Server.Items
|
|||
public override TimeSpan DecayTime => TimeSpan.FromDays(1.0);
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public SecureLevel Level{ get; set; }
|
||||
public SecureLevel Level { get; set; }
|
||||
|
||||
public abstract void CreatePieces();
|
||||
|
||||
|
|
@ -101,15 +101,15 @@ namespace Server.Items
|
|||
}
|
||||
|
||||
public static bool ValidateDefault(Mobile from, BaseBoard board) =>
|
||||
!board.Deleted && (from.AccessLevel >= AccessLevel.GameMaster || from.Alive &&
|
||||
(board.IsChildOf(from.Backpack) || !(board.RootParent is Mobile) &&
|
||||
!board.Deleted && (from.AccessLevel >= AccessLevel.GameMaster || (from.Alive &&
|
||||
(board.IsChildOf(from.Backpack) || (!(board.RootParent is Mobile) &&
|
||||
board.Map == from.Map && from.InRange(board.GetWorldLocation(), 1) &&
|
||||
BaseHouse.FindHouseAt(board)?.IsOwner(from) == true));
|
||||
BaseHouse.FindHouseAt(board)?.IsOwner(from) == true))));
|
||||
|
||||
public class DefaultEntry : ContextMenuEntry
|
||||
{
|
||||
private BaseBoard m_Board;
|
||||
private Mobile m_From;
|
||||
private readonly BaseBoard m_Board;
|
||||
private readonly Mobile m_From;
|
||||
|
||||
public DefaultEntry(Mobile from, BaseBoard board) : base(6162,
|
||||
from.AccessLevel >= AccessLevel.GameMaster ? -1 : 1)
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ namespace Server.Items
|
|||
{
|
||||
}
|
||||
|
||||
public BaseBoard Board{ get; set; }
|
||||
public BaseBoard Board { get; set; }
|
||||
|
||||
public override bool IsVirtualItem => true;
|
||||
|
||||
|
|
@ -31,14 +31,14 @@ namespace Server.Items
|
|||
switch (version)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
Board = (BaseBoard)reader.ReadItem();
|
||||
{
|
||||
Board = (BaseBoard)reader.ReadItem();
|
||||
|
||||
if (Board == null || Parent == null)
|
||||
Delete();
|
||||
if (Board == null || Parent == null)
|
||||
Delete();
|
||||
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,13 +21,13 @@ namespace Server.Engines.Mahjong
|
|||
Wind = (MahjongWind)reader.ReadInt();
|
||||
}
|
||||
|
||||
public MahjongGame Game{ get; }
|
||||
public MahjongGame Game { get; }
|
||||
|
||||
public Point2D Position{ get; private set; }
|
||||
public Point2D Position { get; private set; }
|
||||
|
||||
public MahjongPieceDirection Direction{ get; private set; }
|
||||
public MahjongPieceDirection Direction { get; private set; }
|
||||
|
||||
public MahjongWind Wind{ get; private set; }
|
||||
public MahjongWind Wind { get; private set; }
|
||||
|
||||
public MahjongPieceDim Dimensions => GetDimensions(Position, Direction);
|
||||
|
||||
|
|
|
|||
|
|
@ -19,11 +19,11 @@ namespace Server.Engines.Mahjong
|
|||
Second = reader.ReadInt();
|
||||
}
|
||||
|
||||
public MahjongGame Game{ get; }
|
||||
public MahjongGame Game { get; }
|
||||
|
||||
public int First{ get; private set; }
|
||||
public int First { get; private set; }
|
||||
|
||||
public int Second{ get; private set; }
|
||||
public int Second { get; private set; }
|
||||
|
||||
public void RollDices(Mobile from)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -34,15 +34,15 @@ namespace Server.Engines.Mahjong
|
|||
{
|
||||
}
|
||||
|
||||
public MahjongTile[] Tiles{ get; private set; }
|
||||
public MahjongTile[] Tiles { get; private set; }
|
||||
|
||||
public MahjongDealerIndicator DealerIndicator{ get; private set; }
|
||||
public MahjongDealerIndicator DealerIndicator { get; private set; }
|
||||
|
||||
public MahjongWallBreakIndicator WallBreakIndicator{ get; private set; }
|
||||
public MahjongWallBreakIndicator WallBreakIndicator { get; private set; }
|
||||
|
||||
public MahjongDices Dices{ get; private set; }
|
||||
public MahjongDices Dices { get; private set; }
|
||||
|
||||
public MahjongPlayers Players{ get; private set; }
|
||||
public MahjongPlayers Players { get; private set; }
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public bool ShowScores
|
||||
|
|
@ -87,7 +87,7 @@ namespace Server.Engines.Mahjong
|
|||
}
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public SecureLevel Level{ get; set; }
|
||||
public SecureLevel Level { get; set; }
|
||||
|
||||
private void BuildHorizontalWall(ref int index, int x, int y, int stackLevel, MahjongPieceDirection direction,
|
||||
MahjongTileTypeGenerator typeGenerator)
|
||||
|
|
@ -242,43 +242,43 @@ namespace Server.Engines.Mahjong
|
|||
switch (version)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
Level = (SecureLevel)reader.ReadInt();
|
||||
{
|
||||
Level = (SecureLevel)reader.ReadInt();
|
||||
|
||||
goto case 0;
|
||||
}
|
||||
goto case 0;
|
||||
}
|
||||
case 0:
|
||||
{
|
||||
if (version < 1)
|
||||
Level = SecureLevel.CoOwners;
|
||||
{
|
||||
if (version < 1)
|
||||
Level = SecureLevel.CoOwners;
|
||||
|
||||
int length = reader.ReadInt();
|
||||
Tiles = new MahjongTile[length];
|
||||
int length = reader.ReadInt();
|
||||
Tiles = new MahjongTile[length];
|
||||
|
||||
for (int i = 0; i < length; i++)
|
||||
Tiles[i] = new MahjongTile(this, reader);
|
||||
for (int i = 0; i < length; i++)
|
||||
Tiles[i] = new MahjongTile(this, reader);
|
||||
|
||||
DealerIndicator = new MahjongDealerIndicator(this, reader);
|
||||
DealerIndicator = new MahjongDealerIndicator(this, reader);
|
||||
|
||||
WallBreakIndicator = new MahjongWallBreakIndicator(this, reader);
|
||||
WallBreakIndicator = new MahjongWallBreakIndicator(this, reader);
|
||||
|
||||
Dices = new MahjongDices(this, reader);
|
||||
Dices = new MahjongDices(this, reader);
|
||||
|
||||
Players = new MahjongPlayers(this, reader);
|
||||
Players = new MahjongPlayers(this, reader);
|
||||
|
||||
m_ShowScores = reader.ReadBool();
|
||||
m_SpectatorVision = reader.ReadBool();
|
||||
m_ShowScores = reader.ReadBool();
|
||||
m_SpectatorVision = reader.ReadBool();
|
||||
|
||||
m_LastReset = DateTime.UtcNow;
|
||||
m_LastReset = DateTime.UtcNow;
|
||||
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class ResetGameEntry : ContextMenuEntry
|
||||
{
|
||||
private MahjongGame m_Game;
|
||||
private readonly MahjongGame m_Game;
|
||||
|
||||
public ResetGameEntry(MahjongGame game) : base(6162) => m_Game = game;
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ namespace Server.Engines.Mahjong
|
|||
|
||||
public sealed class MahjongPacketHandlers
|
||||
{
|
||||
private static OnMahjongPacketReceive[] m_SubCommandDelegates = new OnMahjongPacketReceive[0x100];
|
||||
private static readonly OnMahjongPacketReceive[] m_SubCommandDelegates = new OnMahjongPacketReceive[0x100];
|
||||
|
||||
public static void RegisterSubCommand(int subCmd, OnMahjongPacketReceive onReceive)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2,11 +2,11 @@ namespace Server.Engines.Mahjong
|
|||
{
|
||||
public struct MahjongPieceDim
|
||||
{
|
||||
public Point2D Position{ get; }
|
||||
public Point2D Position { get; }
|
||||
|
||||
public int Width{ get; }
|
||||
public int Width { get; }
|
||||
|
||||
public int Height{ get; }
|
||||
public int Height { get; }
|
||||
|
||||
public MahjongPieceDim(Point2D position, int width, int height)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -4,11 +4,11 @@ namespace Server.Engines.Mahjong
|
|||
{
|
||||
public class MahjongPlayers
|
||||
{
|
||||
private bool[] m_InGame;
|
||||
private Mobile[] m_Players;
|
||||
private bool[] m_PublicHand;
|
||||
private int[] m_Scores;
|
||||
private List<Mobile> m_Spectators;
|
||||
private readonly bool[] m_InGame;
|
||||
private readonly Mobile[] m_Players;
|
||||
private readonly bool[] m_PublicHand;
|
||||
private readonly int[] m_Scores;
|
||||
private readonly List<Mobile> m_Spectators;
|
||||
|
||||
public MahjongPlayers(MahjongGame game, int maxPlayers, int baseScore)
|
||||
{
|
||||
|
|
@ -47,11 +47,11 @@ namespace Server.Engines.Mahjong
|
|||
DealerPosition = reader.ReadInt();
|
||||
}
|
||||
|
||||
public MahjongGame Game{ get; }
|
||||
public MahjongGame Game { get; }
|
||||
|
||||
public int Seats => m_Players.Length;
|
||||
public Mobile Dealer => m_Players[DealerPosition];
|
||||
public int DealerPosition{ get; private set; }
|
||||
public int DealerPosition { get; private set; }
|
||||
|
||||
public Mobile GetPlayer(int index)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -30,18 +30,18 @@ namespace Server.Engines.Mahjong
|
|||
Flipped = reader.ReadBool();
|
||||
}
|
||||
|
||||
public MahjongGame Game{ get; }
|
||||
public MahjongGame Game { get; }
|
||||
|
||||
public int Number{ get; }
|
||||
public int Number { get; }
|
||||
|
||||
public MahjongTileType Value{ get; }
|
||||
public MahjongTileType Value { get; }
|
||||
|
||||
public Point2D Position => m_Position;
|
||||
public int StackLevel{ get; private set; }
|
||||
public int StackLevel { get; private set; }
|
||||
|
||||
public MahjongPieceDirection Direction{ get; private set; }
|
||||
public MahjongPieceDirection Direction { get; private set; }
|
||||
|
||||
public bool Flipped{ get; private set; }
|
||||
public bool Flipped { get; private set; }
|
||||
|
||||
public MahjongPieceDim Dimensions => GetDimensions(m_Position, Direction);
|
||||
|
||||
|
|
@ -60,8 +60,8 @@ namespace Server.Engines.Mahjong
|
|||
int curHandArea = Dimensions.GetHandArea();
|
||||
int newHandArea = dim.GetHandArea();
|
||||
|
||||
if (!IsMovable || !dim.IsValid() || validHandArea >= 0 &&
|
||||
(curHandArea >= 0 && curHandArea != validHandArea || newHandArea >= 0 && newHandArea != validHandArea))
|
||||
if (!IsMovable || !dim.IsValid() || (validHandArea >= 0 &&
|
||||
((curHandArea >= 0 && curHandArea != validHandArea) || (newHandArea >= 0 && newHandArea != validHandArea))))
|
||||
return;
|
||||
|
||||
m_Position = position;
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ namespace Server.Engines.Mahjong
|
|||
}
|
||||
}
|
||||
|
||||
public List<MahjongTileType> LeftTileTypes{ get; }
|
||||
public List<MahjongTileType> LeftTileTypes { get; }
|
||||
|
||||
public MahjongTileType Next()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -17,9 +17,9 @@ namespace Server.Engines.Mahjong
|
|||
Position = reader.ReadPoint2D();
|
||||
}
|
||||
|
||||
public MahjongGame Game{ get; }
|
||||
public MahjongGame Game { get; }
|
||||
|
||||
public Point2D Position{ get; private set; }
|
||||
public Point2D Position { get; private set; }
|
||||
|
||||
public MahjongPieceDim Dimensions => GetDimensions(Position);
|
||||
|
||||
|
|
|
|||
|
|
@ -9,9 +9,9 @@ namespace Server.Engines.Mahjong
|
|||
{
|
||||
EnsureCapacity(9);
|
||||
|
||||
m_Stream.Write(game.Serial);
|
||||
m_Stream.Write((byte)0);
|
||||
m_Stream.Write((byte)0x19);
|
||||
Stream.Write(game.Serial);
|
||||
Stream.Write((byte)0);
|
||||
Stream.Write((byte)0x19);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -23,12 +23,12 @@ namespace Server.Engines.Mahjong
|
|||
|
||||
EnsureCapacity(11 + 45 * players.Seats);
|
||||
|
||||
m_Stream.Write(game.Serial);
|
||||
m_Stream.Write((byte)0);
|
||||
m_Stream.Write((byte)0x2);
|
||||
Stream.Write(game.Serial);
|
||||
Stream.Write((byte)0);
|
||||
Stream.Write((byte)0x2);
|
||||
|
||||
m_Stream.Write((byte)0);
|
||||
m_Stream.Write((byte)players.Seats);
|
||||
Stream.Write((byte)0);
|
||||
Stream.Write((byte)players.Seats);
|
||||
|
||||
int n = 0;
|
||||
for (int i = 0; i < players.Seats; i++)
|
||||
|
|
@ -37,40 +37,40 @@ namespace Server.Engines.Mahjong
|
|||
|
||||
if (mobile != null)
|
||||
{
|
||||
m_Stream.Write(mobile.Serial);
|
||||
m_Stream.Write(players.DealerPosition == i ? (byte)0x1 : (byte)0x2);
|
||||
m_Stream.Write((byte)i);
|
||||
Stream.Write(mobile.Serial);
|
||||
Stream.Write(players.DealerPosition == i ? (byte)0x1 : (byte)0x2);
|
||||
Stream.Write((byte)i);
|
||||
|
||||
if (game.ShowScores || mobile == to)
|
||||
m_Stream.Write(players.GetScore(i));
|
||||
Stream.Write(players.GetScore(i));
|
||||
else
|
||||
m_Stream.Write(0);
|
||||
Stream.Write(0);
|
||||
|
||||
m_Stream.Write((short)0);
|
||||
m_Stream.Write((byte)0);
|
||||
Stream.Write((short)0);
|
||||
Stream.Write((byte)0);
|
||||
|
||||
m_Stream.Write(players.IsPublic(i));
|
||||
Stream.Write(players.IsPublic(i));
|
||||
|
||||
m_Stream.WriteAsciiFixed(mobile.Name, 30);
|
||||
m_Stream.Write(!players.IsInGamePlayer(i));
|
||||
Stream.WriteAsciiFixed(mobile.Name, 30);
|
||||
Stream.Write(!players.IsInGamePlayer(i));
|
||||
|
||||
n++;
|
||||
}
|
||||
else if (game.ShowScores)
|
||||
{
|
||||
m_Stream.Write(0);
|
||||
m_Stream.Write((byte)0x2);
|
||||
m_Stream.Write((byte)i);
|
||||
Stream.Write(0);
|
||||
Stream.Write((byte)0x2);
|
||||
Stream.Write((byte)i);
|
||||
|
||||
m_Stream.Write(players.GetScore(i));
|
||||
Stream.Write(players.GetScore(i));
|
||||
|
||||
m_Stream.Write((short)0);
|
||||
m_Stream.Write((byte)0);
|
||||
Stream.Write((short)0);
|
||||
Stream.Write((byte)0);
|
||||
|
||||
m_Stream.Write(players.IsPublic(i));
|
||||
Stream.Write(players.IsPublic(i));
|
||||
|
||||
m_Stream.WriteAsciiFixed("", 30);
|
||||
m_Stream.Write(true);
|
||||
Stream.WriteAsciiFixed("", 30);
|
||||
Stream.Write(true);
|
||||
|
||||
n++;
|
||||
}
|
||||
|
|
@ -78,8 +78,8 @@ namespace Server.Engines.Mahjong
|
|||
|
||||
if (n != players.Seats)
|
||||
{
|
||||
m_Stream.Seek(10, SeekOrigin.Begin);
|
||||
m_Stream.Write((byte)n);
|
||||
Stream.Seek(10, SeekOrigin.Begin);
|
||||
Stream.Write((byte)n);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -90,25 +90,25 @@ namespace Server.Engines.Mahjong
|
|||
{
|
||||
EnsureCapacity(13);
|
||||
|
||||
m_Stream.Write(game.Serial);
|
||||
m_Stream.Write((byte)0);
|
||||
m_Stream.Write((byte)0x5);
|
||||
Stream.Write(game.Serial);
|
||||
Stream.Write((byte)0);
|
||||
Stream.Write((byte)0x5);
|
||||
|
||||
m_Stream.Write((short)0);
|
||||
m_Stream.Write((byte)0);
|
||||
Stream.Write((short)0);
|
||||
Stream.Write((byte)0);
|
||||
|
||||
m_Stream.Write((byte)((game.ShowScores ? 0x1 : 0x0) | (game.SpectatorVision ? 0x2 : 0x0)));
|
||||
Stream.Write((byte)((game.ShowScores ? 0x1 : 0x0) | (game.SpectatorVision ? 0x2 : 0x0)));
|
||||
|
||||
m_Stream.Write((byte)game.Dices.First);
|
||||
m_Stream.Write((byte)game.Dices.Second);
|
||||
Stream.Write((byte)game.Dices.First);
|
||||
Stream.Write((byte)game.Dices.Second);
|
||||
|
||||
m_Stream.Write((byte)game.DealerIndicator.Wind);
|
||||
m_Stream.Write((short)game.DealerIndicator.Position.Y);
|
||||
m_Stream.Write((short)game.DealerIndicator.Position.X);
|
||||
m_Stream.Write((byte)game.DealerIndicator.Direction);
|
||||
Stream.Write((byte)game.DealerIndicator.Wind);
|
||||
Stream.Write((short)game.DealerIndicator.Position.Y);
|
||||
Stream.Write((short)game.DealerIndicator.Position.X);
|
||||
Stream.Write((byte)game.DealerIndicator.Direction);
|
||||
|
||||
m_Stream.Write((short)game.WallBreakIndicator.Position.Y);
|
||||
m_Stream.Write((short)game.WallBreakIndicator.Position.X);
|
||||
Stream.Write((short)game.WallBreakIndicator.Position.Y);
|
||||
Stream.Write((short)game.WallBreakIndicator.Position.X);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -121,37 +121,37 @@ namespace Server.Engines.Mahjong
|
|||
|
||||
EnsureCapacity(11 + 9 * tiles.Length);
|
||||
|
||||
m_Stream.Write(game.Serial);
|
||||
m_Stream.Write((byte)0);
|
||||
m_Stream.Write((byte)0x4);
|
||||
Stream.Write(game.Serial);
|
||||
Stream.Write((byte)0);
|
||||
Stream.Write((byte)0x4);
|
||||
|
||||
m_Stream.Write((short)tiles.Length);
|
||||
Stream.Write((short)tiles.Length);
|
||||
|
||||
foreach (MahjongTile tile in tiles)
|
||||
{
|
||||
m_Stream.Write((byte)tile.Number);
|
||||
Stream.Write((byte)tile.Number);
|
||||
|
||||
if (tile.Flipped)
|
||||
{
|
||||
int hand = tile.Dimensions.GetHandArea();
|
||||
|
||||
if (hand < 0 || players.IsPublic(hand) || players.GetPlayer(hand) == to ||
|
||||
game.SpectatorVision && players.IsSpectator(to))
|
||||
m_Stream.Write((byte)tile.Value);
|
||||
(game.SpectatorVision && players.IsSpectator(to)))
|
||||
Stream.Write((byte)tile.Value);
|
||||
else
|
||||
m_Stream.Write((byte)0);
|
||||
Stream.Write((byte)0);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Stream.Write((byte)0);
|
||||
Stream.Write((byte)0);
|
||||
}
|
||||
|
||||
m_Stream.Write((short)tile.Position.Y);
|
||||
m_Stream.Write((short)tile.Position.X);
|
||||
m_Stream.Write((byte)tile.StackLevel);
|
||||
m_Stream.Write((byte)tile.Direction);
|
||||
Stream.Write((short)tile.Position.Y);
|
||||
Stream.Write((short)tile.Position.X);
|
||||
Stream.Write((byte)tile.StackLevel);
|
||||
Stream.Write((byte)tile.Direction);
|
||||
|
||||
m_Stream.Write(tile.Flipped ? (byte)0x10 : (byte)0x0);
|
||||
Stream.Write(tile.Flipped ? (byte)0x10 : (byte)0x0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -165,33 +165,33 @@ namespace Server.Engines.Mahjong
|
|||
|
||||
EnsureCapacity(18);
|
||||
|
||||
m_Stream.Write(tile.Game.Serial);
|
||||
m_Stream.Write((byte)0);
|
||||
m_Stream.Write((byte)0x3);
|
||||
Stream.Write(tile.Game.Serial);
|
||||
Stream.Write((byte)0);
|
||||
Stream.Write((byte)0x3);
|
||||
|
||||
m_Stream.Write((byte)tile.Number);
|
||||
Stream.Write((byte)tile.Number);
|
||||
|
||||
if (tile.Flipped)
|
||||
{
|
||||
int hand = tile.Dimensions.GetHandArea();
|
||||
|
||||
if (hand < 0 || players.IsPublic(hand) || players.GetPlayer(hand) == to ||
|
||||
game.SpectatorVision && players.IsSpectator(to))
|
||||
m_Stream.Write((byte)tile.Value);
|
||||
(game.SpectatorVision && players.IsSpectator(to)))
|
||||
Stream.Write((byte)tile.Value);
|
||||
else
|
||||
m_Stream.Write((byte)0);
|
||||
Stream.Write((byte)0);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Stream.Write((byte)0);
|
||||
Stream.Write((byte)0);
|
||||
}
|
||||
|
||||
m_Stream.Write((short)tile.Position.Y);
|
||||
m_Stream.Write((short)tile.Position.X);
|
||||
m_Stream.Write((byte)tile.StackLevel);
|
||||
m_Stream.Write((byte)tile.Direction);
|
||||
Stream.Write((short)tile.Position.Y);
|
||||
Stream.Write((short)tile.Position.X);
|
||||
Stream.Write((byte)tile.StackLevel);
|
||||
Stream.Write((byte)tile.Direction);
|
||||
|
||||
m_Stream.Write(tile.Flipped ? (byte)0x10 : (byte)0x0);
|
||||
Stream.Write(tile.Flipped ? (byte)0x10 : (byte)0x0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -201,9 +201,9 @@ namespace Server.Engines.Mahjong
|
|||
{
|
||||
EnsureCapacity(9);
|
||||
|
||||
m_Stream.Write(game.Serial);
|
||||
m_Stream.Write((byte)0);
|
||||
m_Stream.Write((byte)0x1A);
|
||||
Stream.Write(game.Serial);
|
||||
Stream.Write((byte)0);
|
||||
Stream.Write((byte)0x1A);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue