MCGalaxy/Player/Player.Handlers.cs

1578 lines
73 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.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using MCGalaxy.SQL;
namespace MCGalaxy {
public sealed partial class Player : IDisposable {
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.IsMuseum && 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.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.timeDelta = (int)DateTime.UtcNow.Subtract(Server.StartTime).TotalSeconds;
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.IsMuseum ) {
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);
}
}
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;
HandleMovement(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!", true); 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.", true); return;
}
}
}
DisplayName = name;
SkinName = name;
name += "+";
byte type = message[129];
isDev = Server.Devs.ContainsInsensitive(name);
isMod = Server.Mods.ContainsInsensitive(name);
isGCMod = Server.GCmods.ContainsInsensitive(name);
verifiedName = Server.verify;
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)!", true);
}
} catch { }
if (!CheckWhitelist()) return;
// ban check
if (Server.bannedIP.Contains(ip) && (!Server.useWhitelist || !onWhitelist)) {
Kick(Server.customBanMessage, true); return;
}
if (Group.findPlayerGroup(name) == Group.findPerm(LevelPermission.Banned)) {
if (!Server.useWhitelist || !onWhitelist) {
if (Ban.IsBanned(name)) {
string[] data = Ban.GetBanData(name);
Kick("Banned for \"" + data[1] + "\" by " + data[0], true);
} else {
Kick(Server.customBanMessage, true);
}
return;
}
}
//server maxplayer check
if (!VIP.Find(this))
{
// Check to see how many guests we have
if (PlayerInfo.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 = PlayerInfo.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.");
const string msg = "Server has reached max number of guests";
LeaveServer(msg, msg, true);
return;
}
}
}
if (version != Server.version) { LeaveServer("Wrong version!", "Wrong version!", true); return; }
foreach (Player p in PlayerInfo.players) {
if (p.name == name) {
if (Server.verify) {
p.Kick("Someone logged in as you!"); break;
} else {
Kick("Already logged in!", true); return;
}
}
}
LoadIgnores();
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, 2);
}
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 CompleteLoginProcess() {
try {
SendMotd();
SendMap(null);
if (disconnected) return;
loggedIn = true;
lock (PlayerInfo.players)
PlayerInfo.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 (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.");
string joinm = "&a+ " + this.FullName + Server.DefaultColor + " " + File.ReadAllText("text/login/" + this.name + ".txt");
if (group.Permission < Server.adminchatperm || !Server.adminsjoinsilent) {
if ((Server.guestJoinNotify && group.Permission <= LevelPermission.Guest) || group.Permission > LevelPermission.Guest) {
PlayerInfo.players.ForEach(p1 => Player.SendMessage(p1, joinm));
}
}
if (group.Permission >= Server.adminchatperm && Server.adminsjoinsilent) {
hidden = true;
adminchat = true;
}
if (PlayerConnect != null)
PlayerConnect(this);
OnPlayerConnectEvent.Call(this);
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;
}
}
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.");
Server.zombie.PlayerJoinedServer(this);
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 PlayerInfo.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) {
SendMessage("Welcome " + DisplayName + "! This is your first visit.");
PlayerInfo.CreateInfo(this);
}
void LoadPlayerStats(DataTable playerDb) {
PlayerInfo.LoadInfo(playerDb, this);
SendMessage("Welcome back " + color + prefix + DisplayName + "%S! " +
"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
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) || level.CustomBlockDefs[type] == null) {
SendMessage("Invalid block type: " + type);
RevertBlock(x, y, z); 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);
}
}
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);
p.BlockUntilLoad(10);
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; }
}
static char[] trimChars = { ' ' };
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();
message = message.Replace("\\'", "\'");
if ( message != prevMsg || Server.repeatMessage ) {
if ( message.StartsWith("/") ) {
string[] parts = message.Remove(0, 1).Split(trimChars, 2);
HandleCommand(parts[0], parts.Length > 1 ? parts[1] : "");
} 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.");
RevertBlock(x, y, z); return;
}
}
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_tree__air: //Door_air
case Block.door_obsidian_air:
case Block.door_glass_air:
case Block.door_stone_air:
case Block.door_leaves_air:
case Block.door_sand_air:
case Block.door_wood_air:
case Block.door_green_air:
case Block.door_tnt_air:
case Block.door_stair_air:
case Block.door_iron_air:
case Block.door_gold_air:
case Block.door_cobblestone_air:
case Block.door_red_air:
case Block.door_darkpink_air:
case Block.door_darkgrey_air:
case Block.door_lightgrey_air:
case Block.door_white_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);
}
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
byte above = level.GetTile(x, (ushort)(y + 1), z), extAbove = 0;
if (type == Block.custom_block)
extAbove = level.GetExtTile(x, (ushort)(y + 1), z);
if (Block.LightPass(above, extAbove, level.CustomBlockDefs))
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 HandleMovement(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];
ushort x = NetUtils.ReadU16(message, 1);
ushort y = NetUtils.ReadU16(message, 3);
ushort z = NetUtils.ReadU16(message, 5);
byte rotx = message[7], roty = message[8];
if (Server.Countdown.HandlesMovement(this, x, y, z, rotx, roty))
return;
if (Server.ZombieModeOn && Server.zombie.HandlesMovement(this, x, y, z, rotx, roty))
return;
if (OnMove != null) OnMove(this, x, y, z);
if (PlayerMove != null) PlayerMove(this, x, y, z);
if (PlayerMoveEvent.events.Count > 0) PlayerMoveEvent.Call(this, x, y, z);
if (OnRotate != null) OnRotate(this, rot);
if (PlayerRotate != null) PlayerRotate(this, rot);
if (PlayerRotateEvent.events.Count > 0) PlayerRotateEvent.Call(this, rot);
if (cancelmove) {
SendPos(0xFF, pos[0], pos[1], pos[2], rot[0], rot[1]); return;
}
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);
}
internal void CheckBlock(ushort x, ushort y, ushort z) {
byte b = level.GetTile(x, y, z);
byte b1 = 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)(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)(y - 1), z, b1);
} else if ( b == Block.checkpoint ) {
useCheckpointSpawn = true;
checkpointX = x; checkpointY = y; checkpointZ = z;
int index = level.PosToInt(x, y, z);
if (index != lastCheckpointIndex) {
SendSpawn(0xFF, color + name, pos[0], (ushort)((y - 1) * 32 + 51), pos[2], rot[0], rot[1]);
lastCheckpointIndex = index;
}
} else if ( b1 == Block.checkpoint ) {
useCheckpointSpawn = true;
checkpointX = x; checkpointY = (ushort)(y + 1); checkpointZ = z;
int index = level.PosToInt(x, (ushort)(y - 1), z);
if (index != lastCheckpointIndex) {
SendSpawn(0xFF, color + name, pos[0], (ushort)((y - 1) * 32 + 51), pos[2], rot[0], rot[1]);
lastCheckpointIndex = index;
}
}
}
}
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), y = (ushort)(pos[1] / 32), 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);
SendChatFrom(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 ( Server.Countdown.playersleftlist.Contains(this) ) {
Server.Countdown.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 )
SendChatFrom(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(Colors.red + "[INFO] " + color + DisplayName + "%f is using wom client");
Player.GlobalMessage(Colors.red + "[INFO] %fVersion: " + version);
Server.s.Log(Colors.red + "[INFO] " + color + DisplayName + "%f is using wom client");
Server.s.Log(Colors.red + "[INFO] %fVersion: " + version);
UsingWom = true;
WoMVersion = version.Split('-')[1];
return;
}
if( HasCpeExt(CpeExt.LongerMessages) && continued != 0 ) {
if (text.Length < 64) storedMessage = storedMessage + text + " ";
else storedMessage = 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(Colors.teal + "Partial message: " + Colors.white + storedMessage.Replace("|>|", " ").Replace("|<|", ""));
return;
}
if (text.EndsWith("<"))
{
storedMessage += text.Replace("<", "|<|");
SendMessage(Colors.teal + "Partial message: " + Colors.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");
}
}
// Typing //Command appears in chat as /command
// Suggested by McMrCat
if ( text.StartsWith("//") ) {
text = text.Remove(0, 1);
goto hello;
}
// Typing / will act as /repeat
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;
}
}
if (VoteHandles(text)) return;
// Put this after vote collection so that people can vote even when chat is moderated
if ( Server.chatmod && !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 " + Colors.red + "-" + color + name + Colors.red + "- " + Server.DefaultColor + newtext);
if ( pl.Blue && p.Blue ) SendMessage(p.p, "To Team " + Colors.blue + "-" + color + name + Colors.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 {
SendChatFrom(this, newtext);
}
Server.s.Log("<" + name + "> " + newtext);
//IRCBot.Say("<" + name + "> " + newtext);
if (OnChat != null) OnChat(this, text);
if (PlayerChat != null) PlayerChat(this, text);
if (OnPlayerChatEvent.events.Count > 0) OnPlayerChatEvent.Call(this, text);
return;
}
Server.s.Log("<" + name + "> " + text);
if (OnChat != null) OnChat(this, text);
if (PlayerChat != null) PlayerChat(this, text);
if (OnPlayerChatEvent.events.Count > 0) OnPlayerChatEvent.Call(this, text);
if (cancelchat) {
cancelchat = false; return;
}
if (Server.worldChat) {
SendChatFrom(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); }
}
bool VoteHandles(string text) {
if (Server.voteKickInProgress && text.Length == 1) {
if (text.ToLower() == "y") {
this.voteKickChoice = VoteKickChoice.Yes;
SendMessage("Thanks for voting!");
return true;
} else if (text.ToLower() == "n") {
this.voteKickChoice = VoteKickChoice.No;
SendMessage("Thanks for voting!");
return true;
}
}
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 true;
} else {
SendMessage("&cYou already voted!");
return true;
}
}
if (Server.voting) {
string test = text.ToLower();
if (CheckVote(test, this, "y", "yes", ref Server.YesVotes) ||
CheckVote(test, this, "n", "no", ref Server.NoVotes)) return true;
if (!voice && (test == "y" || test == "n" || test == "yes" || test == "no")) {
SendMessage("Chat moderation is on while voting is on!"); return true;
}
}
if (Server.votingforlevel && Server.zombie.HandlesChatMessage(this, text))
return true;
return false;
}
public void HandleCommand(string cmd, string message) {
cmd = cmd.ToLower();
try {
if (cmd == "") { SendMessage("No command entered."); return; }
if (Server.agreetorulesonentry && !agreed && !(cmd == "agree" || cmd == "rules" || cmd == "disagree")) {
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 && adminpen && !(cmd == "pass" || cmd == "setpass")) {
SendMessage("&cYou must use &a/pass [Password]&c to verify!"); return;
}
//DO NOT REMOVE THE TWO COMMANDS BELOW, /PONY AND /RAINBOWDASHLIKESCOOLTHINGS. -EricKilla
if (cmd == "pony") {
if ( ponycount < 2 ) {
GlobalMessage(color + DisplayName + " %Sjust so happens to be a proud brony! Everyone give " + color + name + " %Sa brohoof!");
ponycount += 1;
} else {
SendMessage("You have used this command 2 times. You cannot use it anymore! Sorry, Brony!");
}
return;
}
if (cmd == "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 shortcut = Command.all.FindShort(cmd);
if (shortcut != "") cmd = shortcut;
byte bindIndex;
if (byte.TryParse(cmd, out bindIndex) && bindIndex < 10) {
if (messageBind[bindIndex] == null) { SendMessage("No command is bound to: /" + cmd); return; }
cmd = cmdBind[bindIndex];
message = messageBind[bindIndex] + " " + message;
message = message.TrimEnd(' ');
}
Alias alias = Alias.Find(cmd);
if (alias != null) {
string[] pars = alias.Command.Split(trimChars, 2);
cmd = pars[0];
if (pars.Length > 1)
message = message == "" ? pars[1] : pars[1] + " " + message;
}
if (OnCommand != null) OnCommand(cmd, this, message);
if (PlayerCommand != null) PlayerCommand(cmd, this, message);
OnPlayerCommandEvent.Call(cmd, this, message);
if (cancelcommand) {
cancelcommand = false; return;
}
Command command = Command.all.Find(cmd);
if (command != null) {
UseCommand(command, cmd, message);
} else if (Block.Byte(cmd.ToLower()) != Block.Zero) {
HandleCommand("mode", cmd.ToLower());
} else if (MapCommand(ref cmd, ref message)) {
HandleCommand(cmd, message);
} else {
SendMessage("Unknown command \"" + cmd + "\"!");
}
}
catch ( Exception e ) { Server.ErrorLog(e); SendMessage("Command failed."); }
}
void UseCommand(Command command, string cmd, string message) {
if (!group.CanExecute(command)) {
SendMessage("You are not allowed to use \"" + cmd + "\"."); return;
}
if (cmd != "repeat") lastCMD = cmd + " " + message;
if (level.IsMuseum && !command.museumUsable ) {
SendMessage("Cannot use this command while in a museum!"); return;
}
if ((joker || muted) && cmd == "me") {
SendMessage("Cannot use /me while muted or jokered."); return;
}
if (!(cmd == "pass" || cmd == "setpass")) {
Server.s.CommandUsed(name + " used /" + cmd + " " + message);
}
try { //opstats patch (since 5.5.11)
if (Server.opstats.Contains(cmd) || (cmd == "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 { }
Thread thread = 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() + ": " + e.Message);
}
}));
thread.Name = "MCG_Command";
thread.Start();
}
bool MapCommand(ref string cmd, ref string message) {
switch (cmd) {
case "guest":
case "builder":
case "advbuilder":
case "adv":
case "operator":
case "op":
case "super":
case "superop": message = cmd + " " + message; cmd = "setrank"; return true;
case "cut": cmd = "copy"; message = "cut"; return true;
case "admins": message = "superop"; cmd = "viewranks"; return true;
case "ops": message = "op"; cmd = "viewranks"; return true;
case "banned": message = cmd; cmd = "viewranks"; return true;
case "ps": message = "ps " + message; cmd = "map"; return true;
case "bhb":
case "hbox": cmd = "cuboid"; message = "hollow"; return true;
case "blb":
case "box": cmd = "cuboid"; return true;
case "sphere": cmd = "spheroid"; return true;
case "cmdlist":
case "commands": cmd = "help"; message = "commands"; return true;
case "cmdhelp": cmd = "help"; return true;
case "worlds":
case "mapsave": cmd = "save"; return true;
case "mapload": cmd = "load"; return true;
case "colour": cmd = "color"; return true;
case "materials": cmd = "blocks"; return true;
case "zz": cmd = "static"; message = "cuboid " + message; return true;
case "fetch": cmd = "summon"; return true;
case "ranks": cmd = "help"; message = "ranks"; return true;
case "j":
case "join": cmd = "goto"; return true;
}
return false;
}
}
}