mirror of
https://github.com/ClassiCube/MCGalaxy.git
synced 2025-09-25 06:04:46 -04:00
Core: Block properties now save.
This commit is contained in:
parent
d043a3d8ed
commit
b86944f59d
@ -51,6 +51,7 @@ namespace MCGalaxy
|
||||
BlockBehaviour.SetupCoreHandlers();
|
||||
BlockBehaviour.SetupCorePhysicsHandlers();
|
||||
InitDefaults();
|
||||
BlockProps.Load("core", Block.Props);
|
||||
|
||||
// Custom permissions set by the user.
|
||||
if (File.Exists("properties/block.properties")) {
|
||||
|
@ -21,7 +21,7 @@ using System.Text;
|
||||
using MCGalaxy.Blocks;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace MCGalaxy {
|
||||
namespace MCGalaxy {
|
||||
public sealed class BlockDefinition {
|
||||
|
||||
public byte BlockID;
|
||||
@ -45,7 +45,7 @@ namespace MCGalaxy {
|
||||
|
||||
public const string GlobalPath = "blockdefs/global.json", GlobalBackupPath = "blockdefs/global.json.bak";
|
||||
|
||||
public static BlockDefinition[] GlobalDefs;
|
||||
public static BlockDefinition[] GlobalDefs;
|
||||
public static Blocks.BlockProps[] GlobalProps;
|
||||
|
||||
public BlockDefinition Copy() {
|
||||
@ -71,7 +71,7 @@ namespace MCGalaxy {
|
||||
GlobalDefs = Load(true, null);
|
||||
GlobalDefs[0] = new BlockDefinition();
|
||||
GlobalDefs[0].Name = "Air fallback";
|
||||
|
||||
|
||||
GlobalProps = new BlockProps[256];
|
||||
for (int i = 0; i < GlobalProps.Length; i++)
|
||||
GlobalProps[i] = new BlockProps((byte)i);
|
||||
@ -84,7 +84,9 @@ namespace MCGalaxy {
|
||||
} catch (Exception ex) {
|
||||
Server.ErrorLog(ex);
|
||||
}
|
||||
|
||||
Save(true, null);
|
||||
BlockProps.Load("global", BlockDefinition.GlobalProps);
|
||||
}
|
||||
|
||||
internal static BlockDefinition[] Load(bool global, Level lvl) {
|
||||
@ -100,7 +102,7 @@ namespace MCGalaxy {
|
||||
defs = new BlockDefinition[256];
|
||||
}
|
||||
|
||||
for (int i = 0; i < 256; i++) {
|
||||
for (int i = 0; i < 256; i++) {
|
||||
if (defs[i] != null && defs[i].Name == null)
|
||||
defs[i] = null;
|
||||
}
|
||||
@ -127,7 +129,7 @@ namespace MCGalaxy {
|
||||
realDefs[i] = defs[i] == GlobalDefs[i] ? null : defs[i];
|
||||
defs = realDefs;
|
||||
}
|
||||
|
||||
|
||||
string json = JsonConvert.SerializeObject(defs);
|
||||
string path = global ? GlobalPath : "blockdefs/lvl_" + lvl.name + ".json";
|
||||
File.WriteAllText(path, json);
|
||||
@ -135,13 +137,12 @@ namespace MCGalaxy {
|
||||
|
||||
public static void Add(BlockDefinition def, BlockDefinition[] defs, Level level) {
|
||||
byte id = def.BlockID;
|
||||
bool global = defs == GlobalDefs;
|
||||
bool global = defs == GlobalDefs;
|
||||
if (global) {
|
||||
Level[] loaded = LevelInfo.Loaded.Items;
|
||||
foreach (Level lvl in loaded) {
|
||||
if (lvl.CustomBlockDefs[id] == null) {
|
||||
lvl.CustomBlockDefs[id] = def;
|
||||
lvl.CustomBlockProps[id] = GlobalProps[id];
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -174,7 +175,6 @@ namespace MCGalaxy {
|
||||
foreach (Level lvl in loaded) {
|
||||
if (lvl.CustomBlockDefs[id] == GlobalDefs[id]) {
|
||||
lvl.CustomBlockDefs[id] = null;
|
||||
lvl.CustomBlockProps[id] = new BlockProps(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -216,7 +216,7 @@ namespace MCGalaxy {
|
||||
public static byte GetBlock(string msg, BlockDefinition[] defs) {
|
||||
for (int i = 1; i < Block.Invalid; i++) {
|
||||
BlockDefinition def = defs[i];
|
||||
if (def == null) continue;
|
||||
if (def == null) continue;
|
||||
if (def.Name.Replace(" ", "").CaselessEq(msg))
|
||||
return def.BlockID;
|
||||
}
|
||||
@ -259,7 +259,7 @@ namespace MCGalaxy {
|
||||
byte rawSpeed = (byte)(64 * Math.Log(def.Speed, 2) + 128);
|
||||
buffer[index++] = def.BlockID;
|
||||
NetUtils.WriteAscii(def.Name, buffer, index);
|
||||
index += 64;
|
||||
index += 64;
|
||||
buffer[index++] = def.CollideType;
|
||||
buffer[index++] = rawSpeed;
|
||||
|
||||
|
@ -17,6 +17,7 @@
|
||||
*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace MCGalaxy.Blocks {
|
||||
|
||||
@ -59,6 +60,9 @@ namespace MCGalaxy.Blocks {
|
||||
/// <summary> Whether this block should allow trains to go over them. </summary>
|
||||
public bool IsRails;
|
||||
|
||||
/// <summary> Whether the properties for this block have been modified and hence require saving. </summary>
|
||||
public bool Changed;
|
||||
|
||||
public BlockProps(byte block) {
|
||||
this = default(BlockProps);
|
||||
BlockId = block;
|
||||
@ -66,5 +70,62 @@ namespace MCGalaxy.Blocks {
|
||||
Name = "unknown";
|
||||
ODoorId = Block.Invalid;
|
||||
}
|
||||
|
||||
|
||||
public static void Save(string group, BlockProps[] scope) {
|
||||
if (!Directory.Exists("blockprops"))
|
||||
Directory.CreateDirectory("blockprops");
|
||||
|
||||
using (StreamWriter w = new StreamWriter("blockprops/" + group + ".txt")) {
|
||||
w.WriteLine("# This represents the physics properties for blocks, in the format of:");
|
||||
w.WriteLine("# id : Is rails : Is tdoor : Is door : Is message block : Is portal : " +
|
||||
"Killed by water : Killed by lava : Kills players : death message");
|
||||
for (int i = 0; i < scope.Length; i++) {
|
||||
if (!scope[i].Changed) continue;
|
||||
BlockProps props = scope[i];
|
||||
|
||||
string deathMsg = props.DeathMessage == null ? "" : props.DeathMessage.Replace(":", "\\;");
|
||||
w.WriteLine(i + ":" + props.IsRails + ":" + props.IsTDoor + ":" + props.IsDoor + ":"
|
||||
+ props.IsMessageBlock + ":" + props.IsPortal + ":" + props.WaterKills + ":"
|
||||
+ props.LavaKills + ":" + props.KillerBlock + ":" + deathMsg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void Load(string group, BlockProps[] scope) {
|
||||
if (!Directory.Exists("blockprops")) return;
|
||||
if (!File.Exists("blockprops/" + group + ".txt")) return;
|
||||
|
||||
string[] lines = File.ReadAllLines("blockprops/" + group + ".txt");
|
||||
for (int i = 0; i < lines.Length; i++) {
|
||||
string line = lines[i].Trim();
|
||||
if (line.Length == 0 || line[0] == '#') continue;
|
||||
|
||||
string[] parts = line.Split(':');
|
||||
if (parts.Length != 10) {
|
||||
Server.s.Log("Invalid line \"" + line + "\" in " + group + " block properties");
|
||||
continue;
|
||||
}
|
||||
byte id;
|
||||
if (!Byte.TryParse(parts[0], out id)) {
|
||||
Server.s.Log("Invalid line \"" + line + "\" in " + group + " block properties");
|
||||
continue;
|
||||
}
|
||||
|
||||
bool.TryParse(parts[1], out scope[id].IsRails);
|
||||
bool.TryParse(parts[2], out scope[id].IsTDoor);
|
||||
bool.TryParse(parts[3], out scope[id].IsDoor);
|
||||
bool.TryParse(parts[4], out scope[id].IsMessageBlock);
|
||||
bool.TryParse(parts[5], out scope[id].IsPortal);
|
||||
bool.TryParse(parts[6], out scope[id].WaterKills);
|
||||
bool.TryParse(parts[7], out scope[id].LavaKills);
|
||||
bool.TryParse(parts[8], out scope[id].KillerBlock);
|
||||
|
||||
scope[id].Changed = true;
|
||||
scope[id].DeathMessage = parts[9].Replace("\\;", ":");
|
||||
if (scope[id].DeathMessage == "")
|
||||
scope[id].DeathMessage = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -17,6 +17,7 @@
|
||||
*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using MCGalaxy.Blocks;
|
||||
using MCGalaxy.Commands.Building;
|
||||
|
||||
namespace MCGalaxy.Commands.CPE {
|
||||
@ -115,6 +116,7 @@ namespace MCGalaxy.Commands.CPE {
|
||||
|
||||
dst = src.Copy();
|
||||
dst.BlockID = (byte)dstId;
|
||||
AddBlockProperties(global, (byte)dstId, p);
|
||||
BlockDefinition.Add(dst, defs, p == null ? null : p.level);
|
||||
|
||||
bool globalBlock = defs[srcId] == BlockDefinition.GlobalDefs[srcId];
|
||||
@ -141,18 +143,20 @@ namespace MCGalaxy.Commands.CPE {
|
||||
Player.Message(p, " Fallback ID: " + def.FallBack + ", Sound: " +
|
||||
def.WalkSound + ", Speed: " + def.Speed.ToString("F2"));
|
||||
|
||||
if (def.FogDensity == 0)
|
||||
if (def.FogDensity == 0) {
|
||||
Player.Message(p, " Block does not use fog");
|
||||
else
|
||||
} else {
|
||||
Player.Message(p, " Fog density: " + def.FogDensity + ", R: " +
|
||||
def.FogR + ", G: " + def.FogG + ", B: " + def.FogB);
|
||||
}
|
||||
|
||||
if (def.Shape == 0)
|
||||
if (def.Shape == 0) {
|
||||
Player.Message(p, " Block is a sprite");
|
||||
else
|
||||
} else {
|
||||
Player.Message(p, " Block is a cube from (" +
|
||||
def.MinX + "," + def.MinY + "," + def.MinZ + ") to ("
|
||||
+ def.MaxX + "," + def.MaxY + "," + def.MaxZ + ")");
|
||||
}
|
||||
}
|
||||
|
||||
static void ListHandler(Player p, string[] parts, bool global, string cmd) {
|
||||
@ -175,18 +179,19 @@ namespace MCGalaxy.Commands.CPE {
|
||||
|
||||
static void RemoveHandler(Player p, string[] parts, bool global, string cmd) {
|
||||
if (parts.Length <= 1) { Help(p, cmd); return; }
|
||||
int blockId;
|
||||
if (!CheckBlockId(p, parts[1], global, out blockId)) return;
|
||||
int id;
|
||||
if (!CheckBlockId(p, parts[1], global, out id)) return;
|
||||
|
||||
BlockDefinition[] defs = global ? BlockDefinition.GlobalDefs : p.level.CustomBlockDefs;
|
||||
BlockDefinition def = defs[blockId];
|
||||
if (!ExistsInScope(def, blockId, global)) { MessageNoBlock(p, blockId, global, cmd); return; }
|
||||
BlockDefinition def = defs[id];
|
||||
if (!ExistsInScope(def, id, global)) { MessageNoBlock(p, id, global, cmd); return; }
|
||||
|
||||
RemoveBlockProperties(global, (byte)id, p);
|
||||
BlockDefinition.Remove(def, defs, p == null ? null : p.level);
|
||||
BlockDefinition globalDef = BlockDefinition.GlobalDefs[blockId];
|
||||
if (!global && globalDef != null) {
|
||||
BlockDefinition.Add(globalDef, defs, p == null ? null : p.level);
|
||||
}
|
||||
|
||||
BlockDefinition globalDef = BlockDefinition.GlobalDefs[id];
|
||||
if (!global && globalDef != null)
|
||||
BlockDefinition.Add(globalDef, defs, p.level);
|
||||
}
|
||||
|
||||
static void DefineBlockStep(Player p, string value, bool global, string cmd) {
|
||||
@ -436,6 +441,7 @@ namespace MCGalaxy.Commands.CPE {
|
||||
|
||||
string scope = global ? "global" : "level";
|
||||
Player.Message(p, "Created a new " + scope + " custom block " + bd.Name + "(" + bd.BlockID + ")");
|
||||
AddBlockProperties(global, bd.BlockID, p);
|
||||
BlockDefinition.Add(bd, defs, p == null ? null : p.level);
|
||||
return true;
|
||||
}
|
||||
@ -544,6 +550,41 @@ namespace MCGalaxy.Commands.CPE {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static void AddBlockProperties(bool global, byte id, Player p) {
|
||||
if (!global) {
|
||||
p.level.CustomBlockProps[id] = new BlockProps((byte)id);
|
||||
} else {
|
||||
BlockDefinition.GlobalProps[id] = new BlockProps((byte)id);
|
||||
Level[] loaded = LevelInfo.Loaded.Items;
|
||||
|
||||
foreach (Level lvl in loaded) {
|
||||
if (lvl.CustomBlockDefs[id] != null) continue;
|
||||
lvl.CustomBlockProps[id] = new BlockProps((byte)id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void RemoveBlockProperties(bool global, byte id, Player p) {
|
||||
BlockDefinition globalDef = BlockDefinition.GlobalDefs[id];
|
||||
|
||||
// Level block reverts to using global block
|
||||
if (!global && BlockDefinition.GlobalDefs[id] != null) {
|
||||
p.level.CustomBlockProps[id] = BlockDefinition.GlobalProps[id];
|
||||
} else if (!global) {
|
||||
p.level.CustomBlockProps[id] = new BlockProps((byte)id);
|
||||
} else {
|
||||
BlockDefinition.GlobalProps[id] = new BlockProps((byte)id);
|
||||
Level[] loaded = LevelInfo.Loaded.Items;
|
||||
|
||||
foreach (Level lvl in loaded) {
|
||||
if (lvl.CustomBlockDefs[id] != BlockDefinition.GlobalDefs[id]) continue;
|
||||
lvl.CustomBlockProps[id] = new BlockProps((byte)id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static BlockDefinition consoleBD;
|
||||
static int consoleStep, consoleTargetId;
|
||||
|
||||
|
@ -37,16 +37,21 @@ namespace MCGalaxy.Commands.World {
|
||||
byte id = GetBlock(p, scope, args[1]);
|
||||
if (id == Block.Invalid) return;
|
||||
string prop = args[2].ToLower();
|
||||
|
||||
// TODO: global and level custom blocks
|
||||
// TODO: adding core blocks, changing core block names
|
||||
SetProperty(p, scope, id, prop, args);
|
||||
}
|
||||
|
||||
BlockProps[] GetScope(Player p, string scope) {
|
||||
if (scope.CaselessEq("core")) return Block.Props;
|
||||
if (scope.CaselessEq("global")) return BlockDefinition.GlobalProps;
|
||||
if (scope.CaselessEq("level")) return p.level.CustomBlockProps;
|
||||
|
||||
if (scope.CaselessEq("level")) {
|
||||
if (Player.IsSuper(p)) {
|
||||
string src = p == null ? "console" : "IRC";
|
||||
Player.Message(p, "Cannot use level scope from {0}.", src);
|
||||
return null;
|
||||
}
|
||||
return p.level.CustomBlockProps;
|
||||
}
|
||||
|
||||
Player.Message(p, "&cScope must \"core\", \"global\", or \"level\"");
|
||||
return null;
|
||||
@ -126,44 +131,55 @@ namespace MCGalaxy.Commands.World {
|
||||
BlockProps props = scope[id];
|
||||
setter(ref props);
|
||||
scope[id] = props;
|
||||
OnPropsChanged(scope, id);
|
||||
Level lvl = Player.IsSuper(p) ? null : p.level;
|
||||
|
||||
Player.Message(p, "Block {0} is {1}: {2}",
|
||||
BlockName(scope, p.level, id),
|
||||
BlockName(scope, lvl, id),
|
||||
type, getter(props) ? "&aYes" : "&cNo");
|
||||
OnPropsChanged(scope, lvl, id);
|
||||
}
|
||||
|
||||
static void SetDeathMessage(Player p, BlockProps[] scope, byte id, string msg) {
|
||||
scope[id].DeathMessage = msg;
|
||||
Level lvl = Player.IsSuper(p) ? null : p.level;
|
||||
|
||||
if (msg == null) {
|
||||
Player.Message(p, "Death message for {0} removed.",
|
||||
BlockName(scope, p.level, id));
|
||||
BlockName(scope, lvl, id));
|
||||
} else {
|
||||
Player.Message(p, "Death message for {0} set to: {1}",
|
||||
BlockName(scope, p.level, id), msg);
|
||||
BlockName(scope, lvl, id), msg);
|
||||
}
|
||||
OnPropsChanged(scope, id);
|
||||
OnPropsChanged(scope, lvl, id);
|
||||
}
|
||||
|
||||
static void OnPropsChanged(BlockProps[] scope, byte id) {
|
||||
static void OnPropsChanged(BlockProps[] scope, Level level, byte id) {
|
||||
scope[id].Changed = true;
|
||||
|
||||
if (scope == Block.Props) {
|
||||
BlockBehaviour.SetupCoreHandlers();
|
||||
BlockProps.Save("core", scope);
|
||||
} else if (scope == BlockDefinition.GlobalProps) {
|
||||
Level[] loaded = LevelInfo.Loaded.Items;
|
||||
|
||||
foreach (Level lvl in loaded) {
|
||||
if (lvl.CustomBlockDefs[id] != BlockDefinition.GlobalDefs[id]) continue;
|
||||
lvl.CustomBlockProps[id] = BlockDefinition.GlobalProps[id];
|
||||
}
|
||||
BlockProps.Save("global", scope);
|
||||
} else {
|
||||
BlockProps.Save("lvl_" + level.name, scope);
|
||||
}
|
||||
}
|
||||
|
||||
static string BlockName(BlockProps[] scope, Level lvl, byte id) {
|
||||
byte block = id, extBlock = 0;
|
||||
if (scope != Block.Props) {
|
||||
block = Block.custom_block; extBlock = id;
|
||||
}
|
||||
return lvl.BlockName(block, extBlock);
|
||||
static string BlockName(BlockProps[] scope, Level lvl, byte raw) {
|
||||
if (scope == Block.Props) return Block.Name(raw);
|
||||
BlockDefinition def = null;
|
||||
|
||||
if (scope == BlockDefinition.GlobalProps)
|
||||
def = BlockDefinition.GlobalDefs[raw];
|
||||
else
|
||||
def = lvl.CustomBlockDefs[raw];
|
||||
return def == null ? raw.ToString() : def.Name.Replace(" ", "");
|
||||
}
|
||||
|
||||
public override void Help(Player p) {
|
||||
|
@ -379,7 +379,9 @@ namespace MCGalaxy {
|
||||
for (int i = 0; i < defs.Length; i++) {
|
||||
if (defs[i] == null) continue;
|
||||
level.CustomBlockDefs[i] = defs[i];
|
||||
level.CustomBlockProps[i] = new BlockProps((byte)i);
|
||||
}
|
||||
BlockProps.Load("lvl_" + level.name, level.CustomBlockProps);
|
||||
Bots.BotsFile.LoadBots(level);
|
||||
|
||||
object locker = ThreadSafeCache.DBCache.Get(name);
|
||||
|
@ -225,7 +225,7 @@ namespace MCGalaxy {
|
||||
cmd = cmd.Replace(" unsigned", " UNSIGNED");
|
||||
if (!Server.useMySQL) return;
|
||||
|
||||
// MySQL does not support the format used by the old SQLite backend for the primary key
|
||||
// MySQL does not support the format used by the SQLite backend for the primary key
|
||||
const string priKey = " PRIMARY KEY AUTOINCREMENT";
|
||||
int priIndex = cmd.ToUpper().IndexOf(priKey);
|
||||
if (priIndex == -1) return;
|
||||
|
@ -19,6 +19,7 @@ using System;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using MCGalaxy.Blocks;
|
||||
using MCGalaxy.Games;
|
||||
using MCGalaxy.Tasks;
|
||||
using Newtonsoft.Json;
|
||||
@ -209,6 +210,7 @@ namespace MCGalaxy {
|
||||
Alias.Load();
|
||||
Bots.BotsFile.Load();
|
||||
BlockDefinition.LoadGlobal();
|
||||
|
||||
SrvProperties.Load("properties/server.properties");
|
||||
Updater.Load("properties/update.properties");
|
||||
Group.InitAll();
|
||||
|
Loading…
x
Reference in New Issue
Block a user