MCGalaxy/Player/Player.cs

2871 lines
122 KiB
C#

/*
Copyright 2010 MCSharp team (Modified for use with MCZall/MCLawl/MCGalaxy)
Dual-licensed under the Educational Community License, Version 2.0 and
the GNU General Public License, Version 3 (the "Licenses"); you may
not use this file except in compliance with the Licenses. You may
obtain a copy of the Licenses at
http://www.opensource.org/licenses/ecl2.php
http://www.gnu.org/licenses/gpl-3.0.html
Unless required by applicable law or agreed to in writing,
software distributed under the Licenses are distributed on an "AS IS"
BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
or implied. See the Licenses for the specific language governing
permissions and limitations under the Licenses.
*/
using System;
using System.Collections.Generic;
using System.Data;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using MCGalaxy.Drawing;
using MCGalaxy.SQL;
using MCGalaxy.Util;
namespace MCGalaxy {
public sealed partial class Player : IDisposable {
/// <summary>
/// List of all server players.
/// </summary>
public static List<Player> players = new List<Player>();
/// <summary>
/// Key - Name
/// Value - IP
/// All players who have left this restart.
/// </summary>
public Dictionary<string, object> ExtraData = new Dictionary<string, object>();
public void ClearChat() { OnChat = null; }
public static Dictionary<string, string> left = new Dictionary<string, string>();
static List<string> pendingNames = new List<string>();
static object pendingLock = new object();
public static List<Player> connections = new List<Player>(Server.players);
System.Timers.Timer muteTimer = new System.Timers.Timer(1000);
public static List<string> emoteList = new List<string>();
public List<string> listignored = new List<string>();
public List<string> mapgroups = new List<string>();
public static List<string> globalignores = new List<string>();
public static int totalMySQLFailed = 0;
public static byte number { get { return (byte)players.Count; } }
static System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
static MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
public static string lastMSG = "";
//TpA
public bool Request = false;
public string senderName = "";
public string currentTpa = "";
public static bool storeHelp = false;
public static string storedHelp = "";
private string truename;
internal bool dontmindme = false;
public Socket socket;
System.Timers.Timer timespent = new System.Timers.Timer(1000);
System.Timers.Timer loginTimer = new System.Timers.Timer(1000);
public System.Timers.Timer pingTimer = new System.Timers.Timer(2000);
System.Timers.Timer extraTimer = new System.Timers.Timer(22000);
public System.Timers.Timer afkTimer = new System.Timers.Timer(2000);
public int afkCount = 0;
public DateTime afkStart;
public string WoMVersion = "";
public bool cmdTimer = false;
public bool UsingWom = false;
byte[] buffer = new byte[0];
byte[] tempbuffer = new byte[0xFF];
public bool disconnected = false;
public string time;
public string name;
public string DisplayName;
public string SkinName;
public string realName;
public int warn = 0;
public byte id;
public int userID = -1;
public string ip;
public string color;
public Group group;
public bool hidden = false;
public bool painting = false;
public bool muted = false;
public bool jailed = false;
public bool agreed = true;
public bool invincible = false;
public string prefix = "";
public string title = "";
public string titlecolor;
public int TotalMessagesSent = 0;
public int passtries = 0;
public int ponycount = 0;
public int rdcount = 0;
public bool hasreadrules = false;
public bool canusereview = true;
public float ReachDistance = 5;
public string FullName { get { return color + prefix + DisplayName; } }
//Gc checks
public string lastmsg = "";
public int spamcount = 0, capscount = 0, floodcount = 0, multi = 0;
public DateTime lastmsgtime = DateTime.MinValue;
/// <summary>
/// Console only please
/// </summary>
public bool canusegc = true;
public bool deleteMode = false;
public bool ignorePermission = false;
public bool ignoreGrief = false;
public bool parseSmiley = true;
public bool smileySaved = true;
public bool opchat = false;
public bool adminchat = false;
public bool onWhitelist = false;
public bool whisper = false;
public string whisperTo = "";
public bool ignoreglobal = false;
public string storedMessage = "";
public bool trainGrab = false;
public bool onTrain = false;
public bool allowTnt = true;
public bool frozen = false;
public string following = "";
public string possess = "";
// Only used for possession.
//Using for anything else can cause unintended effects!
public bool canBuild = true;
public int money = 0;
public long overallBlocks = 0;
public int loginBlocks = 0;
public DateTime timeLogged;
public DateTime firstLogin;
public int totalLogins = 0;
public int totalKicked = 0;
public int overallDeath = 0;
public string savedcolor = "";
public bool staticCommands = false;
public DateTime ZoneSpam;
public bool ZoneCheck = false;
public bool zoneDel = false;
public Thread commThread;
public bool commUse = false;
public bool aiming;
public bool isFlying = false;
public bool joker = false;
public bool adminpen = false;
public bool voice = false;
public string voicestring = "";
public int grieferStoneWarn = 0;
//CTF
public Team team;
public Team hasflag;
//Countdown
public bool playerofcountdown = false;
public bool incountdown = false;
public ushort countdowntempx;
public ushort countdowntempz;
public bool countdownsettemps = false;
//Zombie
public bool referee = false;
public int blockCount = 50;
public bool voted = false;
public int blocksStacked = 0;
public int infectThisRound = 0;
public int lastYblock = 0;
public int lastXblock = 0;
public int lastZblock = 0;
public bool infected = false;
public bool aka = false;
public bool flipHead = true;
public int playersInfected = 0;
public int NoClipcount = 0;
//Tnt Wars
public bool PlayingTntWars = false;
public int CurrentAmountOfTnt = 0;
public int CurrentTntGameNumber; //For keeping track of which game is which
public int TntWarsHealth = 2;
public int TntWarsKillStreak = 0;
public float TntWarsScoreMultiplier = 1f;
public int TNTWarsLastKillStreakAnnounced = 0;
public bool inTNTwarsMap = false;
public Player HarmedBy = null; //For Assists
//Copy
public CopyState CopyBuffer;
public bool copyAir = false;
public int[] copyoffset = new int[3] { 0, 0, 0 };
public ushort[] copystart = new ushort[3] { 0, 0, 0 };
//Center
public int[] centerstart = new int[3] { 0, 0, 0 };
public int[] centerend = new int[3] { 0, 0, 0 };
// GlobalBlock
internal int gbStep = 0;
internal BlockDefinition gbBlock;
public string model = "humanoid";
public bool spawned = false;
public bool Mojangaccount {
get {
return truename.Contains('@');
}
}
//Undo
public struct UndoPos { public ushort x, y, z; public byte type, extType, newtype, newExtType; public string mapName; public DateTime timePlaced; }
public List<UndoPos> UndoBuffer = new List<UndoPos>();
public List<UndoPos> RedoBuffer = new List<UndoPos>();
public bool showPortals = false;
public bool showMBs = false;
public string prevMsg = "";
//Block Change variable holding
public int[] BcVar;
//Movement
public int oldIndex = -1, oldFallY = 10000;
public int fallCount = 0, drownCount = 0;
//Games
public DateTime lastDeath = DateTime.Now;
public byte BlockAction;
public byte modeType;
public byte[] bindings = new byte[128];
public string[] cmdBind = new string[10];
public string[] messageBind = new string[10];
public string lastCMD = "";
public sbyte c4circuitNumber = -1;
public Level level = Server.mainLevel;
public bool Loading = true; //True if player is loading a map.
public ushort[] lastClick = new ushort[] { 0, 0, 0 };
public ushort[] beforeTeleportPos = new ushort[] { 0, 0, 0 };
public string beforeTeleportMap = "";
public ushort[] pos = new ushort[] { 0, 0, 0 };
ushort[] oldpos = new ushort[] { 0, 0, 0 };
ushort[] basepos = new ushort[] { 0, 0, 0 };
public byte[] rot = new byte[] { 0, 0 };
byte[] oldrot = new byte[] { 0, 0 };
//ushort[] clippos = new ushort[3] { 0, 0, 0 };
//byte[] cliprot = new byte[2] { 0, 0 };
// grief/spam detection
public static int spamBlockCount = 200;
public bool isUsingOpenClassic = false;
public static int spamBlockTimer = 5;
Queue<DateTime> spamBlockLog = new Queue<DateTime>(spamBlockCount);
public int consecutivemessages;
private System.Timers.Timer resetSpamCount = new System.Timers.Timer(Server.spamcountreset * 1000);
//public static int spamChatCount = 3;
//public static int spamChatTimer = 4;
//Queue<DateTime> spamChatLog = new Queue<DateTime>(spamChatCount);
// CmdVoteKick
public VoteKickChoice voteKickChoice = VoteKickChoice.HasntVoted;
// Extra storage for custom commands
public ExtrasCollection Extras = new ExtrasCollection();
//Chatrooms
public string Chatroom;
public List<string> spyChatRooms = new List<string>();
public DateTime lastchatroomglobal;
public List<Waypoint> Waypoints = new List<Waypoint>();
public Random random = new Random();
//Global Chat
public bool muteGlobal;
public bool loggedIn;
public bool InGlobalChat { get; set; }
public Dictionary<string, string> sounds = new Dictionary<string, string>();
public bool isDev, isMod, isGCMod; //is this player a dev/mod/gcmod?
public bool isStaff;
public bool verifiedName;
public struct OfflinePlayer {
public string name, color, title, titleColor;
public int money;
//need moar? add moar! just make sure you adjust Player.FindOffline() method
/// <summary>
/// Creates a new OfflinePlayer object.
/// </summary>
/// <param name="nm">Name of the player.</param>
/// <param name="clr">Color of player name.</param>
/// <param name="tl">Title of player.</param>
/// <param name="tlclr">Title color of player</param>
/// <param name="mon">Player's money.</param>
public OfflinePlayer(string nm, string clr, string tl, string tlclr, int mon) { name = nm; color = clr; title = tl; titleColor = tlclr; money = mon; }
}
public static string CheckPlayerStatus(Player p) {
if ( p.hidden )
return "hidden";
if ( Server.afkset.Contains(p.name) )
return "afk";
return "active";
}
public bool Readgcrules = false;
public DateTime Timereadgcrules = DateTime.MinValue;
public bool CheckIfInsideBlock() {
return CheckIfInsideBlock(this);
}
public static bool CheckIfInsideBlock(Player p) {
ushort x, y, z;
x = (ushort)( p.pos[0] / 32 );
y = (ushort)( p.pos[1] / 32 );
y = (ushort)Math.Round((decimal)( ( ( y * 32 ) + 4 ) / 32 ));
z = (ushort)( p.pos[2] / 32 );
byte b = p.level.GetTile(x, y, z);
byte b1 = p.level.GetTile(x, (ushort)( y - 1 ), z);
if ( Block.Walkthrough(Block.Convert(b)) && Block.Walkthrough(Block.Convert(b1)) ) {
return false;
}
return Block.Convert(b) != Block.Zero && Block.Convert(b) != Block.op_air;
}
//This is so that plugin devs can declare a player without needing a socket..
//They would still have to do p.Dispose()..
public Player(string playername) { name = playername; if (playername == "IRC") { group = Group.Find("nobody"); color = c.lime; } }
public Player(Socket s) {
try {
socket = s;
ip = socket.RemoteEndPoint.ToString().Split(':')[0];
/*if (IPInPrivateRange(ip))
exIP = ResolveExternalIP(ip);
else
exIP = ip;*/
Server.s.Log(ip + " connected to the server.");
for ( byte i = 0; i < 128; ++i ) bindings[i] = i;
socket.BeginReceive(tempbuffer, 0, tempbuffer.Length, SocketFlags.None, new AsyncCallback(Receive), this);
InitTimers();
connections.Add(this);
}
catch ( Exception e ) { Kick("Login failed!"); Server.ErrorLog(e); }
}
public void save() {
//safe against SQL injects because no user input is provided
string commandString =
"UPDATE Players SET IP='" + ip + "'" +
", LastLogin='" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "'" +
", totalLogin=" + totalLogins +
", totalDeaths=" + overallDeath +
", Money=" + money +
", totalBlocks=" + overallBlocks +
", totalKicked=" + totalKicked +
", TimeSpent='" + time +
"' WHERE Name='" + name + "'";
if ( MySQLSave != null )
MySQLSave(this, commandString);
OnMySQLSaveEvent.Call(this, commandString);
if ( cancelmysql ) {
cancelmysql = false;
return;
}
Database.executeQuery(commandString);
try {
if ( !smileySaved ) {
if ( parseSmiley )
emoteList.RemoveAll(s => s == name);
else
emoteList.Add(name);
File.WriteAllLines("text/emotelist.txt", emoteList.ToArray());
smileySaved = true;
}
}
catch ( Exception e ) {
Server.ErrorLog(e);
}
try {
SaveUndo();
} catch (Exception e) {
Server.s.Log("Error saving undo data.");
Server.ErrorLog(e);
}
}
#region == INCOMING ==
byte[] HandleMessage(byte[] buffer) {
try {
int length = 0; byte msg = buffer[0];
// Get the length of the message by checking the first byte
switch (msg) {
//For wom
case (byte)'G':
return new byte[1];
case Opcode.Handshake:
length = 130;
break;
case Opcode.SetBlockClient:
if (!loggedIn)
goto default;
length = 8;
break;
case Opcode.EntityTeleport:
if (!loggedIn)
goto default;
length = 9;
break;
case Opcode.Message:
if (!loggedIn)
goto default;
length = 65;
break;
case Opcode.CpeExtInfo:
length = 66;
break;
case Opcode.CpeExtEntry:
length = 68;
break;
case Opcode.CpeCustomBlockSupportLevel:
length = 1;
break;
default:
if (!dontmindme)
Kick("Unhandled message id \"" + msg + "\"!");
else
Server.s.Log(Encoding.UTF8.GetString(buffer, 0, buffer.Length));
return new byte[0];
}
if (buffer.Length > length) {
byte[] message = new byte[length];
Buffer.BlockCopy(buffer, 1, message, 0, length);
byte[] tempbuffer = new byte[buffer.Length - length - 1];
Buffer.BlockCopy(buffer, length + 1, tempbuffer, 0, buffer.Length - length - 1);
buffer = tempbuffer;
switch (msg) {
case Opcode.Handshake:
HandleLogin(message);
lock (pendingLock)
pendingNames.Remove(truename);
break;
case Opcode.SetBlockClient:
if (!loggedIn)
break;
HandleBlockchange(message);
break;
case Opcode.EntityTeleport:
if (!loggedIn)
break;
HandleInput(message);
break;
case Opcode.Message:
if (!loggedIn)
break;
HandleChat(message);
break;
case Opcode.CpeExtInfo:
HandleExtInfo( message );
break;
case Opcode.CpeExtEntry:
HandleExtEntry( message );
break;
case Opcode.CpeCustomBlockSupportLevel:
HandleCustomBlockSupportLevel( message );
break;
}
//thread.Start((object)message);
if (buffer.Length > 0)
buffer = HandleMessage(buffer);
else
return new byte[0];
}
} catch (Exception e) {
Server.ErrorLog(e);
}
return buffer;
}
#region Login
void HandleLogin(byte[] message)
{
try
{
if (loggedIn) return;
byte version = message[0];
name = enc.GetString(message, 1, 64).Trim();
truename = name;
lock (pendingLock) {
pendingNames.Add(name);
int altsCount = 0;
foreach (string other in pendingNames) {
if (other == truename) altsCount++;
}
if (altsCount > 1) {
Kick("Already logged in!"); return;
}
}
string verify = enc.GetString(message, 65, 32).Trim();
if (Server.verify)
{
if (verify == "--" || verify !=
BitConverter.ToString(md5.ComputeHash(enc.GetBytes(Server.salt + truename)))
.Replace("-", "").ToLower())
{
if (!IPInPrivateRange(ip))
{
Kick("Login failed! Try again."); return;
}
}
}
DisplayName = name;
SkinName = name;
name += "+";
byte type = message[129];
//Forge Protection Check
isDev = Server.Devs.Contains(name.ToLower());
isMod = Server.Mods.Contains(name.ToLower());
isGCMod = Server.GCmods.Contains(name.ToLower());
verifiedName = Server.verify ? true : false;
try
{
Server.TempBan tBan = Server.tempBans.Find(tB => tB.name.ToLower() == name.ToLower());
if (tBan.allowedJoin < DateTime.Now) {
Server.tempBans.Remove(tBan);
} else {
Kick("You're still banned (temporary ban)!");
}
} catch { }
if (!CheckWhitelist())
return;
LoadIgnores();
// ban check
if (Server.bannedIP.Contains(ip))
{
if (Server.useWhitelist)
{
if (!onWhitelist)
{
Kick(Server.customBanMessage);
return;
}
}
else
{
Kick(Server.customBanMessage);
return;
}
}
if (Server.omniban.CheckPlayer(this)) { Kick(Server.omniban.kickMsg); return; } //deprecated
if (Group.findPlayerGroup(name) == Group.findPerm(LevelPermission.Banned))
{
if (Server.useWhitelist)
{
if (!onWhitelist)
{
Kick(Server.customBanMessage);
return;
}
}
else
{
if (Ban.IsBanned(name))
{
string[] data = Ban.GetBanData(name);
Kick("You were banned for \"" + data[1] + "\" by " + data[0]);
}
else
Kick(Server.customBanMessage);
return;
}
}
//server maxplayer check
if (!VIP.Find(this))
{
// Check to see how many guests we have
if (Player.players.Count >= Server.players && !IPInPrivateRange(ip)) { Kick("Server full!"); return; }
// Code for limiting no. of guests
if (Group.findPlayerGroup(name) == Group.findPerm(LevelPermission.Guest))
{
// Check to see how many guests we have
int currentNumOfGuests = Player.players.Count(pl => pl.group.Permission <= LevelPermission.Guest);
if (currentNumOfGuests >= Server.maxGuests)
{
if (Server.guestLimitNotify) Chat.GlobalMessageOps("Guest " + this.DisplayName + " couldn't log in - too many guests.");
Server.s.Log("Guest " + this.name + " couldn't log in - too many guests.");
Kick("Server has reached max number of guests");
return;
}
}
}
if (version != Server.version) { Kick("Wrong version!"); return; }
foreach (Player p in players) {
if (p.name == name) {
if (Server.verify) {
p.Kick("Someone logged in as you!"); break;
} else {
Kick("Already logged in!"); return;
}
}
}
if (type == 0x42) {
hasCpe = true;
SendExtInfo(16);
SendExtEntry(CpeExt.ClickDistance, 1);
SendExtEntry(CpeExt.CustomBlocks, 1);
SendExtEntry(CpeExt.HeldBlock, 1);
SendExtEntry(CpeExt.TextHotkey, 1);
SendExtEntry(CpeExt.EnvColors, 1);
SendExtEntry(CpeExt.SelectionCuboid, 1);
SendExtEntry(CpeExt.BlockPermissions, 1);
SendExtEntry(CpeExt.ChangeModel, 1);
SendExtEntry(CpeExt.EnvMapAppearance, 2);
SendExtEntry(CpeExt.EnvWeatherType, 1);
SendExtEntry(CpeExt.HackControl, 1);
SendExtEntry(CpeExt.EmoteFix, 1);
SendExtEntry(CpeExt.FullCP437, 1);
SendExtEntry(CpeExt.LongerMessages, 1);
SendExtEntry(CpeExt.BlockDefinitions, 1);
SendExtEntry(CpeExt.BlockDefinitionsExt, 1);
}
try { left.Remove(name.ToLower()); }
catch { }
group = Group.findPlayerGroup(name);
Loading = true;
if (disconnected) return;
id = FreeId();
if (type != 0x42)
CompleteLoginProcess();
} catch (Exception e) {
Server.ErrorLog(e);
Player.GlobalMessage("An error occurred: " + e.Message);
}
}
bool CheckWhitelist() {
if (!Server.useWhitelist)
return true;
if (Server.verify) {
if (Server.whiteList.Contains(name))
onWhitelist = true;
} else {
// Verify Names is off. Gotta check the hard way.
Database.AddParams("@IP", ip);
DataTable ipQuery = Database.fillData("SELECT Name FROM Players WHERE IP = @IP");
if (ipQuery.Rows.Count > 0) {
if (ipQuery.Rows.Contains(name) && Server.whiteList.Contains(name)) {
onWhitelist = true;
}
}
ipQuery.Dispose();
}
if (!onWhitelist)
Kick("This is a private server!"); //i think someone forgot this?
return onWhitelist;
}
void LoadIgnores() {
if (File.Exists("ranks/ignore/" + name + ".txt")) {
try {
string[] lines = File.ReadAllLines("ranks/ignore/" + name + ".txt");
foreach (string line in lines)
listignored.Add(line);
File.Delete("ranks/ignore/" + name + ".txt");
} catch {
Server.s.Log("Failed to load ignore list for: " + name);
}
}
if (File.Exists("ranks/ignore/GlobalIgnore.xml")) {
try {
string[] searchxmls = File.ReadAllLines("ranks/ignore/GlobalIgnore.xml");
foreach (string searchxml in searchxmls)
globalignores.Add(searchxml);
foreach (string ignorer in globalignores) {
Player foundignore = Player.Find(ignorer);
foundignore.ignoreglobal = true;
}
File.Delete("ranks/ignore/GlobalIgnore.xml");
} catch {
Server.s.Log("Failed to load global ignore list!");
}
}
}
void CompleteLoginProcess() {
try {
SendMotd();
SendMap();
if (disconnected) return;
loggedIn = true;
lock (players)
players.Add(this);
connections.Remove(this);
Server.s.PlayerListUpdate();
//Test code to show when people come back with different accounts on the same IP
string alts = name + " is lately known as:";
bool found = false;
if (!ip.StartsWith("127.0.0.")) {
foreach (KeyValuePair<string, string> prev in left) {
if (prev.Value == ip)
{
found = true;
alts += " " + prev.Key;
}
}
if (found) {
if (group.Permission < Server.adminchatperm || !Server.adminsjoinsilent) {
Chat.GlobalMessageOps(alts);
//IRCBot.Say(temp, true); //Tells people in op channel on IRC
}
Server.s.Log(alts);
}
}
} catch (Exception e) {
Server.ErrorLog(e);
Player.GlobalMessage("An error occurred: " + e.Message);
}
//OpenClassic Client Check
SendBlockchange(0, 0, 0, 0);
Database.AddParams("@Name", name);
DataTable playerDb = Database.fillData("SELECT * FROM Players WHERE Name=@Name");
if (playerDb.Rows.Count == 0)
InitPlayerStats(playerDb);
else
LoadPlayerStats(playerDb);
if (!Directory.Exists("players"))
Directory.CreateDirectory("players");
PlayerDB.Load(this);
SetPrefix();
playerDb.Dispose();
if (PlayerConnect != null)
PlayerConnect(this);
OnPlayerConnectEvent.Call(this);
if (Server.server_owner != "" && Server.server_owner.ToLower().Equals(name.ToLower())) {
if (color == Group.standard.color)
color = "&c";
if (title == "")
title = "Owner";
SetPrefix();
}
if (Server.verifyadmins && group.Permission >= Server.verifyadminsrank)
adminpen = true;
if (emoteList.Contains(name)) parseSmiley = false;
if (!Directory.Exists("text/login"))
Directory.CreateDirectory("text/login");
if (!File.Exists("text/login/" + this.name + ".txt"))
CP437Writer.WriteAllText("text/login/" + this.name + ".txt", "joined the server.");
CheckLoginJailed();
if (Server.agreetorulesonentry) {
if (!File.Exists("ranks/agreed.txt"))
File.WriteAllText("ranks/agreed.txt", "");
var agreedFile = File.ReadAllText("ranks/agreed.txt");
if (group.Permission == LevelPermission.Guest && !agreedFile.Contains(this.name.ToLower())) {
SendMessage("&9You must read the &c/rules&9 and &c/agree&9 to them before you can build and use commands!");
agreed = false;
}
}
string joinm = "&a+ " + this.FullName + Server.DefaultColor + " " + File.ReadAllText("text/login/" + this.name + ".txt");
if (group.Permission < Server.adminchatperm || Server.adminsjoinsilent == false)
{
if ((Server.guestJoinNotify && group.Permission <= LevelPermission.Guest) || group.Permission > LevelPermission.Guest)
{
Player.players.ForEach(p1 => Player.SendMessage(p1, joinm));
}
}
if (group.Permission >= Server.adminchatperm && Server.adminsjoinsilent) {
hidden = true;
adminchat = true;
}
if (Server.verifyadmins && group.Permission >= Server.verifyadminsrank) {
if (!Directory.Exists("extra/passwords") || !File.Exists("extra/passwords/" + this.name + ".dat"))
SendMessage("&cPlease set your admin verification password with &a/setpass [Password]!");
else
SendMessage("&cPlease complete admin verification with &a/pass [Password]!");
}
try
{
WaypointList.Load(this);
//if (Waypoints.Count > 0) { this.SendMessage("Loaded " + Waypoints.Count + " waypoints!"); }
}
catch (Exception ex)
{
SendMessage("Error loading waypoints!");
Server.ErrorLog(ex);
}
try
{
if (File.Exists("ranks/muted.txt"))
{
using (StreamReader read = new StreamReader("ranks/muted.txt"))
{
string line;
while ((line = read.ReadLine()) != null)
{
if (line.ToLower() == this.name.ToLower())
{
this.muted = true;
Player.SendMessage(this, "!%cYou are still %8muted%c since your last login.");
break;
}
}
}
}
else { File.Create("ranks/muted.txt").Close(); }
}
catch { muted = false; }
Server.s.Log(name + " [" + ip + "] has joined the server.");
if (Server.zombie.ZombieStatus() != 0) { Player.SendMessage(this, "There is a Zombie Survival game currently in-progress! Join it by typing /g " + Server.zombie.currentLevelName); }
{
try
{
ushort x = (ushort)((0.5 + level.spawnx) * 32);
ushort y = (ushort)((1 + level.spawny) * 32);
ushort z = (ushort)((0.5 + level.spawnz) * 32);
pos = new ushort[3] { x, y, z }; rot = new byte[2] { level.rotx, level.roty };
GlobalSpawn(this, x, y, z, rot[0], rot[1], true);
foreach (Player p in players)
{
if (p.level == level && p != this && !p.hidden)
{
SendSpawn(p.id, p.color + p.name, p.pos[0], p.pos[1], p.pos[2], p.rot[0], p.rot[1]);
}
if (HasCpeExt(CpeExt.ChangeModel))
{
SendChangeModel(p.id, p.model);
}
}
foreach (PlayerBot pB in PlayerBot.playerbots)
{
if (pB.level == level)
SendSpawn(pB.id, pB.color + pB.name, pB.pos[0], pB.pos[1], pB.pos[2], pB.rot[0], pB.rot[1]);
}
}
catch (Exception e)
{
Server.ErrorLog(e);
Server.s.Log("Error spawning player \"" + name + "\"");
}
}
Loading = false;
}
void InitPlayerStats(DataTable playerDb) {
prefix = "";
time = "0 0 0 1";
title = "";
titlecolor = "";
color = group.color;
money = 0;
firstLogin = DateTime.Now;
totalLogins = 1;
totalKicked = 0;
overallDeath = 0;
overallBlocks = 0;
timeLogged = DateTime.Now;
SendMessage("Welcome " + DisplayName + "! This is your first visit.");
Database.executeQuery(String.Format("INSERT INTO Players (Name, IP, FirstLogin, LastLogin, totalLogin, Title, totalDeaths, Money, totalBlocks, totalKicked, TimeSpent) VALUES " +
"('{0}', '{1}', '{2:yyyy-MM-dd HH:mm:ss}', '{3:yyyy-MM-dd HH:mm:ss}', {4}, '{5}', {6}, {7}, {8}, {9}, '{10}')",
name, ip, firstLogin, DateTime.Now, totalLogins, prefix, overallDeath, money, loginBlocks, totalKicked, time));
string query = "INSERT INTO Economy (player, money, total, purchase, payment, salary, fine) VALUES ('" + name + "', " + money + ", 0, '%cNone', '%cNone', '%cNone', '%cNone')";
Database.executeQuery(query);
}
void LoadPlayerStats(DataTable playerDb) {
DataRow row = playerDb.Rows[0];
totalLogins = int.Parse(row["totalLogin"].ToString()) + 1;
time = row["TimeSpent"].ToString();
userID = int.Parse(row["ID"].ToString());
firstLogin = DateTime.Parse(row["firstLogin"].ToString());
timeLogged = DateTime.Now;
if (row["Title"].ToString().Trim() != "") {
string parse = row["Title"].ToString().Trim().Replace("[", "");
title = parse.Replace("]", "");
}
if (row["title_color"].ToString().Trim() != "")
titlecolor = c.Parse(row["title_color"].ToString().Trim());
else
titlecolor = "";
if (row["color"].ToString().Trim() != "")
color = c.Parse(row["color"].ToString().Trim());
else
color = group.color;
overallDeath = int.Parse(row["TotalDeaths"].ToString());
overallBlocks = long.Parse(row["totalBlocks"].ToString().Trim());
//money = int.Parse(playerDb.Rows[0]["Money"].ToString());
money = Economy.RetrieveEcoStats(this.name).money;
totalKicked = int.Parse(row["totalKicked"].ToString());
SendMessage("Welcome back " + color + prefix + DisplayName + Server.DefaultColor + "! You've been here " + totalLogins + " times!");
if (Server.muted.Contains(name))
{
muted = true;
GlobalMessage(DisplayName + " is still muted from the last time they went offline.");
}
}
void CheckLoginJailed() {
//very very sloppy, yes I know.. but works for the time
bool gotoJail = false;
string gotoJailMap = "", gotoJailName = "";
try {
if (File.Exists("ranks/jailed.txt"))
{
using (StreamReader read = new StreamReader("ranks/jailed.txt"))
{
string line;
while ((line = read.ReadLine()) != null)
{
string[] parts = line.Split();
if (parts[0].ToLower() == this.name.ToLower())
{
gotoJail = true;
gotoJailName = parts[0];
gotoJailMap = parts[1];
break;
}
}
}
} else {
File.Create("ranks/jailed.txt").Close();
}
} catch {
gotoJail = false;
}
if (gotoJail) {
try {
Command.all.Find("goto").Use(this, gotoJailMap);
Command.all.Find("jail").Use(null, gotoJailName);
} catch (Exception e) {
Kick(e.ToString());
}
}
}
#endregion
public void SetPrefix() {
string viptitle = isDev ? string.Format("{1}[{0}Dev{1}] ", c.Parse("blue"), color) : isMod ? string.Format("{1}[{0}Mod{1}] ", c.Parse("lime"), color) : isGCMod ? string.Format("{1}[{0}GCMod{1}] ", c.Parse("gold"), color) : "";
//prefix = ( title == "" ) ? "" : ( titlecolor == "" ) ? color + "[" + title + color + "] " : titlecolor + "[" + titlecolor + title + titlecolor + "] " + color;
prefix = ( title == "" ) ? "" : ( titlecolor == "" ) ? color + "[" + title + "] " : color + "[" + titlecolor + title + color + "] ";
prefix = viptitle + prefix;
}
void HandleBlockchange(byte[] message) {
try {
if ( !loggedIn )
return;
if ( CheckBlockSpam() )
return;
ushort x = NetUtils.ReadU16(message, 0);
ushort y = NetUtils.ReadU16(message, 2);
ushort z = NetUtils.ReadU16(message, 4);
byte action = message[6];
byte type = message[7];
byte extType = type;
if ((action == 0 || type == 0) && !level.Deletable) {
SendMessage("You cannot currently delete blocks in this level.");
RevertBlock(x, y, z); return;
} else if (action == 1 && !level.Buildable) {
SendMessage("You cannot currently place blocks in this level.");
RevertBlock(x, y, z); return;
}
if (type >= Block.CpeCount) {
if (!HasCpeExt(CpeExt.BlockDefinitions)
|| BlockDefinition.GlobalDefinitions[type] == null) {
SendMessage("Invalid block type: " + type); return;
}
extType = type;
type = Block.custom_block;
}
ManualChange(x, y, z, action, type, extType);
} catch ( Exception e ) {
// Don't ya just love it when the server tattles?
Chat.GlobalMessageOps(DisplayName + " has triggered a block change error");
Chat.GlobalMessageOps(e.GetType().ToString() + ": " + e.Message);
Server.ErrorLog(e);
}
}
public void ManualChange(ushort x, ushort y, ushort z, byte action, byte type, byte extType = 0) {
byte b = level.GetTile(x, y, z);
if ( b == Block.Zero ) { return; }
if ( jailed || !agreed ) { RevertBlock(x, y, z); return; }
if ( level.name.Contains("Museum " + Server.DefaultColor) && Blockchange == null ) {
return;
}
if ( !deleteMode ) {
string info = level.foundInfo(x, y, z);
if ( info.Contains("wait") ) return;
}
if ( !canBuild ) {
RevertBlock(x, y, z); return;
}
if ( Server.verifyadmins && adminpen ) {
SendMessage("&cYou must use &a/pass [Password]&c to verify!");
RevertBlock(x, y, z); return;
}
if (Server.ZombieModeOn && Server.zombie != null
&& Server.zombie.HandlesManualChange(this, x, y, z, action, type, b)) return;
if ( Server.lava.active && Server.lava.HasPlayer(this) && Server.lava.IsPlayerDead(this) ) {
SendMessage("You are out of the round, and cannot build.");
RevertBlock(x, y, z); return;
}
Level.BlockPos bP;
bP.name = name;
bP.TimePerformed = DateTime.Now;
bP.index = level.PosToInt(x, y, z);
bP.type = type;
bP.extType = extType;
lastClick[0] = x; lastClick[1] = y; lastClick[2] = z;
if ( Blockchange != null ) {
if ( Blockchange.Method.ToString().IndexOf("AboutBlockchange") == -1 && !level.name.Contains("Museum " + Server.DefaultColor) ) {
bP.deleted = true;
level.blockCache.Add(bP);
}
Blockchange(this, x, y, z, type, extType);
return;
}
if ( PlayerBlockChange != null )
PlayerBlockChange(this, x, y, z, type, extType);
OnBlockChangeEvent.Call(this, x, y, z, type, extType);
if ( cancelBlock ) {
cancelBlock = false;
return;
}
if ( group.Permission == LevelPermission.Banned ) return;
if ( group.Permission == LevelPermission.Guest ) {
int Diff = Math.Abs((pos[0] / 32) - x) + Math.Abs((pos[1] / 32) - y)
+ Math.Abs((pos[2] / 32) - z);
if ((Diff > ReachDistance + 4) && lastCMD != "click") {
Server.s.Log(name + " attempted to build with a " + Diff + " distance offset");
SendMessage("You can't build that far away.");
RevertBlock(x, y, z); return;
}
}
if (!Block.canPlace(this, b) && !Block.BuildIn(b) && !Block.AllowBreak(b)) {
SendMessage("Cannot build here!");
RevertBlock(x, y, z); return;
}
if (!Block.canPlace(this, type)) {
SendMessage("You can't place this block type!");
RevertBlock(x, y, z); return;
}
if (b >= 200 && b < 220) {
SendMessage("Block is active, you cant disturb it!");
RevertBlock(x, y, z); return;
}
if (action > 1 ) { Kick("Unknown block action!"); return; }
byte oldType = type;
if (type < 128) type = bindings[type];
//Ignores updating blocks that are the same and send block only to the player
byte newBlock = (painting || action == 1) ? type : (byte)0;
if (b == newBlock && (painting || oldType != type)) {
if (b != Block.custom_block || extType == level.GetExtTile(x, y, z)) {
RevertBlock(x, y, z); return;
}
}
//else
if ( !painting && action == 0 ) {
if ( !deleteMode ) {
if ( Block.portal(b) ) { HandlePortal(this, x, y, z, b); return; }
if ( Block.mb(b) ) { HandleMsgBlock(this, x, y, z, b); return; }
}
bP.deleted = true;
level.blockCache.Add(bP);
DeleteBlock(b, x, y, z, type, extType);
} else {
bP.deleted = false;
level.blockCache.Add(bP);
PlaceBlock(b, x, y, z, type, extType);
}
}
public void HandlePortal(Player p, ushort x, ushort y, ushort z, byte b) {
try {
//safe against SQL injections because no user input is given here
DataTable Portals = Database.fillData("SELECT * FROM `Portals" + level.name + "` WHERE EntryX=" + (int)x + " AND EntryY=" + (int)y + " AND EntryZ=" + (int)z);
int LastPortal = Portals.Rows.Count - 1;
if ( LastPortal > -1 ) {
if ( level.name != Portals.Rows[LastPortal]["ExitMap"].ToString() ) {
if ( level.permissionvisit > this.group.Permission ) {
Player.SendMessage(this, "You do not have the adequate rank to visit this map!");
return;
}
ignorePermission = true;
Level thisLevel = level;
Command.all.Find("goto").Use(this, Portals.Rows[LastPortal]["ExitMap"].ToString());
if ( thisLevel == level ) { Player.SendMessage(p, "The map the portal goes to isn't loaded."); return; }
ignorePermission = false;
}
else SendBlockchange(x, y, z, b);
while ( p.Loading ) { } //Wait for player to spawn in new map
Command.all.Find("move").Use(this, this.name + " " + Portals.Rows[LastPortal]["ExitX"].ToString() + " " + Portals.Rows[LastPortal]["ExitY"].ToString() + " " + Portals.Rows[LastPortal]["ExitZ"].ToString());
}
else {
Blockchange(this, x, y, z, Block.air, 0);
}
Portals.Dispose();
}
catch { Player.SendMessage(p, "Portal had no exit."); return; }
}
public void HandleMsgBlock(Player p, ushort x, ushort y, ushort z, byte b) {
try {
//safe against SQL injections because no user input is given here
DataTable Messages = Database.fillData("SELECT * FROM `Messages" + level.name + "` WHERE X=" + (int)x + " AND Y=" + (int)y + " AND Z=" + (int)z);
int LastMsg = Messages.Rows.Count - 1;
if ( LastMsg > -1 ) {
string message = Messages.Rows[LastMsg]["Message"].ToString().Trim();
if ( message != prevMsg || Server.repeatMessage ) {
if ( message.StartsWith("/") ) {
List<string> Message = message.Remove(0, 1).Split(' ').ToList();
string command = Message[0];
Message.RemoveAt(0);
string args = string.Join(" ", Message.ToArray());
HandleCommand(command, args);
}
else
Player.SendMessage(p, message);
prevMsg = message;
}
SendBlockchange(x, y, z, b);
} else {
Blockchange(this, x, y, z, Block.air, 0);
}
Messages.Dispose();
}
catch { Player.SendMessage(p, "No message was stored."); return; }
}
private void DeleteBlock(byte b, ushort x, ushort y, ushort z, byte type, byte extType) {
if ( deleteMode && b != Block.c4det ) { level.Blockchange(this, x, y, z, Block.air); return; }
if ( Block.tDoor(b) ) { RevertBlock(x, y, z); return; }
if ( Block.DoorAirs(b) != 0 ) {
if ( level.physics != 0 )
level.Blockchange(x, y, z, Block.DoorAirs(b));
else
RevertBlock(x, y, z);
return;
}
if ( Block.odoor(b) != Block.Zero ) {
if ( b == Block.odoor8 || b == Block.odoor8_air ) {
level.Blockchange(this, x, y, z, Block.odoor(b));
} else {
RevertBlock(x, y, z);
}
return;
}
switch ( b ) {
case Block.door_air: //Door_air
case Block.door2_air:
case Block.door3_air:
case Block.door4_air:
case Block.door5_air:
case Block.door6_air:
case Block.door7_air:
case Block.door8_air:
case Block.door9_air:
case Block.door10_air:
case Block.door_iron_air:
case Block.door_gold_air:
case Block.door_cobblestone_air:
case Block.door_red_air:
case Block.door_dirt_air:
case Block.door_grass_air:
case Block.door_blue_air:
case Block.door_book_air:
break;
case Block.rocketstart:
if ( level.physics < 2 || level.physics == 5 ) {
RevertBlock(x, y, z);
} else {
int newZ = 0, newX = 0, newY = 0;
SendBlockchange(x, y, z, Block.rocketstart);
if ( rot[0] < 48 || rot[0] > ( 256 - 48 ) )
newZ = -1;
else if ( rot[0] > ( 128 - 48 ) && rot[0] < ( 128 + 48 ) )
newZ = 1;
if ( rot[0] > ( 64 - 48 ) && rot[0] < ( 64 + 48 ) )
newX = 1;
else if ( rot[0] > ( 192 - 48 ) && rot[0] < ( 192 + 48 ) )
newX = -1;
if ( rot[1] >= 192 && rot[1] <= ( 192 + 32 ) )
newY = 1;
else if ( rot[1] <= 64 && rot[1] >= 32 )
newY = -1;
if ( 192 <= rot[1] && rot[1] <= 196 || 60 <= rot[1] && rot[1] <= 64 ) { newX = 0; newZ = 0; }
byte b1 = level.GetTile((ushort)( x + newX * 2 ), (ushort)( y + newY * 2 ), (ushort)( z + newZ * 2 ));
byte b2 = level.GetTile((ushort)( x + newX ), (ushort)( y + newY ), (ushort)( z + newZ ));
if ( b1 == Block.air && b2 == Block.air && level.CheckClear((ushort)( x + newX * 2 ), (ushort)( y + newY * 2 ), (ushort)( z + newZ * 2 )) && level.CheckClear((ushort)( x + newX ), (ushort)( y + newY ), (ushort)( z + newZ )) ) {
level.Blockchange((ushort)( x + newX * 2 ), (ushort)( y + newY * 2 ), (ushort)( z + newZ * 2 ), Block.rockethead);
level.Blockchange((ushort)( x + newX ), (ushort)( y + newY ), (ushort)( z + newZ ), Block.fire);
}
}
break;
case Block.firework:
if ( level.physics == 5 ) {
RevertBlock(x, y, z); return;
}
if ( level.physics != 0 ) {
Random rand = new Random();
int mx = rand.Next(0, 2); int mz = rand.Next(0, 2);
byte b1 = level.GetTile((ushort)( x + mx - 1 ), (ushort)( y + 2 ), (ushort)( z + mz - 1 ));
byte b2 = level.GetTile((ushort)( x + mx - 1 ), (ushort)( y + 1 ), (ushort)( z + mz - 1 ));
if ( b1 == Block.air && b2 == Block.air && level.CheckClear((ushort)( x + mx - 1 ), (ushort)( y + 2 ), (ushort)( z + mz - 1 )) && level.CheckClear((ushort)( x + mx - 1 ), (ushort)( y + 1 ), (ushort)( z + mz - 1 )) ) {
level.Blockchange((ushort)( x + mx - 1 ), (ushort)( y + 2 ), (ushort)( z + mz - 1 ), Block.firework);
level.Blockchange((ushort)( x + mx - 1 ), (ushort)( y + 1 ), (ushort)( z + mz - 1 ), Block.lavastill, false, "wait 1 dissipate 100");
}
}
RevertBlock(x, y, z);
break;
case Block.c4det:
Level.C4.BlowUp(new ushort[] { x, y, z }, level);
level.Blockchange(x, y, z, Block.air);
break;
default:
level.Blockchange(this, x, y, z, (byte)( Block.air ));
break;
}
if ( (level.physics == 0 || level.physics == 5) && level.GetTile(x, (ushort)( y - 1 ), z) == Block.dirt )
level.Blockchange(this, x, (ushort)( y - 1 ), z, Block.grass);
}
public void PlaceBlock(byte b, ushort x, ushort y, ushort z, byte type, byte extType) {
if ( Block.odoor(b) != Block.Zero ) { SendMessage("oDoor here!"); return; }
switch ( BlockAction ) {
case 0: //normal
if ( level.physics == 0 || level.physics == 5 ) {
switch ( type ) {
case Block.dirt: //instant dirt to grass
if ( Block.LightPass(level.GetTile(x, (ushort)( y + 1 ), z)) ) level.Blockchange(this, x, y, z, (byte)( Block.grass ));
else level.Blockchange(this, x, y, z, (byte)( Block.dirt ));
break;
case Block.staircasestep: //stair handler
if ( level.GetTile(x, (ushort)( y - 1 ), z) == Block.staircasestep ) {
SendBlockchange(x, y, z, Block.air); //send the air block back only to the user.
//level.Blockchange(this, x, y, z, (byte)(Block.air));
level.Blockchange(this, x, (ushort)( y - 1 ), z, (byte)( Block.staircasefull ));
break;
}
//else
level.Blockchange(this, x, y, z, type, extType);
break;
default:
level.Blockchange(this, x, y, z, type, extType);
break;
}
} else {
level.Blockchange(this, x, y, z, type, extType);
}
break;
case 6:
if ( b == modeType ) { SendBlockchange(x, y, z, b); return; }
level.Blockchange(this, x, y, z, modeType);
break;
case 13: //Small TNT
level.Blockchange(this, x, y, z, Block.smalltnt);
break;
case 14: //Big TNT
level.Blockchange(this, x, y, z, Block.bigtnt);
break;
case 15: //Nuke TNT
level.Blockchange(this, x, y, z, Block.nuketnt);
break;
default:
Server.s.Log(name + " is breaking something");
BlockAction = 0;
break;
}
}
void HandleInput(byte[] message) {
if ( !loggedIn || trainGrab || following != "" || frozen )
return;
/*if (CheckIfInsideBlock())
{
this.SendPos(0xFF, (ushort)(clippos[0] - 18), (ushort)(clippos[1] - 18), (ushort)(clippos[2] - 18), cliprot[0], cliprot[1]);
return;
}*/
byte thisid = message[0];
if ( this.incountdown && CountdownGame.gamestatus == CountdownGameStatus.InProgress && CountdownGame.freezemode ) {
if ( this.countdownsettemps ) {
countdowntempx = NetUtils.ReadU16(message, 1);
Thread.Sleep(100);
countdowntempz = NetUtils.ReadU16(message, 5);
Thread.Sleep(100);
countdownsettemps = false;
}
ushort x = countdowntempx;
ushort y = NetUtils.ReadU16(message, 3);
ushort z = countdowntempz;
byte rotx = message[7];
byte roty = message[8];
pos = new ushort[3] { x, y, z };
rot = new byte[2] { rotx, roty };
if ( countdowntempx != NetUtils.ReadU16(message, 1) || countdowntempz != NetUtils.ReadU16(message, 5) ) {
this.SendPos(0xFF, pos[0], pos[1], pos[2], rot[0], rot[1]);
}
} else {
ushort x = NetUtils.ReadU16(message, 1);
ushort y = NetUtils.ReadU16(message, 3);
ushort z = NetUtils.ReadU16(message, 5);
if ( !this.referee && Server.noRespawn && Server.ZombieModeOn ) {
if ( this.pos[0] >= x + 70 || this.pos[0] <= x - 70 ) {
SendPos(0xFF, pos[0], pos[1], pos[2], rot[0], rot[1]);
return;
}
if ( this.pos[2] >= z + 70 || this.pos[2] <= z - 70 ) {
SendPos(0xFF, pos[0], pos[1], pos[2], rot[0], rot[1]);
return;
}
}
if ( OnMove != null )
OnMove(this, x, y, z);
if ( PlayerMove != null )
PlayerMove(this, x, y, z);
PlayerMoveEvent.Call(this, x, y, z);
if (OnRotate != null)
OnRotate(this, rot);
if (PlayerRotate != null)
PlayerRotate(this, rot);
PlayerRotateEvent.Call(this, rot);
if ( cancelmove ) {
SendPos(0xFF, pos[0], pos[1], pos[2], rot[0], rot[1]);
return;
}
byte rotx = message[7];
byte roty = message[8];
pos = new ushort[3] { x, y, z };
rot = new byte[2] { rotx, roty };
/*if (!CheckIfInsideBlock())
{
clippos = pos;
cliprot = rot;
}*/
}
}
internal void CheckSurvival(ushort x, ushort y, ushort z) {
byte bFeet = GetSurvivalBlock(x, (ushort)(y - 2), z);
byte bHead = GetSurvivalBlock(x, y, z);
if (level.PosToInt(x, y, z) != oldIndex || y != oldFallY) {
byte conv = Block.Convert(bFeet);
if (conv == Block.air) {
if (y < oldFallY)
fallCount++;
else if (y > oldFallY) // flying up, for example
fallCount = 0;
oldFallY = y;
drownCount = 0;
return;
} else if (!(conv == Block.water || conv == Block.waterstill ||
conv == Block.lava || conv == Block.lavastill)) {
if (fallCount > level.fall)
HandleDeath(Block.air, null, false, true);
fallCount = 0;
drownCount = 0;
return;
}
}
switch (Block.Convert(bHead)) {
case Block.water:
case Block.waterstill:
case Block.lava:
case Block.lavastill:
fallCount = 0;
drownCount++;
if (drownCount > level.drown * (100/3)) {
HandleDeath(Block.water);
drownCount = 0;
}
break;
case Block.air:
drownCount = 0;
break;
default:
fallCount = 0;
drownCount = 0;
break;
}
}
byte GetSurvivalBlock(ushort x, ushort y, ushort z) {
if (y >= ushort.MaxValue - 512) return Block.blackrock;
if (y >= level.Height) return Block.air;
return level.GetTile(x, y, z);
}
public void CheckBlock(ushort x, ushort y, ushort z) {
y = (ushort)Math.Round((decimal)( ( ( y * 32 ) + 4 ) / 32 ));
byte b = this.level.GetTile(x, y, z);
byte b1 = this.level.GetTile(x, (ushort)( y - 1 ), z);
if ( Block.Mover(b) || Block.Mover(b1) ) {
if ( Block.DoorAirs(b) != 0 )
level.Blockchange(x, y, z, Block.DoorAirs(b));
if ( Block.DoorAirs(b1) != 0 )
level.Blockchange(x, (ushort)( y - 1 ), z, Block.DoorAirs(b1));
if ( level.PosToInt( x, y, z ) != oldIndex ) {
if ( b == Block.air_portal || b == Block.water_portal || b == Block.lava_portal ) {
HandlePortal(this, x, y, z, b);
}
else if ( b1 == Block.air_portal || b1 == Block.water_portal || b1 == Block.lava_portal ) {
HandlePortal(this, x, (ushort)( (int)y - 1 ), z, b1);
}
if ( b == Block.MsgAir || b == Block.MsgWater || b == Block.MsgLava ) {
HandleMsgBlock(this, x, y, z, b);
}
else if ( b1 == Block.MsgAir || b1 == Block.MsgWater || b1 == Block.MsgLava ) {
HandleMsgBlock(this, x, (ushort)( (int)y - 1 ), z, b1);
}
}
}
if ( ( b == Block.tntexplosion || b1 == Block.tntexplosion ) && PlayingTntWars ) { }
else if ( Block.Death(b) ) HandleDeath(b); else if ( Block.Death(b1) ) HandleDeath(b1);
}
public void HandleDeath(byte b, string customMessage = "", bool explode = false, bool immediate = false) {
ushort x = (ushort)( pos[0] / 32 );
ushort y = (ushort)( pos[1] / 32 );
ushort z = (ushort)( pos[2] / 32 );
if ( OnDeath != null )
OnDeath(this, b);
if ( PlayerDeath != null )
PlayerDeath(this, b);
OnPlayerDeathEvent.Call(this, b);
if ( Server.lava.active && Server.lava.HasPlayer(this) && Server.lava.IsPlayerDead(this) )
return;
if ( immediate || lastDeath.AddSeconds(2) < DateTime.Now ) {
if ( level.Killer && !invincible && !hidden ) {
switch ( b ) {
case Block.tntexplosion: Chat.GlobalChatLevel(this, this.FullName + Server.DefaultColor + " &cblew into pieces.", false); break;
case Block.deathair: Chat.GlobalChatLevel(this, this.FullName + Server.DefaultColor + " walked into &cnerve gas and suffocated.", false); break;
case Block.deathwater:
case Block.activedeathwater: Chat.GlobalChatLevel(this, this.FullName + Server.DefaultColor + " stepped in &dcold water and froze.", false); break;
case Block.deathlava:
case Block.activedeathlava:
case Block.fastdeathlava: Chat.GlobalChatLevel(this, this.FullName + Server.DefaultColor + " stood in &cmagma and melted.", false); break;
case Block.magma: Chat.GlobalChatLevel(this, this.FullName + Server.DefaultColor + " was hit by &cflowing magma and melted.", false); break;
case Block.geyser: Chat.GlobalChatLevel(this, this.FullName + Server.DefaultColor + " was hit by &cboiling water and melted.", false); break;
case Block.birdkill: Chat.GlobalChatLevel(this, this.FullName + Server.DefaultColor + " was hit by a &cphoenix and burnt.", false); break;
case Block.train: Chat.GlobalChatLevel(this, this.FullName + Server.DefaultColor + " was hit by a &ctrain.", false); break;
case Block.fishshark: Chat.GlobalChatLevel(this, this.FullName + Server.DefaultColor + " was eaten by a &cshark.", false); break;
case Block.fire: Chat.GlobalChatLevel(this, this.FullName + Server.DefaultColor + " burnt to a &ccrisp.", false); break;
case Block.rockethead: Chat.GlobalChatLevel(this, this.FullName + Server.DefaultColor + " was &cin a fiery explosion.", false); level.MakeExplosion(x, y, z, 0); break;
case Block.zombiebody: Chat.GlobalChatLevel(this, this.FullName + Server.DefaultColor + " died due to lack of &5brain.", false); break;
case Block.creeper: Chat.GlobalChatLevel(this, this.FullName + Server.DefaultColor + " was killed &cb-SSSSSSSSSSSSSS", false); level.MakeExplosion(x, y, z, 1); break;
case Block.air: Chat.GlobalChatLevel(this, this.FullName + Server.DefaultColor + " hit the floor &chard.", false); break;
case Block.water: Chat.GlobalChatLevel(this, this.FullName + Server.DefaultColor + " &cdrowned.", false); break;
case Block.Zero: Chat.GlobalChatLevel(this, this.FullName + Server.DefaultColor + " was &cterminated", false); break;
case Block.fishlavashark: Chat.GlobalChatLevel(this, this.FullName + Server.DefaultColor + " was eaten by a ... LAVA SHARK?!", false); break;
case Block.rock:
if ( explode ) level.MakeExplosion(x, y, z, 1);
GlobalChat(this, this.FullName + Server.DefaultColor + customMessage, false);
break;
case Block.stone:
if ( explode ) level.MakeExplosion(x, y, z, 1);
Chat.GlobalChatLevel(this, this.FullName + Server.DefaultColor + customMessage, false);
break;
}
if ( team != null && this.level.ctfmode ) {
//if (carryingFlag)
//{
// level.ctfgame.DropFlag(this, hasflag);
//}
team.SpawnPlayer(this);
//this.health = 100;
}
else if ( CountdownGame.playersleftlist.Contains(this) ) {
CountdownGame.Death(this);
Command.all.Find("spawn").Use(this, "");
}
else if ( PlayingTntWars ) {
TntWarsKillStreak = 0;
TntWarsScoreMultiplier = 1f;
}
else if ( Server.lava.active && Server.lava.HasPlayer(this) ) {
if ( !Server.lava.IsPlayerDead(this) ) {
Server.lava.KillPlayer(this);
Command.all.Find("spawn").Use(this, "");
}
}
else {
Command.all.Find("spawn").Use(this, "");
overallDeath++;
}
if ( Server.deathcount )
if ( overallDeath > 0 && overallDeath % 10 == 0 ) GlobalChat(this, this.FullName + Server.DefaultColor + " has died &3" + overallDeath + " times", false);
}
lastDeath = DateTime.Now;
}
}
/* void HandleFly(Player p, ushort x, ushort y, ushort z) {
FlyPos pos;
ushort xx; ushort yy; ushort zz;
TempFly.Clear();
if (!flyGlass) y = (ushort)(y + 1);
for (yy = y; yy >= (ushort)(y - 1); --yy)
for (xx = (ushort)(x - 2); xx <= (ushort)(x + 2); ++xx)
for (zz = (ushort)(z - 2); zz <= (ushort)(z + 2); ++zz)
if (p.level.GetTile(xx, yy, zz) == Block.air) {
pos.x = xx; pos.y = yy; pos.z = zz;
TempFly.Add(pos);
}
FlyBuffer.ForEach(delegate(FlyPos pos2) {
try { if (!TempFly.Contains(pos2)) SendBlockchange(pos2.x, pos2.y, pos2.z, Block.air); } catch { }
});
FlyBuffer.Clear();
TempFly.ForEach(delegate(FlyPos pos3){
FlyBuffer.Add(pos3);
});
if (flyGlass) {
FlyBuffer.ForEach(delegate(FlyPos pos1) {
try { SendBlockchange(pos1.x, pos1.y, pos1.z, Block.glass); } catch { }
});
} else {
FlyBuffer.ForEach(delegate(FlyPos pos1) {
try { SendBlockchange(pos1.x, pos1.y, pos1.z, Block.waterstill); } catch { }
});
}
} */
void HandleChat(byte[] message) {
try {
if ( !loggedIn ) return;
byte continued = message[0];
string text = GetString(message, 1);
// handles the /womid client message, which displays the WoM vrersion
if ( text.Truncate(6) == "/womid" ) {
string version = (text.Length <= 21 ? text.Substring(text.IndexOf(' ') + 1) : text.Substring(7, 15));
Player.GlobalMessage(c.red + "[INFO] " + color + DisplayName + "%f is using wom client");
Player.GlobalMessage(c.red + "[INFO] %fVersion: " + version);
Server.s.Log(c.red + "[INFO] " + color + DisplayName + "%f is using wom client");
Server.s.Log(c.red + "[INFO] %fVersion: " + version);
UsingWom = true;
WoMVersion = version.Split('-')[1];
return;
}
if( HasCpeExt(CpeExt.LongerMessages) && continued != 0 ) {
storedMessage += text;
return;
}
if ( storedMessage != "" ) {
if ( !text.EndsWith(">") && !text.EndsWith("<") ) {
text = storedMessage.Replace("|>|", " ").Replace("|<|", "") + text;
storedMessage = "";
}
}
//if (text.StartsWith(">") || text.StartsWith("<")) return;
if (text.EndsWith(">"))
{
storedMessage += text.Replace(">", "|>|");
SendMessage(c.teal + "Partial message: " + c.white + storedMessage.Replace("|>|", " ").Replace("|<|", ""));
return;
}
if (text.EndsWith("<"))
{
storedMessage += text.Replace("<", "|<|");
SendMessage(c.teal + "Partial message: " + c.white + storedMessage.Replace("|<|", "").Replace("|>|", " "));
return;
}
text = Regex.Replace(text, @"\s\s+", " ");
if ( text.Any(ch => ch == '&') ) {
Kick("Illegal character in chat message!");
return;
}
if ( text.Length == 0 )
return;
afkCount = 0;
if ( text != "/afk" ) {
if ( Server.afkset.Contains(this.name) ) {
Server.afkset.Remove(this.name);
Player.GlobalMessage("-" + this.color + this.DisplayName + Server.DefaultColor + "- is no longer AFK");
Server.IRC.Say(this.DisplayName + " is no longer AFK");
}
}
// This will allow people to type
// //Command
// and in chat it will appear as
// /Command
// Suggested by McMrCat
if ( text.StartsWith("//") ) {
text = text.Remove(0, 1);
goto hello;
}
//This will make / = /repeat
//For lazy people :P
if ( text == "/" ) {
HandleCommand("repeat", "");
return;
}
if ( text[0] == '/' || text[0] == '!' ) {
text = text.Remove(0, 1);
int pos = text.IndexOf(' ');
if ( pos == -1 ) {
HandleCommand(text.ToLower(), "");
return;
}
string cmd = text.Substring(0, pos).ToLower();
string msg = text.Substring(pos + 1);
HandleCommand(cmd, msg);
return;
}
hello:
// People who are muted can't speak or vote
if ( muted ) { this.SendMessage("You are muted."); return; } //Muted: Only allow commands
// Lava Survival map vote recorder
if ( Server.lava.HasPlayer(this) && Server.lava.HasVote(text.ToLower()) ) {
if ( Server.lava.AddVote(this, text.ToLower()) ) {
SendMessage("Your vote for &5" + text.ToLower().Capitalize() + Server.DefaultColor + " has been placed. Thanks!");
Server.lava.map.ChatLevelOps(name + " voted for &5" + text.ToLower().Capitalize() + Server.DefaultColor + ".");
return;
}
else {
SendMessage("&cYou already voted!");
return;
}
}
//CmdVoteKick core vote recorder
if ( Server.voteKickInProgress && text.Length == 1 ) {
if ( text.ToLower() == "y" ) {
this.voteKickChoice = VoteKickChoice.Yes;
SendMessage("Thanks for voting!");
return;
}
if ( text.ToLower() == "n" ) {
this.voteKickChoice = VoteKickChoice.No;
SendMessage("Thanks for voting!");
return;
}
}
// Put this after vote collection so that people can vote even when chat is moderated
if ( Server.chatmod && !this.voice ) { this.SendMessage("Chat moderation is on, you cannot speak."); return; }
// Filter out bad words
if ( Server.profanityFilter ) {
text = ProfanityFilter.Parse(text);
}
if ( Server.checkspam ) {
//if (consecutivemessages == 0)
//{
// consecutivemessages++;
//}
if ( Player.lastMSG == this.name ) {
consecutivemessages++;
}
else {
consecutivemessages--;
}
if ( this.consecutivemessages >= Server.spamcounter ) {
int total = Server.mutespamtime;
Command.all.Find("mute").Use(null, this.name);
Player.GlobalMessage(this.color + this.DisplayName + Server.DefaultColor + " has been &0muted &efor spamming!");
muteTimer.Elapsed += delegate {
total--;
if ( total <= 0 ) {
muteTimer.Stop();
if ( this.muted ) {
Command.all.Find("mute").Use(null, this.name);
}
this.consecutivemessages = 0;
Player.SendMessage(this, "Remember, no &cspamming &e" + "next time!");
}
};
muteTimer.Start();
return;
}
}
Player.lastMSG = this.name;
if( Chat.HandleModes(this, text) )
return;
if ( InGlobalChat ) {
Command.all.Find("global").Use(this, text); //Didn't want to rewrite the whole command... you lazy bastard :3
return;
}
if ( text[0] == ':' ) {
if ( PlayingTntWars ) {
string newtext = text;
if ( text[0] == ':' ) newtext = text.Remove(0, 1).Trim();
TntWarsGame it = TntWarsGame.GetTntWarsGame(this);
if ( it.GameMode == TntWarsGame.TntWarsGameMode.TDM ) {
TntWarsGame.player pl = it.FindPlayer(this);
foreach ( TntWarsGame.player p in it.Players ) {
if ( pl.Red && p.Red ) SendMessage(p.p, "To Team " + c.red + "-" + color + name + c.red + "- " + Server.DefaultColor + newtext);
if ( pl.Blue && p.Blue ) SendMessage(p.p, "To Team " + c.blue + "-" + color + name + c.blue + "- " + Server.DefaultColor + newtext);
}
Server.s.Log("[TNT Wars] [TeamChat (" + ( pl.Red ? "Red" : "Blue" ) + ") " + name + " " + newtext);
return;
}
}
}
/*if (this.teamchat)
{
if (team == null)
{
Player.SendMessage(this, "You are not on a team.");
return;
}
foreach (Player p in team.players)
{
Player.SendMessage(p, "(" + team.teamstring + ") " + this.color + this.name + ":&f " + text);
}
return;
}*/
if ( this.joker ) {
if ( File.Exists("text/joker.txt") ) {
Server.s.Log("<JOKER>: " + this.name + ": " + text);
Chat.GlobalMessageOps(Server.DefaultColor + "<&aJ&bO&cK&5E&9R" + Server.DefaultColor + ">: " + this.color + this.DisplayName + ":&f " + text);
FileInfo jokertxt = new FileInfo("text/joker.txt");
StreamReader stRead = jokertxt.OpenText();
List<string> lines = new List<string>();
Random rnd = new Random();
int i = 0;
while ( !( stRead.Peek() == -1 ) )
lines.Add(stRead.ReadLine());
stRead.Close();
stRead.Dispose();
if ( lines.Count > 0 ) {
i = rnd.Next(lines.Count);
text = lines[i];
}
}
else { File.Create("text/joker.txt").Dispose(); }
}
//chatroom stuff
if ( this.Chatroom != null ) {
Chat.ChatRoom(this, text, true, this.Chatroom);
return;
}
if ( !level.worldChat ) {
Server.s.Log("<" + name + ">[level] " + text);
Chat.GlobalChatLevel(this, text, true);
return;
}
if ( text[0] == '%' ) {
string newtext = text;
if ( !Server.worldChat ) {
newtext = text.Remove(0, 1).Trim();
Chat.GlobalChatWorld(this, newtext, true);
} else {
GlobalChat(this, newtext);
}
Server.s.Log("<" + name + "> " + newtext);
//IRCBot.Say("<" + name + "> " + newtext);
if ( OnChat != null )
OnChat(this, text);
if ( PlayerChat != null )
PlayerChat(this, text);
OnPlayerChatEvent.Call(this, text);
return;
}
Server.s.Log("<" + name + "> " + text);
if ( OnChat != null )
OnChat(this, text);
if ( PlayerChat != null )
PlayerChat(this, text);
OnPlayerChatEvent.Call(this, text);
if ( cancelchat ) {
cancelchat = false;
return;
}
if ( Server.worldChat ) {
GlobalChat(this, text);
} else {
Chat.GlobalChatLevel(this, text, true);
}
//IRCBot.Say(name + ": " + text);
}
catch ( Exception e ) { Server.ErrorLog(e); Player.GlobalMessage("An error occurred: " + e.Message); }
}
public void HandleCommand(string cmd, string message) {
try {
if ( Server.verifyadmins ) {
if ( cmd.ToLower() == "setpass" ) {
Command.all.Find(cmd).Use(this, message);
Server.s.CommandUsed(this.name + " used /setpass");
return;
}
if ( cmd.ToLower() == "pass" ) {
Command.all.Find(cmd).Use(this, message);
Server.s.CommandUsed(this.name + " used /pass");
return;
}
}
if ( Server.agreetorulesonentry ) {
if ( cmd.ToLower() == "agree" ) {
Command.all.Find(cmd).Use(this, String.Empty);
Server.s.CommandUsed(this.name + " used /agree");
return;
}
if ( cmd.ToLower() == "rules" ) {
Command.all.Find(cmd).Use(this, String.Empty);
Server.s.CommandUsed(this.name + " used /rules");
return;
}
if ( cmd.ToLower() == "disagree" ) {
Command.all.Find(cmd).Use(this, String.Empty);
Server.s.CommandUsed(this.name + " used /disagree");
return;
}
}
if ( cmd == String.Empty ) { SendMessage("No command entered."); return; }
if ( Server.agreetorulesonentry && !agreed ) {
SendMessage("You must read /rules then agree to them with /agree!");
return;
}
if ( jailed ) {
SendMessage("You cannot use any commands while jailed.");
return;
}
if ( Server.verifyadmins ) {
if ( this.adminpen ) {
this.SendMessage("&cYou must use &a/pass [Password]&c to verify!");
return;
}
}
//DO NOT REMOVE THE TWO COMMANDS BELOW, /PONY AND /RAINBOWDASHLIKESCOOLTHINGS. -EricKilla
if ( cmd.ToLower() == "pony" ) {
if ( ponycount < 2 ) {
GlobalMessage(this.color + this.DisplayName + Server.DefaultColor + " just so happens to be a proud brony! Everyone give " + this.color + this.name + Server.DefaultColor + " a brohoof!");
ponycount += 1;
}
else {
SendMessage("You have used this command 2 times. You cannot use it anymore! Sorry, Brony!");
}
return;
}
if ( cmd.ToLower() == "rainbowdashlikescoolthings" ) {
if ( rdcount < 2 ) {
GlobalMessage("&1T&2H&3I&4S &5S&6E&7R&8V&9E&aR &bJ&cU&dS&eT &fG&0O&1T &22&30 &4P&CE&7R&DC&EE&9N&1T &5C&6O&7O&8L&9E&aR&b!");
rdcount += 1;
}
else {
SendMessage("You have used this command 2 times. You cannot use it anymore! Sorry, Brony!");
}
return;
}
string foundShortcut = Command.all.FindShort(cmd);
if ( foundShortcut != "" ) cmd = foundShortcut;
if ( OnCommand != null )
OnCommand(cmd, this, message);
if ( PlayerCommand != null )
PlayerCommand(cmd, this, message);
OnPlayerCommandEvent.Call(cmd, this, message);
if ( cancelcommand ) {
cancelcommand = false;
return;
}
try {
int foundCb = int.Parse(cmd);
if ( messageBind[foundCb] == null ) { SendMessage("No CMD is stored on /" + cmd); return; }
message = messageBind[foundCb] + " " + message;
message = message.TrimEnd(' ');
cmd = cmdBind[foundCb];
}
catch { }
Alias alias = Alias.Find(cmd);
if (alias != null)
{
string[] pars = alias.Command.Split(new string[] { " " }, (int)2, StringSplitOptions.None);
try
{
Command.all.Find(pars[0]).Use(this, pars[1] + " " + message);
}
catch
{ //pars[1] is empty/null
Command.all.Find(pars[0]).Use(this, message);
}
return;
}
Command command = Command.all.Find(cmd);
//Group old = null;
if ( command != null ) {
//this part checks if MCGalaxy staff are able to USE protection commands
/*if (isProtected && Server.ProtectOver.Contains(cmd.ToLower())) {
old = Group.findPerm(this.group.Permission);
this.group = Group.findPerm(LevelPermission.Nobody);
}*/
if ( group.CanExecute(command)) {
if ( cmd != "repeat" ) lastCMD = cmd + " " + message;
if ( level.name.Contains("Museum " + Server.DefaultColor) ) {
if ( !command.museumUsable ) {
SendMessage("Cannot use this command while in a museum!");
return;
}
}
if ( this.joker || this.muted ) {
if ( cmd.ToLower() == "me" ) {
SendMessage("Cannot use /me while muted or jokered.");
return;
}
}
if ( cmd.ToLower() != "setpass" || cmd.ToLower() != "pass" ) {
Server.s.CommandUsed(name + " used /" + cmd + " " + message);
}
try { //opstats patch (since 5.5.11)
if (Server.opstats.Contains(cmd.ToLower()) || (cmd.ToLower() == "review" && message.ToLower() == "next" && Server.reviewlist.Count > 0)) {
Database.AddParams("@Time", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
Database.AddParams("@Name", name);
Database.AddParams("@Cmd", cmd);
Database.AddParams("@Cmdmsg", message);
Database.executeQuery("INSERT INTO Opstats (Time, Name, Cmd, Cmdmsg) VALUES (@Time, @Name, @Cmd, @Cmdmsg)");
}
} catch { }
this.commThread = new Thread(new ThreadStart(delegate {
try {
command.Use(this, message);
} catch (Exception e) {
Server.ErrorLog(e);
Player.SendMessage(this, "An error occured when using the command!");
Player.SendMessage(this, e.GetType().ToString() + ": " + e.Message);
}
//finally { if (old != null) this.group = old; }
}));
commThread.Name = "MCG_Command";
commThread.Start();
}
else { SendMessage("You are not allowed to use \"" + cmd + "\"!"); }
}
else if ( Block.Byte(cmd.ToLower()) != Block.Zero ) {
HandleCommand("mode", cmd.ToLower());
}
else {
bool retry = true;
switch ( cmd.ToLower() ) { //Check for command switching
case "guest": message = message + " " + cmd.ToLower(); cmd = "setrank"; break;
case "builder": message = message + " " + cmd.ToLower(); cmd = "setrank"; break;
case "advbuilder":
case "adv": message = message + " " + cmd.ToLower(); cmd = "setrank"; break;
case "operator":
case "op": message = message + " " + cmd.ToLower(); cmd = "setrank"; break;
case "super":
case "superop": message = message + " " + cmd.ToLower(); cmd = "setrank"; break;
case "cut": cmd = "copy"; message = "cut"; break;
case "admins": message = "superop"; cmd = "viewranks"; break;
case "ops": message = "op"; cmd = "viewranks"; break;
case "banned": message = cmd; cmd = "viewranks"; break;
case "ps": message = "ps " + message; cmd = "map"; break;
//How about we start adding commands from other softwares
//and seamlessly switch here?
case "bhb":
case "hbox": cmd = "cuboid"; message = "hollow"; break;
case "blb":
case "box": cmd = "cuboid"; break;
case "sphere": cmd = "spheroid"; break;
case "cmdlist":
case "commands": cmd = "help"; message = "old"; break;
case "cmdhelp": cmd = "help"; break;
case "worlds":
case "mapsave": cmd = "save"; break;
case "mapload": cmd = "load"; break;
case "colour": cmd = "color"; break;
case "materials": cmd = "blocks"; break;
case "zz": cmd = "static"; message = "cuboid " + message; break;
case "fetch": cmd = "summon"; break;
case "ranks": cmd = "help"; message = "ranks"; break;
default: retry = false; break; //Unknown command, then
}
if ( retry ) HandleCommand(cmd, message);
else SendMessage("Unknown command \"" + cmd + "\"!");
}
}
catch ( Exception e ) { Server.ErrorLog(e); SendMessage("Command failed."); }
}
#endregion
#region == GLOBAL MESSAGES ==
public static void GlobalBlockchange(Level level, int b, byte type, byte extType) {
ushort x, y, z;
level.IntToPos(b, out x, out y, out z);
GlobalBlockchange(level, x, y, z, type, extType);
}
public static void GlobalBlockchange(Level level, ushort x, ushort y, ushort z, byte type, byte extType) {
players.ForEach(delegate(Player p) { if ( p.level == level ) { p.SendBlockchange(x, y, z, type, extType); } });
}
// THIS IS NOT FOR SENDING GLOBAL MESSAGES!!! IT IS TO SEND A MESSAGE FROM A SPECIFIED PLAYER!!!!!!!!!!!!!!
public static void GlobalChat(Player from, string message) { GlobalChat(from, message, true); }
public static void GlobalChat(Player from, string message, bool showname) {
if ( from == null ) return; // So we don't fucking derp the hell out!
if ( Server.lava.HasPlayer(from) && Server.lava.HasVote(message.ToLower()) ) {
if ( Server.lava.AddVote(from, message.ToLower()) ) {
SendMessage(from, "Your vote for &5" + message.ToLower().Capitalize() + Server.DefaultColor + " has been placed. Thanks!");
Server.lava.map.ChatLevelOps(from.name + " voted for &5" + message.ToLower().Capitalize() + Server.DefaultColor + ".");
return;
} else {
SendMessage(from, "&cYou already voted!");
return;
}
}
if (Server.voting) {
string test = message.ToLower();
if (CheckVote(test, from, "y", "yes", ref Server.YesVotes) ||
CheckVote(test, from, "n", "no", ref Server.NoVotes)) return;
if (!from.voice && (test == "y" || test == "n" || test == "yes" || test == "no")) {
from.SendMessage("Chat moderation is on while voting is on!"); return;
}
}
if (Server.votingforlevel && Server.zombie.HandlesChatMessage(from, message))
return;
if (Last50Chat.Count() == 50)
Last50Chat.RemoveAt(0);
var chatmessage = new ChatMessage();
chatmessage.text = message;
chatmessage.username = from.color + from.name;
chatmessage.time = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ss");
Last50Chat.Add(chatmessage);
if ( showname ) {
String referee = "";
if ( from.referee ) {
referee = c.green + "[Referee] ";
}
message = referee + from.color + from.voicestring + from.color + from.prefix + from.DisplayName + ": %r&f" + message;
}
players.ForEach(delegate(Player p) {
if ( p.level.worldChat && p.Chatroom == null ) {
if ( p.ignoreglobal == false ) {
if ( from != null ) {
if ( !p.listignored.Contains(from.name) ) {
Player.SendMessage(p, message);
return;
}
return;
}
Player.SendMessage(p, message);
return;
}
if ( Server.globalignoreops == false ) {
if ( from.group.Permission >= Server.opchatperm ) {
if ( p.group.Permission < from.group.Permission ) {
Player.SendMessage(p, message);
}
}
}
if ( from != null ) {
if ( from == p ) {
Player.SendMessage(from, message);
return;
}
}
}
});
}
public static bool CommandHasBadColourCodes(Player who, string message) {
string[] checkmessagesplit = message.Split(' ');
bool lastendwithcolour = false;
foreach ( string s in checkmessagesplit ) {
s.Trim();
if ( s.StartsWith("%") ) {
if ( lastendwithcolour ) {
if ( who != null ) {
who.SendMessage("Sorry, Your colour codes in this command were invalid (You cannot use 2 colour codes next to each other");
who.SendMessage("Command failed.");
Server.s.Log(who.name + " attempted to send a command with invalid colours codes (2 colour codes were next to each other)!");
Chat.GlobalMessageOps(who.color + who.DisplayName + " " + Server.DefaultColor + " attempted to send a command with invalid colours codes (2 colour codes were next to each other)!");
}
return true;
}
else if ( s.Length == 2 ) {
lastendwithcolour = true;
}
}
if ( s.TrimEnd(Server.ColourCodesNoPercent).EndsWith("%") ) {
lastendwithcolour = true;
}
else {
lastendwithcolour = false;
}
}
return false;
}
public static List<ChatMessage> Last50Chat = new List<ChatMessage>();
public static void GlobalMessage(string message) {
GlobalMessage(message, false);
}
public static void GlobalMessage(string message, bool global) {
if ( !global )
//message = message.Replace("%", "&");
message = Chat.EscapeColours(message);
else
message = message.Replace("%G", Server.GlobalChatColor);
players.ForEach(delegate(Player p) {
if ( p.level.worldChat && p.Chatroom == null && ( !global || !p.muteGlobal ) ) {
Player.SendMessage(p, message, !global);
}
});
}
public static void GlobalSpawn(Player from, ushort x, ushort y, ushort z, byte rotx, byte roty, bool self, string possession = "")
{
players.ForEach(delegate(Player p)
{
if (p.Loading && p != from) { return; }
if (p.level != from.level || (from.hidden && !self)) { return; }
if (p != from)
{
if (Server.ZombieModeOn && !p.aka) {
if (from.infected) {
if (Server.ZombieName != "")
p.SendSpawn(from.id, c.red + Server.ZombieName + possession, x, y, z, rotx, roty);
else
p.SendSpawn(from.id, c.red + from.name + possession, x, y, z, rotx, roty);
} else if (!from.referee) {
p.SendSpawn(from.id, from.color + from.name + possession, x, y, z, rotx, roty);
}
} else {
p.SendSpawn(from.id, from.color + from.name + possession, x, y, z, rotx, roty);
}
}
else if (self)
{
if (!p.ignorePermission)
{
p.pos = new ushort[3] { x, y, z }; p.rot = new byte[2] { rotx, roty };
p.oldpos = p.pos; p.basepos = p.pos; p.oldrot = p.rot;
p.SendSpawn(0xFF, from.color + from.name + possession, x, y, z, rotx, roty);
}
}
});
}
public static void GlobalDespawn(Player from, bool self) {
players.ForEach(delegate(Player p) {
if ( p.level != from.level || ( from.hidden && !self ) ) { return; }
if ( p != from ) { p.SendDespawn(from.id); }
else if ( self ) { p.SendDespawn(255); }
});
}
public bool MarkPossessed(string marker = "") {
if ( marker != "" ) {
Player controller = Player.Find(marker);
if ( controller == null ) {
return false;
}
marker = " (" + controller.color + controller.name + color + ")";
}
GlobalDespawn(this, true);
GlobalSpawn(this, pos[0], pos[1], pos[2], rot[0], rot[1], true, marker);
return true;
}
public static void GlobalUpdate() {
players.ForEach(
delegate(Player p) {
if ( !p.hidden )
p.UpdatePosition();
});
}
#endregion
#region == DISCONNECTING ==
public void Disconnect() { leftGame(); }
public void Kick(string kickString) { leftGame(kickString); }
public void leftGame(string kickString = "", bool skip = false) {
OnPlayerDisconnectEvent.Call(this, kickString);
//Umm...fixed?
if ( name == "" ) {
if ( socket != null )
CloseSocket();
if ( connections.Contains(this) )
connections.Remove(this);
SaveUndo();
disconnected = true;
return;
}
////If player has been found in the reviewlist he will be removed
bool leavetest = false;
foreach ( string testwho2 in Server.reviewlist ) {
if ( testwho2 == name ) {
leavetest = true;
}
}
if ( leavetest ) {
Server.reviewlist.Remove(name);
}
try {
if ( disconnected ) {
this.CloseSocket();
if ( connections.Contains(this) )
connections.Remove(this);
return;
}
// FlyBuffer.Clear();
disconnected = true;
pingTimer.Stop();
pingTimer.Dispose();
if ( File.Exists("ranks/ignore/" + this.name + ".txt") ) {
try {
File.WriteAllLines("ranks/ignore/" + this.name + ".txt", this.listignored.ToArray());
}
catch {
Server.s.Log("Failed to save ignored list for player: " + this.name);
}
}
if ( File.Exists("ranks/ignore/GlobalIgnore.xml") ) {
try {
File.WriteAllLines("ranks/ignore/GlobalIgnore.xml", globalignores.ToArray());
}
catch {
Server.s.Log("failed to save global ignore list!");
}
}
afkTimer.Stop();
afkTimer.Dispose();
muteTimer.Stop();
muteTimer.Dispose();
timespent.Stop();
timespent.Dispose();
afkCount = 0;
afkStart = DateTime.Now;
if ( Server.afkset.Contains(name) ) Server.afkset.Remove(name);
if ( kickString == "" ) kickString = "Disconnected.";
SendKick(kickString);
if ( loggedIn ) {
isFlying = false;
aiming = false;
if ( team != null ) {
team.RemoveMember(this);
}
if ( CountdownGame.players.Contains(this) ) {
if ( CountdownGame.playersleftlist.Contains(this) ) {
CountdownGame.PlayerLeft(this);
}
CountdownGame.players.Remove(this);
}
TntWarsGame tntwarsgame = TntWarsGame.GetTntWarsGame(this);
if ( tntwarsgame != null ) {
tntwarsgame.Players.Remove(tntwarsgame.FindPlayer(this));
tntwarsgame.SendAllPlayersMessage("TNT Wars: " + color + name + Server.DefaultColor + " has left TNT Wars!");
}
GlobalDespawn(this, false);
if ( kickString == "Disconnected." || kickString.IndexOf("Server shutdown") != -1 || kickString == Server.customShutdownMessage ) {
if ( !Directory.Exists("text/logout") ) {
Directory.CreateDirectory("text/logout");
}
if ( !File.Exists("text/logout/" + name + ".txt") ) {
CP437Writer.WriteAllText("text/logout/" + name + ".txt", "Disconnected.");
}
if ( !hidden ) {
string leavem = "&c- " + color + prefix + DisplayName + Server.DefaultColor + " " +
CP437Reader.ReadAllText("text/logout/" + name + ".txt");
if ((Server.guestLeaveNotify && group.Permission <= LevelPermission.Guest) || group.Permission > LevelPermission.Guest)
{
Player.players.ForEach(p1 => Player.SendMessage(p1, leavem));
}
}
//IRCBot.Say(name + " left the game.");
Server.s.Log(name + " disconnected.");
}
else {
totalKicked++;
GlobalChat(this, "&c- " + color + prefix + DisplayName + Server.DefaultColor + " kicked (" + kickString + Server.DefaultColor + ").", false);
//IRCBot.Say(name + " kicked (" + kickString + ").");
Server.s.Log(name + " kicked (" + kickString + ").");
}
try { save(); }
catch ( Exception e ) { Server.ErrorLog(e); }
players.Remove(this);
Server.s.PlayerListUpdate();
try {
left.Add(this.name.ToLower(), this.ip);
}
catch ( Exception ) {
//Server.ErrorLog(e);
}
/*if (Server.AutoLoad && level.unload)
{
foreach (Player pl in Player.players)
if (pl.level == level) hasplayers = true;
if (!level.name.Contains("Museum " + Server.DefaultColor) && hasplayers == false)
{
level.Unload();
}
}*/
if ( Server.AutoLoad && level.unload && !level.name.Contains("Museum " + Server.DefaultColor) && IsAloneOnCurrentLevel() )
level.Unload(true);
if ( PlayerDisconnect != null )
PlayerDisconnect(this, kickString);
this.Dispose();
}
else {
connections.Remove(this);
Server.s.Log(ip + " disconnected.");
}
Server.zombie.PlayerLeftServer(this);
}
catch ( Exception e ) { Server.ErrorLog(e); }
finally {
CloseSocket();
}
}
public void SaveUndo() { SaveUndo(this); }
public static void SaveUndo(Player p) {
try {
UndoFile.SaveUndo(p);
} catch (Exception e) {
Server.s.Log("Error saving undo data for " + p.name + "!"); Server.ErrorLog(e);
}
}
public void Dispose() {
//throw new NotImplementedException();
if ( connections.Contains(this) ) connections.Remove(this);
Extras.Clear();
if (CopyBuffer != null)
CopyBuffer.Clear();
RedoBuffer.Clear();
UndoBuffer.Clear();
spamBlockLog.Clear();
//spamChatLog.Clear();
spyChatRooms.Clear();
/*try
{
//this.commThread.Abort();
}
catch { }*/
}
//fixed undo code
public bool IsAloneOnCurrentLevel() {
return players.All(pl => pl.level != level || pl == this);
}
#endregion
#region == CHECKING ==
public static List<Player> GetPlayers() { return new List<Player>(players); }
public static bool Exists(string name) {
foreach ( Player p in players ) { if ( p.name.ToLower() == name.ToLower() ) { return true; } } return false;
}
public static bool Exists(byte id) {
foreach ( Player p in players ) { if ( p.id == id ) { return true; } } return false;
}
public static Player Find(string name) {
List<Player> tempList = new List<Player>();
tempList.AddRange(players);
Player match = null; int matches = 0;
name = name.ToLower();
foreach (Player p in tempList) {
if (p.name.ToLower() == name) return p;
if (p.name.ToLower().Contains(name)) {
match = p; matches++;
}
}
return matches == 1 ? match : null;
}
public static Player FindNick(string nick) {
List<Player> tempList = new List<Player>();
tempList.AddRange(players);
Player match = null; int matches = 0;
nick = nick.ToLower();
foreach (Player p in tempList) {
if (p.DisplayName.ToLower() == nick) return p;
if (p.DisplayName.ToLower().Contains(nick)) {
match = p; matches++;
}
}
return matches == 1 ? match : null;
}
public static Group GetGroup(string name) {
return Group.findPlayerGroup(name);
}
public static string GetColor(string name) {
return GetGroup(name).color;
}
public static OfflinePlayer FindOffline(string name) {
OfflinePlayer offPlayer = new OfflinePlayer("", "", "", "", 0);
Database.AddParams("@Name", name);
using (DataTable playerDB = Database.fillData("SELECT * FROM Players WHERE Name = @Name")) {
if (playerDB.Rows.Count == 0)
return offPlayer;
else {
offPlayer.name = playerDB.Rows[0]["Name"].ToString().Trim();
offPlayer.title = playerDB.Rows[0]["Title"].ToString().Trim();
offPlayer.titleColor = c.Parse(playerDB.Rows[0]["title_color"].ToString().Trim());
offPlayer.color = c.Parse(playerDB.Rows[0]["color"].ToString().Trim());
offPlayer.money = int.Parse(playerDB.Rows[0]["Money"].ToString());
if (offPlayer.color == "") { offPlayer.color = GetGroup(offPlayer.name).color; }
}
}
return offPlayer;
}
#endregion
#region == OTHER ==
static byte FreeId() {
/*
for (byte i = 0; i < 255; i++)
{
foreach (Player p in players)
{
if (p.id == i) { goto Next; }
} return i;
Next: continue;
} unchecked { return 0xFF; }*/
for ( byte i = 0; i < 255; i++ ) {
bool used = players.Any(p => p.id == i);
if ( !used )
return i;
}
return (byte)1;
}
// TODO: Optimize this using a StringBuilder
static List<string> Wordwrap(string message) {
List<string> lines = new List<string>();
message = Regex.Replace(message, @"(&[0-9a-f])+(&[0-9a-f])", "$2");
message = Regex.Replace(message, @"(&[0-9a-f])+$", "");
int limit = 64; string color = "";
while ( message.Length > 0 ) {
//if (Regex.IsMatch(message, "&a")) break;
if ( lines.Count > 0 ) {
if ( message[0].ToString() == "&" )
message = "> " + message.Trim();
else
message = "> " + color + message.Trim();
}
if ( message.IndexOf("&") == message.IndexOf("&", message.IndexOf("&") + 1) - 2 )
message = message.Remove(message.IndexOf("&"), 2);
if ( message.Length <= limit ) { lines.Add(message); break; }
for ( int i = limit - 1; i > limit - 20; --i )
if ( message[i] == ' ' ) {
lines.Add(message.Substring(0, i));
goto Next;
}
retry:
if ( message.Length == 0 || limit == 0 ) { return lines; }
try {
if ( message.Substring(limit - 2, 1) == "&" || message.Substring(limit - 1, 1) == "&" ) {
message = message.Remove(limit - 2, 1);
limit -= 2;
goto retry;
}
else if ( message[limit - 1] < 32 || message[limit - 1] > 127 ) {
message = message.Remove(limit - 1, 1);
limit -= 1;
//goto retry;
}
}
catch { return lines; }
lines.Add(message.Substring(0, limit));
Next: message = message.Substring(lines[lines.Count - 1].Length);
if ( lines.Count == 1 ) limit = 60;
int index = lines[lines.Count - 1].LastIndexOf('&');
if ( index != -1 ) {
if ( index < lines[lines.Count - 1].Length - 1 ) {
char next = lines[lines.Count - 1][index + 1];
if ( "0123456789abcdef".IndexOf(next) != -1 ) { color = "&" + next; }
if ( index == lines[lines.Count - 1].Length - 1 ) {
lines[lines.Count - 1] = lines[lines.Count - 1].Substring(0, lines[lines.Count - 1].Length - 2);
}
}
else if ( message.Length != 0 ) {
char next = message[0];
if ( "0123456789abcdef".IndexOf(next) != -1 ) {
color = "&" + next;
}
lines[lines.Count - 1] = lines[lines.Count - 1].Substring(0, lines[lines.Count - 1].Length - 1);
message = message.Substring(1);
}
}
}
char[] temp;
for ( int i = 0; i < lines.Count; i++ ) // Gotta do it the old fashioned way...
{
temp = lines[i].ToCharArray();
if ( temp[temp.Length - 2] == '%' || temp[temp.Length - 2] == '&' ) {
temp[temp.Length - 1] = ' ';
temp[temp.Length - 2] = ' ';
}
StringBuilder message1 = new StringBuilder();
message1.Append(temp);
lines[i] = message1.ToString();
}
return lines;
}
public static bool ValidName(string name) {
string allowedchars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890._+";
return name.All(ch => allowedchars.IndexOf(ch) != -1);
}
public static int GetBannedCount() {
try {
return File.ReadAllLines("ranks/banned.txt").Length;
}
catch/* (Exception ex)*/
{
return 0;
}
}
#endregion
public void RevertBlock(ushort x, ushort y, ushort z) {
byte b = level.GetTile(x, y, z);
SendBlockchange(x, y, z, b);
}
bool CheckBlockSpam() {
if ( spamBlockLog.Count >= spamBlockCount ) {
DateTime oldestTime = spamBlockLog.Dequeue();
double spamTimer = DateTime.Now.Subtract(oldestTime).TotalSeconds;
if ( spamTimer < spamBlockTimer && !ignoreGrief ) {
this.Kick("You were kicked by antigrief system. Slow down.");
SendMessage(c.red + DisplayName + " was kicked for suspected griefing.");
Server.s.Log(name + " was kicked for block spam (" + spamBlockCount + " blocks in " + spamTimer + " seconds)");
return true;
}
}
spamBlockLog.Enqueue(DateTime.Now);
return false;
}
public static bool IPInPrivateRange(string ip) {
//range of 172.16.0.0 - 172.31.255.255
if (ip.StartsWith("172.") && (int.Parse(ip.Split('.')[1]) >= 16 && int.Parse(ip.Split('.')[1]) <= 31))
return true;
return IPAddress.IsLoopback(IPAddress.Parse(ip)) || ip.StartsWith("192.168.") || ip.StartsWith("10.");
//return IsLocalIpAddress(ip);
}
/*public string ResolveExternalIP(string ip) {
HTTPGet req = new HTTPGet();
req.Request("http://checkip.dyndns.org");
string[] a1 = req.ResponseBody.Split(':');
string a2 = a1[1].Substring(1);
string[] a3 = a2.Split('<');
return a3[0];
}*/
public static bool IsLocalIpAddress(string host) {
try { // get host IP addresses
IPAddress[] hostIPs = Dns.GetHostAddresses(host);
// get local IP addresses
IPAddress[] localIPs = Dns.GetHostAddresses(Dns.GetHostName());
// test if any host IP equals to any local IP or to localhost
foreach ( IPAddress hostIP in hostIPs ) {
// is localhost
if ( IPAddress.IsLoopback(hostIP) ) return true;
// is local address
foreach ( IPAddress localIP in localIPs ) {
if ( hostIP.Equals(localIP) ) return true;
}
}
}
catch { }
return false;
}
public bool EnoughMoney(int amount) {
if (this.money >= amount)
return true;
return false;
}
public void ReviewTimer() {
this.canusereview = false;
System.Timers.Timer Clock = new System.Timers.Timer(1000 * Server.reviewcooldown);
Clock.Elapsed += delegate { this.canusereview = true; Clock.Dispose(); };
Clock.Start();
}
public void TntAtATime() {
new Thread(() => {
CurrentAmountOfTnt += 1;
switch ( TntWarsGame.GetTntWarsGame(this).GameDifficulty ) {
case TntWarsGame.TntWarsDifficulty.Easy:
Thread.Sleep(3250);
break;
case TntWarsGame.TntWarsDifficulty.Normal:
Thread.Sleep(2250);
break;
case TntWarsGame.TntWarsDifficulty.Hard:
case TntWarsGame.TntWarsDifficulty.Extreme:
Thread.Sleep(1250);
break;
}
CurrentAmountOfTnt -= 1;
}).Start();
}
public static bool BlacklistCheck(string name, string foundLevel)
{
string path = "levels/blacklists/" + foundLevel + ".txt";
if (!File.Exists(path)) { return false; }
if (File.ReadAllText(path).Contains(name)) { return true; }
return false;
}
public static string GetIPLocation(string IP)
{
string direction;
string direction2;
string city = "http://ipinfo.io/" + IP + "/city";
string country = "http://ipinfo.io/" + IP + "/country";
string replacement;
string replacement2;
WebRequest requestcity = WebRequest.Create(city);
WebRequest requestcountry = WebRequest.Create(country);
using (WebResponse response1 = requestcity.GetResponse())
using (StreamReader stream = new StreamReader(response1.GetResponseStream()))
{
direction = stream.ReadToEnd();
replacement = Regex.Replace(direction, @"\n", "");
if (replacement == "")
{
replacement = "Unknown";
}
}
using (WebResponse response2 = requestcountry.GetResponse())
using (StreamReader stream2 = new StreamReader(response2.GetResponseStream()))
{
direction2 = stream2.ReadToEnd();
replacement2 = Regex.Replace(direction2, @"\n", "");
}
return replacement + "/" + replacement2;
}
internal static bool CheckVote(string message, Player p, string a, string b, ref int totalVotes) {
if (!p.voted && (message == a || message == b)) {
totalVotes++;
p.SendMessage(c.red + "Thanks for voting!");
p.voted = true;
return true;
}
return false;
}
}
}