mirror of
https://github.com/ClassiCube/MCGalaxy.git
synced 2025-09-08 14:48:47 -04:00
Completely separate blockprops from blocks list.
This means you can change blockprops of any block on a per-level basis, no longer only works on /lb. This also means the GUI can change block props of global blocks
This commit is contained in:
parent
c129acb0a4
commit
d357a75a66
@ -20,42 +20,56 @@ using System.Collections.Generic;
|
||||
using System.Windows.Forms;
|
||||
using MCGalaxy.Blocks;
|
||||
using BlockID = System.UInt16;
|
||||
using BlockRaw = System.Byte;
|
||||
|
||||
namespace MCGalaxy.Gui {
|
||||
public partial class PropertyWindow : Form {
|
||||
|
||||
bool blockSupressEvents = true;
|
||||
ComboBox[] blockAllowBoxes, blockDisallowBoxes;
|
||||
byte blockID;
|
||||
BlockID curBlock;
|
||||
List<BlockID> blockIDMap;
|
||||
|
||||
// need to keep a list of changed block perms, because we don't want
|
||||
// to modify the server's live permissions if user clicks 'discard'
|
||||
BlockPerms blockPermsOrig, blockPerms;
|
||||
List<BlockPerms> blockPermsChanged = new List<BlockPerms>();
|
||||
BlockProps[] blockPropsChanged = new BlockProps[Block.Props.Length];
|
||||
BlockProps[] blockPropsChanged = new BlockProps[Block.Props.Length];
|
||||
|
||||
void LoadBlocks() {
|
||||
blk_list.Items.Clear();
|
||||
blockPermsChanged.Clear();
|
||||
for (int i = 0; i < Block.Props.Length; i++) {
|
||||
blockPropsChanged[i] = Block.Props[i];
|
||||
blockPropsChanged[i].Changed = false;
|
||||
if (Block.Undefined((BlockID)i)) continue;
|
||||
|
||||
string name = Block.GetName(null, (byte)i);
|
||||
blockIDMap = new List<BlockID>();
|
||||
|
||||
for (int b = 0; b < blockPropsChanged.Length; b++) {
|
||||
blockPropsChanged[b] = Block.Props[b];
|
||||
blockPropsChanged[b].ChangedScope = 0;
|
||||
|
||||
BlockID block = (BlockID)b;
|
||||
if (!BlockExists(block)) continue;
|
||||
|
||||
string name = Block.GetName(null, block);
|
||||
blk_list.Items.Add(name);
|
||||
blockIDMap.Add(block);
|
||||
}
|
||||
|
||||
if (blk_list.SelectedIndex == -1)
|
||||
if (blk_list.SelectedIndex == -1) {
|
||||
blk_list.SelectedIndex = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool BlockExists(BlockID b) {
|
||||
if (b < Block.Count) return !Block.Undefined(b);
|
||||
BlockRaw raw = (BlockRaw)b;
|
||||
return BlockDefinition.GlobalDefs[raw] != null;
|
||||
}
|
||||
|
||||
void SaveBlocks() {
|
||||
void SaveBlocks() {
|
||||
if (!BlocksChanged()) { LoadBlocks(); return; }
|
||||
|
||||
for (int i = 0; i < blockPropsChanged.Length; i++) {
|
||||
if (!blockPropsChanged[i].Changed) continue;
|
||||
Block.Props[i] = blockPropsChanged[i];
|
||||
for (int b = 0; b < blockPropsChanged.Length; b++) {
|
||||
if (blockPropsChanged[b].ChangedScope == 0) continue;
|
||||
Block.Props[b] = blockPropsChanged[b];
|
||||
}
|
||||
|
||||
foreach (BlockPerms perms in blockPermsChanged) {
|
||||
@ -63,28 +77,28 @@ namespace MCGalaxy.Gui {
|
||||
}
|
||||
BlockPerms.ResendAllBlockPermissions();
|
||||
|
||||
BlockProps.Save("core", Block.Props, Block.CorePropsLock, null);
|
||||
BlockProps.Save("default", Block.Props, Block.PropsLock, 1);
|
||||
BlockPerms.Save();
|
||||
Block.SetBlocks();
|
||||
LoadBlocks();
|
||||
}
|
||||
|
||||
bool BlocksChanged() {
|
||||
for (int i = 0; i < blockPropsChanged.Length; i++) {
|
||||
if (blockPropsChanged[i].Changed) return true;
|
||||
for (int b = 0; b < blockPropsChanged.Length; b++) {
|
||||
if (blockPropsChanged[b].ChangedScope != 0) return true;
|
||||
}
|
||||
return blockPermsChanged.Count > 0;
|
||||
}
|
||||
|
||||
|
||||
void blk_list_SelectedIndexChanged(object sender, EventArgs e) {
|
||||
blockID = Block.Byte(blk_list.SelectedItem.ToString());
|
||||
blockPermsOrig = BlockPerms.List[blockID];
|
||||
blockPerms = blockPermsChanged.Find(p => p.ID == blockID);
|
||||
curBlock = blockIDMap[blk_list.SelectedIndex];
|
||||
blockPermsOrig = BlockPerms.List[curBlock];
|
||||
blockPerms = blockPermsChanged.Find(p => p.ID == curBlock);
|
||||
BlockInitSpecificArrays();
|
||||
blockSupressEvents = true;
|
||||
|
||||
BlockProps props = blockPropsChanged[blockID];
|
||||
BlockProps props = blockPropsChanged[curBlock];
|
||||
blk_cbMsgBlock.Checked = props.IsMessageBlock;
|
||||
blk_cbPortal.Checked = props.IsPortal;
|
||||
blk_cbDeath.Checked = props.KillerBlock;
|
||||
@ -96,7 +110,7 @@ namespace MCGalaxy.Gui {
|
||||
blk_cbRails.Checked = props.IsRails;
|
||||
blk_cbLava.Checked = props.LavaKills;
|
||||
blk_cbWater.Checked = props.WaterKills;
|
||||
|
||||
|
||||
BlockPerms perms = blockPerms != null ? blockPerms : blockPermsOrig;
|
||||
GuiPerms.SetDefaultIndex(blk_cmbMin, perms.MinRank);
|
||||
GuiPerms.SetSpecificPerms(perms.Allowed, blockAllowBoxes);
|
||||
@ -161,49 +175,55 @@ namespace MCGalaxy.Gui {
|
||||
|
||||
|
||||
void blk_cbMsgBlock_CheckedChanged(object sender, EventArgs e) {
|
||||
blockPropsChanged[blockID].IsMessageBlock = blk_cbMsgBlock.Checked;
|
||||
blockPropsChanged[blockID].Changed = !blockSupressEvents;
|
||||
blockPropsChanged[curBlock].IsMessageBlock = blk_cbMsgBlock.Checked;
|
||||
MarkBlockPropsChanged();
|
||||
}
|
||||
|
||||
void blk_cbPortal_CheckedChanged(object sender, EventArgs e) {
|
||||
blockPropsChanged[blockID].IsPortal = blk_cbPortal.Checked;
|
||||
blockPropsChanged[blockID].Changed = !blockSupressEvents;
|
||||
blockPropsChanged[curBlock].IsPortal = blk_cbPortal.Checked;
|
||||
MarkBlockPropsChanged();
|
||||
}
|
||||
|
||||
void blk_cbDeath_CheckedChanged(object sender, EventArgs e) {
|
||||
blockPropsChanged[blockID].KillerBlock = blk_cbDeath.Checked;
|
||||
blockPropsChanged[curBlock].KillerBlock = blk_cbDeath.Checked;
|
||||
blk_txtDeath.Enabled = blk_cbDeath.Checked;
|
||||
blockPropsChanged[blockID].Changed = !blockSupressEvents;
|
||||
MarkBlockPropsChanged();
|
||||
}
|
||||
|
||||
void blk_txtDeath_TextChanged(object sender, EventArgs e) {
|
||||
blockPropsChanged[blockID].DeathMessage = blk_txtDeath.Text;
|
||||
blockPropsChanged[blockID].Changed = !blockSupressEvents;
|
||||
blockPropsChanged[curBlock].DeathMessage = blk_txtDeath.Text;
|
||||
MarkBlockPropsChanged();
|
||||
}
|
||||
|
||||
void blk_cbDoor_CheckedChanged(object sender, EventArgs e) {
|
||||
blockPropsChanged[blockID].IsDoor = blk_cbDoor.Checked;
|
||||
blockPropsChanged[blockID].Changed = !blockSupressEvents;
|
||||
blockPropsChanged[curBlock].IsDoor = blk_cbDoor.Checked;
|
||||
MarkBlockPropsChanged();
|
||||
}
|
||||
|
||||
void blk_cbTdoor_CheckedChanged(object sender, EventArgs e) {
|
||||
blockPropsChanged[blockID].IsTDoor = blk_cbTdoor.Checked;
|
||||
blockPropsChanged[blockID].Changed = !blockSupressEvents;
|
||||
blockPropsChanged[curBlock].IsTDoor = blk_cbTdoor.Checked;
|
||||
MarkBlockPropsChanged();
|
||||
}
|
||||
|
||||
void blk_cbRails_CheckedChanged(object sender, EventArgs e) {
|
||||
blockPropsChanged[blockID].IsRails = blk_cbRails.Checked;
|
||||
blockPropsChanged[blockID].Changed = !blockSupressEvents;
|
||||
blockPropsChanged[curBlock].IsRails = blk_cbRails.Checked;
|
||||
MarkBlockPropsChanged();
|
||||
}
|
||||
|
||||
void blk_cbLava_CheckedChanged(object sender, EventArgs e) {
|
||||
blockPropsChanged[blockID].LavaKills = blk_cbLava.Checked;
|
||||
blockPropsChanged[blockID].Changed = !blockSupressEvents;
|
||||
blockPropsChanged[curBlock].LavaKills = blk_cbLava.Checked;
|
||||
MarkBlockPropsChanged();
|
||||
}
|
||||
|
||||
void blk_cbWater_CheckedChanged(object sender, EventArgs e) {
|
||||
blockPropsChanged[blockID].WaterKills = blk_cbWater.Checked;
|
||||
blockPropsChanged[blockID].Changed = !blockSupressEvents;
|
||||
blockPropsChanged[curBlock].WaterKills = blk_cbWater.Checked;
|
||||
MarkBlockPropsChanged();
|
||||
}
|
||||
|
||||
void MarkBlockPropsChanged() {
|
||||
// don't mark props as changed when supressing events
|
||||
int changed = blockSupressEvents ? 0 : 1;
|
||||
blockPropsChanged[curBlock].ChangedScope = (byte)changed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -18,104 +18,118 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using MCGalaxy.Blocks;
|
||||
using BlockID = System.UInt16;
|
||||
|
||||
namespace MCGalaxy {
|
||||
|
||||
public sealed partial class Block {
|
||||
|
||||
public static BlockProps[] Props = new BlockProps[Block.Count];
|
||||
public static readonly object CorePropsLock = new object();
|
||||
public static BlockProps[] Props = new BlockProps[Block.ExtendedCount];
|
||||
public static readonly object PropsLock = new object();
|
||||
public static Dictionary<string, byte> Aliases = new Dictionary<string, byte>();
|
||||
|
||||
static void SetCoreProperties() {
|
||||
for (int i = 0; i < Block.Count; i++)
|
||||
Props[i] = BlockProps.MakeDefault();
|
||||
for (int i = 0; i < Block.Count; i++) {
|
||||
if ((i >= Op_Glass && i <= Op_Lava) || i == Invalid || i == RocketStart || i == Bedrock) {
|
||||
Props[i].OPBlock = true;
|
||||
internal static void ChangeGlobalProps(BlockID block, BlockProps props) {
|
||||
Level[] loaded = LevelInfo.Loaded.Items;
|
||||
Block.Props[block] = props;
|
||||
|
||||
foreach (Level lvl in loaded) {
|
||||
if (lvl.HasCustomProps(block)) continue;
|
||||
lvl.Props[block] = props;
|
||||
lvl.UpdateBlockHandler(block);
|
||||
}
|
||||
}
|
||||
|
||||
internal static void MakeDefaultProps(BlockProps[] props) {
|
||||
for (int b = 0; b < props.Length; b++) {
|
||||
props[b] = BlockProps.MakeDefault();
|
||||
if ((b >= Op_Glass && b <= Op_Lava) || b == Invalid || b == RocketStart || b == Bedrock) {
|
||||
props[b].OPBlock = true;
|
||||
}
|
||||
|
||||
if ((i >= tDoor_Log && i <= tDoor_Green) || (i >= tDoor_TNT && i <= tDoor_Lava)) {
|
||||
Props[i].IsTDoor = true;
|
||||
if ((b >= tDoor_Log && b <= tDoor_Green) || (b >= tDoor_TNT && b <= tDoor_Lava)) {
|
||||
props[b].IsTDoor = true;
|
||||
}
|
||||
if (i >= MB_White && i <= MB_Lava) {
|
||||
Props[i].IsMessageBlock = true;
|
||||
if (b >= MB_White && b <= MB_Lava) {
|
||||
props[b].IsMessageBlock = true;
|
||||
}
|
||||
if (i == Portal_Blue || i == Portal_Orange || (i >= Portal_Air && i <= Portal_Lava)) {
|
||||
Props[i].IsPortal = true;
|
||||
if (b == Portal_Blue || b == Portal_Orange || (b >= Portal_Air && b <= Portal_Lava)) {
|
||||
props[b].IsPortal = true;
|
||||
}
|
||||
|
||||
// oDoor blocks
|
||||
if (i >= oDoor_Log && i <= oDoor_Wood) {
|
||||
Props[i].oDoorBlock = (ushort)(oDoor_Log_air + (i - oDoor_Log));
|
||||
if (b >= oDoor_Log && b <= oDoor_Wood) {
|
||||
props[b].oDoorBlock = (ushort)(oDoor_Log_air + (b - oDoor_Log));
|
||||
}
|
||||
if (i >= oDoor_Green && i <= oDoor_Water) {
|
||||
Props[i].oDoorBlock = (ushort)(oDoor_Green_air + (i - oDoor_Green));
|
||||
if (b >= oDoor_Green && b <= oDoor_Water) {
|
||||
props[b].oDoorBlock = (ushort)(oDoor_Green_air + (b - oDoor_Green));
|
||||
}
|
||||
if (i >= oDoor_Log_air && i <= oDoor_Wood_air) {
|
||||
Props[i].oDoorBlock = (ushort)(oDoor_Log + (i - oDoor_Log_air));
|
||||
if (b >= oDoor_Log_air && b <= oDoor_Wood_air) {
|
||||
props[b].oDoorBlock = (ushort)(oDoor_Log + (b - oDoor_Log_air));
|
||||
}
|
||||
if (i >= oDoor_Green_air && i <= oDoor_Water_air) {
|
||||
Props[i].oDoorBlock = (ushort)(oDoor_Green + (i - oDoor_Green_air));
|
||||
if (b >= oDoor_Green_air && b <= oDoor_Water_air) {
|
||||
props[b].oDoorBlock = (ushort)(oDoor_Green + (b - oDoor_Green_air));
|
||||
}
|
||||
|
||||
if ((i >= Red && i <= White) || (i >= LightPink && i <= turquoise)) {
|
||||
Props[i].LavaKills = true;
|
||||
if ((b >= Red && b <= White) || (b >= LightPink && b <= turquoise)) {
|
||||
props[b].LavaKills = true;
|
||||
}
|
||||
if (i == Air || i == Sapling || (i >= Dandelion && i <= RedMushroom)) {
|
||||
Props[i].LavaKills = true;
|
||||
Props[i].WaterKills = true;
|
||||
if (b == Air || b == Sapling || (b >= Dandelion && b <= RedMushroom)) {
|
||||
props[b].LavaKills = true;
|
||||
props[b].WaterKills = true;
|
||||
}
|
||||
|
||||
// Door blocks
|
||||
if (i >= Door_Obsidian && i <= Door_Slab) Props[i].IsDoor = true;
|
||||
if (i >= Door_Iron && i <= Door_Bookshelf) Props[i].IsDoor = true;
|
||||
if (i >= Door_Orange && i <= Door_White) Props[i].IsDoor = true;
|
||||
if (b >= Door_Obsidian && b <= Door_Slab) props[b].IsDoor = true;
|
||||
if (b >= Door_Iron && b <= Door_Bookshelf) props[b].IsDoor = true;
|
||||
if (b >= Door_Orange && b <= Door_White) props[b].IsDoor = true;
|
||||
}
|
||||
|
||||
// Other door blocks, since they aren't in a consistent order
|
||||
Props[Door_Log].IsDoor = true;
|
||||
Props[Door_Red].IsDoor = true;
|
||||
Props[Door_Cobblestone].IsDoor = true;
|
||||
Props[Door_Gold].IsDoor = true;
|
||||
Props[Door_Air].IsDoor = true;
|
||||
Props[Door_AirActivatable].IsDoor = true;
|
||||
Props[Door_Water].IsDoor = true;
|
||||
Props[Door_Lava].IsDoor = true;
|
||||
props[Door_Log].IsDoor = true;
|
||||
props[Door_Red].IsDoor = true;
|
||||
props[Door_Cobblestone].IsDoor = true;
|
||||
props[Door_Gold].IsDoor = true;
|
||||
props[Door_Air].IsDoor = true;
|
||||
props[Door_AirActivatable].IsDoor = true;
|
||||
props[Door_Water].IsDoor = true;
|
||||
props[Door_Lava].IsDoor = true;
|
||||
|
||||
// Block specific properties
|
||||
Props[Wood].LavaKills = true; Props[Log].LavaKills = true;
|
||||
Props[Sponge].LavaKills = true; Props[Bookshelf].LavaKills = true;
|
||||
Props[Leaves].LavaKills = true; Props[Crate].LavaKills = true;
|
||||
Props[Red].IsRails = true; Props[Op_Air].IsRails = true;
|
||||
Props[Slab].StackBlock = DoubleSlab;
|
||||
Props[CobblestoneSlab].StackBlock = Cobblestone;
|
||||
Props[Water].Drownable = true; Props[StillWater].Drownable = true;
|
||||
Props[Lava].Drownable = true; Props[StillLava].Drownable = true;
|
||||
Props[Dirt].GrassBlock = Block.Grass; Props[Grass].DirtBlock = Block.Dirt;
|
||||
props[Wood].LavaKills = true; props[Log].LavaKills = true;
|
||||
props[Sponge].LavaKills = true; props[Bookshelf].LavaKills = true;
|
||||
props[Leaves].LavaKills = true; props[Crate].LavaKills = true;
|
||||
props[Red].IsRails = true; props[Op_Air].IsRails = true;
|
||||
props[Slab].StackBlock = DoubleSlab;
|
||||
props[CobblestoneSlab].StackBlock = Cobblestone;
|
||||
props[Water].Drownable = true; props[StillWater].Drownable = true;
|
||||
props[Lava].Drownable = true; props[StillLava].Drownable = true;
|
||||
props[Dirt].GrassBlock = Block.Grass; props[Grass].DirtBlock = Block.Dirt;
|
||||
|
||||
// Block specific physics properties
|
||||
Props[Block.Bird_Black].AnimalAI = AnimalAI.Fly;
|
||||
Props[Block.Bird_White].AnimalAI = AnimalAI.Fly;
|
||||
Props[Block.Bird_Lava].AnimalAI = AnimalAI.Fly;
|
||||
Props[Block.Bird_Water].AnimalAI = AnimalAI.Fly;
|
||||
props[Block.Bird_Black].AnimalAI = AnimalAI.Fly;
|
||||
props[Block.Bird_White].AnimalAI = AnimalAI.Fly;
|
||||
props[Block.Bird_Lava].AnimalAI = AnimalAI.Fly;
|
||||
props[Block.Bird_Water].AnimalAI = AnimalAI.Fly;
|
||||
|
||||
Props[Block.Bird_Red].AnimalAI = AnimalAI.KillerAir;
|
||||
Props[Block.Bird_Blue].AnimalAI = AnimalAI.KillerAir;
|
||||
Props[Block.Bird_Killer].AnimalAI = AnimalAI.KillerAir;
|
||||
props[Block.Bird_Red].AnimalAI = AnimalAI.KillerAir;
|
||||
props[Block.Bird_Blue].AnimalAI = AnimalAI.KillerAir;
|
||||
props[Block.Bird_Killer].AnimalAI = AnimalAI.KillerAir;
|
||||
|
||||
Props[Block.Fish_Betta].AnimalAI = AnimalAI.KillerWater;
|
||||
Props[Block.Fish_Shark].AnimalAI = AnimalAI.KillerWater;
|
||||
Props[Block.Fish_LavaShark].AnimalAI = AnimalAI.KillerLava;
|
||||
|
||||
Props[Block.Fish_Gold].AnimalAI = AnimalAI.FleeWater;
|
||||
Props[Block.Fish_Salmon].AnimalAI = AnimalAI.FleeWater;
|
||||
Props[Block.Fish_Sponge].AnimalAI = AnimalAI.FleeWater;
|
||||
props[Block.Fish_Betta].AnimalAI = AnimalAI.KillerWater;
|
||||
props[Block.Fish_Shark].AnimalAI = AnimalAI.KillerWater;
|
||||
props[Block.Fish_LavaShark].AnimalAI = AnimalAI.KillerLava;
|
||||
|
||||
props[Block.Fish_Gold].AnimalAI = AnimalAI.FleeWater;
|
||||
props[Block.Fish_Salmon].AnimalAI = AnimalAI.FleeWater;
|
||||
props[Block.Fish_Sponge].AnimalAI = AnimalAI.FleeWater;
|
||||
}
|
||||
|
||||
static void SetCoreProperties() {
|
||||
MakeDefaultProps(Props);
|
||||
SetDefaultNames();
|
||||
SetDefaultDeaths();
|
||||
}
|
||||
|
||||
|
||||
internal static void SetDefaultNames() {
|
||||
string[] names = new string[] { "Air", "Stone", "Grass", "Dirt", "Cobblestone",
|
||||
"Wood", "Sapling", "Bedrock", "Active_Water", "Water", "Active_Lava", "Lava",
|
||||
|
@ -16,6 +16,7 @@
|
||||
permissions and limitations under the Licenses.
|
||||
*/
|
||||
using System;
|
||||
using System.IO;
|
||||
using MCGalaxy.Blocks;
|
||||
using MCGalaxy.Maths;
|
||||
using BlockID = System.UInt16;
|
||||
@ -151,15 +152,23 @@ namespace MCGalaxy {
|
||||
def.MaxX * 2, def.MaxZ * 2, def.MaxY * 2);
|
||||
}
|
||||
|
||||
if (block >= Block.Extended) return new AABB(0, 0, 0, 32, 32, 32);
|
||||
if (block >= Block.Extended) return new AABB(0, 0, 0, 32, 32, 32);
|
||||
BlockID core = Convert(block);
|
||||
return new AABB(0, 0, 0, 32, DefaultSet.Height(core) * 2, 32);
|
||||
}
|
||||
}
|
||||
|
||||
public static void SetBlocks() {
|
||||
SetCoreProperties();
|
||||
BlockProps.Load("core", Props, CorePropsLock, false);
|
||||
BlockDefinition.UpdateGlobalBlockProps();
|
||||
string propsPath = BlockProps.PropsPath("default");
|
||||
|
||||
// backwards compatibility with older versions
|
||||
if (!File.Exists(propsPath)) {
|
||||
BlockProps.Load("core", Props, PropsLock, 1, false);
|
||||
BlockProps.Load("global", Props, PropsLock, 1, true);
|
||||
} else {
|
||||
BlockProps.Load("default", Props, PropsLock, 1, false);
|
||||
}
|
||||
|
||||
BlockPerms.Load();
|
||||
UpdateLoadedLevels();
|
||||
}
|
||||
@ -169,7 +178,7 @@ namespace MCGalaxy {
|
||||
foreach (Level lvl in loaded) {
|
||||
lvl.UpdateBlockProps();
|
||||
lvl.UpdateBlockHandlers();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static BlockID FromRaw(byte raw) {
|
||||
@ -181,6 +190,7 @@ namespace MCGalaxy {
|
||||
}
|
||||
|
||||
public static BlockID MapOldRaw(BlockID raw) {
|
||||
// old raw form was: 0 - 65 core block ids, 66 - 255 custom block ids
|
||||
return IsPhysicsType(raw) ? ((BlockID)(Block.Extended | raw)) : raw;
|
||||
}
|
||||
|
||||
|
@ -50,7 +50,6 @@ namespace MCGalaxy {
|
||||
public const string GlobalPath = "blockdefs/global.json", GlobalBackupPath = "blockdefs/global.json.bak";
|
||||
|
||||
public static BlockDefinition[] GlobalDefs;
|
||||
public static BlockProps[] GlobalProps = new BlockProps[Block.Count];
|
||||
internal static readonly object GlobalPropsLock = new object();
|
||||
|
||||
public BlockDefinition Copy() {
|
||||
@ -145,26 +144,6 @@ namespace MCGalaxy {
|
||||
if (oldDefs != null) UpdateLoadedLevels(oldDefs);
|
||||
}
|
||||
|
||||
public static void UpdateGlobalBlockProps() {
|
||||
for (int i = 0; i < GlobalProps.Length; i++) {
|
||||
BlockID_ block = Block.FromRaw((byte)i);
|
||||
GlobalProps[i] = BlockProps.MakeDefault();
|
||||
GlobalProps[i] = DefaultProps(block);
|
||||
}
|
||||
BlockProps.Load("global", GlobalProps, GlobalPropsLock, false);
|
||||
}
|
||||
|
||||
internal static BlockProps DefaultProps(BlockID_ block) {
|
||||
BlockRaw raw = (BlockRaw)block;
|
||||
if (Block.IsPhysicsType(block)) {
|
||||
return Block.Props[block];
|
||||
} else if (block < Block.Extended && GlobalDefs[raw] == null) {
|
||||
return Block.Props[raw];
|
||||
} else {
|
||||
return GlobalProps[raw];
|
||||
}
|
||||
}
|
||||
|
||||
static void UpdateLoadedLevels(BlockDefinition[] oldGlobalDefs) {
|
||||
Level[] loaded = LevelInfo.Loaded.Items;
|
||||
foreach (Level lvl in loaded) {
|
||||
@ -172,7 +151,7 @@ namespace MCGalaxy {
|
||||
if (lvl.CustomBlockDefs[i] != oldGlobalDefs[i]) continue;
|
||||
|
||||
BlockID_ block = Block.FromRaw((byte)i);
|
||||
lvl.Props[block] = DefaultProps(block);
|
||||
lvl.Props[block] = Block.Props[block];
|
||||
lvl.UpdateCustomBlock((BlockRaw)block, GlobalDefs[i]);
|
||||
}
|
||||
}
|
||||
|
@ -163,13 +163,12 @@ namespace MCGalaxy.Blocks {
|
||||
}
|
||||
|
||||
static void SetDefaultPerms() {
|
||||
BlockProps defProps = BlockProps.MakeDefault();
|
||||
for (int i = 0; i < Block.ExtendedCount; i++) {
|
||||
for (BlockID block = 0; block < Block.ExtendedCount; block++) {
|
||||
BlockPerms perms = new BlockPerms();
|
||||
perms.ID = (BlockID)i;
|
||||
BlockProps props = i < Block.Count ? Block.Props[i] : defProps;
|
||||
perms.ID = block;
|
||||
BlockProps props = Block.Props[block];
|
||||
|
||||
if (i == Block.Invalid) {
|
||||
if (block == Block.Invalid) {
|
||||
perms.MinRank = LevelPermission.Admin;
|
||||
} else if (props.OPBlock) {
|
||||
perms.MinRank = LevelPermission.Operator;
|
||||
@ -178,9 +177,9 @@ namespace MCGalaxy.Blocks {
|
||||
} else if (props.IsPortal || props.IsMessageBlock) {
|
||||
perms.MinRank = LevelPermission.AdvBuilder;
|
||||
} else {
|
||||
perms.MinRank = DefaultPerm(i);
|
||||
perms.MinRank = DefaultPerm(block);
|
||||
}
|
||||
List[i] = perms;
|
||||
List[block] = perms;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -75,7 +75,7 @@ namespace MCGalaxy.Blocks {
|
||||
public BlockID DirtBlock;
|
||||
|
||||
/// <summary> Whether the properties for this block have been modified and hence require saving. </summary>
|
||||
public bool Changed;
|
||||
public byte ChangedScope;
|
||||
|
||||
public static BlockProps MakeDefault() {
|
||||
BlockProps props = default(BlockProps);
|
||||
@ -86,29 +86,27 @@ namespace MCGalaxy.Blocks {
|
||||
}
|
||||
|
||||
|
||||
public static void Save(string group, BlockProps[] scope, object locker, Predicate<int> selector) {
|
||||
public static void Save(string group, BlockProps[] list, object locker, byte scope) {
|
||||
lock (locker) {
|
||||
if (!Directory.Exists("blockprops"))
|
||||
Directory.CreateDirectory("blockprops");
|
||||
SaveCore(group, scope, selector);
|
||||
SaveCore(group, list, scope);
|
||||
}
|
||||
}
|
||||
|
||||
static void SaveCore(string group, BlockProps[] scope, Predicate<int> selector) {
|
||||
static void SaveCore(string group, BlockProps[] list, byte scope) {
|
||||
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 : " +
|
||||
"Animal AI type : Stack block : Is OP block : oDoor block : Drownable : " +
|
||||
"Grass block : Dirt block");
|
||||
for (int i = 0; i < scope.Length; i++) {
|
||||
if (!scope[i].Changed || (selector != null && !selector(i))) continue;
|
||||
BlockProps props = scope[i];
|
||||
// Convert ext to raw ids
|
||||
int id = i >= Block.Count ? (i - Block.Count) : i;
|
||||
for (int b = 0; b < list.Length; b++) {
|
||||
if ((list[b].ChangedScope & scope) == 0) continue;
|
||||
BlockProps props = list[b];
|
||||
|
||||
string deathMsg = props.DeathMessage == null ? "" : props.DeathMessage.Replace(":", "\\;");
|
||||
w.WriteLine(id + ":" + props.IsRails + ":" + props.IsTDoor + ":" + props.IsDoor + ":"
|
||||
w.WriteLine(b + ":" + props.IsRails + ":" + props.IsTDoor + ":" + props.IsDoor + ":"
|
||||
+ props.IsMessageBlock + ":" + props.IsPortal + ":" + props.WaterKills + ":"
|
||||
+ props.LavaKills + ":" + props.KillerBlock + ":" + deathMsg + ":"
|
||||
+ (byte)props.AnimalAI + ":" + props.StackBlock + ":" + props.OPBlock + ":"
|
||||
@ -118,71 +116,71 @@ namespace MCGalaxy.Blocks {
|
||||
}
|
||||
}
|
||||
|
||||
public static void Load(string group, BlockProps[] scope, object locker, bool lbScope) {
|
||||
public static string PropsPath(string group) { return "blockprops/" + group + ".txt"; }
|
||||
|
||||
public static void Load(string group, BlockProps[] list, object locker, byte scope, bool mapOld) {
|
||||
lock (locker) {
|
||||
if (!Directory.Exists("blockprops")) return;
|
||||
if (!File.Exists("blockprops/" + group + ".txt")) return;
|
||||
LoadCore(group, scope, lbScope);
|
||||
string path = PropsPath(group);
|
||||
if (File.Exists(path)) LoadCore(path, list, scope, mapOld);
|
||||
}
|
||||
}
|
||||
|
||||
static void LoadCore(string group, BlockProps[] scope, bool lbScope) {
|
||||
string[] lines = File.ReadAllLines("blockprops/" + group + ".txt");
|
||||
static void LoadCore(string path, BlockProps[] list, byte scope, bool mapOld) {
|
||||
string[] lines = File.ReadAllLines(path);
|
||||
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) {
|
||||
Logger.Log(LogType.Warning, "Invalid line \"{0}\" in {1} block properties", line, group);
|
||||
Logger.Log(LogType.Warning, "Invalid line \"{0}\" in {1}", line, path);
|
||||
continue;
|
||||
}
|
||||
|
||||
// TODO fix fix fix
|
||||
byte raw;
|
||||
if (!Byte.TryParse(parts[0], out raw)) {
|
||||
Logger.Log(LogType.Warning, "Invalid line \"{0}\" in {1} block properties", line, group);
|
||||
BlockID b;
|
||||
if (!BlockID.TryParse(parts[0], out b)) {
|
||||
Logger.Log(LogType.Warning, "Invalid line \"{0}\" in {1}", line, path);
|
||||
continue;
|
||||
}
|
||||
int idx = raw;
|
||||
if (lbScope && raw >= Block.CpeCount) idx += Block.Count;
|
||||
if (mapOld) b = Block.MapOldRaw(b);
|
||||
|
||||
bool.TryParse(parts[1], out scope[idx].IsRails);
|
||||
bool.TryParse(parts[2], out scope[idx].IsTDoor);
|
||||
bool.TryParse(parts[3], out scope[idx].IsDoor);
|
||||
bool.TryParse(parts[4], out scope[idx].IsMessageBlock);
|
||||
bool.TryParse(parts[5], out scope[idx].IsPortal);
|
||||
bool.TryParse(parts[6], out scope[idx].WaterKills);
|
||||
bool.TryParse(parts[7], out scope[idx].LavaKills);
|
||||
bool.TryParse(parts[8], out scope[idx].KillerBlock);
|
||||
bool.TryParse(parts[1], out list[b].IsRails);
|
||||
bool.TryParse(parts[2], out list[b].IsTDoor);
|
||||
bool.TryParse(parts[3], out list[b].IsDoor);
|
||||
bool.TryParse(parts[4], out list[b].IsMessageBlock);
|
||||
bool.TryParse(parts[5], out list[b].IsPortal);
|
||||
bool.TryParse(parts[6], out list[b].WaterKills);
|
||||
bool.TryParse(parts[7], out list[b].LavaKills);
|
||||
bool.TryParse(parts[8], out list[b].KillerBlock);
|
||||
|
||||
scope[idx].Changed = true;
|
||||
scope[idx].DeathMessage = parts[9].Replace("\\;", ":");
|
||||
if (scope[idx].DeathMessage.Length == 0)
|
||||
scope[idx].DeathMessage = null;
|
||||
list[b].ChangedScope = scope;
|
||||
list[b].DeathMessage = parts[9].Replace("\\;", ":");
|
||||
if (list[b].DeathMessage.Length == 0)
|
||||
list[b].DeathMessage = null;
|
||||
|
||||
if (parts.Length > 10) {
|
||||
byte ai; byte.TryParse(parts[10], out ai);
|
||||
scope[idx].AnimalAI = (AnimalAI)ai;
|
||||
list[b].AnimalAI = (AnimalAI)ai;
|
||||
}
|
||||
if (parts.Length > 11) {
|
||||
BlockID.TryParse(parts[11], out scope[idx].StackBlock);
|
||||
scope[idx].StackBlock = Block.MapOldRaw(scope[idx].StackBlock);
|
||||
BlockID.TryParse(parts[11], out list[b].StackBlock);
|
||||
list[b].StackBlock = Block.MapOldRaw(list[b].StackBlock);
|
||||
}
|
||||
if (parts.Length > 12) {
|
||||
bool.TryParse(parts[12], out scope[idx].OPBlock);
|
||||
bool.TryParse(parts[12], out list[b].OPBlock);
|
||||
}
|
||||
if (parts.Length > 13) {
|
||||
BlockID.TryParse(parts[13], out scope[idx].oDoorBlock);
|
||||
BlockID.TryParse(parts[13], out list[b].oDoorBlock);
|
||||
}
|
||||
if (parts.Length > 14) {
|
||||
bool.TryParse(parts[14], out scope[idx].Drownable);
|
||||
bool.TryParse(parts[14], out list[b].Drownable);
|
||||
}
|
||||
if (parts.Length > 15) {
|
||||
BlockID.TryParse(parts[15], out scope[idx].GrassBlock);
|
||||
BlockID.TryParse(parts[15], out list[b].GrassBlock);
|
||||
}
|
||||
if (parts.Length > 16) {
|
||||
BlockID.TryParse(parts[16], out scope[idx].DirtBlock);
|
||||
BlockID.TryParse(parts[16], out list[b].DirtBlock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -119,7 +119,7 @@ namespace MCGalaxy.Commands.CPE {
|
||||
if (srcDef == null) { MessageNoBlock(p, src, global, cmd); return; }
|
||||
if (ExistsInScope(dstDef, dst, global)) { MessageAlreadyBlock(p, dst, global, cmd); return; }
|
||||
|
||||
BlockProps props = global ? BlockDefinition.GlobalProps[srcRaw] : p.level.Props[src];
|
||||
BlockProps props = global ? Block.Props[src] : p.level.Props[src];
|
||||
dstDef = srcDef.Copy();
|
||||
dstDef.BlockID = dstRaw;
|
||||
dstDef.InventoryOrder = -1;
|
||||
@ -287,8 +287,7 @@ namespace MCGalaxy.Commands.CPE {
|
||||
bd.FallBack = fallback;
|
||||
|
||||
BlockID block = Block.FromRaw(bd.BlockID);
|
||||
BlockProps props = BlockDefinition.DefaultProps(block);
|
||||
if (!AddBlock(p, bd, global, cmd, props)) return;
|
||||
if (!AddBlock(p, bd, global, cmd, Block.Props[block])) return;
|
||||
|
||||
SetBD(p, global, null);
|
||||
SetStep(p, global, 0);
|
||||
@ -314,17 +313,17 @@ namespace MCGalaxy.Commands.CPE {
|
||||
BlockID block;
|
||||
if (!CheckBlock(p, parts[1], out block)) return;
|
||||
BlockRaw raw = (BlockRaw)block;
|
||||
|
||||
|
||||
BlockDefinition[] defs = global ? BlockDefinition.GlobalDefs : p.level.CustomBlockDefs;
|
||||
BlockDefinition def = defs[raw], globalDef = BlockDefinition.GlobalDefs[raw];
|
||||
|
||||
if (def == null && block < Block.CpeCount) {
|
||||
def = DefaultSet.MakeCustomBlock(block);
|
||||
AddBlock(p, def, global, cmd, BlockDefinition.DefaultProps(block));
|
||||
AddBlock(p, def, global, cmd, Block.Props[block]);
|
||||
}
|
||||
if (def != null && !global && def == globalDef) {
|
||||
def = globalDef.Copy();
|
||||
AddBlock(p, def, global, cmd, BlockDefinition.DefaultProps(block));
|
||||
AddBlock(p, def, global, cmd, Block.Props[block]);
|
||||
}
|
||||
if (!ExistsInScope(def, block, global)) { MessageNoBlock(p, block, global, cmd); return; }
|
||||
|
||||
@ -432,7 +431,7 @@ namespace MCGalaxy.Commands.CPE {
|
||||
def.InventoryOrder = order == def.BlockID ? -1 : order;
|
||||
BlockDefinition.UpdateOrder(def, global, level);
|
||||
BlockDefinition.Save(global, level);
|
||||
Player.Message(p, "Set inventory order for {0} to {1}", blockName,
|
||||
Player.Message(p, "Set inventory order for {0} to {1}", blockName,
|
||||
order == def.BlockID ? "default" : order.ToString());
|
||||
return;
|
||||
default:
|
||||
@ -557,39 +556,19 @@ namespace MCGalaxy.Commands.CPE {
|
||||
if (!global) {
|
||||
p.level.Props[block] = props;
|
||||
p.level.UpdateBlockHandler(block);
|
||||
return;
|
||||
}
|
||||
|
||||
BlockRaw raw = (BlockRaw)block;
|
||||
BlockDefinition.GlobalProps[raw] = props;
|
||||
Level[] loaded = LevelInfo.Loaded.Items;
|
||||
|
||||
foreach (Level lvl in loaded) {
|
||||
if (lvl.CustomBlockDefs[raw] != BlockDefinition.GlobalDefs[raw]) continue;
|
||||
lvl.Props[block] = props;
|
||||
lvl.UpdateBlockHandler(block);
|
||||
} else {
|
||||
Block.ChangeGlobalProps(block, props);
|
||||
}
|
||||
}
|
||||
|
||||
static void RemoveBlockProps(bool global, BlockID block, Player p) {
|
||||
// Level block reverts to using global block
|
||||
if (!global) {
|
||||
p.level.Props[block] = BlockDefinition.DefaultProps(block);
|
||||
p.level.Props[block] = Block.Props[block];
|
||||
p.level.UpdateBlockHandler(block);
|
||||
return;
|
||||
}
|
||||
|
||||
BlockProps props = BlockProps.MakeDefault();
|
||||
if (block < Block.Extended) props = Block.Props[block];
|
||||
|
||||
BlockRaw raw = (BlockRaw)block;
|
||||
BlockDefinition.GlobalProps[raw] = props;
|
||||
Level[] loaded = LevelInfo.Loaded.Items;
|
||||
|
||||
foreach (Level lvl in loaded) {
|
||||
if (lvl.CustomBlockDefs[raw] != BlockDefinition.GlobalDefs[raw]) continue;
|
||||
lvl.Props[block] = BlockDefinition.GlobalProps[raw];
|
||||
lvl.UpdateBlockHandler(block);
|
||||
} else {
|
||||
BlockProps[] defProps = new BlockProps[Block.ExtendedCount];
|
||||
Block.MakeDefaultProps(defProps);
|
||||
Block.ChangeGlobalProps(block, defProps[block]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -724,7 +703,7 @@ namespace MCGalaxy.Commands.CPE {
|
||||
}
|
||||
|
||||
internal static void Help(Player p, string cmd, string args) {
|
||||
if (!args.CaselessStarts("edit ")) { Help(p, cmd); return; }
|
||||
if (!args.CaselessStarts("edit ")) { Help(p, cmd); return; }
|
||||
string prop = args.Substring(args.IndexOf(' ') + 1);
|
||||
prop = MapPropertyName(prop.ToLower());
|
||||
|
||||
|
@ -34,17 +34,20 @@ namespace MCGalaxy.Commands.World {
|
||||
|
||||
BlockProps[] scope = GetScope(p, args[0]);
|
||||
if (scope == null) return;
|
||||
BlockID block = GetBlock(p, scope, args[1]);
|
||||
if (block == Block.Invalid) return;
|
||||
|
||||
Player pScope = scope == Block.Props ? null : p;
|
||||
BlockID block = CommandParser.RawGetBlock(pScope, args[1]);
|
||||
if (block == Block.Invalid) {
|
||||
Player.Message(p, "&cThere is no block \"{0}\".", args[1]); return;
|
||||
}
|
||||
|
||||
string prop = args[2].ToLower();
|
||||
SetProperty(p, scope, block, prop, args);
|
||||
}
|
||||
|
||||
static BlockProps[] GetScope(Player p, string scope) {
|
||||
if (scope.CaselessEq("core")) return Block.Props;
|
||||
if (scope.CaselessEq("global")) return BlockDefinition.GlobalProps;
|
||||
|
||||
if (scope.CaselessEq("core") || scope.CaselessEq("global")) return Block.Props;
|
||||
|
||||
if (scope.CaselessEq("level")) {
|
||||
if (Player.IsSuper(p)) {
|
||||
string src = p == null ? "console" : "IRC";
|
||||
@ -56,84 +59,47 @@ namespace MCGalaxy.Commands.World {
|
||||
return p.level.Props;
|
||||
}
|
||||
|
||||
Player.Message(p, "&cScope must \"core\", \"global\", or \"level\"");
|
||||
Player.Message(p, "&cScope must be: core/global, or level");
|
||||
return null;
|
||||
}
|
||||
|
||||
static BlockID GetBlock(Player p, BlockProps[] scope, string input) {
|
||||
if (scope == Block.Props) {
|
||||
byte raw;
|
||||
if (!byte.TryParse(input, out raw))
|
||||
raw = Block.Byte(input);
|
||||
|
||||
if (Block.Undefined(raw)) {
|
||||
Player.Message(p, "&cThere is no block with id or name \"{0}\"", input);
|
||||
return Block.Invalid;
|
||||
}
|
||||
return raw;
|
||||
} else if (scope == BlockDefinition.GlobalProps) {
|
||||
int raw = BlockDefinition.GetBlock(input, BlockDefinition.GlobalDefs);
|
||||
if (raw == -1) {
|
||||
Player.Message(p, "&cThere is no global custom block with id or name \"{0}\"", input);
|
||||
return Block.Invalid;
|
||||
}
|
||||
return Block.FromRaw((byte)raw);
|
||||
} else {
|
||||
int raw = BlockDefinition.GetBlock(input, p.level.CustomBlockDefs);
|
||||
if (raw == -1) {
|
||||
Player.Message(p, "&cThere is no level custom block with id or name \"{0}\"", input);
|
||||
return Block.Invalid;
|
||||
}
|
||||
|
||||
if (p.level.CustomBlockDefs[raw] == BlockDefinition.GlobalDefs[raw]) {
|
||||
Player.Message(p, "&cUse %T/BlockProps global &cto modify this custom block."); return Block.Invalid;
|
||||
}
|
||||
return Block.FromRaw((byte)raw);
|
||||
}
|
||||
}
|
||||
|
||||
static int GetIndex(BlockProps[] scope, BlockID block) {
|
||||
return scope == BlockDefinition.GlobalProps ? (BlockRaw)block : block;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void SetProperty(Player p, BlockProps[] scope, BlockID block,
|
||||
string prop, string[] args) {
|
||||
int i = GetIndex(scope, block);
|
||||
string text = args.Length > 3 ? args[3] : null;
|
||||
|
||||
if (prop == "portal") {
|
||||
Toggle(p, scope, block, "a portal", ref scope[i].IsPortal);
|
||||
Toggle(p, scope, block, "a portal", ref scope[block].IsPortal);
|
||||
} else if (prop == "mb" || prop == "messageblock") {
|
||||
Toggle(p, scope, block, "a message block", ref scope[i].IsMessageBlock);
|
||||
Toggle(p, scope, block, "a message block", ref scope[block].IsMessageBlock);
|
||||
} else if (prop == "rails") {
|
||||
Toggle(p, scope, block, "train rails", ref scope[i].IsRails);
|
||||
Toggle(p, scope, block, "train rails", ref scope[block].IsRails);
|
||||
} else if (prop == "waterkills") {
|
||||
Toggle(p, scope, block, "killed by water", ref scope[i].WaterKills);
|
||||
Toggle(p, scope, block, "killed by water", ref scope[block].WaterKills);
|
||||
} else if (prop == "lavakills") {
|
||||
Toggle(p, scope, block, "killed by lava", ref scope[i].LavaKills);
|
||||
Toggle(p, scope, block, "killed by lava", ref scope[block].LavaKills);
|
||||
} else if (prop == "door") {
|
||||
Toggle(p, scope, block, "a door", ref scope[i].IsDoor);
|
||||
Toggle(p, scope, block, "a door", ref scope[block].IsDoor);
|
||||
} else if (prop == "tdoor") {
|
||||
Toggle(p, scope, block, "a tdoor", ref scope[i].IsTDoor);
|
||||
Toggle(p, scope, block, "a tdoor", ref scope[block].IsTDoor);
|
||||
} else if (prop == "killer" || prop == "death") {
|
||||
Toggle(p, scope, block, "a killer block", ref scope[i].KillerBlock);
|
||||
Toggle(p, scope, block, "a killer block", ref scope[block].KillerBlock);
|
||||
} else if (prop == "deathmsg" || prop == "deathmessage") {
|
||||
SetDeathMessage(p, scope, block, i, text);
|
||||
SetDeathMessage(p, scope, block, text);
|
||||
} else if (prop == "animalai" || prop == "animal") {
|
||||
SetEnum(p, scope, block, i, text);
|
||||
SetEnum(p, scope, block, text);
|
||||
} else if (prop == "stackid" || prop == "stackblock") {
|
||||
SetStackId(p, scope, block, i, text);
|
||||
SetStackId(p, scope, block, text);
|
||||
} else if (prop == "opblock" || prop == "op") {
|
||||
Toggle(p, scope, block, "an OP block", ref scope[i].OPBlock);
|
||||
Toggle(p, scope, block, "an OP block", ref scope[block].OPBlock);
|
||||
} else if (prop == "odoor") {
|
||||
SetBlock(p, scope, block, i, text, ref scope[i].oDoorBlock, "oDoor");
|
||||
SetBlock(p, scope, block, text, ref scope[block].oDoorBlock, "oDoor");
|
||||
} else if (prop == "grass") {
|
||||
SetBlock(p, scope, block, i, text, ref scope[i].GrassBlock, "Grass form");
|
||||
SetBlock(p, scope, block, text, ref scope[block].GrassBlock, "Grass form");
|
||||
} else if (prop == "dirt") {
|
||||
SetBlock(p, scope, block, i, text, ref scope[i].DirtBlock, "Dirt form");
|
||||
SetBlock(p, scope, block, text, ref scope[block].DirtBlock, "Dirt form");
|
||||
} else if (prop == "drownable" || prop == "drown") {
|
||||
Toggle(p, scope, block, "drowns players", ref scope[i].Drownable);
|
||||
Toggle(p, scope, block, "drowns players", ref scope[block].Drownable);
|
||||
} else {
|
||||
Help(p);
|
||||
}
|
||||
@ -142,122 +108,84 @@ namespace MCGalaxy.Commands.World {
|
||||
|
||||
static void Toggle(Player p, BlockProps[] scope, BlockID block, string type, ref bool on) {
|
||||
on = !on;
|
||||
Level lvl = Player.IsSuper(p) ? null : p.level;
|
||||
Player.Message(p, "Block {0} is {1}: {2}",
|
||||
BlockName(scope, lvl, block), type, on ? "&aYes" : "&cNo");
|
||||
OnPropsChanged(scope, lvl, block);
|
||||
|
||||
string blockName = BlockName(scope, p, block);
|
||||
Player.Message(p, "Block {0} is {1}: {2}", blockName, type, on ? "&aYes" : "&cNo");
|
||||
OnPropsChanged(scope, p, block);
|
||||
}
|
||||
|
||||
static void SetEnum(Player p, BlockProps[] scope, BlockID block, int i, string msg) {
|
||||
Level lvl = Player.IsSuper(p) ? null : p.level;
|
||||
static void SetEnum(Player p, BlockProps[] scope, BlockID block, string msg) {
|
||||
AnimalAI ai = AnimalAI.None;
|
||||
if (!CommandParser.GetEnum(p, msg, "Animal AI", ref ai)) return;
|
||||
scope[block].AnimalAI = ai;
|
||||
|
||||
scope[i].AnimalAI = ai;
|
||||
Player.Message(p, "Animal AI for {0} set to: {1}",
|
||||
BlockName(scope, lvl, block), ai);
|
||||
OnPropsChanged(scope, lvl, block);
|
||||
string blockName = BlockName(scope, p, block);
|
||||
Player.Message(p, "Animal AI for {0} set to: {1}", blockName, ai);
|
||||
OnPropsChanged(scope, p, block);
|
||||
}
|
||||
|
||||
static void SetDeathMessage(Player p, BlockProps[] scope, BlockID block, int i, string msg) {
|
||||
scope[i].DeathMessage = msg;
|
||||
Level lvl = Player.IsSuper(p) ? null : p.level;
|
||||
static void SetDeathMessage(Player p, BlockProps[] scope, BlockID block, string msg) {
|
||||
scope[block].DeathMessage = msg;
|
||||
|
||||
string blockName = BlockName(scope, p, block);
|
||||
if (msg == null) {
|
||||
Player.Message(p, "Death message for {0} removed.",
|
||||
BlockName(scope, lvl, block));
|
||||
Player.Message(p, "Death message for {0} removed.", blockName);
|
||||
} else {
|
||||
Player.Message(p, "Death message for {0} set to: {1}",
|
||||
BlockName(scope, lvl, block), msg);
|
||||
Player.Message(p, "Death message for {0} set to: {1}", blockName, msg);
|
||||
}
|
||||
OnPropsChanged(scope, lvl, block);
|
||||
OnPropsChanged(scope, p, block);
|
||||
}
|
||||
|
||||
static void SetStackId(Player p, BlockProps[] scope, BlockID block, int i, string msg) {
|
||||
Level lvl = Player.IsSuper(p) ? null : p.level;
|
||||
|
||||
static void SetStackId(Player p, BlockProps[] scope, BlockID block, string msg) {
|
||||
BlockID stackBlock;
|
||||
if (msg == null) {
|
||||
stackBlock = Block.Air;
|
||||
} else {
|
||||
if (!CommandParser.GetBlock(p, msg, out stackBlock)) return;
|
||||
}
|
||||
scope[i].StackBlock = stackBlock;
|
||||
scope[block].StackBlock = stackBlock;
|
||||
|
||||
string blockName = BlockName(scope, p, block);
|
||||
if (stackBlock == Block.Air) {
|
||||
Player.Message(p, "Removed stack block for {0}", BlockName(scope, lvl, block));
|
||||
Player.Message(p, "Removed stack block for {0}", blockName);
|
||||
} else {
|
||||
Player.Message(p, "Stack block for {0} set to: {1}",
|
||||
BlockName(scope, lvl, block), Block.GetName(p, stackBlock));
|
||||
blockName, BlockName(scope, p, stackBlock));
|
||||
}
|
||||
OnPropsChanged(scope, lvl, block);
|
||||
OnPropsChanged(scope, p, block);
|
||||
}
|
||||
|
||||
static void SetBlock(Player p, BlockProps[] scope, BlockID block,
|
||||
int i, string msg, ref BlockID target, string type) {
|
||||
Level lvl = Player.IsSuper(p) ? null : p.level;
|
||||
static void SetBlock(Player p, BlockProps[] scope, BlockID block,
|
||||
string msg, ref BlockID target, string type) {
|
||||
string blockName = BlockName(scope, p, block);
|
||||
if (msg == null) {
|
||||
target = Block.Invalid;
|
||||
Player.Message(p, "{1} for {0} removed.", BlockName(scope, lvl, block), type);
|
||||
Player.Message(p, "{1} for {0} removed.", blockName, type);
|
||||
} else {
|
||||
BlockID other;
|
||||
if (!CommandParser.GetBlock(p, msg, out other)) return;
|
||||
if (other == block) { Player.Message(p, "ID of {0} must be different.", type); return; }
|
||||
|
||||
target = other;
|
||||
Player.Message(p, "{2} for {0} set to: {1}", BlockName(scope, lvl, block),
|
||||
BlockName(scope, lvl, other), type);
|
||||
target = other;
|
||||
Player.Message(p, "{2} for {0} set to: {1}", blockName, BlockName(scope, p, other), type);
|
||||
}
|
||||
OnPropsChanged(scope, lvl, block);
|
||||
}
|
||||
OnPropsChanged(scope, p, block);
|
||||
}
|
||||
|
||||
static void OnPropsChanged(BlockProps[] scope, Level level, BlockID block) {
|
||||
scope[GetIndex(scope, block)].Changed = true;
|
||||
BlockRaw raw = (BlockRaw)block;
|
||||
|
||||
static void OnPropsChanged(BlockProps[] scope, Player p, BlockID block) {
|
||||
if (scope == Block.Props) {
|
||||
BlockProps.Save("core", scope, Block.CorePropsLock, null);
|
||||
Level[] loaded = LevelInfo.Loaded.Items;
|
||||
if (!Block.IsPhysicsType(block)) {
|
||||
BlockDefinition.GlobalProps[raw] = BlockDefinition.DefaultProps(block);
|
||||
}
|
||||
|
||||
foreach (Level lvl in loaded) {
|
||||
if (lvl.HasCustomProps(block)) continue;
|
||||
|
||||
lvl.Props[block] = BlockDefinition.DefaultProps(block);
|
||||
lvl.UpdateBlockHandler(block);
|
||||
}
|
||||
} else if (scope == BlockDefinition.GlobalProps) {
|
||||
Level[] loaded = LevelInfo.Loaded.Items;
|
||||
BlockProps.Save("global", scope, BlockDefinition.GlobalPropsLock, null);
|
||||
|
||||
foreach (Level lvl in loaded) {
|
||||
if (lvl.CustomBlockDefs[raw] != BlockDefinition.GlobalDefs[raw]) continue;
|
||||
if (lvl.HasCustomProps(block)) continue;
|
||||
|
||||
lvl.Props[block] = BlockDefinition.DefaultProps(block);
|
||||
lvl.UpdateBlockHandler(block);
|
||||
}
|
||||
scope[block].ChangedScope |= 1;
|
||||
BlockProps.Save("default", Block.Props, Block.PropsLock, 1);
|
||||
Block.ChangeGlobalProps(block, scope[block]);
|
||||
} else {
|
||||
BlockProps.Save("lvl_" + level.name, scope, level.PropsLock, idx => SelectLevel(level, idx));
|
||||
level.UpdateBlockHandler(block);
|
||||
scope[block].ChangedScope |= 2;
|
||||
BlockProps.Save("_" + p.level.name, scope, p.level.PropsLock, 2);
|
||||
p.level.UpdateBlockHandler(block);
|
||||
}
|
||||
}
|
||||
|
||||
static bool SelectLevel(Level lvl, int i) { return lvl.HasCustomProps((BlockID)i); }
|
||||
|
||||
static string BlockName(BlockProps[] scope, Level lvl, BlockID block) {
|
||||
BlockRaw raw = (BlockRaw)block;
|
||||
if (scope == Block.Props) return Block.coreNames[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(" ", "");
|
||||
static string BlockName(BlockProps[] scope, Player p, BlockID block) {
|
||||
return scope == Block.Props ? Block.GetName(null, block) : Block.GetName(p, block);
|
||||
}
|
||||
|
||||
|
||||
|
@ -225,7 +225,7 @@ namespace MCGalaxy.Commands.World {
|
||||
if (name.Length == 0) { Player.Message(p, "You need to provide a player name."); return; }
|
||||
AddBuildPlayer(p, name);
|
||||
} else if (cmd == "DEL") {
|
||||
if (name.Length == 0) { Player.Message(p, "You need to provide a player name, or \"ALL\"."); return; }
|
||||
if (name.Length == 0) { Player.Message(p, "You need to provide a player name."); return; }
|
||||
DeleteBuildPlayer(p, name);
|
||||
} else if (cmd == "BLOCK") {
|
||||
if (name.Length == 0) { Player.Message(p, "You need to provide a player name."); return; }
|
||||
|
@ -192,28 +192,21 @@ namespace MCGalaxy.Commands.Building {
|
||||
return Block.GetName(p, block);
|
||||
}
|
||||
|
||||
static void AllNames(Player p, List<string> names) {
|
||||
for (int i = 0; i < Block.ExtendedCount; i++) {
|
||||
string name = Format((BlockID)i, p, p.level.Props);
|
||||
if (name != null) names.Add(name);
|
||||
}
|
||||
}
|
||||
|
||||
static void CoreNames(List<string> names) {
|
||||
for (int i = 0; i < Block.Count; i++) {
|
||||
string name = Format((BlockID)i, null, Block.Props);
|
||||
static List<string> SupportedBlocks(Player p) {
|
||||
List<string> names = new List<string>();
|
||||
BlockProps[] props = Player.IsSuper(p) ? Block.Props : p.level.Props;
|
||||
|
||||
for (int i = 0; i < props.Length; i++) {
|
||||
string name = Format((BlockID)i, p, props);
|
||||
if (name != null) names.Add(name);
|
||||
}
|
||||
return names;
|
||||
}
|
||||
|
||||
public override void Help(Player p) {
|
||||
Player.Message(p, "%T/MB [block] [message]");
|
||||
Player.Message(p, "%HPlaces a message in your next block.");
|
||||
|
||||
List<string> names = new List<string>();
|
||||
if (Player.IsSuper(p)) CoreNames(names);
|
||||
else AllNames(p, names);
|
||||
|
||||
List<string> names = SupportedBlocks(p);
|
||||
Player.Message(p, "%H Supported blocks: %S{0}", names.Join());
|
||||
Player.Message(p, "%H Use | to separate commands, e.g. /say 1 |/say 2");
|
||||
Player.Message(p, "%H Note: \"@p\" is a placeholder for player who clicked.");
|
||||
|
@ -195,18 +195,15 @@ namespace MCGalaxy.Commands.Building {
|
||||
return Block.GetName(p, block);
|
||||
}
|
||||
|
||||
static void AllNames(Player p, List<string> names) {
|
||||
for (int i = 0; i < Block.ExtendedCount; i++) {
|
||||
string name = Format((ushort)i, p, p.level.Props);
|
||||
if (name != null) names.Add(name);
|
||||
}
|
||||
}
|
||||
|
||||
static void CoreNames(List<string> names) {
|
||||
for (int i = 0; i < Block.Count; i++) {
|
||||
string name = Format((ushort)i, null, Block.Props);
|
||||
static List<string> SupportedBlocks(Player p) {
|
||||
List<string> names = new List<string>();
|
||||
BlockProps[] props = Player.IsSuper(p) ? Block.Props : p.level.Props;
|
||||
|
||||
for (int i = 0; i < props.Length; i++) {
|
||||
string name = Format((BlockID)i, p, props);
|
||||
if (name != null) names.Add(name);
|
||||
}
|
||||
return names;
|
||||
}
|
||||
|
||||
public override void Help(Player p) {
|
||||
@ -215,11 +212,7 @@ namespace MCGalaxy.Commands.Building {
|
||||
Player.Message(p, "%T/Portal [block] multi");
|
||||
Player.Message(p, "%HPlace multiple blocks for entries, then a red block for exit.");
|
||||
Player.Message(p, "%H Note: The exit can be on a different level.");
|
||||
|
||||
List<string> names = new List<string>();
|
||||
if (Player.IsSuper(p)) CoreNames(names);
|
||||
else AllNames(p, names);
|
||||
|
||||
List<string> names = SupportedBlocks(p);
|
||||
Player.Message(p, "%H Supported blocks: %S{0}", names.Join());
|
||||
Player.Message(p, "%T/Portal show %H- Shows portals (green = entry, red = exit)");
|
||||
}
|
||||
|
@ -444,6 +444,8 @@ namespace MCGalaxy {
|
||||
}
|
||||
|
||||
internal bool HasCustomProps(BlockID block) {
|
||||
if ((Props[block].ChangedScope & 2) != 0) return true;
|
||||
|
||||
if (Block.IsPhysicsType(block)) return false;
|
||||
BlockRaw raw = (BlockRaw)block;
|
||||
return CustomBlockDefs[raw] != BlockDefinition.GlobalDefs[raw];
|
||||
@ -453,7 +455,7 @@ namespace MCGalaxy {
|
||||
for (int i = 0; i < Props.Length; i++) {
|
||||
BlockID block = (BlockID)i;
|
||||
if (!HasCustomProps(block)) {
|
||||
Props[i] = BlockDefinition.DefaultProps(block);
|
||||
Props[i] = Block.Props[i];
|
||||
} else {
|
||||
Props[i] = BlockProps.MakeDefault();
|
||||
}
|
||||
@ -462,7 +464,14 @@ namespace MCGalaxy {
|
||||
|
||||
public void UpdateBlockProps() {
|
||||
LoadCoreProps();
|
||||
BlockProps.Load("lvl_" + MapName, Props, PropsLock, true);
|
||||
string propsPath = BlockProps.PropsPath("_" + MapName);
|
||||
|
||||
// backwards compatibility with older versions
|
||||
if (!File.Exists(propsPath)) {
|
||||
BlockProps.Load("lvl_" + MapName, Props, PropsLock, 2, true);
|
||||
} else {
|
||||
BlockProps.Load("_" + MapName, Props, PropsLock, 2, false);
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateBlockHandlers() {
|
||||
|
@ -201,7 +201,6 @@ namespace MCGalaxy {
|
||||
Command.InitAll();
|
||||
CommandPerms.Load();
|
||||
Block.SetBlocks();
|
||||
BlockDefinition.UpdateGlobalBlockProps();
|
||||
Awards.Load();
|
||||
Economy.Load();
|
||||
WarpList.Global.Filename = "extra/warps.save";
|
||||
|
Loading…
x
Reference in New Issue
Block a user