//using System;
//using System.Data;
//using System.Text;
//using System.Threading;
//using System.Collections.ObjectModel;
//using Holo.Virtual.Users;
//using Holo.Virtual.Rooms.Pathfinding;
//using Ion.Storage;
//namespace Holo.Virtual.Rooms.Games
//{
// internal class Game
// {
// #region Declares
// ///
// /// The gameLobby object where this game is hosted in.
// ///
// internal gameLobby Lobby;
// ///
// /// Indicates if this game is of the type 'BattleBall'. If false, then the game is of the type 'SnowStorm'.
// ///
// internal bool isBattleBall;
// ///
// /// The ID of this game.
// ///
// internal int ID;
// ///
// /// The display name of this game.
// ///
// internal string Name;
// ///
// /// The ID of the map that is played with this game.
// ///
// internal int mapID;
// ///
// /// The total amount of gametime in seconds.
// ///
// internal int totalTime;
// ///
// /// The amount of gametime is seconds that is still left on this game.
// ///
// internal int leftTime;
// internal gameState State;
// ///
// /// BattleBall only. The numbers of the enabled powerups for this game.
// ///
// internal int[] enabledPowerups;
// ///
// /// The gamePlayer object (bbPlayer or ssPlayer) of the virtual user that has created this game.
// ///
// internal gamePlayer Owner;
// ///
// /// Collection with the gamePlayer objects of the virtual users that have 'checked in' to this game sub and should receive updates about team status etc.
// ///
// internal Collection Subviewers = new Collection();
// internal Collection[] Teams;
// #region Map declares
// #region Enumerators etc
// internal enum gameState { Waiting = 0, Started = 1, Ended = 2 };
// ///
// /// Represents the state of a tile on the gamemap in a game of 'BattleBall'.
// ///
// private enum bbTileState { Default = 0, Touched = 1, Clicked = 2, Pressed = 3, Sealed = 4 }
// ///
// /// Represents the color of the team that owns a tile on the gamemap in a game of 'BattleBall'.
// ///
// private enum bbTileColor { Disabled = -2, Default = -1, Red = 0, Blue = 1, Yellow = 2, Green = 3 }
// #endregion
// ///
// /// The amount of seconds that the 'loading game' bar still has to be displayed.
// ///
// private int leftCountdownSeconds = Config.Game_Countdown_Seconds;
// ///
// /// The length of the arena.
// private int bX;
// ///
// /// The max width of the arena.
// ///
// private int bY;
// ///
// /// The heightmap of the arena.
// ///
// internal string Heightmap;
// private byte[,] Height;
// private bool[,] Blocked;
// private bbTileState[,] bbTState;
// private bbTileColor[,] bbTColor;
// private Thread updateHandler;
// #endregion
// #endregion
// #region Constructors/destructor
// ///
// /// Initializes a 'BattleBall' game.
// ///
// /// The gameLobby object of the lobby where this game is hosted in.
// /// The ID of this game.
// /// The display name of this game.
// /// The ID of the map that is played with this game.
// /// The amount of teams that is used with the game.
// /// The numbers of the enabled powerups for this game.
// /// The gamePlayer instance of the virtual user that has created this game.
// internal Game(gameLobby Lobby, int ID, string Name, int mapID, int teamAmount, int[] enabledPowerups, gamePlayer Owner)
// {
// this.Lobby = Lobby;
// this.ID = ID;
// this.Name = Name;
// this.mapID = mapID;
// this.Owner = Owner;
// this.enabledPowerups = enabledPowerups;
// this.totalTime = Config.Game_BattleBall_gameLength_Seconds;
// this.leftTime = Config.Game_BattleBall_gameLength_Seconds;
// this.isBattleBall = true;
// // Dimension teams
// this.Teams = new Collection[teamAmount];
// for (int i = 0; i < teamAmount; i++)
// Teams[i] = new Collection();
// }
// ///
// /// Initializes a 'SnowStorm' game.
// ///
// /// The gameLobby object of the lobby where this game is hosted in.
// /// The ID of this game.
// /// The display name of this game.
// /// The ID of the map that is played with this game.
// /// The amount of teams that is used with the game.
// /// The total amount of gametime in seconds.
// /// The gamePlayer instance of the virtual user that has created this game.
// internal Game(gameLobby Lobby, int ID, string Name, int mapID, int teamAmount, int totalTime, gamePlayer Owner)
// {
// this.Lobby = Lobby;
// this.ID = ID;
// this.Name = Name;
// this.mapID = mapID;
// this.Owner = Owner;
// this.totalTime = totalTime;
// this.leftTime = totalTime;
// this.isBattleBall = false;
// // Dimension teams
// this.Teams = new Collection[teamAmount];
// for (int i = 0; i < teamAmount; i++)
// Teams[i] = new Collection();
// }
// ///
// /// Stops the game, and removes all players and subviewers from the game.
// ///
// internal void Abort()
// {
// try { updateHandler.Abort(); }
// catch { }
// string Data = "Cm" + "H";
// for (int i = 0; i < Teams.Length; i++)
// foreach (gamePlayer Member in Teams[i])
// {
// if (Member.User != null)
// {
// if (State == gameState.Waiting)
// Member.User.sendData(Data);
// Member.User.gamePlayer = null;
// }
// }
// foreach (gamePlayer subViewer in Subviewers)
// {
// if (subViewer.User != null)
// {
// if (State == gameState.Waiting)
// subViewer.User.sendData(Data);
// subViewer.User.gamePlayer = null;
// }
// }
// }
// #endregion
// #region Player management
// ///
// /// Moves a player to a certain team, or removes a player from the game.
// ///
// /// The gamePlayer object of the player to move.
// /// The ID of the team where the player was in before. If the player is new to the game, then this parameter should be -1.
// /// The ID of the team where the player is moving to. If the player is leaving the game, then this parameter should be -1.
// internal void movePlayer(gamePlayer Player, int fromTeamID, int toTeamID)
// {
// try
// {
// if (fromTeamID != -1) // Remove player from previous team
// Teams[fromTeamID].Remove(Player);
// if (toTeamID != -1) // User added to team
// {
// if (Teams[toTeamID].Contains(Player) == false)
// Teams[toTeamID].Add(Player);
// Player.teamID = toTeamID;
// }
// else
// {
// Teams[Player.teamID].Remove(Player);
// Player.User.gamePlayer = null;
// }
// sendData("Ci" + this.Sub);
// }
// catch { }
// }
// ///
// /// Indicates if the game can be launched. Games are 'launchable' when there are atleast two teams with players.
// ///
// internal bool Launchable
// {
// get
// {
// int activeTeamCount = 0;
// for (int i = 0; i < Teams.Length; i++)
// if (Teams[i].Count != 0) // This team has got players
// activeTeamCount++;
// return (activeTeamCount > 1); // Atleast two teams with players
// }
// }
// ///
// /// Returns a boolean that indicates if a certain team has space left for new team members. On error, false is returned.
// ///
// /// The ID of the team to check.
// internal bool teamHasSpace(int teamID)
// {
// try
// {
// int m = 0;
// int l = Teams.Length;
// if (l == 2)
// m = 6;
// else if (l == 3)
// m = 4;
// else if (l == 4)
// m = 3;
// return (Teams[teamID].Count < m);
// }
// catch { return false; }
// }
// ///
// /// Sends a single packet to all players, spectators and subviewers of this game.
// ///
// /// The packet to send.
// internal void sendData(string Data)
// {
// for (int i = 0; i < Teams.Length; i++)
// foreach (gamePlayer Member in Teams[i])
// Member.sendData(Data);
// if (State == gameState.Waiting) // Game hasn't started yet
// {
// foreach (gamePlayer subViewer in Subviewers)
// subViewer.sendData(Data);
// }
// }
// #endregion
// #region Properties
// internal string Sub
// {
// get
// {
// StringBuilder Entry = new StringBuilder(Encoding.encodeVL64((int)State));
// if (Launchable) // Atleast two teams with waiting players
// Entry.Append("I"); // 1 = Game can be started
// else
// Entry.Append("H"); // 0 = Game can't be started yet
// Entry.Append(Name + Convert.ToChar(2) + Encoding.encodeVL64(Owner.roomUID) + Owner.User._Username + Convert.ToChar(2));
// if (isBattleBall == false) // SnowStorm game
// Entry.Append(Encoding.encodeVL64(totalTime));
// Entry.Append(Encoding.encodeVL64(mapID) + Encoding.encodeVL64(0) + Encoding.encodeVL64(Teams.Length));
// for (int i = 0; i < Teams.Length; i++)
// {
// Entry.Append(Encoding.encodeVL64(Teams[i].Count));
// foreach (gamePlayer Member in Teams[i])
// Entry.Append(Encoding.encodeVL64(Member.roomUID) + Member.User._Username + Convert.ToChar(2));
// }
// if (isBattleBall) // BattleBall game
// {
// for (int i = 0; i < enabledPowerups.Length; i++)
// Entry.Append(enabledPowerups[i] + ",");
// Entry.Append("9" + Convert.ToChar(2));
// }
// else // SnowStorm game
// Entry.Append(Encoding.encodeVL64(leftTime) + Encoding.encodeVL64(mapID));
// return Entry.ToString();
// }
// }
// #endregion
// #region Arena
// internal void startGame()
// {
// State = gameState.Started;
// foreach (gamePlayer subViewer in Subviewers)
// subViewer.sendData(this.Sub);
// using (DatabaseClient dbClient = Eucalypt.dbManager.GetClient())
// {
// this.Heightmap = dbClient.getString("SELECT heightmap FROM games_maps WHERE type = '" + Lobby.Type + "' AND id = '" + mapID + "'");
// }
// string[] _H = Heightmap.Split(Convert.ToChar(13));
// this.bX = _H[0].Length;
// this.bY = _H.Length - 1;
// string[] _T = null;
// if (isBattleBall)
// {
// this.bbTState = new bbTileState[bX, bY];
// this.bbTColor = new bbTileColor[bX, bY];
// using (DatabaseClient dbClient = Eucalypt.dbManager.GetClient())
// {
// _T = dbClient.getString("SELECT bb_tilemap FROM games_maps WHERE type = 'bb' AND id = '" + mapID + "'").Split(Convert.ToChar(13));
// }
// }
// this.Height = new byte[bX, bY];
// this.Blocked = new bool[bX, bY];
// for (int y = 0; y < bY; y++)
// {
// for (int x = 0; x < bX; x++)
// {
// string q = _H[y].Substring(x, 1);
// if (q == "x")
// {
// Blocked[x, y] = true;
// if (isBattleBall)
// {
// bbTColor[x, y] = bbTileColor.Disabled;
// bbTState[x, y] = bbTileState.Sealed;
// }
// }
// else
// {
// Height[x, y] = Convert.ToByte(q);
// if (isBattleBall)
// {
// if (_T[y].Substring(x, 1) == "1")
// bbTColor[x, y] = bbTileColor.Default;
// else
// {
// bbTColor[x, y] = bbTileColor.Disabled;
// bbTState[x, y] = bbTileState.Sealed;
// }
// }
// }
// }
// }
// int j = 0;
// for (int i = 0; i < Teams.Length; i++)
// {
// if (Teams[i].Count == 0) // Empty team
// continue;
// DataRow dRow;
// using (DatabaseClient dbClient = Eucalypt.dbManager.GetClient())
// {
// dRow = dbClient.getRow("SELECT x,y,z FROM games_maps_playerspawns WHERE type = '" + Lobby.Type + "' AND mapid = '" + mapID + "' AND teamid = '" + i + "'");
// }
// int spawnX = Convert.ToInt32(dRow["x"]);
// int spawnY = Convert.ToInt32(dRow["y"]);
// byte spawnZ = Convert.ToByte(dRow["z"]);
// bool Flip = false;
// foreach (gamePlayer Player in Teams[i])
// {
// Player.roomUID = j;
// rs:
// try
// {
// while (Blocked[spawnX, spawnY])
// {
// if (spawnZ == 0 || spawnZ == 2)
// {
// if (Flip)
// spawnX -= 1;
// else
// spawnX += 1;
// }
// else if (spawnZ == 4 || spawnZ == 6)
// {
// if (Flip)
// spawnY -= 1;
// else
// spawnY += 1;
// }
// }
// Flip = (Flip != true);
// }
// catch { Flip = (Flip != true); goto rs; } // Out of range of map, reverse spawn
// Blocked[spawnX, spawnY] = true;
// Player.X = spawnX;
// Player.Y = spawnY;
// Player.Z = spawnZ;
// Player.H = Height[spawnX, spawnY];
// Player.goalX = -1;
// Player.enteringGame = true;
// j++;
// Out.WriteLine("Assigned spawnpoint [" + spawnX + "," + spawnY + "] to player [" + j + ", team id: " + Player.teamID + "]");
// }
// }
// sendData("Cq" + Encoding.encodeVL64(-1)); // Send players to arena
// new Eucalypt.commonDelegate(countDownTicker).BeginInvoke(null, null); // Start countdown bar
// }
// ///
// /// Counts
// ///
// private void countDownTicker()
// {
// while (leftCountdownSeconds > 0)
// {
// leftCountdownSeconds--;
// Thread.Sleep(1000);
// }
// using (DatabaseClient dbClient = Eucalypt.dbManager.GetClient())
// {
// for (int i = 0; i < Teams.Length; i++)
// foreach (gamePlayer Player in Teams[i])
// {
// Player.User._Tickets -= 2;
// Player.User.sendData("A|" + Player.User._Tickets);
// dbClient.runQuery("UPDATE users SET tickets = '" + Player.User._Tickets + "' WHERE id = '" + Player.User.userID + "' LIMIT 1");
// }
// }
// // Start game
// updateHandler = new Thread(new ThreadStart(updateLoop));
// updateHandler.Start();
// sendData("Cw" + Encoding.encodeVL64(totalTime));
// }
// internal string getMap()
// {
// StringBuilder Setup = new StringBuilder();
// if (isBattleBall)
// {
// Setup.Append("I" + Encoding.encodeVL64(leftCountdownSeconds) + Encoding.encodeVL64(Config.Game_Countdown_Seconds) + "H" + Encoding.encodeVL64(bX) + Encoding.encodeVL64(bY));
// for (int y = 0; y < bY; y++)
// for (int x = 0; x < bX; x++)
// Setup.Append(Encoding.encodeVL64((int)bbTColor[x, y]) + Encoding.encodeVL64((int)bbTState[x, y]));
// Setup.Append("IH");
// }
// else
// Setup.Append("holo.cast.not_finished");
// return Setup.ToString();
// }
// internal string getPlayers()
// {
// StringBuilder Setup = null;
// StringBuilder Helper = new StringBuilder();
// Random RND = new Random(DateTime.Now.Millisecond * totalTime);
// if (isBattleBall)
// {
// int p = 0;
// for (int i = 0; i < Teams.Length; i++)
// foreach (gamePlayer Player in Teams[i])
// {
// Out.WriteLine(Player.roomUID + "!");
// Helper.Append("H" + Encoding.encodeVL64(p) + Encoding.encodeVL64(Player.X) + Encoding.encodeVL64(Player.Y) + Encoding.encodeVL64(Player.H) + Encoding.encodeVL64(Player.Z) + "HM" + Player.User._Username + Convert.ToChar(2) + Player.User._Mission + Convert.ToChar(2) + Player.User._Figure + Convert.ToChar(2) + Player.User._Sex + Convert.ToChar(2) + Encoding.encodeVL64(Player.teamID) + Encoding.encodeVL64(Player.roomUID));
// p++;
// }
// Setup = new StringBuilder("I" + Encoding.encodeVL64(leftCountdownSeconds) + Encoding.encodeVL64(Config.Game_Countdown_Seconds) + Encoding.encodeVL64(p));
// Setup.Append(Helper.ToString());
// Helper = null;
// Setup.Append(Encoding.encodeVL64(bX) + Encoding.encodeVL64(bY));
// for (int y = 0; y < bY; y++)
// for (int x = 0; x < bX; x++)
// Setup.Append(Encoding.encodeVL64((int)bbTColor[x, y]) + Encoding.encodeVL64((int)bbTState[x, y]));
// Setup.Append("IH");
// }
// else
// Setup.Append("holo.cast.not_finished");
// return Setup.ToString();
// }
// private void updateLoop()
// {
// if (isBattleBall)
// {
// int teamAmount = Teams.Length;
// int[] teamScores = new int[teamAmount];
// bool subtrSecond = false;
// int activeTeamAmount = 0;
// for (int i = 0; i < teamAmount; i++)
// {
// if (Teams[i].Count > 0)
// activeTeamAmount++;
// else
// teamScores[i] = -1;
// }
// Random RND = new Random(DateTime.Now.Millisecond * teamAmount);
// while (leftTime > 0)
// {
// int[] Amounts = new int[3]; // [0] = unit amount, [1] = updated tile amount, [2] = moving units amount
// StringBuilder Players = new StringBuilder();
// StringBuilder updatedTiles = new StringBuilder();
// StringBuilder Movements = new StringBuilder();
// for (int i = 0; i < teamAmount; i++)
// foreach (gamePlayer Player in Teams[i])
// {
// Players.Append("H" + Encoding.encodeVL64(Player.roomUID) + Encoding.encodeVL64(Player.X) + Encoding.encodeVL64(Player.Y) + Encoding.encodeVL64(Player.H) + Encoding.encodeVL64(Player.Z) + "HM");
// if (Player.bbColorTile)
// {
// Player.bbColorTile = false;
// updatedTiles.Append(Encoding.encodeVL64(Player.X) + Encoding.encodeVL64(Player.Y) + Encoding.encodeVL64((int)bbTColor[Player.X, Player.Y]) + Encoding.encodeVL64((int)bbTState[Player.X, Player.Y]));
// Amounts[1]++;
// }
// if (Player.goalX != -1)
// {
// Coord Next = gamePathfinder.getNextStep(Player.X, Player.Y, Player.goalX, Player.goalY);
// if (Next.X != -1 && Blocked[Next.X, Next.Y] == false)
// {
// Amounts[2]++;
// Movements.Append("J" + Encoding.encodeVL64(Player.roomUID) + Encoding.encodeVL64(Next.X) + Encoding.encodeVL64(Next.Y));
// if (Next.X == Player.goalX && Next.Y == Player.goalY)
// Player.goalX = -1;
// Blocked[Player.X, Player.Y] = false;
// Blocked[Next.X, Next.Y] = true;
// Player.Z = Rotation.Calculate(Player.X, Player.Y, Next.X, Next.Y);
// Player.X = Next.X;
// Player.Y = Next.Y;
// Player.H = Height[Next.X, Next.Y];
// if (bbTState[Next.X, Next.Y] != bbTileState.Sealed)
// {
// if (bbTColor[Next.X, Next.Y] == (bbTileColor)Player.teamID) // Already property of this team, increment the state
// bbTState[Next.X, Next.Y]++;
// else
// {
// bbTState[Next.X, Next.Y] = bbTileState.Touched;
// bbTColor[Next.X, Next.Y] = (bbTileColor)Player.teamID;
// }
// int extraPoints = 0;
// switch ((int)bbTState[Next.X, Next.Y]) // Check the new status and calculate extra points
// {
// case 1:
// extraPoints = activeTeamAmount;
// break;
// case 2:
// extraPoints = activeTeamAmount * 3;
// break;
// case 3:
// extraPoints = activeTeamAmount * 5;
// break;
// case 4:
// extraPoints = activeTeamAmount * 7;
// break;
// }
// teamScores[Player.teamID] += extraPoints;
// Player.Score += extraPoints;
// Player.bbColorTile = true;
// }
// }
// else
// Player.goalX = -1; // Stop moving
// }
// Amounts[0]++;
// }
// string scoreString = "H" + Encoding.encodeVL64(teamAmount);
// for (int i = 0; i < teamAmount; i++)
// scoreString += Encoding.encodeVL64(teamScores[i]);
// sendData("Ct" + Encoding.encodeVL64(Amounts[0]) + Players.ToString() + Encoding.encodeVL64(Amounts[1]) + updatedTiles.ToString() + scoreString + "I" + Encoding.encodeVL64(Amounts[2]) + Movements.ToString());
// if (subtrSecond)
// leftTime--;
// subtrSecond = (subtrSecond != true);
// Thread.Sleep(470);
// }
// State = gameState.Ended;
// StringBuilder Scores = new StringBuilder("Cx" + Encoding.encodeVL64(Config.Game_scoreWindow_restartGame_Seconds) + Encoding.encodeVL64(teamAmount));
// for (int i = 0; i < teamAmount; i++)
// {
// int memberAmount = Teams[i].Count;
// if (memberAmount > 0)
// {
// Scores.Append(Encoding.encodeVL64(memberAmount));
// using (DatabaseClient dbClient = Eucalypt.dbManager.GetClient())
// {
// foreach (gamePlayer Player in Teams[i])
// {
// Scores.Append(Encoding.encodeVL64(Player.roomUID));
// if (Player.User != null)
// {
// dbClient.runQuery("UPDATE users SET bb_playedgames = bb_playedgames + 1,bb_totalpoints = bb_totalpoints + " + Player.Score + " WHERE id = '" + Player.User.userID + "' LIMIT 1");
// Scores.Append(Player.User._Username + Convert.ToChar(2));
// }
// else
// Scores.Append("M");
// Scores.Append(Encoding.encodeVL64(Player.Score));
// }
// }
// Scores.Append(Encoding.encodeVL64(teamScores[i]));
// }
// else
// Scores.Append("M");
// }
// sendData(Scores.ToString());
// }
// }
// private Coord[] getSurfaceTiles(Coord Start)
// {
// return null;
// }
// #endregion
// }
//}
using System;
using System.Data;
using System.Text;
using System.Threading;
using System.Collections.ObjectModel;
using Holo.Virtual.Users;
using Holo.Virtual.Rooms.Pathfinding;
using Ion.Storage;
namespace Holo.Virtual.Rooms.Games
{
internal class Game
{
#region Declares
///
/// Indicates if this game is of the type 'BattleBall'. If false, then the game is of the type 'SnowStorm'.
///
internal bool isBattleBall;
///
/// The ID of this game.
///
internal int ID;
///
/// The ID of the map that is played with this game.
///
internal int mapID;
///
/// The total amount of gametime in seconds.
///
internal int totalTime;
///
/// Indicates if this game is private or not
///
internal bool isPrivate;
///
/// The amount of gametime is seconds that is still left on this game.
///
internal int leftTime;
internal gameState State;
///
/// BattleBall only. The numbers of the enabled powerups for this game.
///
internal int[] enabledPowerups;
///
/// The gamePlayer object (bbPlayer or ssPlayer) of the virtual user that has created this game.
///
internal gamePlayer Owner;
///
/// Collection with the gamePlayer objects of the virtual users that have 'checked in' to this game sub and should receive updates about team status etc.
///
internal Collection Subviewers = new Collection();
internal Collection[] Teams;
#region Map declares
#region Enumerators etc
internal enum gameState { Waiting = 0, Started = 1, Ended = 2 };
///
/// Represents the state of a tile on the gamemap in a game of 'BattleBall'.
///
private enum bbTileState { Default = 0, Touched = 1, Clicked = 2, Pressed = 3, Sealed = 4 }
///
/// Represents the color of the team that owns a tile on the gamemap in a game of 'BattleBall'.
///
private enum bbTileColor { Disabled = -2, Default = -1, Red = 0, Blue = 1, Yellow = 2, Green = 3 }
#endregion
///
/// The amount of seconds that the 'loading game' bar still has to be displayed.
///
private int leftCountdownSeconds = Config.Game_Countdown_Seconds;
///
/// The length of the arena.
private int bX;
///
/// The max width of the arena.
///
private int bY;
///
/// The heightmap of the arena.
///
internal string Heightmap;
private byte[,] Height;
private bool[,] Blocked;
private bbTileState[,] bbTState;
private bbTileColor[,] bbTColor;
private Thread updateHandler;
#endregion
#endregion
#region Constructors/destructor
///
/// Initializes a 'BattleBall' game.
///
/// The gameLobby object of the lobby where this game is hosted in.
/// The ID of this game.
/// The display name of this game.
/// The ID of the map that is played with this game.
/// The amount of teams that is used with the game.
/// The numbers of the enabled powerups for this game.
/// The gamePlayer instance of the virtual user that has created this game.
internal Game(int ID, int mapID, int teamAmount, int[] enabledPowerups, bool isPrivate, gamePlayer Owner)
{
this.isPrivate = isPrivate;
this.ID = ID;
this.mapID = mapID;
this.Owner = Owner;
this.enabledPowerups = enabledPowerups;
this.totalTime = Config.Game_BattleBall_gameLength_Seconds;
this.leftTime = Config.Game_BattleBall_gameLength_Seconds;
this.isBattleBall = true;
// Dimension teams
this.Teams = new Collection[teamAmount];
for (int i = 0; i < teamAmount; i++)
Teams[i] = new Collection();
}
///
/// Initializes a 'SnowStorm' game.
///
/// The gameLobby object of the lobby where this game is hosted in.
/// The ID of this game.
/// The display name of this game.
/// The ID of the map that is played with this game.
/// The amount of teams that is used with the game.
/// The total amount of gametime in seconds.
/// The gamePlayer instance of the virtual user that has created this game.
internal Game(int ID, int mapID, int teamAmount, int totalTime, gamePlayer Owner)
{
this.ID = ID;
this.mapID = mapID;
this.Owner = Owner;
this.totalTime = totalTime;
this.leftTime = totalTime;
this.isBattleBall = false;
// Dimension teams
this.Teams = new Collection[teamAmount];
for (int i = 0; i < teamAmount; i++)
Teams[i] = new Collection();
}
///
/// Stops the game, and removes all players and subviewers from the game.
///
internal void Abort()
{
try { updateHandler.Abort(); }
catch { }
string Data = "Cm" + "H";
for (int i = 0; i < Teams.Length; i++)
foreach (gamePlayer Member in Teams[i])
{
if (Member.User != null)
{
if (State == gameState.Waiting)
Member.User.sendData(Data);
Member.User.gamePlayer = null;
}
}
foreach (gamePlayer subViewer in Subviewers)
{
if (subViewer.User != null)
{
if (State == gameState.Waiting)
subViewer.User.sendData(Data);
subViewer.User.gamePlayer = null;
}
}
}
#endregion
#region Player management
///
/// Moves a player to a certain team, or removes a player from the game.
///
/// The gamePlayer object of the player to move.
/// The ID of the team where the player was in before. If the player is new to the game, then this parameter should be -1.
/// The ID of the team where the player is moving to. If the player is leaving the game, then this parameter should be -1.
internal void movePlayer(gamePlayer Player, int fromTeamID, int toTeamID)
{
try
{
if (fromTeamID != -1) // Remove player from previous team
Teams[fromTeamID].Remove(Player);
if (toTeamID != -1) // User added to team
{
if (Teams[toTeamID].Contains(Player) == false)
Teams[toTeamID].Add(Player);
Player.teamID = toTeamID;
}
else
{
Teams[Player.teamID].Remove(Player);
Player.User.gamePlayer = null;
}
// sendData("Ci" + this.Sub);
}
catch { }
}
///
/// Indicates if the game can be launched. Games are 'launchable' when there are atleast two teams with players.
///
internal bool Launchable
{
get
{
int activeTeamCount = 0;
for (int i = 0; i < Teams.Length; i++)
if (Teams[i].Count != 0) // This team has got players
activeTeamCount++;
return (activeTeamCount > 1); // Atleast two teams with players
}
}
///
/// Returns a boolean that indicates if a certain team has space left for new team members. On error, false is returned.
///
/// The ID of the team to check.
internal bool teamHasSpace(int teamID)
{
try
{
int ID = teamID - 1;
int m = 0;
int l = Teams.Length;
if (l == 2)
m = 6;
else if (l == 3)
m = 4;
else if (l == 4)
m = 3;
return (Teams[ID].Count < m);
}
catch { return false; }
}
///
/// Sends a single packet to all players, spectators and subviewers of this game.
///
/// The packet to send.
internal void sendData(string Data)
{
for (int i = 0; i < Teams.Length; i++)
foreach (gamePlayer Member in Teams[i])
Member.User.sendData(Data);
if (State == gameState.Waiting) // Game hasn't started yet
{
foreach (gamePlayer subViewer in Subviewers)
subViewer.User.sendData(Data);
}
}
#endregion
#region Properties
internal string Info
{
get
{
StringBuilder Entry = new StringBuilder(Encoding.encodeVL64(ID));
Entry.Append("SnowStorm level 6");
Entry.Append(Convert.ToChar(2));
Entry.Append("I");
Entry.Append(Encoding.encodeVL64(mapID));
Entry.Append(Encoding.encodeVL64(1)); // Snowstorm only, time
Entry.Append(Encoding.encodeVL64(getPlayerCount()));
Entry.Append(Encoding.encodeVL64(12));
Entry.Append(Owner.User._Username);
Entry.Append(Convert.ToChar(2));
Entry.Append("I"); // UNKNOWN
Entry.Append(Encoding.encodeVL64(Teams.Length));
Entry.Append(Encoding.encodeVL64(getPlayerCount())); // UNKNOWN
for (int i = 0; i < Teams.Length; i++)
{
int h = 0;
foreach (gamePlayer Member in Teams[i])
{
Entry.Append(Encoding.encodeVL64(h));
Entry.Append(Member.User._Username);
Entry.Append(Convert.ToChar(2));
Entry.Append(Member.User._Figure);
Entry.Append(Convert.ToChar(2));
Entry.Append(Member.User._Sex.ToString().ToLower());
Entry.Append(Convert.ToChar(2));
h++;
}
}
//Entry.Append(Convert.ToChar(2));
//Entry.Append("JXKA"); // UNKNOWN
//Entry.Append("Fa"
//+ "RP"
//+ "SnowStorm level 6"
//+ ""
//+ "I"
//+ "RA"
//+ "I"
//+ "RA"
//+ "PC"
//+ "Monsta."
//+ ""
//+ "RA"
//+ "I"
//+ "I");
//Entry.Append("H"
//+ "Monsta."
//+ ""
//+ "hd-190-1.ch-255-81.lg-280-89.sh-906-63.hr-831-61.he-1609-62"
//+ ""
//+ "m"
//+ "");
/* + "I"
+ "BUCK245"
+ ""
+ "hd-180-16.ch-260-82.lg-285-64.sh-906-64.hr-155-38.ea-1404-64"
+ ""
+ "m"
+ ""
+ "J"
+ "bourno25"
+ ""
+ "hr-889-40.hd-207-30.ch-267-62.lg-281-62.sh-906-62.ea-1404-64.wa-2012-.ha-1002-64.ca-1802-.fa-1205-64"
+ ""
+ "m"
+ ""
+ "K"
+ "rosiebear999"
+ ""
+ "hr-545-34.hd-600-7.ch-630-62.lg-700-64.sh-725-62.ea-1406-62.fa-1204-62"
+ ""
+ "f"
+ ""
+ "PA"
+ "addzy1996"
+ ""
+ "hd-205-12.ch-260-71.lg-270-64.sh-305-71.hr-165-39.ha-1010-71"
+ ""
+ "m"
+ ""
+ "QA"
+ "MallonBopper"
+ ""
+ "hd-180-1.ch-255-64.lg-280-64.sh-300-64.wa-2002-.hr-165-48"
+ ""
+ "m"
+ ""*/
//Entry.Append("HXKA");
return Entry.ToString();
}
}
#endregion
#region Arena
internal void startGame()
{
State = gameState.Started;
// foreach (gamePlayer subViewer in Subviewers)
// subViewer.sendData(this.Sub);
using (DatabaseClient dbClient = Eucalypt.dbManager.GetClient())
{
this.Heightmap = dbClient.getString("SELECT heightmap FROM games_maps WHERE id = '" + mapID + "'");
}
string[] _H = Heightmap.Split(Convert.ToChar(13));
this.bX = _H[0].Length;
this.bY = _H.Length - 1;
string[] _T = null;
if (isBattleBall)
{
this.bbTState = new bbTileState[bX, bY];
this.bbTColor = new bbTileColor[bX, bY];
using (DatabaseClient dbClient = Eucalypt.dbManager.GetClient())
{
_T = dbClient.getString("SELECT bb_tilemap FROM games_maps WHERE type = 'bb' AND id = '" + mapID + "'").Split(Convert.ToChar(13));
}
}
this.Height = new byte[bX, bY];
this.Blocked = new bool[bX, bY];
for (int y = 0; y < bY; y++)
{
for (int x = 0; x < bX; x++)
{
string q = _H[y].Substring(x, 1);
if (q == "x")
{
Blocked[x, y] = true;
if (isBattleBall)
{
bbTColor[x, y] = bbTileColor.Disabled;
bbTState[x, y] = bbTileState.Sealed;
}
}
else
{
Height[x, y] = Convert.ToByte(q);
if (isBattleBall)
{
if (_T[y].Substring(x, 1) == "1")
bbTColor[x, y] = bbTileColor.Default;
else
{
bbTColor[x, y] = bbTileColor.Disabled;
bbTState[x, y] = bbTileState.Sealed;
}
}
}
}
}
int j = 0;
for (int i = 0; i < Teams.Length; i++)
{
if (Teams[i].Count == 0) // Empty team
continue;
DataRow dRow;
using (DatabaseClient dbClient = Eucalypt.dbManager.GetClient())
{
dRow = dbClient.getRow("SELECT x,y,z FROM games_maps_playerspawns WHERE mapid = '" + mapID + "' AND teamid = '" + i + "'");
}
int spawnX = Convert.ToInt32(dRow["x"]);
int spawnY = Convert.ToInt32(dRow["y"]);
byte spawnZ = Convert.ToByte(dRow["z"]);
bool Flip = false;
foreach (gamePlayer Player in Teams[i])
{
Player.roomUID = j;
rs:
try
{
while (Blocked[spawnX, spawnY])
{
if (spawnZ == 0 || spawnZ == 2)
{
if (Flip)
spawnX -= 1;
else
spawnX += 1;
}
else if (spawnZ == 4 || spawnZ == 6)
{
if (Flip)
spawnY -= 1;
else
spawnY += 1;
}
}
Flip = (Flip != true);
}
catch { Flip = (Flip != true); goto rs; } // Out of range of map, reverse spawn
Blocked[spawnX, spawnY] = true;
Player.X = spawnX;
Player.Y = spawnY;
Player.Z = spawnZ;
Player.H = Height[spawnX, spawnY];
Player.goalX = -1;
Player.enteringGame = true;
j++;
Out.WriteLine("Assigned spawnpoint [" + spawnX + "," + spawnY + "] to player [" + j + ", team id: " + Player.teamID + "]");
}
}
sendData("FP" + Encoding.encodeVL64(-1)); // Send players to arena
sendData("FR");
sendData("FS");
new Eucalypt.commonDelegate(countDownTicker).BeginInvoke(null, null); // Start countdown bar
}
///
/// Counts
///
private void countDownTicker()
{
while (leftCountdownSeconds > 0)
{
leftCountdownSeconds--;
Thread.Sleep(1000);
}
using (DatabaseClient dbClient = Eucalypt.dbManager.GetClient())
{
for (int i = 0; i < Teams.Length; i++)
foreach (gamePlayer Player in Teams[i])
{
Player.User._Tickets -= 2;
Player.User.sendData("A|" + Player.User._Tickets);
dbClient.runQuery("UPDATE users SET tickets = '" + Player.User._Tickets + "' WHERE id = '" + Player.User.userID + "' LIMIT 1");
}
}
// Start game
updateHandler = new Thread(new ThreadStart(updateLoop));
updateHandler.Start();
sendData("Cw" + Encoding.encodeVL64(totalTime));
}
internal string getMap()
{
StringBuilder Setup = new StringBuilder();
if (isBattleBall)
{
Setup.Append("I" + Encoding.encodeVL64(leftCountdownSeconds) + Encoding.encodeVL64(Config.Game_Countdown_Seconds) + "H" + Encoding.encodeVL64(bX) + Encoding.encodeVL64(bY));
for (int y = 0; y < bY; y++)
for (int x = 0; x < bX; x++)
Setup.Append(Encoding.encodeVL64((int)bbTColor[x, y]) + Encoding.encodeVL64((int)bbTState[x, y]));
Setup.Append("IH");
}
else
Setup.Append("holo.cast.not_finished");
return Setup.ToString();
}
internal string getPlayers()
{
StringBuilder Setup = null;
StringBuilder Helper = new StringBuilder();
Random RND = new Random(DateTime.Now.Millisecond * totalTime);
if (isBattleBall)
{
int p = 0;
for (int i = 0; i < Teams.Length; i++)
foreach (gamePlayer Player in Teams[i])
{
Out.WriteLine(Player.roomUID + "!");
Helper.Append("H" + Encoding.encodeVL64(p) + Encoding.encodeVL64(Player.X) + Encoding.encodeVL64(Player.Y) + Encoding.encodeVL64(Player.H) + Encoding.encodeVL64(Player.Z) + "HM" + Player.User._Username + Convert.ToChar(2) + Player.User._Mission + Convert.ToChar(2) + Player.User._Figure + Convert.ToChar(2) + Player.User._Sex + Convert.ToChar(2) + Encoding.encodeVL64(Player.teamID) + Encoding.encodeVL64(Player.roomUID));
p++;
}
Setup = new StringBuilder("I" + Encoding.encodeVL64(leftCountdownSeconds) + Encoding.encodeVL64(Config.Game_Countdown_Seconds) + Encoding.encodeVL64(p));
Setup.Append(Helper.ToString());
Helper = null;
Setup.Append(Encoding.encodeVL64(bX) + Encoding.encodeVL64(bY));
for (int y = 0; y < bY; y++)
for (int x = 0; x < bX; x++)
Setup.Append(Encoding.encodeVL64((int)bbTColor[x, y]) + Encoding.encodeVL64((int)bbTState[x, y]));
Setup.Append("IH");
}
else
Setup.Append("holo.cast.not_finished");
return Setup.ToString();
}
internal int getPlayerCount()
{
int p = 0;
for (int i = 0; i < Teams.Length; i++)
foreach (gamePlayer Player in Teams[i])
p++;
return p;
}
internal bool addPlayer(gamePlayer Player, int team)
{
team = team - 1;
if (teamHasSpace(team))
{
Teams[team].Add(Player);
return true;
}
else
for (int i = 0; i < Teams.Length; i++)
{
if (teamHasSpace(i))
{
Teams[i].Add(Player);
return true;
}
}
return false;
}
private void updateLoop()
{
if (isBattleBall)
{
int teamAmount = Teams.Length;
int[] teamScores = new int[teamAmount];
bool subtrSecond = false;
int activeTeamAmount = 0;
for (int i = 0; i < teamAmount; i++)
{
if (Teams[i].Count > 0)
activeTeamAmount++;
else
teamScores[i] = -1;
}
Random RND = new Random(DateTime.Now.Millisecond * teamAmount);
while (leftTime > 0)
{
int[] Amounts = new int[3]; // [0] = unit amount, [1] = updated tile amount, [2] = moving units amount
StringBuilder Players = new StringBuilder();
StringBuilder updatedTiles = new StringBuilder();
StringBuilder Movements = new StringBuilder();
for (int i = 0; i < teamAmount; i++)
foreach (gamePlayer Player in Teams[i])
{
Players.Append("H" + Encoding.encodeVL64(Player.roomUID) + Encoding.encodeVL64(Player.X) + Encoding.encodeVL64(Player.Y) + Encoding.encodeVL64(Player.H) + Encoding.encodeVL64(Player.Z) + "HM");
if (Player.bbColorTile)
{
Player.bbColorTile = false;
updatedTiles.Append(Encoding.encodeVL64(Player.X) + Encoding.encodeVL64(Player.Y) + Encoding.encodeVL64((int)bbTColor[Player.X, Player.Y]) + Encoding.encodeVL64((int)bbTState[Player.X, Player.Y]));
Amounts[1]++;
}
if (Player.goalX != -1)
{
Coord Next = gamePathfinder.getNextStep(Player.X, Player.Y, Player.goalX, Player.goalY);
if (Next.X != -1 && Blocked[Next.X, Next.Y] == false)
{
Amounts[2]++;
Movements.Append("J" + Encoding.encodeVL64(Player.roomUID) + Encoding.encodeVL64(Next.X) + Encoding.encodeVL64(Next.Y));
if (Next.X == Player.goalX && Next.Y == Player.goalY)
Player.goalX = -1;
Blocked[Player.X, Player.Y] = false;
Blocked[Next.X, Next.Y] = true;
Player.Z = Rotation.Calculate(Player.X, Player.Y, Next.X, Next.Y);
Player.X = Next.X;
Player.Y = Next.Y;
Player.H = Height[Next.X, Next.Y];
if (bbTState[Next.X, Next.Y] != bbTileState.Sealed)
{
if (bbTColor[Next.X, Next.Y] == (bbTileColor)Player.teamID) // Already property of this team, increment the state
bbTState[Next.X, Next.Y]++;
else
{
bbTState[Next.X, Next.Y] = bbTileState.Touched;
bbTColor[Next.X, Next.Y] = (bbTileColor)Player.teamID;
}
int extraPoints = 0;
switch ((int)bbTState[Next.X, Next.Y]) // Check the new status and calculate extra points
{
case 1:
extraPoints = activeTeamAmount;
break;
case 2:
extraPoints = activeTeamAmount * 3;
break;
case 3:
extraPoints = activeTeamAmount * 5;
break;
case 4:
extraPoints = activeTeamAmount * 7;
break;
}
teamScores[Player.teamID] += extraPoints;
Player.Score += extraPoints;
Player.bbColorTile = true;
}
}
else
Player.goalX = -1; // Stop moving
}
Amounts[0]++;
}
string scoreString = "H" + Encoding.encodeVL64(teamAmount);
for (int i = 0; i < teamAmount; i++)
scoreString += Encoding.encodeVL64(teamScores[i]);
sendData("Ct" + Encoding.encodeVL64(Amounts[0]) + Players.ToString() + Encoding.encodeVL64(Amounts[1]) + updatedTiles.ToString() + scoreString + "I" + Encoding.encodeVL64(Amounts[2]) + Movements.ToString());
if (subtrSecond)
leftTime--;
subtrSecond = (subtrSecond != true);
Thread.Sleep(470);
}
State = gameState.Ended;
StringBuilder Scores = new StringBuilder("Cx" + Encoding.encodeVL64(Config.Game_scoreWindow_restartGame_Seconds) + Encoding.encodeVL64(teamAmount));
for (int i = 0; i < teamAmount; i++)
{
int memberAmount = Teams[i].Count;
if (memberAmount > 0)
{
Scores.Append(Encoding.encodeVL64(memberAmount));
using (DatabaseClient dbClient = Eucalypt.dbManager.GetClient())
{
foreach (gamePlayer Player in Teams[i])
{
Scores.Append(Encoding.encodeVL64(Player.roomUID));
if (Player.User != null)
{
dbClient.runQuery("UPDATE users SET bb_playedgames = bb_playedgames + 1,bb_totalpoints = bb_totalpoints + " + Player.Score + " WHERE id = '" + Player.User.userID + "' LIMIT 1");
Scores.Append(Player.User._Username + Convert.ToChar(2));
}
else
Scores.Append("M");
Scores.Append(Encoding.encodeVL64(Player.Score));
}
}
Scores.Append(Encoding.encodeVL64(teamScores[i]));
}
else
Scores.Append("M");
}
sendData(Scores.ToString());
}
}
private Coord[] getSurfaceTiles(Coord Start)
{
return null;
}
#endregion
}
}