summaryrefslogtreecommitdiffstats
path: root/src/BlockID.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/BlockID.cpp')
-rw-r--r--src/BlockID.cpp958
1 files changed, 958 insertions, 0 deletions
diff --git a/src/BlockID.cpp b/src/BlockID.cpp
new file mode 100644
index 000000000..a4a1ab2d8
--- /dev/null
+++ b/src/BlockID.cpp
@@ -0,0 +1,958 @@
+// BlockID.cpp
+
+// Implements the helper functions for converting Block ID string to int etc.
+
+#include "Globals.h"
+#include "BlockID.h"
+#include "../iniFile/iniFile.h"
+#include "Item.h"
+#include "Mobs/Monster.h"
+
+
+
+
+
+NIBBLETYPE g_BlockLightValue[256];
+NIBBLETYPE g_BlockSpreadLightFalloff[256];
+bool g_BlockTransparent[256];
+bool g_BlockOneHitDig[256];
+bool g_BlockPistonBreakable[256];
+bool g_BlockIsSnowable[256];
+bool g_BlockRequiresSpecialTool[256];
+bool g_BlockIsSolid[256];
+bool g_BlockIsTorchPlaceable[256];
+
+
+
+
+
+class cBlockIDMap
+{
+ // Making the map case-insensitive:
+ struct Comparator
+ {
+ bool operator()(const AString & a_Item1, const AString & a_Item2) const
+ {
+ return (NoCaseCompare(a_Item1, a_Item2) > 0);
+ }
+ } ;
+
+ typedef std::map<AString, std::pair<short, short>, Comparator> ItemMap;
+
+public:
+ cBlockIDMap(void)
+ {
+ cIniFile Ini;
+ if (!Ini.ReadFile("items.ini"))
+ {
+ return;
+ }
+ int KeyID = Ini.FindKey("Items");
+ if (KeyID == cIniFile::noID)
+ {
+ return;
+ }
+ int NumValues = Ini.GetNumValues(KeyID);
+ for (int i = 0; i < NumValues; i++)
+ {
+ AString Name = Ini.GetValueName(KeyID, i);
+ if (Name.empty())
+ {
+ continue;
+ }
+ AString Value = Ini.GetValue(KeyID, i);
+ AddToMap(Name, Value);
+ } // for i - Ini.Values[]
+ }
+
+
+ int Resolve(const AString & a_ItemName)
+ {
+ ItemMap::iterator itr = m_Map.find(a_ItemName);
+ if (itr == m_Map.end())
+ {
+ return -1;
+ }
+ return itr->second.first;
+ }
+
+
+ bool ResolveItem(const AString & a_ItemName, cItem & a_Item)
+ {
+ // Split into parts divided by either ':' or '^'
+ AStringVector Split = StringSplitAndTrim(a_ItemName, ":^");
+ if (Split.empty())
+ {
+ return false;
+ }
+
+ ItemMap::iterator itr = m_Map.find(Split[0]);
+ if (itr != m_Map.end())
+ {
+ // Resolved as a string, assign the type and the default damage / count
+ a_Item.m_ItemType = itr->second.first;
+ a_Item.m_ItemDamage = itr->second.second;
+ if (a_Item.m_ItemDamage == -1)
+ {
+ a_Item.m_ItemDamage = 0;
+ }
+ }
+ else
+ {
+ // Not a resolvable string, try pure numbers: "45:6", "45^6" etc.
+ a_Item.m_ItemType = (short)atoi(Split[0].c_str());
+ if ((a_Item.m_ItemType == 0) && (Split[0] != "0"))
+ {
+ // Parsing the number failed
+ return false;
+ }
+ }
+
+ // Parse the damage, if present:
+ if (Split.size() < 2)
+ {
+ // Not present, set the item as valid and return success:
+ a_Item.m_ItemCount = 1;
+ return true;
+ }
+
+ a_Item.m_ItemDamage = atoi(Split[1].c_str());
+ if ((a_Item.m_ItemDamage == 0) && (Split[1] != "0"))
+ {
+ // Parsing the number failed
+ return false;
+ }
+ a_Item.m_ItemCount = 1;
+ return true;
+ }
+
+
+ AString Desolve(short a_ItemType, short a_ItemDamage)
+ {
+ // First try an exact match, both ItemType and ItemDamage ("birchplanks=5:2"):
+ for (ItemMap::iterator itr = m_Map.begin(), end = m_Map.end(); itr != end; ++itr)
+ {
+ if ((itr->second.first == a_ItemType) && (itr->second.second == a_ItemDamage))
+ {
+ return itr->first;
+ }
+ } // for itr - m_Map[]
+
+ // There is no exact match, try matching ItemType only ("planks=5"):
+ if (a_ItemDamage == 0)
+ {
+ for (ItemMap::iterator itr = m_Map.begin(), end = m_Map.end(); itr != end; ++itr)
+ {
+ if ((itr->second.first == a_ItemType) && (itr->second.second == -1))
+ {
+ return itr->first;
+ }
+ } // for itr - m_Map[]
+ }
+
+ // No match at all, synthesize a string ("5:1"):
+ AString res;
+ if (a_ItemDamage == -1)
+ {
+ Printf(res, "%d", a_ItemType);
+ }
+ else
+ {
+ Printf(res, "%d:%d", a_ItemType, a_ItemDamage);
+ }
+ return res;
+ }
+
+
+protected:
+ ItemMap m_Map;
+
+
+ void AddToMap(const AString & a_Name, const AString & a_Value)
+ {
+ AStringVector Split = StringSplit(a_Value, ":");
+ if (Split.size() == 1)
+ {
+ Split = StringSplit(a_Value, "^");
+ }
+ if (Split.empty())
+ {
+ return;
+ }
+ short ItemType = (short)atoi(Split[0].c_str());
+ short ItemDamage = (Split.size() > 1) ? (short)atoi(Split[1].c_str()) : -1;
+ m_Map[a_Name] = std::make_pair(ItemType, ItemDamage);
+ }
+} ;
+
+
+
+
+
+static cBlockIDMap gsBlockIDMap;
+
+
+
+
+
+/*
+// Quick self-test:
+class Tester
+{
+public:
+ Tester(void)
+ {
+ cItem Item;
+ gsBlockIDMap.ResolveItem("charcoal", Item);
+ AString Charcoal = gsBlockIDMap.Desolve(Item.m_ItemType, Item.m_ItemDamage);
+ ASSERT(Charcoal == "charcoal");
+ }
+} test;
+//*/
+
+
+
+
+
+BLOCKTYPE BlockStringToType(const AString & a_BlockTypeString)
+{
+ int res = atoi(a_BlockTypeString.c_str());
+ if ((res != 0) || (a_BlockTypeString.compare("0") == 0))
+ {
+ // It was a valid number, return that
+ return res;
+ }
+
+ return gsBlockIDMap.Resolve(TrimString(a_BlockTypeString));
+}
+
+
+
+
+bool StringToItem(const AString & a_ItemTypeString, cItem & a_Item)
+{
+ return gsBlockIDMap.ResolveItem(TrimString(a_ItemTypeString), a_Item);
+}
+
+
+
+
+
+AString ItemToString(const cItem & a_Item)
+{
+ return gsBlockIDMap.Desolve(a_Item.m_ItemType, a_Item.m_ItemDamage);
+}
+
+
+
+
+
+AString ItemTypeToString(short a_ItemType)
+{
+ return gsBlockIDMap.Desolve(a_ItemType, -1);
+}
+
+
+
+
+
+AString ItemToFullString(const cItem & a_Item)
+{
+ AString res;
+ Printf(res, "%s:%d * %d", ItemToString(a_Item).c_str(), a_Item.m_ItemDamage, a_Item.m_ItemCount);
+ return res;
+}
+
+
+
+
+
+EMCSBiome StringToBiome(const AString & a_BiomeString)
+{
+ // If it is a number, return it:
+ int res = atoi(a_BiomeString.c_str());
+ if ((res != 0) || (a_BiomeString.compare("0") == 0))
+ {
+ // It was a valid number
+ return (EMCSBiome)res;
+ }
+
+ // Convert using the built-in map:
+ static struct {
+ EMCSBiome m_Biome;
+ const char * m_String;
+ } BiomeMap[] =
+ {
+ {biOcean, "Ocean"} ,
+ {biPlains, "Plains"},
+ {biDesert, "Desert"},
+ {biExtremeHills, "ExtremeHills"},
+ {biForest, "Forest"},
+ {biTaiga, "Taiga"},
+ {biSwampland, "Swampland"},
+ {biRiver, "River"},
+ {biNether, "Hell"},
+ {biNether, "Nether"},
+ {biEnd, "Sky"},
+ {biEnd, "End"},
+ {biFrozenOcean, "FrozenOcean"},
+ {biFrozenRiver, "FrozenRiver"},
+ {biIcePlains, "IcePlains"},
+ {biIcePlains, "Tundra"},
+ {biIceMountains, "IceMountains"},
+ {biMushroomIsland, "MushroomIsland"},
+ {biMushroomShore, "MushroomShore"},
+ {biBeach, "Beach"},
+ {biDesertHills, "DesertHills"},
+ {biForestHills, "ForestHills"},
+ {biTaigaHills, "TaigaHills"},
+ {biExtremeHillsEdge, "ExtremeHillsEdge"},
+ {biJungle, "Jungle"},
+ {biJungleHills, "JungleHills"},
+
+ // Release 1.7 biomes:
+ {biJungleEdge, "JungleEdge"},
+ {biDeepOcean, "DeepOcean"},
+ {biStoneBeach, "StoneBeach"},
+ {biColdBeach, "ColdBeach"},
+ {biBirchForest, "BirchForest"},
+ {biBirchForestHills, "BirchForestHills"},
+ {biRoofedForest, "RoofedForest"},
+ {biColdTaiga, "ColdTaiga"},
+ {biColdTaigaHills, "ColdTaigaHills"},
+ {biMegaTaiga, "MegaTaiga"},
+ {biMegaTaigaHills, "MegaTaigaHills"},
+ {biExtremeHillsPlus, "ExtremeHillsPlus"},
+ {biSavanna, "Savanna"},
+ {biSavannaPlateau, "SavannaPlateau"},
+ {biMesa, "Mesa"},
+ {biMesaPlateauF, "MesaPlateauF"},
+ {biMesaPlateau, "MesaPlateau"},
+
+ // Release 1.7 variants:
+ {biSunflowerPlains, "SunflowerPlains"},
+ {biDesertM, "DesertM"},
+ {biExtremeHillsM, "ExtremeHillsM"},
+ {biFlowerForest, "FlowerForest"},
+ {biTaigaM, "TaigaM"},
+ {biSwamplandM, "SwamplandM"},
+ {biIcePlainsSpikes, "IcePlainsSpikes"},
+ {biJungleM, "JungleM"},
+ {biJungleEdgeM, "JungleEdgeM"},
+ {biBirchForestM, "BirchForestM"},
+ {biBirchForestHillsM, "BirchForestHillsM"},
+ {biRoofedForestM, "RoofedForestM"},
+ {biColdTaigaM, "ColdTaigaM"},
+ {biMegaSpruceTaiga, "MegaSpruceTaiga"},
+ {biMegaSpruceTaigaHills, "MegaSpruceTaigaHills"},
+ {biExtremeHillsPlusM, "ExtremeHillsPlusM"},
+ {biSavannaM, "SavannaM"},
+ {biSavannaPlateauM, "SavannaPlateauM"},
+ {biMesaBryce, "MesaBryce"},
+ {biMesaPlateauFM, "MesaPlateauFM"},
+ {biMesaPlateauM, "MesaPlateauM"},
+ } ;
+
+ for (int i = 0; i < ARRAYCOUNT(BiomeMap); i++)
+ {
+ if (NoCaseCompare(BiomeMap[i].m_String, a_BiomeString) == 0)
+ {
+ return BiomeMap[i].m_Biome;
+ }
+ } // for i - BiomeMap[]
+ return (EMCSBiome)-1;
+}
+
+
+
+
+
+int StringToMobType(const AString & a_MobString)
+{
+ static struct {
+ int m_MobType;
+ const char * m_String;
+ } MobMap [] =
+ {
+ {cMonster::mtCreeper, "Creeper"},
+ {cMonster::mtSkeleton, "Skeleton"},
+ {cMonster::mtSpider, "Spider"},
+ {cMonster::mtGiant, "Giant"},
+ {cMonster::mtZombie, "Zombie"},
+ {cMonster::mtSlime, "Slime"},
+ {cMonster::mtGhast, "Ghast"},
+ {cMonster::mtZombiePigman, "ZombiePigman"},
+ {cMonster::mtEnderman, "Enderman"},
+ {cMonster::mtCaveSpider, "CaveSpider"},
+ {cMonster::mtSilverfish, "SilverFish"},
+ {cMonster::mtBlaze, "Blaze"},
+ {cMonster::mtMagmaCube, "MagmaCube"},
+ {cMonster::mtEnderDragon, "EnderDragon"},
+ {cMonster::mtWither, "Wither"},
+ {cMonster::mtBat, "Bat"},
+ {cMonster::mtWitch, "Witch"},
+ {cMonster::mtPig, "Pig"},
+ {cMonster::mtSheep, "Sheep"},
+ {cMonster::mtCow, "Cow"},
+ {cMonster::mtChicken, "Chicken"},
+ {cMonster::mtSquid, "Squid"},
+ {cMonster::mtWolf, "Wolf"},
+ {cMonster::mtMooshroom, "Mooshroom"},
+ {cMonster::mtSnowGolem, "SnowGolem"},
+ {cMonster::mtOcelot, "Ocelot"},
+ {cMonster::mtIronGolem, "IronGolem"},
+ {cMonster::mtVillager, "Villager"},
+ };
+ for (int i = 0; i < ARRAYCOUNT(MobMap); i++)
+ {
+ if (NoCaseCompare(MobMap[i].m_String, a_MobString) == 0)
+ {
+ return MobMap[i].m_MobType;
+ }
+ } // for i - MobMap[]
+ return -1;
+}
+
+
+
+
+
+eDimension StringToDimension(const AString & a_DimensionString)
+{
+ // First try decoding as a number
+ int res = atoi(a_DimensionString.c_str());
+ if ((res != 0) || (a_DimensionString == "0"))
+ {
+ // It was a valid number
+ return (eDimension)res;
+ }
+
+ // Decode using a built-in map:
+ static struct
+ {
+ eDimension m_Dimension;
+ const char * m_String;
+ } DimensionMap [] =
+ {
+ { dimOverworld, "Overworld"},
+ { dimOverworld, "Normal"},
+ { dimOverworld, "World"},
+ { dimNether, "Nether"},
+ { dimNether, "Hell"}, // Alternate name for End
+ { dimEnd, "End"},
+ { dimEnd, "Sky"}, // Old name for End
+ } ;
+ for (int i = 0; i < ARRAYCOUNT(DimensionMap); i++)
+ {
+ if (NoCaseCompare(DimensionMap[i].m_String, a_DimensionString) == 0)
+ {
+ return DimensionMap[i].m_Dimension;
+ }
+ } // for i - DimensionMap[]
+
+ // Not found
+ return (eDimension)-1000;
+}
+
+
+
+
+
+/// Translates damage type constant to a string representation (built-in).
+AString DamageTypeToString(eDamageType a_DamageType)
+{
+ // Make sure to keep this alpha-sorted.
+ switch (a_DamageType)
+ {
+ case dtAdmin: return "dtAdmin";
+ case dtAttack: return "dtAttack";
+ case dtCactusContact: return "dtCactusContact";
+ case dtDrowning: return "dtDrowning";
+ case dtEnderPearl: return "dtEnderPearl";
+ case dtFalling: return "dtFalling";
+ case dtFireContact: return "dtFireContact";
+ case dtInVoid: return "dtInVoid";
+ case dtLavaContact: return "dtLavaContact";
+ case dtLightning: return "dtLightning";
+ case dtOnFire: return "dtOnFire";
+ case dtPoisoning: return "dtPoisoning";
+ case dtPotionOfHarming: return "dtPotionOfHarming";
+ case dtRangedAttack: return "dtRangedAttack";
+ case dtStarving: return "dtStarving";
+ case dtSuffocating: return "dtSuffocation";
+
+ }
+
+ // Unknown damage type:
+ ASSERT(!"Unknown DamageType");
+ return Printf("dtUnknown_%d", (int)a_DamageType);
+}
+
+
+
+
+
+/// Translates a damage type string to damage type. Takes either a number or a damage type alias (built-in). Returns -1 on failure
+eDamageType StringToDamageType(const AString & a_DamageTypeString)
+{
+ // First try decoding as a number:
+ int res = atoi(a_DamageTypeString.c_str());
+ if ((res != 0) || (a_DamageTypeString == "0"))
+ {
+ // It was a valid number
+ return (eDamageType)res;
+ }
+
+ // Decode using a built-in map:
+ static struct
+ {
+ eDamageType m_DamageType;
+ const char * m_String;
+ } DamageTypeMap [] =
+ {
+ // Cannonical names:
+ { dtAttack, "dtAttack"},
+ { dtRangedAttack, "dtRangedAttack"},
+ { dtLightning, "dtLightning"},
+ { dtFalling, "dtFalling"},
+ { dtDrowning, "dtDrowning"},
+ { dtSuffocating, "dtSuffocation"},
+ { dtStarving, "dtStarving"},
+ { dtCactusContact, "dtCactusContact"},
+ { dtLavaContact, "dtLavaContact"},
+ { dtPoisoning, "dtPoisoning"},
+ { dtOnFire, "dtOnFire"},
+ { dtFireContact, "dtFireContact"},
+ { dtInVoid, "dtInVoid"},
+ { dtPotionOfHarming, "dtPotionOfHarming"},
+ { dtAdmin, "dtAdmin"},
+
+ // Common synonyms:
+ { dtAttack, "dtPawnAttack"},
+ { dtAttack, "dtEntityAttack"},
+ { dtAttack, "dtMob"},
+ { dtAttack, "dtMobAttack"},
+ { dtRangedAttack, "dtArrowAttack"},
+ { dtRangedAttack, "dtArrow"},
+ { dtRangedAttack, "dtProjectile"},
+ { dtFalling, "dtFall"},
+ { dtDrowning, "dtDrown"},
+ { dtSuffocating, "dtSuffocation"},
+ { dtStarving, "dtStarvation"},
+ { dtStarving, "dtHunger"},
+ { dtCactusContact, "dtCactus"},
+ { dtCactusContact, "dtCactuses"},
+ { dtCactusContact, "dtCacti"},
+ { dtLavaContact, "dtLava"},
+ { dtPoisoning, "dtPoison"},
+ { dtOnFire, "dtBurning"},
+ { dtFireContact, "dtInFire"},
+ { dtAdmin, "dtPlugin"},
+ } ;
+ for (int i = 0; i < ARRAYCOUNT(DamageTypeMap); i++)
+ {
+ if (NoCaseCompare(DamageTypeMap[i].m_String, a_DamageTypeString) == 0)
+ {
+ return DamageTypeMap[i].m_DamageType;
+ }
+ } // for i - DamageTypeMap[]
+
+ // Not found:
+ return (eDamageType)-1;
+}
+
+
+
+
+
+cItem GetIniItemSet(cIniFile & a_IniFile, const char * a_Section, const char * a_Key, const char * a_Default)
+{
+ AString ItemStr = a_IniFile.GetValueSet(a_Section, a_Key, a_Default);
+ cItem res;
+ if (!StringToItem(ItemStr, res))
+ {
+ res.Empty();
+ }
+ return res;
+}
+
+
+
+
+
+// This is actually just some code that needs to run at program startup, so it is wrapped into a global var's constructor:
+class cBlockPropertiesInitializer
+{
+public:
+ cBlockPropertiesInitializer(void)
+ {
+ memset(g_BlockLightValue, 0x00, sizeof(g_BlockLightValue));
+ memset(g_BlockSpreadLightFalloff, 0x0f, sizeof(g_BlockSpreadLightFalloff)); // 0x0f means total falloff
+ memset(g_BlockTransparent, 0x00, sizeof(g_BlockTransparent));
+ memset(g_BlockOneHitDig, 0x00, sizeof(g_BlockOneHitDig));
+ memset(g_BlockPistonBreakable, 0x00, sizeof(g_BlockPistonBreakable));
+ memset(g_BlockIsTorchPlaceable, 0x00, sizeof(g_BlockIsTorchPlaceable));
+
+ // Setting bools to true must be done manually, see http://forum.mc-server.org/showthread.php?tid=629&pid=5415#pid5415
+ for (int i = 0; i < ARRAYCOUNT(g_BlockIsSnowable); i++)
+ {
+ g_BlockIsSnowable[i] = true;
+ }
+ memset(g_BlockRequiresSpecialTool, 0x00, sizeof(g_BlockRequiresSpecialTool)); // Set all blocks to false
+
+ // Setting bools to true must be done manually, see http://forum.mc-server.org/showthread.php?tid=629&pid=5415#pid5415
+ for (int i = 0; i < ARRAYCOUNT(g_BlockIsSolid); i++)
+ {
+ g_BlockIsSolid[i] = true;
+ }
+
+ // Emissive blocks
+ g_BlockLightValue[E_BLOCK_FIRE] = 15;
+ g_BlockLightValue[E_BLOCK_GLOWSTONE] = 15;
+ g_BlockLightValue[E_BLOCK_JACK_O_LANTERN] = 15;
+ g_BlockLightValue[E_BLOCK_LAVA] = 15;
+ g_BlockLightValue[E_BLOCK_STATIONARY_LAVA] = 15;
+ g_BlockLightValue[E_BLOCK_END_PORTAL] = 15;
+ g_BlockLightValue[E_BLOCK_REDSTONE_LAMP_ON] = 15;
+ g_BlockLightValue[E_BLOCK_TORCH] = 14;
+ g_BlockLightValue[E_BLOCK_BURNING_FURNACE] = 13;
+ g_BlockLightValue[E_BLOCK_NETHER_PORTAL] = 11;
+ g_BlockLightValue[E_BLOCK_REDSTONE_ORE_GLOWING] = 9;
+ g_BlockLightValue[E_BLOCK_REDSTONE_REPEATER_ON] = 9;
+ g_BlockLightValue[E_BLOCK_REDSTONE_TORCH_ON] = 7;
+ g_BlockLightValue[E_BLOCK_BREWING_STAND] = 1;
+ g_BlockLightValue[E_BLOCK_BROWN_MUSHROOM] = 1;
+ g_BlockLightValue[E_BLOCK_DRAGON_EGG] = 1;
+
+ // Spread blocks
+ g_BlockSpreadLightFalloff[E_BLOCK_AIR] = 1;
+ g_BlockSpreadLightFalloff[E_BLOCK_CAKE] = 1;
+ g_BlockSpreadLightFalloff[E_BLOCK_CHEST] = 1;
+ g_BlockSpreadLightFalloff[E_BLOCK_COBWEB] = 1;
+ g_BlockSpreadLightFalloff[E_BLOCK_CROPS] = 1;
+ g_BlockSpreadLightFalloff[E_BLOCK_FENCE] = 1;
+ g_BlockSpreadLightFalloff[E_BLOCK_FENCE_GATE] = 1;
+ g_BlockSpreadLightFalloff[E_BLOCK_FIRE] = 1;
+ g_BlockSpreadLightFalloff[E_BLOCK_GLASS] = 1;
+ g_BlockSpreadLightFalloff[E_BLOCK_GLASS_PANE] = 1;
+ g_BlockSpreadLightFalloff[E_BLOCK_GLOWSTONE] = 1;
+ g_BlockSpreadLightFalloff[E_BLOCK_IRON_BARS] = 1;
+ g_BlockSpreadLightFalloff[E_BLOCK_IRON_DOOR] = 1;
+ g_BlockSpreadLightFalloff[E_BLOCK_LEAVES] = 1;
+ g_BlockSpreadLightFalloff[E_BLOCK_SIGN_POST] = 1;
+ g_BlockSpreadLightFalloff[E_BLOCK_TORCH] = 1;
+ g_BlockSpreadLightFalloff[E_BLOCK_VINES] = 1;
+ g_BlockSpreadLightFalloff[E_BLOCK_WALLSIGN] = 1;
+ g_BlockSpreadLightFalloff[E_BLOCK_WOODEN_DOOR] = 1;
+
+ // Light in water and lava dissapears faster:
+ g_BlockSpreadLightFalloff[E_BLOCK_LAVA] = 3;
+ g_BlockSpreadLightFalloff[E_BLOCK_STATIONARY_LAVA] = 3;
+ g_BlockSpreadLightFalloff[E_BLOCK_STATIONARY_WATER] = 3;
+ g_BlockSpreadLightFalloff[E_BLOCK_WATER] = 3;
+
+ // Transparent blocks
+ g_BlockTransparent[E_BLOCK_ACTIVATOR_RAIL] = true;
+ g_BlockTransparent[E_BLOCK_AIR] = true;
+ g_BlockTransparent[E_BLOCK_BIG_FLOWER] = true;
+ g_BlockTransparent[E_BLOCK_BROWN_MUSHROOM] = true;
+ g_BlockTransparent[E_BLOCK_CARROTS] = true;
+ g_BlockTransparent[E_BLOCK_CHEST] = true;
+ g_BlockTransparent[E_BLOCK_COBWEB] = true;
+ g_BlockTransparent[E_BLOCK_CROPS] = true;
+ g_BlockTransparent[E_BLOCK_DANDELION] = true;
+ g_BlockTransparent[E_BLOCK_DETECTOR_RAIL] = true;
+ g_BlockTransparent[E_BLOCK_FENCE] = true;
+ g_BlockTransparent[E_BLOCK_FENCE_GATE] = true;
+ g_BlockTransparent[E_BLOCK_FIRE] = true;
+ g_BlockTransparent[E_BLOCK_FLOWER] = true;
+ g_BlockTransparent[E_BLOCK_FLOWER_POT] = true;
+ g_BlockTransparent[E_BLOCK_GLASS] = true;
+ g_BlockTransparent[E_BLOCK_GLASS_PANE] = true;
+ g_BlockTransparent[E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE] = true;
+ g_BlockTransparent[E_BLOCK_ICE] = true;
+ g_BlockTransparent[E_BLOCK_IRON_DOOR] = true;
+ g_BlockTransparent[E_BLOCK_LAVA] = true;
+ g_BlockTransparent[E_BLOCK_LEAVES] = true;
+ g_BlockTransparent[E_BLOCK_LEVER] = true;
+ g_BlockTransparent[E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE] = true;
+ g_BlockTransparent[E_BLOCK_MELON_STEM] = true;
+ g_BlockTransparent[E_BLOCK_NETHER_BRICK_FENCE] = true;
+ g_BlockTransparent[E_BLOCK_NEW_LEAVES] = true;
+ g_BlockTransparent[E_BLOCK_POTATOES] = true;
+ g_BlockTransparent[E_BLOCK_POWERED_RAIL] = true;
+ g_BlockTransparent[E_BLOCK_PISTON_EXTENSION] = true;
+ g_BlockTransparent[E_BLOCK_PUMPKIN_STEM] = true;
+ g_BlockTransparent[E_BLOCK_RAIL] = true;
+ g_BlockTransparent[E_BLOCK_RED_MUSHROOM] = true;
+ g_BlockTransparent[E_BLOCK_SIGN_POST] = true;
+ g_BlockTransparent[E_BLOCK_SNOW] = true;
+ g_BlockTransparent[E_BLOCK_STAINED_GLASS] = true;
+ g_BlockTransparent[E_BLOCK_STAINED_GLASS_PANE] = true;
+ g_BlockTransparent[E_BLOCK_STATIONARY_LAVA] = true;
+ g_BlockTransparent[E_BLOCK_STATIONARY_WATER] = true;
+ g_BlockTransparent[E_BLOCK_STONE_PRESSURE_PLATE] = true;
+ g_BlockTransparent[E_BLOCK_TALL_GRASS] = true;
+ g_BlockTransparent[E_BLOCK_TORCH] = true;
+ g_BlockTransparent[E_BLOCK_VINES] = true;
+ g_BlockTransparent[E_BLOCK_WALLSIGN] = true;
+ g_BlockTransparent[E_BLOCK_WATER] = true;
+ g_BlockTransparent[E_BLOCK_WOODEN_DOOR] = true;
+ g_BlockTransparent[E_BLOCK_WOODEN_PRESSURE_PLATE] = true;
+
+ // TODO: Any other transparent blocks?
+
+ // One hit break blocks:
+ g_BlockOneHitDig[E_BLOCK_ACTIVE_COMPARATOR] = true;
+ g_BlockOneHitDig[E_BLOCK_BIG_FLOWER] = true;
+ g_BlockOneHitDig[E_BLOCK_BROWN_MUSHROOM] = true;
+ g_BlockOneHitDig[E_BLOCK_CARROTS] = true;
+ g_BlockOneHitDig[E_BLOCK_CROPS] = true;
+ g_BlockOneHitDig[E_BLOCK_DANDELION] = true;
+ g_BlockOneHitDig[E_BLOCK_FIRE] = true;
+ g_BlockOneHitDig[E_BLOCK_FLOWER] = true;
+ g_BlockOneHitDig[E_BLOCK_FLOWER_POT] = true;
+ g_BlockOneHitDig[E_BLOCK_INACTIVE_COMPARATOR] = true;
+ g_BlockOneHitDig[E_BLOCK_MELON_STEM] = true;
+ g_BlockOneHitDig[E_BLOCK_POTATOES] = true;
+ g_BlockOneHitDig[E_BLOCK_PUMPKIN_STEM] = true;
+ g_BlockOneHitDig[E_BLOCK_REDSTONE_REPEATER_OFF] = true;
+ g_BlockOneHitDig[E_BLOCK_REDSTONE_REPEATER_ON] = true;
+ g_BlockOneHitDig[E_BLOCK_REDSTONE_TORCH_OFF] = true;
+ g_BlockOneHitDig[E_BLOCK_REDSTONE_TORCH_ON] = true;
+ g_BlockOneHitDig[E_BLOCK_REDSTONE_WIRE] = true;
+ g_BlockOneHitDig[E_BLOCK_RED_MUSHROOM] = true;
+ g_BlockOneHitDig[E_BLOCK_REEDS] = true;
+ g_BlockOneHitDig[E_BLOCK_SAPLING] = true;
+ g_BlockOneHitDig[E_BLOCK_TNT] = true;
+ g_BlockOneHitDig[E_BLOCK_TALL_GRASS] = true;
+ g_BlockOneHitDig[E_BLOCK_TORCH] = true;
+
+ // Blocks that break when pushed by piston:
+ g_BlockPistonBreakable[E_BLOCK_ACTIVE_COMPARATOR] = true;
+ g_BlockPistonBreakable[E_BLOCK_AIR] = true;
+ g_BlockPistonBreakable[E_BLOCK_BED] = true;
+ g_BlockPistonBreakable[E_BLOCK_BIG_FLOWER] = true;
+ g_BlockPistonBreakable[E_BLOCK_BROWN_MUSHROOM] = true;
+ g_BlockPistonBreakable[E_BLOCK_COBWEB] = true;
+ g_BlockPistonBreakable[E_BLOCK_CROPS] = true;
+ g_BlockPistonBreakable[E_BLOCK_DANDELION] = true;
+ g_BlockPistonBreakable[E_BLOCK_DEAD_BUSH] = true;
+ g_BlockPistonBreakable[E_BLOCK_FIRE] = true;
+ g_BlockPistonBreakable[E_BLOCK_FLOWER] = true;
+ g_BlockPistonBreakable[E_BLOCK_INACTIVE_COMPARATOR] = true;
+ g_BlockPistonBreakable[E_BLOCK_IRON_DOOR] = true;
+ g_BlockPistonBreakable[E_BLOCK_JACK_O_LANTERN] = true;
+ g_BlockPistonBreakable[E_BLOCK_LADDER] = true;
+ g_BlockPistonBreakable[E_BLOCK_LAVA] = true;
+ g_BlockPistonBreakable[E_BLOCK_LEVER] = true;
+ g_BlockPistonBreakable[E_BLOCK_MELON] = true;
+ g_BlockPistonBreakable[E_BLOCK_MELON_STEM] = true;
+ g_BlockPistonBreakable[E_BLOCK_PUMPKIN] = true;
+ g_BlockPistonBreakable[E_BLOCK_PUMPKIN_STEM] = true;
+ g_BlockPistonBreakable[E_BLOCK_REDSTONE_REPEATER_OFF] = true;
+ g_BlockPistonBreakable[E_BLOCK_REDSTONE_REPEATER_ON] = true;
+ g_BlockPistonBreakable[E_BLOCK_REDSTONE_TORCH_OFF] = true;
+ g_BlockPistonBreakable[E_BLOCK_REDSTONE_TORCH_ON] = true;
+ g_BlockPistonBreakable[E_BLOCK_REDSTONE_WIRE] = true;
+ g_BlockPistonBreakable[E_BLOCK_RED_MUSHROOM] = true;
+ g_BlockPistonBreakable[E_BLOCK_REEDS] = true;
+ g_BlockPistonBreakable[E_BLOCK_SNOW] = true;
+ g_BlockPistonBreakable[E_BLOCK_STATIONARY_LAVA] = true;
+ g_BlockPistonBreakable[E_BLOCK_STATIONARY_WATER] = true;
+ g_BlockPistonBreakable[E_BLOCK_STONE_BUTTON] = true;
+ g_BlockPistonBreakable[E_BLOCK_STONE_PRESSURE_PLATE] = true;
+ g_BlockPistonBreakable[E_BLOCK_TALL_GRASS] = true;
+ g_BlockPistonBreakable[E_BLOCK_TORCH] = true;
+ g_BlockPistonBreakable[E_BLOCK_VINES] = true;
+ g_BlockPistonBreakable[E_BLOCK_WATER] = true;
+ g_BlockPistonBreakable[E_BLOCK_WOODEN_BUTTON] = true;
+ g_BlockPistonBreakable[E_BLOCK_WOODEN_DOOR] = true;
+ g_BlockPistonBreakable[E_BLOCK_WOODEN_PRESSURE_PLATE] = true;
+
+
+ // Blocks that cannot be snowed over:
+ g_BlockIsSnowable[E_BLOCK_ACTIVE_COMPARATOR] = false;
+ g_BlockIsSnowable[E_BLOCK_AIR] = false;
+ g_BlockIsSnowable[E_BLOCK_BIG_FLOWER] = false;
+ g_BlockIsSnowable[E_BLOCK_BROWN_MUSHROOM] = false;
+ g_BlockIsSnowable[E_BLOCK_CACTUS] = false;
+ g_BlockIsSnowable[E_BLOCK_CHEST] = false;
+ g_BlockIsSnowable[E_BLOCK_CROPS] = false;
+ g_BlockIsSnowable[E_BLOCK_DANDELION] = false;
+ g_BlockIsSnowable[E_BLOCK_FIRE] = false;
+ g_BlockIsSnowable[E_BLOCK_FLOWER] = false;
+ g_BlockIsSnowable[E_BLOCK_GLASS] = false;
+ g_BlockIsSnowable[E_BLOCK_ICE] = false;
+ g_BlockIsSnowable[E_BLOCK_INACTIVE_COMPARATOR] = false;
+ g_BlockIsSnowable[E_BLOCK_LAVA] = false;
+ g_BlockIsSnowable[E_BLOCK_LILY_PAD] = false;
+ g_BlockIsSnowable[E_BLOCK_REDSTONE_REPEATER_OFF] = false;
+ g_BlockIsSnowable[E_BLOCK_REDSTONE_REPEATER_ON] = false;
+ g_BlockIsSnowable[E_BLOCK_REDSTONE_TORCH_OFF] = false;
+ g_BlockIsSnowable[E_BLOCK_REDSTONE_TORCH_ON] = false;
+ g_BlockIsSnowable[E_BLOCK_REDSTONE_WIRE] = false;
+ g_BlockIsSnowable[E_BLOCK_RED_MUSHROOM] = false;
+ g_BlockIsSnowable[E_BLOCK_REEDS] = false;
+ g_BlockIsSnowable[E_BLOCK_SAPLING] = false;
+ g_BlockIsSnowable[E_BLOCK_SIGN_POST] = false;
+ g_BlockIsSnowable[E_BLOCK_SNOW] = false;
+ g_BlockIsSnowable[E_BLOCK_STAINED_GLASS] = false;
+ g_BlockIsSnowable[E_BLOCK_STAINED_GLASS_PANE] = false;
+ g_BlockIsSnowable[E_BLOCK_STATIONARY_LAVA] = false;
+ g_BlockIsSnowable[E_BLOCK_STATIONARY_WATER] = false;
+ g_BlockIsSnowable[E_BLOCK_TALL_GRASS] = false;
+ g_BlockIsSnowable[E_BLOCK_TNT] = false;
+ g_BlockIsSnowable[E_BLOCK_TORCH] = false;
+ g_BlockIsSnowable[E_BLOCK_VINES] = false;
+ g_BlockIsSnowable[E_BLOCK_WALLSIGN] = false;
+ g_BlockIsSnowable[E_BLOCK_WATER] = false;
+
+
+ // Blocks that don't drop without a special tool:
+ g_BlockRequiresSpecialTool[E_BLOCK_BRICK] = true;
+ g_BlockRequiresSpecialTool[E_BLOCK_CAULDRON] = true;
+ g_BlockRequiresSpecialTool[E_BLOCK_COAL_ORE] = true;
+ g_BlockRequiresSpecialTool[E_BLOCK_COBBLESTONE] = true;
+ g_BlockRequiresSpecialTool[E_BLOCK_COBBLESTONE_STAIRS] = true;
+ g_BlockRequiresSpecialTool[E_BLOCK_COBWEB] = true;
+ g_BlockRequiresSpecialTool[E_BLOCK_DIAMOND_BLOCK] = true;
+ g_BlockRequiresSpecialTool[E_BLOCK_DIAMOND_ORE] = true;
+ g_BlockRequiresSpecialTool[E_BLOCK_DOUBLE_STONE_SLAB] = true;
+ g_BlockRequiresSpecialTool[E_BLOCK_EMERALD_ORE] = true;
+ g_BlockRequiresSpecialTool[E_BLOCK_END_STONE] = true;
+ g_BlockRequiresSpecialTool[E_BLOCK_GOLD_BLOCK] = true;
+ g_BlockRequiresSpecialTool[E_BLOCK_GOLD_ORE] = true;
+ g_BlockRequiresSpecialTool[E_BLOCK_IRON_BLOCK] = true;
+ g_BlockRequiresSpecialTool[E_BLOCK_IRON_ORE] = true;
+ g_BlockRequiresSpecialTool[E_BLOCK_LAPIS_BLOCK] = true;
+ g_BlockRequiresSpecialTool[E_BLOCK_LAPIS_ORE] = true;
+ g_BlockRequiresSpecialTool[E_BLOCK_MOSSY_COBBLESTONE] = true;
+ g_BlockRequiresSpecialTool[E_BLOCK_NETHERRACK] = true;
+ g_BlockRequiresSpecialTool[E_BLOCK_NETHER_BRICK] = true;
+ g_BlockRequiresSpecialTool[E_BLOCK_NETHER_BRICK_STAIRS] = true;
+ g_BlockRequiresSpecialTool[E_BLOCK_OBSIDIAN] = true;
+ g_BlockRequiresSpecialTool[E_BLOCK_REDSTONE_ORE] = true;
+ g_BlockRequiresSpecialTool[E_BLOCK_REDSTONE_ORE_GLOWING] = true;
+ g_BlockRequiresSpecialTool[E_BLOCK_SANDSTONE] = true;
+ g_BlockRequiresSpecialTool[E_BLOCK_SANDSTONE_STAIRS] = true;
+ g_BlockRequiresSpecialTool[E_BLOCK_SNOW] = true;
+ g_BlockRequiresSpecialTool[E_BLOCK_STONE] = true;
+ g_BlockRequiresSpecialTool[E_BLOCK_STONE_BRICKS] = true;
+ g_BlockRequiresSpecialTool[E_BLOCK_STONE_BRICK_STAIRS] = true;
+ g_BlockRequiresSpecialTool[E_BLOCK_STONE_PRESSURE_PLATE] = true;
+ g_BlockRequiresSpecialTool[E_BLOCK_STONE_SLAB] = true;
+ g_BlockRequiresSpecialTool[E_BLOCK_VINES] = true;
+
+ // Nonsolid blocks:
+ g_BlockIsSolid[E_BLOCK_ACTIVATOR_RAIL] = false;
+ g_BlockIsSolid[E_BLOCK_AIR] = false;
+ g_BlockIsSolid[E_BLOCK_BIG_FLOWER] = false;
+ g_BlockIsSolid[E_BLOCK_BROWN_MUSHROOM] = false;
+ g_BlockIsSolid[E_BLOCK_CARROTS] = false;
+ g_BlockIsSolid[E_BLOCK_COBWEB] = false;
+ g_BlockIsSolid[E_BLOCK_CROPS] = false;
+ g_BlockIsSolid[E_BLOCK_DANDELION] = false;
+ g_BlockIsSolid[E_BLOCK_DETECTOR_RAIL] = false;
+ g_BlockIsSolid[E_BLOCK_END_PORTAL] = false;
+ g_BlockIsSolid[E_BLOCK_FIRE] = false;
+ g_BlockIsSolid[E_BLOCK_FLOWER] = false;
+ g_BlockIsSolid[E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE] = false;
+ g_BlockIsSolid[E_BLOCK_LAVA] = false;
+ g_BlockIsSolid[E_BLOCK_LEVER] = false;
+ g_BlockIsSolid[E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE] = false;
+ g_BlockIsSolid[E_BLOCK_MELON_STEM] = false;
+ g_BlockIsSolid[E_BLOCK_NETHER_PORTAL] = false;
+ g_BlockIsSolid[E_BLOCK_PISTON_EXTENSION] = false;
+ g_BlockIsSolid[E_BLOCK_RAIL] = false;
+ g_BlockIsSolid[E_BLOCK_REDSTONE_TORCH_OFF] = false;
+ g_BlockIsSolid[E_BLOCK_REDSTONE_TORCH_ON] = false;
+ g_BlockIsSolid[E_BLOCK_REDSTONE_WIRE] = false;
+ g_BlockIsSolid[E_BLOCK_RED_MUSHROOM] = false;
+ g_BlockIsSolid[E_BLOCK_REEDS] = false;
+ g_BlockIsSolid[E_BLOCK_SAPLING] = false;
+ g_BlockIsSolid[E_BLOCK_SIGN_POST] = false;
+ g_BlockIsSolid[E_BLOCK_SNOW] = false;
+ g_BlockIsSolid[E_BLOCK_STATIONARY_LAVA] = false;
+ g_BlockIsSolid[E_BLOCK_STATIONARY_WATER] = false;
+ g_BlockIsSolid[E_BLOCK_STONE_BUTTON] = false;
+ g_BlockIsSolid[E_BLOCK_STONE_PRESSURE_PLATE] = false;
+ g_BlockIsSolid[E_BLOCK_TALL_GRASS] = false;
+ g_BlockIsSolid[E_BLOCK_TORCH] = false;
+ g_BlockIsSolid[E_BLOCK_TRIPWIRE] = false;
+ g_BlockIsSolid[E_BLOCK_VINES] = false;
+ g_BlockIsSolid[E_BLOCK_WALLSIGN] = false;
+ g_BlockIsSolid[E_BLOCK_WATER] = false;
+ g_BlockIsSolid[E_BLOCK_WOODEN_BUTTON] = false;
+ g_BlockIsSolid[E_BLOCK_WOODEN_PRESSURE_PLATE] = false;
+ g_BlockIsSolid[E_BLOCK_WOODEN_SLAB] = false;
+
+ // Torch placeable blocks:
+ g_BlockIsTorchPlaceable[E_BLOCK_BEDROCK] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_BLOCK_OF_COAL] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_BLOCK_OF_REDSTONE] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_BOOKCASE] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_BRICK] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_CLAY] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_COAL_ORE] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_COBBLESTONE] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_COMMAND_BLOCK] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_CRAFTING_TABLE] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_DIAMOND_BLOCK] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_DIAMOND_ORE] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_DIRT] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_DISPENSER] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_DOUBLE_STONE_SLAB] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_DOUBLE_WOODEN_SLAB] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_DROPPER] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_EMERALD_BLOCK] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_EMERALD_ORE] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_END_STONE] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_FURNACE] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_GLOWSTONE] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_GOLD_BLOCK] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_GOLD_ORE] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_GRASS] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_GRAVEL] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_HARDENED_CLAY] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_HAY_BALE] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_HUGE_BROWN_MUSHROOM] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_HUGE_RED_MUSHROOM] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_IRON_BLOCK] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_IRON_ORE] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_JACK_O_LANTERN] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_JUKEBOX] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_LAPIS_BLOCK] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_LAPIS_ORE] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_LOG] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_MELON] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_MOSSY_COBBLESTONE] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_MYCELIUM] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_NETHERRACK] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_NETHER_BRICK] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_NETHER_QUARTZ_ORE] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_NOTE_BLOCK] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_OBSIDIAN] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_PACKED_ICE] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_PLANKS] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_PUMPKIN] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_QUARTZ_BLOCK] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_REDSTONE_LAMP_OFF] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_REDSTONE_LAMP_ON] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_REDSTONE_ORE] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_REDSTONE_ORE_GLOWING] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_SANDSTONE] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_SAND] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_SILVERFISH_EGG] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_SPONGE] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_STAINED_CLAY] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_WOOL] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_STONE] = true;
+ g_BlockIsTorchPlaceable[E_BLOCK_STONE_BRICKS] = true;
+ }
+} BlockPropertiesInitializer;
+
+
+
+
+