Validate perbuild and pervisit permissions for world-changing commands, and regardless of whether level is loaded or not. Fixes #309

This commit is contained in:
UnknownShadow200 2017-09-09 20:47:14 +10:00
parent 89a8823981
commit 20a3aa6b90
47 changed files with 170 additions and 188 deletions

View File

@ -45,8 +45,8 @@ namespace MCGalaxy.Blocks {
case Block.C4: return PlaceBehaviour.C4; case Block.C4: return PlaceBehaviour.C4;
case Block.C4Detonator: return PlaceBehaviour.C4Det; case Block.C4Detonator: return PlaceBehaviour.C4Det;
} }
if (props[block.Index].StackId != Block.Air) return PlaceBehaviour.Stack(block); if (props[block.Index].StackId != Block.Air) return PlaceBehaviour.Stack(block);
return null; return null;
} }

View File

@ -19,9 +19,9 @@ using System;
namespace MCGalaxy { namespace MCGalaxy {
public sealed partial class Block { public sealed partial class Block {
static string[] coreNames = new string[Block.Count]; static string[] coreNames = new string[Block.Count];
public static string Name(byte block) { return coreNames[block]; } public static string Name(byte block) { return coreNames[block]; }
public static byte Byte(string type) { public static byte Byte(string type) {
byte block; byte block;

View File

@ -39,7 +39,7 @@ namespace MCGalaxy.Blocks.Physics {
index = lvl.PosToInt((ushort)(x + Math.Sign(closest.Pos.BlockX - x)), y, z); index = lvl.PosToInt((ushort)(x + Math.Sign(closest.Pos.BlockX - x)), y, z);
if (MoveTo(lvl, block, C.b, index, target)) return; if (MoveTo(lvl, block, C.b, index, target)) return;
} }
dirsVisited++; dirsVisited++;
if (dirsVisited >= 3) break; if (dirsVisited >= 3) break;
goto case 4; goto case 4;
@ -88,7 +88,7 @@ namespace MCGalaxy.Blocks.Physics {
index = lvl.PosToInt((ushort)(x - Math.Sign(closest.Pos.BlockX - x)), y, z); index = lvl.PosToInt((ushort)(x - Math.Sign(closest.Pos.BlockX - x)), y, z);
if (MoveTo(lvl, block, C.b, index, target)) return; if (MoveTo(lvl, block, C.b, index, target)) return;
} }
dirsVisited++; dirsVisited++;
if (dirsVisited >= 3) break; if (dirsVisited >= 3) break;
goto case 4; goto case 4;
@ -128,7 +128,7 @@ namespace MCGalaxy.Blocks.Physics {
} }
static void RandomlyMove(Level lvl, ref Check C, ExtBlock block, Random rand, static void RandomlyMove(Level lvl, ref Check C, ExtBlock block, Random rand,
ushort x, ushort y, ushort z, byte target) { ushort x, ushort y, ushort z, byte target) {
switch (rand.Next(1, 15)) { switch (rand.Next(1, 15)) {
case 1: case 1:
if (MoveTo(lvl, block, C.b, lvl.PosToInt(x, (ushort)(y - 1), z), target)) return; if (MoveTo(lvl, block, C.b, lvl.PosToInt(x, (ushort)(y - 1), z), target)) return;

View File

@ -39,7 +39,7 @@ namespace MCGalaxy {
{ "vv", '▼' }, { "down", '▼' }, { "vv", '▼' }, { "down", '▼' },
{ "house", '⌂' } { "house", '⌂' }
}; };
/// <summary> Conversion for code page 437 characters from index 0 to 31 to unicode. </summary> /// <summary> Conversion for code page 437 characters from index 0 to 31 to unicode. </summary>
public const string ControlCharReplacements = "\0☺☻♥♦♣♠•◘○◙♂♀♪♫☼►◄↕‼¶§▬↨↑↓→←∟↔▲▼"; public const string ControlCharReplacements = "\0☺☻♥♦♣♠•◘○◙♂♀♪♫☼►◄↕‼¶§▬↨↑↓→←∟↔▲▼";

View File

@ -78,10 +78,10 @@ namespace MCGalaxy.Commands {
public static Alias Find(string cmd) { public static Alias Find(string cmd) {
foreach (Alias alias in aliases) { foreach (Alias alias in aliases) {
if (alias.Trigger.CaselessEq(cmd)) return alias; if (alias.Trigger.CaselessEq(cmd)) return alias;
} }
foreach (Alias alias in coreAliases) { foreach (Alias alias in coreAliases) {
if (alias.Trigger.CaselessEq(cmd)) return alias; if (alias.Trigger.CaselessEq(cmd)) return alias;
} }
return null; return null;
} }

View File

@ -48,10 +48,7 @@ namespace MCGalaxy.Commands.Bots {
} }
void AddBot(Player p, string botName) { void AddBot(Player p, string botName) {
if (!p.level.BuildAccess.CheckDetailed(p)) { if (!LevelInfo.ValidateAction(p, p.level.name, "add bots to this level")) return;
Player.Message(p, "Hence, you cannot add bots to this map.");
return;
}
if (BotExists(p.level, botName)) { if (BotExists(p.level, botName)) {
Player.Message(p, "A bot with that name already exists."); return; Player.Message(p, "A bot with that name already exists."); return;
@ -77,10 +74,7 @@ namespace MCGalaxy.Commands.Bots {
} }
void RemoveBot(Player p, string botName) { void RemoveBot(Player p, string botName) {
if (!p.level.BuildAccess.CheckDetailed(p)) { if (!LevelInfo.ValidateAction(p, p.level.name, "remove bots from this level")) return;
Player.Message(p, "Hence, you cannot remove bots from this map.");
return;
}
if (botName.CaselessEq("all")) { if (botName.CaselessEq("all")) {
PlayerBot.RemoveLoadedBots(p.level, false); PlayerBot.RemoveLoadedBots(p.level, false);
@ -97,6 +91,7 @@ namespace MCGalaxy.Commands.Bots {
void SetBotText(Player p, string botName, string text) { void SetBotText(Player p, string botName, string text) {
PlayerBot bot = Matcher.FindBots(p, botName); PlayerBot bot = Matcher.FindBots(p, botName);
if (bot == null) return; if (bot == null) return;
if (!LevelInfo.ValidateAction(p, p.level.name, "set bot text of that bot")) return;
if (text == null) { if (text == null) {
Player.Message(p, "Removed text shown when bot {0} %Sclicked on", bot.ColoredName); Player.Message(p, "Removed text shown when bot {0} %Sclicked on", bot.ColoredName);

View File

@ -34,12 +34,8 @@ namespace MCGalaxy.Commands.Bots {
if (message.Length == 0) { Help(p); return; } if (message.Length == 0) { Help(p); return; }
string[] args = message.SplitSpaces(); string[] args = message.SplitSpaces();
PlayerBot bot = Matcher.FindBots(p, args[0]); PlayerBot bot = Matcher.FindBots(p, args[0]);
if (bot == null) return; if (bot == null) return;
if (!LevelInfo.ValidateAction(p, p.level.name, "change AI of bots in this level")) return;
if (p != null && !bot.level.BuildAccess.CheckDetailed(p)) {
Player.Message(p, "Hence, you cannot change the AI of bots on this map.");
return;
}
if (args.Length == 1) { if (args.Length == 1) {
bot.Instructions.Clear(); bot.Instructions.Clear();

View File

@ -27,10 +27,7 @@ namespace MCGalaxy.Commands.Bots {
public override void Use(Player p, string message) { public override void Use(Player p, string message) {
if (message.Length == 0) { Help(p); return; } if (message.Length == 0) { Help(p); return; }
if (!p.level.BuildAccess.CheckDetailed(p)) { if (!LevelInfo.ValidateAction(p, p.level.name, "summon that bot")) return;
Player.Message(p, "Hence, you cannot summon bots on this map.");
return;
}
PlayerBot bot = Matcher.FindBots(p, message); PlayerBot bot = Matcher.FindBots(p, message);
if (bot == null) return; if (bot == null) return;

View File

@ -68,6 +68,7 @@ namespace MCGalaxy.Commands.CPE {
Player.Message(p, "Set server's default terrain to " + path); Player.Message(p, "Set server's default terrain to " + path);
UpdateGlobally(p, false); UpdateGlobally(p, false);
} else if (scope == "level") { } else if (scope == "level") {
if (!LevelInfo.ValidateAction(p, p.level.name, "set texture of this level")) return;
p.level.Config.Terrain = url; p.level.Config.Terrain = url;
Player.Message(p, "Set level's terrain to " + path); Player.Message(p, "Set level's terrain to " + path);
UpdateLevel(p); UpdateLevel(p);
@ -76,6 +77,7 @@ namespace MCGalaxy.Commands.CPE {
Player.Message(p, "Set server's default texture pack to " + path); Player.Message(p, "Set server's default texture pack to " + path);
UpdateGlobally(p, true); UpdateGlobally(p, true);
} else if (scope == "levelzip") { } else if (scope == "levelzip") {
if (!LevelInfo.ValidateAction(p, p.level.name, "set texture pack of this level")) return;
p.level.Config.TexturePack = url; p.level.Config.TexturePack = url;
Player.Message(p, "Set level's texture pack to " + path); Player.Message(p, "Set level's texture pack to " + path);
UpdateLevel(p); UpdateLevel(p);

View File

@ -33,10 +33,7 @@ namespace MCGalaxy.Commands.Chatting {
public override void Use(Player p, string message) { UseBotOrPlayer(p, message, "color"); } public override void Use(Player p, string message) { UseBotOrPlayer(p, message, "color"); }
protected override void SetBotData(Player p, PlayerBot bot, string colName) { protected override void SetBotData(Player p, PlayerBot bot, string colName) {
if (p != null && !bot.level.BuildAccess.CheckDetailed(p)) { if (!LevelInfo.ValidateAction(p, bot.level.name, "change color of that bot")) return;
Player.Message(p, "Hence, you cannot change the color of that bot.");
return;
}
string color = colName.Length == 0 ? "&1" : Matcher.FindColor(p, colName); string color = colName.Length == 0 ? "&1" : Matcher.FindColor(p, colName);
if (color == null) return; if (color == null) return;

View File

@ -80,7 +80,7 @@ namespace MCGalaxy.Commands.Chatting {
if (num >= Inbox.Rows.Count) { if (num >= Inbox.Rows.Count) {
Player.Message(p, "Message #{0} does not exist.", num); return; Player.Message(p, "Message #{0} does not exist.", num); return;
} }
OutputMessage(p, Inbox.Rows[num]); OutputMessage(p, Inbox.Rows[num]);
} }
} }

View File

@ -39,7 +39,7 @@ namespace MCGalaxy {
/// <summary> Finds the command which has the given name or shortcut, or null if not found. </summary> /// <summary> Finds the command which has the given name or shortcut, or null if not found. </summary>
public Command Find(string name) { public Command Find(string name) {
foreach (Command cmd in commands) { foreach (Command cmd in commands) {
if (cmd.name.CaselessEq(name) || cmd.shortcut.CaselessEq(name)) return cmd; if (cmd.name.CaselessEq(name) || cmd.shortcut.CaselessEq(name)) return cmd;
} }
return null; return null;
} }

View File

@ -35,10 +35,7 @@ namespace MCGalaxy.Commands {
if (isBot) { if (isBot) {
if (!CheckExtraPerm(p, 2)) return; if (!CheckExtraPerm(p, 2)) return;
if (p != null && !bot.level.BuildAccess.CheckDetailed(p)) { if (!LevelInfo.ValidateAction(p, bot.level.name, "change the " + type + " of that bot")) return;
Player.Message(p, "Hence, you cannot change the " + type + " of that bot.");
return;
}
SetBotData(p, bot, args.Length > 2 ? args[2] : ""); SetBotData(p, bot, args.Length > 2 ? args[2] : "");
} else { } else {
if (p != who && !CheckExtraPerm(p, 1)) return; if (p != who && !CheckExtraPerm(p, 1)) return;

View File

@ -79,7 +79,7 @@ namespace MCGalaxy.Commands.Info {
static void SearchRanks(Player p, string keyword, string modifier) { static void SearchRanks(Player p, string keyword, string modifier) {
List<string> ranks = new List<string>(); List<string> ranks = new List<string>();
foreach (Group g in Group.GroupList) { foreach (Group g in Group.GroupList) {
if (g.Name.CaselessContains(keyword)) { if (g.Name.CaselessContains(keyword)) {
ranks.Add(g.ColoredName); ranks.Add(g.ColoredName);
} }
} }

View File

@ -38,6 +38,7 @@ namespace MCGalaxy.Commands.Maintenance {
lvl = Matcher.FindLevels(p, args[1]); lvl = Matcher.FindLevels(p, args[1]);
if (lvl == null) return; if (lvl == null) return;
} }
if (!LevelInfo.ValidateAction(p, lvl.name, "change BlockDB state of this level")) return;
if (args[0].CaselessEq("clear")) { if (args[0].CaselessEq("clear")) {
Player.Message(p, "Clearing &cALL %Sblock changes for {0}%S...", lvl.ColoredName); Player.Message(p, "Clearing &cALL %Sblock changes for {0}%S...", lvl.ColoredName);

View File

@ -105,7 +105,7 @@ namespace MCGalaxy.Commands.Moderation {
} }
public override void SendMessage(byte id, string message, bool colorParse = true) { public override void SendMessage(byte id, string message, bool colorParse = true) {
Logger.Log(LogType.ConsoleMessage, message); Logger.Log(LogType.ConsoleMessage, message);
} }
} }

View File

@ -50,6 +50,8 @@ namespace MCGalaxy.Commands.World {
Player.Message(p, "Cannot use level scope from {0}.", src); Player.Message(p, "Cannot use level scope from {0}.", src);
return null; return null;
} }
if (!LevelInfo.ValidateAction(p, p.level.name, "change block properties in this level")) return null;
return p.level.Props; return p.level.Props;
} }

View File

@ -37,15 +37,18 @@ namespace MCGalaxy.Commands.World {
if (args.Length < 2) { if (args.Length < 2) {
Player.Message(p, "You did not specify the destination level name."); return; Player.Message(p, "You did not specify the destination level name."); return;
} }
string src = args[0], dst = args[1];
if (p != null && !p.group.CanExecute("newlvl")) { if (p != null && !p.group.CanExecute("newlvl")) {
Player.Message(p, "You cannot use /copylvl as you cannot use /newlvl."); return; Player.Message(p, "You cannot use /copylvl as you cannot use /newlvl."); return;
} }
string src = args[0];
src = Matcher.FindMaps(p, src); src = Matcher.FindMaps(p, src);
if (src == null) return; if (src == null) return;
if (!LevelInfo.ValidateAction(p, src, "copy this level")) return;
string dst = args[1];
if (!Formatter.ValidName(p, dst, "level")) return; if (!Formatter.ValidName(p, dst, "level")) return;
if (LevelInfo.MapExists(dst)) { Player.Message(p, "The level \"" + dst + "\" already exists."); return; } if (LevelInfo.MapExists(dst)) { Player.Message(p, "Level \"" + dst + "\" already exists."); return; }
try { try {
LevelActions.CopyLevel(src, dst); LevelActions.CopyLevel(src, dst);

View File

@ -35,26 +35,14 @@ namespace MCGalaxy.Commands.World {
if (!Formatter.ValidName(p, message, "level")) return; if (!Formatter.ValidName(p, message, "level")) return;
string map = Matcher.FindMaps(p, message); string map = Matcher.FindMaps(p, message);
if (map == null) return; if (map == null) return;
if (map.CaselessEq(ServerConfig.MainLevel)) { Player.Message(p, "Cannot delete the main level."); return; }
if (!LevelInfo.ValidateAction(p, map, "delete this level")) return;
Level lvl = LevelInfo.FindExact(map);
if (lvl != null && p != null && !lvl.BuildAccess.CheckDetailed(p)) {
Player.Message(p, "Hence you cannot delete this level."); return;
}
if (lvl == Server.mainLevel) { Player.Message(p, "Cannot delete the main level."); return; }
LevelPermission perbuild = GetPerBuildPermission(map);
if (p != null && perbuild > p.Rank) {
Player.Message(p, "%cYou can't delete levels with a perbuild rank higher than yours!"); return;
}
Player.Message(p, "Created backup."); Player.Message(p, "Created backup.");
LevelActions.Delete(map.ToLower()); LevelActions.Delete(map.ToLower());
} }
LevelPermission GetPerBuildPermission(string level) {
string value = LevelInfo.FindOfflineProperty(level, "perbuild");
return Group.ParsePermOrName(value, LevelPermission.Guest);
}
public override void Help(Player p) { public override void Help(Player p) {
Player.Message(p, "%T/DeleteLvl [map]"); Player.Message(p, "%T/DeleteLvl [map]");
Player.Message(p, "%HCompletely deletes [map] (portals, MBs, everything"); Player.Message(p, "%HCompletely deletes [map] (portals, MBs, everything");

View File

@ -30,9 +30,7 @@ namespace MCGalaxy.Commands.World {
public override void Use(Player p, string message) { public override void Use(Player p, string message) {
int totalFixed = 0; int totalFixed = 0;
Level lvl = p.level; Level lvl = p.level;
if (!lvl.BuildAccess.CheckDetailed(p)) { if (!LevelInfo.ValidateAction(p, lvl.name, "use %T/fixgrass %Son this level")) return;
Player.Message(p, "Hence you cannot use %T/fixgrass %Son this map"); return;
}
if (message.Length == 0) { if (message.Length == 0) {
FixDirtAndGrass(p, lvl, ref totalFixed); FixDirtAndGrass(p, lvl, ref totalFixed);

View File

@ -42,9 +42,12 @@ namespace MCGalaxy.Commands.World {
} else { } else {
if (!CheckExtraPerm(p, 1)) return; if (!CheckExtraPerm(p, 1)) return;
if (!Formatter.ValidName(p, message, "level")) return; if (!Formatter.ValidName(p, message, "level")) return;
if (!LevelInfo.ValidateAction(p, ServerConfig.MainLevel, "set main to another level")) return;
string map = Matcher.FindMaps(p, message); string map = Matcher.FindMaps(p, message);
if (map == null) return; if (map == null) return;
if (!LevelInfo.ValidateAction(p, map, "set main to this level")) return;
Server.SetMainLevel(map); Server.SetMainLevel(map);
SrvProperties.Save(); SrvProperties.Save();
Player.Message(p, "Set main level to {0}", Server.mainLevel.ColoredName); Player.Message(p, "Set main level to {0}", Server.mainLevel.ColoredName);

View File

@ -50,7 +50,7 @@ namespace MCGalaxy.Commands.World {
string map = Matcher.FindMaps(p, args[0]); string map = Matcher.FindMaps(p, args[0]);
if (map == null) return; if (map == null) return;
PrintMapInfo(p, GetConfig(map)); PrintMapInfo(p, LevelInfo.GetConfig(map, out lvl));
return; return;
} else { } else {
lvl = Matcher.FindLevels(p, args[0]); lvl = Matcher.FindLevels(p, args[0]);
@ -63,20 +63,11 @@ namespace MCGalaxy.Commands.World {
if (!CheckExtraPerm(p, 1)) return; if (!CheckExtraPerm(p, 1)) return;
if (opt.CaselessEq("realmowner") && !CheckExtraPerm(p, 2)) return; if (opt.CaselessEq("realmowner") && !CheckExtraPerm(p, 2)) return;
if (!LevelInfo.ValidateAction(p, lvl.name, "change map settings of this level")) return;
if (SetMapOption(p, lvl, opt, value)) return; if (SetMapOption(p, lvl, opt, value)) return;
Player.Message(p, "Could not find option entered."); Player.Message(p, "Could not find option entered.");
} }
static LevelConfig GetConfig(string map) {
Level lvl = LevelInfo.FindExact(map);
if (lvl != null) return lvl.Config;
string propsPath = LevelInfo.PropertiesPath(map);
LevelConfig cfg = new LevelConfig();
LevelConfig.Load(propsPath, cfg);
return cfg;
}
static bool IsMapOption(string[] args) { static bool IsMapOption(string[] args) {
string opt = LevelOptions.Map(args[0].ToLower()); string opt = LevelOptions.Map(args[0].ToLower());
if (!ValidOption(opt)) return false; if (!ValidOption(opt)) return false;

View File

@ -44,9 +44,11 @@ namespace MCGalaxy.Commands.World {
} }
} }
if (!LevelInfo.ValidateAction(p, lvl.name, "pause physics on this level")) return;
bool enabled = lvl.physPause; bool enabled = lvl.physPause;
lvl.PhysicsEnabled = enabled; lvl.PhysicsEnabled = enabled;
lvl.physPause = !lvl.physPause; lvl.physPause = !lvl.physPause;
if (enabled) { if (enabled) {
Chat.MessageGlobal("Physics on {0} %Swere re-enabled.", lvl.ColoredName); Chat.MessageGlobal("Physics on {0} %Swere re-enabled.", lvl.ColoredName);
} else { } else {

View File

@ -38,6 +38,8 @@ namespace MCGalaxy.Commands.World {
level = Matcher.FindLevels(p, args[0]); level = Matcher.FindLevels(p, args[0]);
if (level == null) return; if (level == null) return;
} }
if (!LevelInfo.ValidateAction(p, level.name, "set physics of this level")) return;
SetPhysics(level, state); SetPhysics(level, state);
} }

View File

@ -40,6 +40,7 @@ namespace MCGalaxy.Commands.World {
if (LevelInfo.MapExists(newName)) { Player.Message(p, "Level already exists."); return; } if (LevelInfo.MapExists(newName)) { Player.Message(p, "Level already exists."); return; }
if (lvl == Server.mainLevel) { Player.Message(p, "Cannot rename the main level."); return; } if (lvl == Server.mainLevel) { Player.Message(p, "Cannot rename the main level."); return; }
if (!LevelInfo.ValidateAction(p, lvl.name, "rename this level")) return;
List<Player> players = lvl.getPlayers(); List<Player> players = lvl.getPlayers();
lvl.Unload(); lvl.Unload();

View File

@ -42,6 +42,7 @@ namespace MCGalaxy.Commands.World {
public static bool DoResize(Player p, string[] args) { public static bool DoResize(Player p, string[] args) {
Level lvl = Matcher.FindLevels(p, args[0]); Level lvl = Matcher.FindLevels(p, args[0]);
if (lvl == null) return true; if (lvl == null) return true;
if (!LevelInfo.ValidateAction(p, lvl.name, "resize this level")) return false;
ushort x = 0, y = 0, z = 0; ushort x = 0, y = 0, z = 0;
if (!CmdNewLvl.CheckMapAxis(p, args[1], "Width", ref x)) return false; if (!CmdNewLvl.CheckMapAxis(p, args[1], "Width", ref x)) return false;

View File

@ -44,12 +44,13 @@ namespace MCGalaxy.Commands.World {
} }
} }
if (!LevelInfo.ValidateAction(p, lvl.name, "restore a backup of this level")) return;
if (File.Exists(LevelInfo.BackupPath(lvl.name, args[0]))) { if (File.Exists(LevelInfo.BackupPath(lvl.name, args[0]))) {
try { try {
DoRestore(lvl, args[0]); DoRestore(lvl, args[0]);
} catch (Exception ex) { } catch (Exception ex) {
Logger.LogError(ex); Logger.LogError(ex);
Logger.Log(LogType.Warning, "Restore failed"); Logger.Log(LogType.Warning, "Restore failed");
} }
} else { } else {
Player.Message(p, "Backup " + args[0] + " does not exist."); Player.Message(p, "Backup " + args[0] + " does not exist.");

View File

@ -26,6 +26,7 @@ namespace MCGalaxy.Commands.World {
public override void Use(Player p, string message) { public override void Use(Player p, string message) {
if (message.Length > 0) { Help(p); return; } if (message.Length > 0) { Help(p); return; }
if (!LevelInfo.ValidateAction(p, p.level.name, "set spawn of this level")) return;
Player.Message(p, "Spawn location set to your current position."); Player.Message(p, "Spawn location set to your current position.");
p.level.spawnx = (ushort)p.Pos.BlockX; p.level.spawnx = (ushort)p.Pos.BlockX;
p.level.spawny = (ushort)p.Pos.BlockY; p.level.spawny = (ushort)p.Pos.BlockY;

View File

@ -26,7 +26,7 @@ namespace MCGalaxy.Commands.Misc {
if (p.PreTeleportMap.Length == 0) { if (p.PreTeleportMap.Length == 0) {
Player.Message(p, "You have not teleported anywhere yet"); return; Player.Message(p, "You have not teleported anywhere yet"); return;
} }
if (!p.level.name.CaselessEq(p.PreTeleportMap)) if (!p.level.name.CaselessEq(p.PreTeleportMap))
PlayerActions.ChangeMap(p, p.PreTeleportMap); PlayerActions.ChangeMap(p, p.PreTeleportMap);
p.SendPos(Entities.SelfID, p.PreTeleportPos, new Orientation(0, 0)); p.SendPos(Entities.SelfID, p.PreTeleportPos, new Orientation(0, 0));

View File

@ -61,7 +61,7 @@ namespace MCGalaxy.Core {
static void LoadWaypoints(Player p) { static void LoadWaypoints(Player p) {
try { try {
p.Waypoints.Filename = "extra/Waypoints/" + p.name + ".save"; p.Waypoints.Filename = "extra/Waypoints/" + p.name + ".save";
p.Waypoints.Load(); p.Waypoints.Load();
} catch (IOException ex) { } catch (IOException ex) {
Player.Message(p, "Error loading waypoints."); Player.Message(p, "Error loading waypoints.");

View File

@ -41,7 +41,7 @@ namespace MCGalaxy.Core {
OnEcoTransactionEvent.Register(EcoHandlers.HandleEcoTransaction, Priority.Critical); OnEcoTransactionEvent.Register(EcoHandlers.HandleEcoTransaction, Priority.Critical);
OnModActionEvent.Register(ModActionHandler.HandleModAction, Priority.Critical); OnModActionEvent.Register(ModActionHandler.HandleModAction, Priority.Critical);
OnGroupLoadEvent.Register(MiscHandlers.HandleGroupLoad, Priority.Critical); OnGroupLoadEvent.Register(MiscHandlers.HandleGroupLoad, Priority.Critical);
clearTask = Server.Background.QueueRepeat(IPThrottler.CleanupTask, null, clearTask = Server.Background.QueueRepeat(IPThrottler.CleanupTask, null,
TimeSpan.FromMinutes(10)); TimeSpan.FromMinutes(10));

View File

@ -27,7 +27,7 @@ namespace MCGalaxy.DB {
/// <summary> Formats a value in a column. </summary> /// <summary> Formats a value in a column. </summary>
public delegate string TopStatFormatter(string input); public delegate string TopStatFormatter(string input);
/// <summary> Outputs ordered stats from a column in a database table. </summary> /// <summary> Outputs ordered stats from a column in a database table. </summary>
public sealed class TopStat { public sealed class TopStat {

View File

@ -21,70 +21,70 @@ using MCGalaxy.Drawing.Brushes;
using MCGalaxy.Maths; using MCGalaxy.Maths;
namespace MCGalaxy.Drawing.Ops { namespace MCGalaxy.Drawing.Ops {
public class BezierDrawOp : DrawOp { public class BezierDrawOp : DrawOp {
public override string Name { get { return "Bezier"; } } public override string Name { get { return "Bezier"; } }
public bool WallsMode; public bool WallsMode;
public int MaxLength = int.MaxValue; public int MaxLength = int.MaxValue;
public override long BlocksAffected(Level lvl, Vec3S32[] marks) { public override long BlocksAffected(Level lvl, Vec3S32[] marks) {
Vec3S32 p0 = marks[0], p2 = marks[1], p1 = marks[2]; Vec3S32 p0 = marks[0], p2 = marks[1], p1 = marks[2];
return (long)((p1 - p0).Length + (p1 - p2).Length); return (long)((p1 - p0).Length + (p1 - p2).Length);
} }
static Vec3F32 offset = new Vec3F32(0.5f); static Vec3F32 offset = new Vec3F32(0.5f);
public override void Perform(Vec3S32[] marks, Brush brush, DrawOpOutput output) { public override void Perform(Vec3S32[] marks, Brush brush, DrawOpOutput output) {
points.Add(marks[0]); points.Add(marks[0]);
// Want to rasterize bezier curve from centre of 'grid' // Want to rasterize bezier curve from centre of 'grid'
TesselateCurve(marks[0] + offset, marks[2] + offset, marks[1] + offset, 0); TesselateCurve(marks[0] + offset, marks[2] + offset, marks[1] + offset, 0);
List<Vec3S32> buffer = new List<Vec3S32>(); List<Vec3S32> buffer = new List<Vec3S32>();
for (int i = 0; i < points.Count - 1; i++) { for (int i = 0; i < points.Count - 1; i++) {
LineDrawOp.DrawLine(points[i].X, points[i].Y, points[i].Z, 1000000, LineDrawOp.DrawLine(points[i].X, points[i].Y, points[i].Z, 1000000,
points[i+1].X, points[i+1].Y, points[i+1].Z, buffer); points[i+1].X, points[i+1].Y, points[i+1].Z, buffer);
foreach (Vec3S32 P in buffer) { foreach (Vec3S32 P in buffer) {
output(Place((ushort)P.X, (ushort)P.Y, (ushort)P.Z, brush)); output(Place((ushort)P.X, (ushort)P.Y, (ushort)P.Z, brush));
} }
} }
} }
List<Vec3S32> points = new List<Vec3S32>(); List<Vec3S32> points = new List<Vec3S32>();
const float objspace_flatness_squared = 0.35f * 0.35f; const float objspace_flatness_squared = 0.35f * 0.35f;
// Based off stbtt__tesselate_curve from https://github.com/nothings/stb/blob/master/stb_truetype.h // Based off stbtt__tesselate_curve from https://github.com/nothings/stb/blob/master/stb_truetype.h
void TesselateCurve(Vec3F32 p0, Vec3F32 p1, Vec3F32 p2, int n) { void TesselateCurve(Vec3F32 p0, Vec3F32 p1, Vec3F32 p2, int n) {
// midpoint // midpoint
Vec3F32 m; Vec3F32 m;
m.X = (p0.X + 2 * p1.X + p2.X) * 0.25f; m.X = (p0.X + 2 * p1.X + p2.X) * 0.25f;
m.Y = (p0.Y + 2 * p1.Y + p2.Y) * 0.25f; m.Y = (p0.Y + 2 * p1.Y + p2.Y) * 0.25f;
m.Z = (p0.Z + 2 * p1.Z + p2.Z) * 0.25f; m.Z = (p0.Z + 2 * p1.Z + p2.Z) * 0.25f;
// versus directly drawn line // versus directly drawn line
Vec3F32 d; Vec3F32 d;
d.X = (p0.X + p2.X) * 0.5f - m.X; d.X = (p0.X + p2.X) * 0.5f - m.X;
d.Y = (p0.Y + p2.Y) * 0.5f - m.Y; d.Y = (p0.Y + p2.Y) * 0.5f - m.Y;
d.Z = (p0.Z + p2.Z) * 0.5f - m.Z; d.Z = (p0.Z + p2.Z) * 0.5f - m.Z;
if (n > 16) return; // 65536 segments on one curve better be enough! if (n > 16) return; // 65536 segments on one curve better be enough!
// half-pixel error allowed... need to be smaller if AA // half-pixel error allowed... need to be smaller if AA
if (d.X * d.X + d.Y * d.Y + d.Z * d.Z > objspace_flatness_squared) { if (d.X * d.X + d.Y * d.Y + d.Z * d.Z > objspace_flatness_squared) {
Vec3F32 p0_p1 = new Vec3F32((p0.X + p1.X) * 0.5f, (p0.Y + p1.Y) * 0.5f, (p0.Z + p1.Z) * 0.5f); Vec3F32 p0_p1 = new Vec3F32((p0.X + p1.X) * 0.5f, (p0.Y + p1.Y) * 0.5f, (p0.Z + p1.Z) * 0.5f);
TesselateCurve(p0, p0_p1, m, n + 1); TesselateCurve(p0, p0_p1, m, n + 1);
Vec3F32 p1_p2 = new Vec3F32((p1.X + p2.X) * 0.5f, (p1.Y + p2.Y) * 0.5f, (p1.Z + p2.Z) * 0.5f); Vec3F32 p1_p2 = new Vec3F32((p1.X + p2.X) * 0.5f, (p1.Y + p2.Y) * 0.5f, (p1.Z + p2.Z) * 0.5f);
TesselateCurve(m, p1_p2, p2, n + 1); TesselateCurve(m, p1_p2, p2, n + 1);
} else { } else {
// TODO: do we need to round properly here or not // TODO: do we need to round properly here or not
points.Add(new Vec3S32((int)p2.X, (int)p2.Y, (int)p2.Z)); points.Add(new Vec3S32((int)p2.X, (int)p2.Y, (int)p2.Z));
} }
} }
/*static ushort Round(float value) { /*static ushort Round(float value) {
int valueI = (int)value; int valueI = (int)value;
int floored = value < valueI ? valueI - 1 : valueI; int floored = value < valueI ? valueI - 1 : valueI;
float frac = (value % 1.0f); float frac = (value % 1.0f);
return (ushort)(floored + (frac > 0.5f ? 1 : 0)); return (ushort)(floored + (frac > 0.5f ? 1 : 0));
}*/ }*/
} }
} }

View File

@ -30,9 +30,9 @@ namespace MCGalaxy {
} }
namespace MCGalaxy.Drawing.Ops { namespace MCGalaxy.Drawing.Ops {
/// <summary> Performs on action on a block output from a draw operation. </summary> /// <summary> Performs on action on a block output from a draw operation. </summary>
public delegate void DrawOpOutput(DrawOpBlock block); public delegate void DrawOpOutput(DrawOpBlock block);
public abstract partial class DrawOp { public abstract partial class DrawOp {

View File

@ -192,7 +192,7 @@ namespace MCGalaxy.Drawing.Ops {
// Potentially buffer the block change // Potentially buffer the block change
if (op.TotalModified == reloadThreshold) { if (op.TotalModified == reloadThreshold) {
if (p == null || !p.Ignores.DrawOutput) { if (p == null || !p.Ignores.DrawOutput) {
Player.Message(p, "Changed over {0} blocks, preparing to reload map..", reloadThreshold); Player.Message(p, "Changed over {0} blocks, preparing to reload map..", reloadThreshold);
} }
lock (lvl.queueLock) lock (lvl.queueLock)

View File

@ -23,7 +23,7 @@ using MCGalaxy.Drawing.Ops;
namespace MCGalaxy.Drawing { namespace MCGalaxy.Drawing {
public delegate void PixelGetterCallback(Pixel pixel, DrawOpOutput output); public delegate void PixelGetterCallback(Pixel pixel, DrawOpOutput output);
public sealed class PixelGetter : IDisposable { public sealed class PixelGetter : IDisposable {
Bitmap bmp; Bitmap bmp;

View File

@ -70,7 +70,7 @@ namespace MCGalaxy.Eco {
if (value.IndexOf(',') != -1) { if (value.IndexOf(',') != -1) {
foreach (string award in value.Split(',')) { foreach (string award in value.Split(',')) {
pl.Awards.Add(award); pl.Awards.Add(award);
} }
} else { } else {
pl.Awards.Add(value); pl.Awards.Add(value);
} }

View File

@ -128,9 +128,9 @@ namespace MCGalaxy.Games {
} }
static void ZSLineProcessor(string key, string value) { static void ZSLineProcessor(string key, string value) {
if (!ConfigElement.Parse(Server.zombieConfig, key, value, null)) { if (!ConfigElement.Parse(Server.zombieConfig, key, value, null)) {
Logger.Log(LogType.Warning, "\"{0}\" was not a recognised zombie survival property key.", key); Logger.Log(LogType.Warning, "\"{0}\" was not a recognised zombie survival property key.", key);
} }
} }
} }
} }

View File

@ -20,7 +20,7 @@ using System.Collections.Generic;
namespace MCGalaxy.Generator { namespace MCGalaxy.Generator {
/// <summary> Holds arguments for a map generator. </summary> /// <summary> Holds arguments for a map generator. </summary>
public struct MapGenArgs { public struct MapGenArgs {
public Player Player; public Player Player;
public Level Level; public Level Level;
@ -28,9 +28,9 @@ namespace MCGalaxy.Generator {
public bool UseSeed; public bool UseSeed;
public int Seed; public int Seed;
} }
/// <summary> Represents a map generator, returning whether map generation succeeded or not. </summary> /// <summary> Represents a map generator, returning whether map generation succeeded or not. </summary>
public delegate bool MapGenerator(MapGenArgs args); public delegate bool MapGenerator(MapGenArgs args);
/// <summary> Maintains a list of map generator instances. </summary> /// <summary> Maintains a list of map generator instances. </summary>
public static class MapGen { public static class MapGen {

View File

@ -19,9 +19,9 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
namespace MCGalaxy.Generator { namespace MCGalaxy.Generator {
public delegate ushort CalcLiquidLevel(ushort lvlHeight); public delegate ushort CalcLiquidLevel(ushort lvlHeight);
public sealed class RealisticGenParams { public sealed class RealisticGenParams {
public float RangeLow = 0.2f; public float RangeLow = 0.2f;
public float RangeHigh = 0.8f; public float RangeHigh = 0.8f;

View File

@ -21,8 +21,8 @@ using System.Collections.Generic;
namespace MCGalaxy.Generator { namespace MCGalaxy.Generator {
public static class SimpleGen { public static class SimpleGen {
delegate byte NextBlock(); delegate byte NextBlock();
public static void RegisterGenerators() { public static void RegisterGenerators() {
MapGen.RegisterSimpleGen("island", GenSimple); MapGen.RegisterSimpleGen("island", GenSimple);
MapGen.RegisterSimpleGen("mountains", GenSimple); MapGen.RegisterSimpleGen("mountains", GenSimple);

View File

@ -201,7 +201,7 @@ namespace MCGalaxy {
} }
public static bool Load(string path, LevelConfig config) { public static bool Load(string path, LevelConfig config) {
return PropertiesFile.Read(path, ref config, LineProcessor); return PropertiesFile.Read(path, ref config, LineProcessor);
} }

View File

@ -88,32 +88,36 @@ namespace MCGalaxy {
public static string PropertiesPath(string name) { public static string PropertiesPath(string name) {
return "levels/level properties/" + name + ".properties"; return "levels/level properties/" + name + ".properties";
} }
public static string FindOfflineProperty(string name, string propKey) { internal static LevelConfig GetConfig(string map, out Level lvl) {
string path = PropertiesPath(name); lvl = FindExact(map);
if (!File.Exists(path)) return null; if (lvl != null) return lvl.Config;
string[] lines = null; string propsPath = PropertiesPath(map);
try { LevelConfig cfg = new LevelConfig();
lines = File.ReadAllLines(path); LevelConfig.Load(propsPath, cfg);
} catch { return cfg;
return null; }
internal static bool ValidateAction(Player p, string map, string action) {
if (p == null) return true;
LevelAccessController visit, build;
Level lvl = null;
LevelConfig cfg = GetConfig(map, out lvl);
if (lvl != null) {
visit = lvl.VisitAccess;
build = lvl.BuildAccess;
} else {
visit = new LevelAccessController(cfg, map, true);
build = new LevelAccessController(cfg, map, false);
} }
foreach (string line in lines) { if (!visit.CheckDetailed(p) || !build.CheckDetailed(p)) {
try { Player.Message(p, "Hence, you cannot {0}.", action);
if (line.Length == 0 || line[0] == '#') continue; return false;
int index = line.IndexOf(" = ");
if (index == -1) continue;
string key = line.Substring(0, index).ToLower();
if (key == propKey) return line.Substring(index + 3);
} catch (Exception e) {
Logger.LogError(e);
}
} }
return null; return true;
} }
} }
} }

View File

@ -89,7 +89,7 @@ namespace MCGalaxy {
instance.Load(startup); instance.Load(startup);
Logger.Log(LogType.SystemActivity, "Plugin: {0} loaded...build: {1}", instance.name, instance.build); Logger.Log(LogType.SystemActivity, "Plugin: {0} loaded...build: {1}", instance.name, instance.build);
} else { } else {
Logger.Log(LogType.SystemActivity, "Plugin: {0} was not loaded, you can load it with /pload", instance.name); Logger.Log(LogType.SystemActivity, "Plugin: {0} was not loaded, you can load it with /pload", instance.name);
} }
Logger.Log(LogType.SystemActivity, instance.welcome); Logger.Log(LogType.SystemActivity, instance.welcome);
} catch (Exception e) { } catch (Exception e) {

View File

@ -50,8 +50,8 @@ namespace MCGalaxy.Scripting {
compiler = CodeDomProvider.CreateProvider(ProviderName); compiler = CodeDomProvider.CreateProvider(ProviderName);
if (compiler == null) { if (compiler == null) {
Logger.Log(LogType.Warning, Logger.Log(LogType.Warning,
"WARNING: Provider {0} is missing, you will be unable to compile {1} commands.", "WARNING: Provider {0} is missing, you will be unable to compile {1} commands.",
ProviderName, Ext); ProviderName, Ext);
// TODO: Should we log "You must have .net developer tools. (You need a visual studio)" ? // TODO: Should we log "You must have .net developer tools. (You need a visual studio)" ?
} }
} }

View File

@ -91,7 +91,7 @@ namespace MCGalaxy {
} }
static void SetupSocket(SchedulerTask task) { static void SetupSocket(SchedulerTask task) {
Logger.Log(LogType.SystemActivity, "Creating listening socket on port {0}... ", ServerConfig.Port); Logger.Log(LogType.SystemActivity, "Creating listening socket on port {0}... ", ServerConfig.Port);
Listener = new TcpListen(); Listener = new TcpListen();
IPAddress ip; IPAddress ip;

View File

@ -56,7 +56,7 @@ namespace MCGalaxy.Gui {
} }
} catch (Exception ex) { } catch (Exception ex) {
Logger.LogError(ex); Logger.LogError(ex);
} }
try { try {
string level = null; string level = null;