1
0

Merge branch 'master' into ballisticmissiles

Conflicts:
	src/ClientHandle.cpp
This commit is contained in:
Tiger Wang 2014-03-09 12:53:50 +00:00
commit c2978a3457
134 changed files with 3964 additions and 1400 deletions

View File

@ -22,8 +22,10 @@ Code Stuff
- This helps prevent mistakes such as `if (a & 1 == 0)`
* White space is free, so use it freely
- "freely" as in "plentifully", not "arbitrarily"
* All `case` statements inside a `switch` need an extra indent.
* Each and every control statement deserves its braces. This helps maintainability later on when the file is edited, lines added or removed - the control logic doesn't break so easily.
- The only exception: a `switch` statement with all `case` statements being a single short statement is allowed to use the short brace-less form.
- These two rules really mean that indent is governed by braces
* Add an empty last line in all source files (GCC and GIT can complain otherwise)
* Use doxy-comments for functions in the header file, format as `/** Description */`
* Use spaces after the comment markers: `// Comment` instead of `//Comment`

View File

@ -665,9 +665,7 @@ WARN_LOGFILE =
# directories like "/usr/src/myproject". Separate the files or directories
# with spaces.
INPUT = source \
iniFile \
WebServer
INPUT = src
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is

View File

@ -1,2 +1,3 @@
*.txt
*.md
*/

View File

@ -0,0 +1,29 @@
-- @EnableMobDebug.lua
-- Enables the MobDebug debugger, used by ZeroBrane Studio, for a plugin
-- Needs to be named with a @ at the start so that it's loaded as the first file of the plugin
--[[
Usage:
Copy this file to your plugin's folder when you want to debug that plugin
You should neither check this file into the plugin's version control system,
nor distribute it in the final release.
--]]
-- Try to load the debugger, be silent about failures:
local IsSuccess, MobDebug = pcall(require, "mobdebug")
if (IsSuccess) then
MobDebug.start()
-- The debugger will automatically put a breakpoint on this line, use this opportunity to set more breakpoints in your code
LOG(cPluginManager:GetCurrentPlugin():GetName() .. ": MobDebug enabled")
end

View File

@ -134,6 +134,7 @@ g_APIDesc =
HasBlockSkyLights = { Params = "", Return = "bool", Notes = "Returns true if current datatypes include skylight" },
HasBlockTypes = { Params = "", Return = "bool", Notes = "Returns true if current datatypes include block types" },
LoadFromSchematicFile = { Params = "FileName", Return = "", Notes = "Clears current content and loads new content from the specified schematic file. Returns true if successful. Returns false and logs error if unsuccessful, old content is preserved in such a case." },
LoadFromSchematicString = { Params = "SchematicData", Return = "", Notes = "Clears current content and loads new content from the specified string (assumed to contain .schematic data). Returns true if successful. Returns false and logs error if unsuccessful, old content is preserved in such a case." },
Merge =
{
{ Params = "BlockAreaSrc, {{Vector3i|RelMinCoords}}, Strategy", Return = "", Notes = "Merges BlockAreaSrc into this object at the specified relative coords, using the specified strategy" },
@ -161,6 +162,7 @@ g_APIDesc =
RotateCW = { Params = "", Return = "", Notes = "Rotates the block area around the Y axis, clockwise (north -> east). Modifies blocks' metas (if present) to match." },
RotateCWNoMeta = { Params = "", Return = "", Notes = "Rotates the block area around the Y axis, clockwise (north -> east). Doesn't modify blocks' metas." },
SaveToSchematicFile = { Params = "FileName", Return = "", Notes = "Saves the current contents to a schematic file. Returns true if successful." },
SaveToSchematicString = { Params = "", Return = "string", Notes = "Saves the current contents to a string (in a .schematic file format). Returns the data if successful, nil if failed." },
SetBlockLight = { Params = "BlockX, BlockY, BlockZ, BlockLight", Return = "", Notes = "Sets the blocklight at the specified absolute coords" },
SetBlockMeta = { Params = "BlockX, BlockY, BlockZ, BlockMeta", Return = "", Notes = "Sets the block meta at the specified absolute coords" },
SetBlockSkyLight = { Params = "BlockX, BlockY, BlockZ, SkyLight", Return = "", Notes = "Sets the skylight at the specified absolute coords" },
@ -290,6 +292,38 @@ g_APIDesc =
}, -- AdditionalInfo
}, -- cBlockArea
cBlockInfo =
{
Desc = [[
This class is used to query and register block properties.
]],
Functions =
{
FullyOccupiesVoxel = { Params = "Type", Return = "bool", Notes = "(STATIC) Returns whether the specified block fully occupies its voxel." },
Get = { Params = "Type", Return = "{{cBlockInfo}}", Notes = "(STATIC) Returns the {{cBlockInfo}} structure for the specified type." },
GetLightValue = { Params = "Type", Return = "number", Notes = "(STATIC) Returns how much light the specified block emits on its own." },
GetSpreadLightFalloff = { Params = "Type", Return = "number", Notes = "(STATIC) Returns how much light the specified block consumes." },
IsOneHitDig = { Params = "Type", Return = "bool", Notes = "(STATIC) Returns whether the specified block will be destroyed after a single hit." },
IsPistonBreakable = { Params = "Type", Return = "bool", Notes = "(STATIC) Returns whether a piston can break the specified block." },
IsSnowable = { Params = "Type", Return = "bool", Notes = "(STATIC) Returns whether the specified block can hold snow atop." },
IsSolid = { Params = "Type", Return = "bool", Notes = "(STATIC) Returns whether the specified block is solid." },
IsTransparent = { Params = "Type", Return = "bool", Notes = "(STATIC) Returns whether the specified block is transparent." },
RequiresSpecialTool = { Params = "Type", Return = "bool", Notes = "(STATIC) Returns whether the specified block requires a special tool to drop." },
},
Variables =
{
m_FullyOccupiesVoxel = { Type = "bool", Notes = "Does this block fully occupy its voxel - is it a 'full' block?" },
m_IsSnowable = { Type = "bool", Notes = "Can this block hold snow atop?" },
m_IsSolid = { Type = "bool", Notes = "Is this block solid (player cannot walk through)?" },
m_LightValue = { Type = "number", Notes = "How much light do the blocks emit on their own?" },
m_OneHitDig = { Type = "bool", Notes = "Is a block destroyed after a single hit?" },
m_PistonBreakable = { Type = "bool", Notes = "Can a piston break this block?" },
m_RequiresSpecialTool = { Type = "bool", Notes = "Does this block require a tool to drop?" },
m_SpreadLightFalloff = { Type = "number", Notes = "How much light do the blocks consume?" },
m_Transparent = { Type = "bool", Notes = "Is a block completely transparent? (light doesn't get decreased(?))" },
},
}, -- cBlockInfo
cChatColor =
{
Desc = [[
@ -451,6 +485,58 @@ end
},
}, -- cClientHandle
cCompositeChat =
{
Desc = [[
Encapsulates a chat message that can contain various formatting, URLs, commands executed on click
and commands suggested on click. The chat message can be sent by the regular chat-sending functions,
{{cPlayer}}:SendMessage(), {{cWorld}}:BroadcastChat() and {{cRoot}}:BroadcastChat().</p>
<p>
Note that most of the functions in this class are so-called modifiers - they modify the object and
then return the object itself, so that they can be chained one after another.
]],
Functions =
{
constructor =
{
{ Params = "", Return = "", Notes = "Creates an empty chat message" },
{ Params = "Text", Return = "", Notes = "Creates a chat message containing the specified text, parsed by the ParseText() function. This allows easy migration from old chat messages." },
},
AddRunCommandPart = { Params = "Text, Command, [Style]", Return = "self", Notes = "Adds a text which, when clicked, runs the specified command. Chaining." },
AddSuggestCommandPart = { Params = "Text, Command, [Style]", Return = "self", Notes = "Adds a text which, when clicked, puts the specified command into the player's chat input area. Chaining." },
AddTextPart = { Params = "Text, [Style]", Return = "self", Notes = "Adds a regular text. Chaining." },
AddUrlPart = { Params = "Text, Url, [Style]", Return = "self", Notes = "Adds a text which, when clicked, opens up a browser at the specified URL. Chaining." },
Clear = { Params = "", Return = "", Notes = "Removes all parts from this object" },
GetMessageType = { Params = "", Return = "MessageType", Notes = "Returns the MessageType (mtXXX constant) that is associated with this message. When sent to a player, the message will be formatted according to this message type and the player's settings (adding \"[INFO]\" prefix etc.)" },
ParseText = { Params = "Text", Return = "self", Notes = "Adds text, while recognizing http and https URLs and old-style formatting codes (\"@2\"). Chaining." },
SetMessageType = { Params = "MessageType", Return = "self", Notes = "Sets the MessageType (mtXXX constant) that is associated with this message. When sent to a player, the message will be formatted according to this message type and the player's settings (adding \"[INFO]\" prefix etc.) Chaining." },
UnderlineUrls = { Params = "", Return = "self", Notes = "Makes all URL parts contained in the message underlined. Doesn't affect parts added in the future. Chaining." },
},
AdditionalInfo =
{
{
Header = "Chaining example",
Contents = [[
Sending a chat message that is composed of multiple different parts has been made easy thanks to
chaining. Consider the following example that shows how a message containing all kinds of parts
is sent (adapted from the Debuggers plugin):
<pre class="prettyprint lang-lua">
function OnPlayerJoined(a_Player)
-- Send an example composite chat message to the player:
a_Player:SendMessage(cCompositeChat()
:AddTextPart("Hello, ")
:AddUrlPart(a_Player:GetName(), "www.mc-server.org", "u@2") -- Colored underlined link
:AddSuggestCommandPart(", and welcome.", "/help", "u") -- Underlined suggest-command
:AddRunCommandPart(" SetDay", "/time set 0") -- Regular text that will execute command when clicked
:SetMessageType(mtJoin) -- It is a join-message
)
end</pre>
]],
},
}, -- AdditionalInfo
}, -- cCompositeChat
cCraftingGrid =
{
Desc = [[
@ -1115,6 +1201,42 @@ local Item5 = cItem(E_ITEM_DIAMOND_CHESTPLATE, 1, 0, "thorns=1;unbreaking=3");
},
}, -- cItem
cObjective =
{
Desc = [[
This class represents a single scoreboard objective.
]],
Functions =
{
AddScore = { Params = "string, number", Return = "Score", Notes = "Adds a value to the score of the specified player and returns the new value." },
GetDisplayName = { Params = "", Return = "string", Notes = "Returns the display name of the objective. This name will be shown to the connected players." },
GetName = { Params = "", Return = "string", Notes = "Returns the internal name of the objective." },
GetScore = { Params = "string", Return = "Score", Notes = "Returns the score of the specified player." },
GetType = { Params = "", Return = "eType", Notes = "Returns the type of the objective. (i.e what is being tracked)" },
Reset = { Params = "", Return = "", Notes = "Resets the scores of the tracked players." },
ResetScore = { Params = "string", Return = "", Notes = "Reset the score of the specified player." },
SetDisplayName = { Params = "string", Return = "", Notes = "Sets the display name of the objective." },
SetScore = { Params = "string, Score", Return = "", Notes = "Sets the score of the specified player." },
SubScore = { Params = "string, number", Return = "Score", Notes = "Subtracts a value from the score of the specified player and returns the new value." },
},
Constants =
{
otAchievement = { Notes = "" },
otDeathCount = { Notes = "" },
otDummy = { Notes = "" },
otHealth = { Notes = "" },
otPlayerKillCount = { Notes = "" },
otStat = { Notes = "" },
otStatBlockMine = { Notes = "" },
otStatEntityKill = { Notes = "" },
otStatEntityKilledBy = { Notes = "" },
otStatItemBreak = { Notes = "" },
otStatItemCraft = { Notes = "" },
otStatItemUse = { Notes = "" },
otTotalKillCount = { Notes = "" },
},
}, -- cObjective
cPainting =
{
Desc = "This class represents a painting in the world. These paintings are special and different from Vanilla in that they can be critical-hit.",
@ -1773,6 +1895,7 @@ cPluginManager.AddHook(cPluginManager.HOOK_CHAT, OnChatMessage);
BroadcastChatInfo = { Params = "Message", Return = "", Notes = "Prepends Yellow [INFO] / colours entire text (depending on ShouldUseChatPrefixes()) and broadcasts message. For informational messages, such as command usage." },
BroadcastChatSuccess = { Params = "Message", Return = "", Notes = "Prepends Green [INFO] / colours entire text (depending on ShouldUseChatPrefixes()) and broadcasts message. For success messages." },
BroadcastChatWarning = { Params = "Message", Return = "", Notes = "Prepends Rose [WARN] / colours entire text (depending on ShouldUseChatPrefixes()) and broadcasts message. For concerning events, such as plugin reload etc." },
CreateAndInitializeWorld = { Params = "WorldName", Return = "{{cWorld|cWorld}}", Notes = "Creates a new world and initializes it. If there is a world whith the same name it returns nil." },
FindAndDoWithPlayer = { Params = "PlayerName, CallbackFunction", Return = "", Notes = "Calls the given callback function for the given player." },
ForEachPlayer = { Params = "CallbackFunction", Return = "", Notes = "Calls the given callback function for each player. The callback function has the following signature: <pre class=\"prettyprint lang-lua\">function Callback({{cPlayer|cPlayer}})</pre>" },
ForEachWorld = { Params = "CallbackFunction", Return = "", Notes = "Calls the given callback function for each world. The callback function has the following signature: <pre class=\"prettyprint lang-lua\">function Callback({{cWorld|cWorld}})</pre>" },
@ -1821,6 +1944,36 @@ end
},
}, -- cRoot
cScoreboard =
{
Desc = [[
This class manages the objectives and teams of a single world.
]],
Functions =
{
AddPlayerScore = { Params = "Name, Type, Value", Return = "", Notes = "Adds a value to all player scores of the specified objective type." },
ForEachObjective = { Params = "CallBackFunction, [CallbackData]", Return = "bool", Notes = "Calls the specified callback for each objective in the scoreboard. Returns true if all objectives have been processed (including when there are zero objectives), or false if the callback function has aborted the enumeration by returning true. The callback function has the following signature: <pre class=\"prettyprint lang-lua\">function Callback({{cObjective|Objective}}, [CallbackData])</pre> The callback should return false or no value to continue with the next objective, or true to abort the enumeration." },
ForEachTeam = { Params = "CallBackFunction, [CallbackData]", Return = "bool", Notes = "Calls the specified callback for each team in the scoreboard. Returns true if all teams have been processed (including when there are zero teams), or false if the callback function has aborted the enumeration by returning true. The callback function has the following signature: <pre class=\"prettyprint lang-lua\">function Callback({{cObjective|Objective}}, [CallbackData])</pre> The callback should return false or no value to continue with the next team, or true to abort the enumeration." },
GetNumObjectives = { Params = "", Return = "number", Notes = "Returns the nuber of registered objectives." },
GetNumTeams = { Params = "", Return = "number", Notes = "Returns the number of registered teams." },
GetObjective = { Params = "string", Return = "{{cObjective}}", Notes = "Returns the objective with the specified name." },
GetObjectiveIn = { Params = "DisplaySlot", Return = "{{cObjective}}", Notes = "Returns the objective in the specified display slot. Can be nil." },
GetTeam = { Params = "string", Return = "{{cTeam}}", Notes = "Returns the team with the specified name." },
RegisterObjective = { Params = "Name, DisplayName, Type", Return = "{{cObjective}}", Notes = "Registers a new scoreboard objective. Returns the {{cObjective}} instance, nil on error." },
RegisterTeam = { Params = "Name, DisplayName, Prefix, Suffix", Return = "{{cTeam}}", Notes = "Registers a new team. Returns the {{cTeam}} instance, nil on error." },
RemoveObjective = { Params = "string", Return = "bool", Notes = "Removes the objective with the specified name. Returns true if operation was successful." },
RemoveTeam = { Params = "string", Return = "bool", Notes = "Removes the team with the specified name. Returns true if operation was successful." },
SetDisplay = { Params = "Name, DisplaySlot", Return = "", Notes = "Updates the currently displayed objective." },
},
Constants =
{
dsCount = { Notes = "" },
dsList = { Notes = "" },
dsName = { Notes = "" },
dsSidebar = { Notes = "" },
},
}, -- cScoreboard
cServer =
{
Desc = [[
@ -1841,6 +1994,32 @@ end
},
}, -- cServer
cTeam =
{
Desc = [[
This class manages a single player team.
]],
Functions =
{
AddPlayer = { Params = "string", Returns = "bool", Notes = "Adds a player to this team. Returns true if the operation was successful." },
AllowsFriendlyFire = { Params = "", Return = "bool", Notes = "Returns whether team friendly fire is allowed." },
CanSeeFriendlyInvisible = { Params = "", Return = "bool", Notes = "Returns whether players can see invisible teammates." },
HasPlayer = { Params = "string", Returns = "bool", Notes = "Returns whether the specified player is a member of this team." },
GetDisplayName = { Params = "", Return = "string", Notes = "Returns the display name of the team." },
GetName = { Params = "", Return = "string", Notes = "Returns the internal name of the team." },
GetNumPlayers = { Params = "", Return = "number", Notes = "Returns the number of registered players." },
GetPrefix = { Params = "", Return = "string", Notes = "Returns the prefix prepended to the names of the members of this team." },
RemovePlayer = { Params = "string", Returns = "bool", Notes = "Removes the player with the specified name from this team. Returns true if the operation was successful." },
Reset = { Params = "", Returns = "", Notes = "Removes all players from this team." },
GetSuffix = { Params = "", Return = "string", Notes = "Returns the suffix appended to the names of the members of this team." },
SetCanSeeFriendlyInvisible = { Params = "bool", Return = "", Notes = "Set whether players can see invisible teammates." },
SetDisplayName = { Params = "string", Return = "", Notes = "Sets the display name of this team. (i.e. what will be shown to the players)" },
SetFriendlyFire = { Params = "bool", Return = "", Notes = "Sets whether team friendly fire is allowed." },
SetPrefix = { Params = "string", Return = "", Notes = "Sets the prefix prepended to the names of the members of this team." },
SetSuffix = { Params = "string", Return = "", Notes = "Sets the suffix appended to the names of the members of this team." },
},
}, -- cTeam
cTNTEntity =
{
Desc = "This class manages a TNT entity.",
@ -1973,7 +2152,9 @@ end
DoWithDropSpenserAt = { Params = "X, Y, Z, CallbackFunction, [CallbackData]", Return = "bool", Notes = "If there is a dropper or a dispenser at the specified coords, calls the CallbackFunction with the {{cDropSpenserEntity}} parameter representing the dropper or dispenser. The CallbackFunction has the following signature: <pre class=\"prettyprint lang-lua\">function Callback({{cDropSpenserEntity|DropSpenserEntity}}, [CallbackData])</pre> Note that this can be used to access both dispensers and droppers in a similar way. The function returns false if there is neither dispenser nor dropper, or if there is, it returns the bool value that the callback has returned." },
DoWithDropperAt = { Params = "X, Y, Z, CallbackFunction, [CallbackData]", Return = "bool", Notes = "If there is a dropper at the specified coords, calls the CallbackFunction with the {{cDropperEntity}} parameter representing the dropper. The CallbackFunction has the following signature: <pre class=\"prettyprint lang-lua\">function Callback({{cDropperEntity|DropperEntity}}, [CallbackData])</pre> The function returns false if there is no dropper, or if there is, it returns the bool value that the callback has returned." },
DoWithEntityByID = { Params = "EntityID, CallbackFunction, [CallbackData]", Return = "bool", Notes = "If an entity with the specified ID exists, calls the callback with the {{cEntity}} parameter representing the entity. The CallbackFunction has the following signature: <pre class=\"prettyprint lang-lua\">function Callback({{cEntity|Entity}}, [CallbackData])</pre> The function returns false if the entity was not found, and it returns the same bool value that the callback has returned if the entity was found." },
DoWithFlowerPotAt = { Params = "X, Y, Z, CallbackFunction, [CallbackData]", Return = "bool", Notes = "If there is a flower pot at the specified coords, calls the CallbackFunction with the {{cFlowerPotEntity}} parameter representing the flower pot. The CallbackFunction has the following signature: <pre class=\"prettyprint lang-lua\">function Callback({{cFlowerPotEntity|FlowerPotEntity}}, [CallbackData])</pre> The function returns false if there is no flower pot, or if there is, it returns the bool value that the callback has returned." },
DoWithFurnaceAt = { Params = "X, Y, Z, CallbackFunction, [CallbackData]", Return = "bool", Notes = "If there is a furnace at the specified coords, calls the CallbackFunction with the {{cFurnaceEntity}} parameter representing the furnace. The CallbackFunction has the following signature: <pre class=\"prettyprint lang-lua\">function Callback({{cFurnaceEntity|FurnaceEntity}}, [CallbackData])</pre> The function returns false if there is no furnace, or if there is, it returns the bool value that the callback has returned." },
DoWithMobHeadAt = { Params = "X, Y, Z, CallbackFunction, [CallbackData]", Return = "bool", Notes = "If there is a mob head at the specified coords, calls the CallbackFunction with the {{cMobHeadEntity}} parameter representing the furnace. The CallbackFunction has the following signature: <pre class=\"prettyprint lang-lua\">function Callback({{cMobHeadEntity|MobHeadEntity}}, [CallbackData])</pre> The function returns false if there is no mob head, or if there is, it returns the bool value that the callback has returned." },
DoWithNoteBlockAt = { Params = "BlockX, BlockY, BlockZ, CallbackFunction, [CallbackData]", Return = "bool", Notes = "If there is a note block at the specified coords, calls the CallbackFunction with the {{cNoteEntity}} parameter representing the note block. The CallbackFunction has the following signature: <pre class=\"prettyprint lang-lua\">function Callback({{cNoteEntity|NoteEntity}}, [CallbackData])</pre> The function returns false if there is no note block, or if there is, it returns the bool value that the callback has returned." },
DoWithPlayer = { Params = "PlayerName, CallbackFunction, [CallbackData]", Return = "bool", Notes = "If there is a player of the specified name (exact match), calls the CallbackFunction with the {{cPlayer}} parameter representing the player. The CallbackFunction has the following signature: <pre class=\"prettyprint lang-lua\">function Callback({{cPlayer|Player}}, [CallbackData])</pre> The function returns false if the player was not found, or whatever bool value the callback returned if the player was found." },
FastSetBlock =
@ -2576,16 +2757,16 @@ end
IgnoreClasses =
{
"coroutine",
"debug",
"io",
"math",
"package",
"os",
"string",
"table",
"g_Stats",
"g_TrackedPages",
"^coroutine$",
"^debug$",
"^io$",
"^math$",
"^package$",
"^os$",
"^string$",
"^table$",
"^g_Stats$",
"^g_TrackedPages$",
},
IgnoreFunctions =

View File

@ -196,9 +196,11 @@ World:ForEachChestInChunk(Player:GetChunkX(), Player:GetChunkZ(),
Inherits = "cBlockEntity",
Functions =
{
EjectRecord = { Params = "", Return = "", Notes = "Ejects the current record as a {{cPickup|pickup}}. No action if there's no current record. To remove record without generating the pickup, use SetRecord(0)" },
EjectRecord = { Params = "", Return = "bool", Notes = "Ejects the current record as a {{cPickup|pickup}}. No action if there's no current record. To remove record without generating the pickup, use SetRecord(0). Returns true if pickup ejected." },
GetRecord = { Params = "", Return = "number", Notes = "Returns the record currently present. Zero for no record, E_ITEM_*_DISC for records." },
PlayRecord = { Params = "", Return = "", Notes = "Plays the currently present record. No action if there's no current record." },
IsPlayingRecord = { Params = "", Return = "bool", Notes = "Returns true if the jukebox is playing a record." },
IsRecordItem = { Params = "ItemType", Return = "bool", Notes = "Returns true if the specified item is a record that can be played." },
PlayRecord = { Params = "RecordItemType", Return = "bool", Notes = "Plays the specified Record. Return false if the parameter isn't a playable Record (E_ITEM_XXX_DISC). If there is a record already playing, ejects it first." },
SetRecord = { Params = "number", Return = "", Notes = "Sets the currently present record. Use zero for no record, or E_ITEM_*_DISC for records." },
},
}, -- cJukeboxEntity
@ -236,6 +238,20 @@ World:ForEachChestInChunk(Player:GetChunkX(), Player:GetChunkZ(),
},
Inherits = "cBlockEntity";
}, -- cSignEntity
cFlowerPotEntity =
{
Desc = [[
This class represents a flower pot entity in the world.
]],
Functions =
{
IsItemInPot = { Params = "", Return = "bool", Notes = "Is a flower in the pot?" },
GetItem = { Params = "", Return = "{{cItem|Item}}", Notes = "Returns the item in the flower pot." },
SetItem = { Params = "{{cItem|Item}}", Return = "", Notes = "Set the item in the flower pot" },
},
Inherits = "cBlockEntity";
}, -- cFlowerPotEntity
}

@ -1 +1 @@
Subproject commit 3b416b07a339b3abcbc127070d56eea05b05373d
Subproject commit 013a32a7fb3c8a6cfe0aef892d4c7394d4e1be59

View File

@ -30,6 +30,7 @@ function Initialize(Plugin)
PM:AddHook(cPluginManager.HOOK_CHUNK_GENERATED, OnChunkGenerated);
PM:AddHook(cPluginManager.HOOK_PLUGINS_LOADED, OnPluginsLoaded);
PM:AddHook(cPluginManager.HOOK_PLUGIN_MESSAGE, OnPluginMessage);
PM:AddHook(cPluginManager.HOOK_PLAYER_JOINED, OnPlayerJoined)
PM:BindCommand("/le", "debuggers", HandleListEntitiesCmd, "- Shows a list of all the loaded entities");
PM:BindCommand("/ke", "debuggers", HandleKillEntitiesCmd, "- Kills all the loaded entities");
@ -70,6 +71,8 @@ function Initialize(Plugin)
-- TestExpatBindings();
-- TestPluginCalls();
TestBlockAreasString()
return true
end;
@ -201,6 +204,42 @@ end
function TestBlockAreasString()
-- Write one area to string, then to file:
local BA1 = cBlockArea()
BA1:Create(5, 5, 5, cBlockArea.baTypes + cBlockArea.baMetas)
BA1:Fill(cBlockArea.baTypes, E_BLOCK_DIAMOND_BLOCK)
BA1:FillRelCuboid(1, 3, 1, 3, 1, 3, cBlockArea.baTypes, E_BLOCK_GOLD_BLOCK)
local Data = BA1:SaveToSchematicString()
if ((type(Data) ~= "string") or (Data == "")) then
LOG("Cannot save schematic to string")
return
end
cFile:CreateFolder("schematics")
local f = io.open("schematics/StringTest.schematic", "w")
f:write(Data)
f:close()
-- Load a second area from that file:
local BA2 = cBlockArea()
if not(BA2:LoadFromSchematicFile("schematics/StringTest.schematic")) then
LOG("Cannot read schematic from string test file")
return
end
BA2:Clear()
-- Load another area from a string in that file:
f = io.open("schematics/StringTest.schematic", "r")
Data = f:read("*all")
if not(BA2:LoadFromSchematicString(Data)) then
LOG("Cannot load schematic from string")
end
end
function TestSQLiteBindings()
LOG("Testing SQLite bindings...");
@ -1258,3 +1297,17 @@ end
function OnPlayerJoined(a_Player)
-- Test composite chat chaining:
a_Player:SendMessage(cCompositeChat()
:AddTextPart("Hello, ")
:AddUrlPart(a_Player:GetName(), "www.mc-server.org", "u@2")
:AddSuggestCommandPart(", and welcome.", "/help", "u")
:AddRunCommandPart(" SetDay", "/time set 0")
)
end

View File

@ -317,26 +317,19 @@ local function WriteCommandsCategoryGithub(a_Category, f)
if (CategoryName == "") then
CategoryName = "General";
end
f:write("\n## ", GithubizeString(a_Category.DisplayName or CategoryName), "\n");
f:write("\n### ", GithubizeString(a_Category.DisplayName or CategoryName), "\n");
-- Write description:
if (a_Category.Description ~= "") then
f:write(GithubizeString(a_Category.Description), "\n");
f:write(GithubizeString(a_Category.Description), "\n\n");
end
f:write("| Command | Permission | Description | \n")
f:write("| ------- | ---------- | ----------- | \n")
-- Write commands:
f:write("\n");
for idx2, cmd in ipairs(a_Category.Commands) do
f:write("\n### ", cmd.CommandString, "\n", GithubizeString(cmd.Info.HelpString or "UNDOCUMENTED"), "\n\n");
if (cmd.Info.Permission ~= nil) then
f:write("Permission required: **", cmd.Info.Permission, "**\n\n");
end
if (cmd.Info.DetailedDescription ~= nil) then
f:write(GithubizeString(cmd.Info.DetailedDescription));
end
if (cmd.Info.ParameterCombinations ~= nil) then
WriteCommandParameterCombinationsGithub(cmd.CommandString, cmd.Info.ParameterCombinations, f);
end
f:write("|", cmd.CommandString, " | ", cmd.Info.Permission or "", " | ", GithubizeString(cmd.Info.HelpString or "UNDOCUMENTED"), "| \n")
end
f:write("\n\n")
end
@ -537,12 +530,13 @@ local function DumpPermissionsGithub(a_PluginInfo, f)
-- Dump the permissions:
f:write("\n# Permissions\n");
f:write("| Permissions | Description | Commands | Recommended groups |\n")
f:write("| ----------- | ----------- | -------- | ------------------ |\n")
for idx, perm in ipairs(Permissions) do
f:write("### ", perm.Name, "\n");
f:write(GithubizeString(perm.Info.Description or ""));
f:write(perm.Name, " | ");
f:write(GithubizeString(perm.Info.Description or ""), " | ");
local CommandsAffected = perm.Info.CommandsAffected or {};
if (#CommandsAffected > 0) then
f:write("\n\nCommands affected:\n - ");
local Affects = {};
for idx2, cmd in ipairs(CommandsAffected) do
if (type(cmd) == "string") then
@ -551,11 +545,10 @@ local function DumpPermissionsGithub(a_PluginInfo, f)
table.insert(Affects, GetCommandRefGithub(cmd.Name, cmd));
end
end
f:write(table.concat(Affects, "\n - "));
f:write("\n");
f:write(table.concat(Affects, ", "), " | ");
end
if (perm.Info.RecommendedGroups ~= nil) then
f:write("\n\nRecommended groups: ", perm.Info.RecommendedGroups, "\n");
f:write(perm.Info.RecommendedGroups, " |");
end
f:write("\n");
end
@ -578,7 +571,10 @@ local function DumpPluginInfoForum(a_PluginFolder, a_PluginInfo)
DumpAdditionalInfoForum(a_PluginInfo, f);
DumpCommandsForum(a_PluginInfo, f);
DumpPermissionsForum(a_PluginInfo, f);
if (a_PluginInfo.SourceLocation ~= nil) then
f:write("[b][color=blue]Source:[/color] [url=", a_PluginInfo.SourceLocation, "]Link[/url][/b]");
end
f:close();
end

BIN
MCServer/lua5.1.dll Normal file

Binary file not shown.

View File

@ -1,5 +1,3 @@
macro (add_flags_lnk FLAGS)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${FLAGS}")
set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} ${FLAGS}")
@ -62,6 +60,7 @@ macro(set_flags)
# We use a signed char (fixes #640 on RasPi)
add_flags_cxx("-fsigned-char")
endif()
@ -184,6 +183,14 @@ macro(set_exe_flags)
string(REPLACE "-w" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
string(REPLACE "-w" "" CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}")
add_flags_cxx("-Wall -Wextra")
# we support non-IEEE 754 fpus so can make no guarentees about error
add_flags_cxx("-ffast-math")
# clang does not provide the __extern_always_inline macro and a part of libm depends on this when using fast-math
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
add_flags_cxx("-D__extern_always_inline=inline")
endif()
endif()
endmacro()

View File

@ -47,8 +47,12 @@ if (WIN32)
)
endif()
set_target_properties(lua PROPERTIES OUTPUT_NAME "lua51")
# NOTE: The DLL for each configuration is stored at the same place, thus overwriting each other.
# This is known, however such behavior is needed for LuaRocks - they always load "lua.dll"
# This is known, however such behavior is needed for LuaRocks - they always load "lua5.1.dll" or "lua51.dll"
# We make it work by compiling to "lua51.dll" and providing a proxy-DLL "lua5.1.dll"
# See http://lua-users.org/wiki/LuaProxyDllFour for details
else()
add_library(lua ${SOURCE})
endif()

@ -1 +1 @@
Subproject commit 2ceda579893ceb23c5eb0d56df47dc235644e0f4
Subproject commit 2cb1a0c4009ecf368ecc74eb428394e10f9e6d00

View File

@ -26,6 +26,7 @@ $cfile "WebPlugin.h"
$cfile "LuaWindow.h"
$cfile "../BlockID.h"
$cfile "../BlockInfo.h"
$cfile "../StringUtils.h"
$cfile "../Defines.h"
$cfile "../ChatColor.h"
@ -57,6 +58,8 @@ $cfile "../BlockEntities/HopperEntity.h"
$cfile "../BlockEntities/JukeboxEntity.h"
$cfile "../BlockEntities/NoteEntity.h"
$cfile "../BlockEntities/SignEntity.h"
$cfile "../BlockEntities/MobHeadEntity.h"
$cfile "../BlockEntities/FlowerPotEntity.h"
$cfile "../WebAdmin.h"
$cfile "../Root.h"
$cfile "../Vector3f.h"
@ -75,6 +78,7 @@ $cfile "../Mobs/Monster.h"
$cfile "../CompositeChat.h"
$cfile "../Map.h"
$cfile "../MapManager.h"
$cfile "../Scoreboard.h"

View File

@ -0,0 +1,506 @@
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
#include "DeprecatedBindings.h"
#include "tolua++/include/tolua++.h"
#include "Plugin.h"
#include "PluginLua.h"
#include "PluginManager.h"
#include "LuaWindow.h"
#include "LuaChunkStay.h"
#include "../BlockInfo.h"
/* get function: g_BlockLightValue */
#ifndef TOLUA_DISABLE_tolua_get_AllToLua_g_BlockLightValue
static int tolua_get_AllToLua_g_BlockLightValue(lua_State* tolua_S)
{
int tolua_index;
#ifndef TOLUA_RELEASE
{
tolua_Error tolua_err;
if (!tolua_isnumber(tolua_S,2,0,&tolua_err))
tolua_error(tolua_S,"#vinvalid type in array indexing.",&tolua_err);
}
#endif
tolua_index = (int)tolua_tonumber(tolua_S,2,0);
#ifndef TOLUA_RELEASE
if (tolua_index<0)
tolua_error(tolua_S,"array indexing out of range.",NULL);
#endif
tolua_pushnumber(tolua_S,(lua_Number)cBlockInfo::GetLightValue(tolua_index));
return 1;
}
#endif //#ifndef TOLUA_DISABLE
/* set function: g_BlockLightValue */
#ifndef TOLUA_DISABLE_tolua_set_AllToLua_g_BlockLightValue
static int tolua_set_AllToLua_g_BlockLightValue(lua_State* tolua_S)
{
int tolua_index;
#ifndef TOLUA_RELEASE
{
tolua_Error tolua_err;
if (!tolua_isnumber(tolua_S,2,0,&tolua_err))
tolua_error(tolua_S,"#vinvalid type in array indexing.",&tolua_err);
}
#endif
tolua_index = (int)tolua_tonumber(tolua_S,2,0);
#ifndef TOLUA_RELEASE
if (tolua_index<0)
tolua_error(tolua_S,"array indexing out of range.",NULL);
#endif
cBlockInfo::Get(tolua_index).m_LightValue = ((unsigned char) tolua_tonumber(tolua_S,3,0));
return 0;
}
#endif //#ifndef TOLUA_DISABLE
/* get function: g_BlockSpreadLightFalloff */
#ifndef TOLUA_DISABLE_tolua_get_AllToLua_g_BlockSpreadLightFalloff
static int tolua_get_AllToLua_g_BlockSpreadLightFalloff(lua_State* tolua_S)
{
int tolua_index;
#ifndef TOLUA_RELEASE
{
tolua_Error tolua_err;
if (!tolua_isnumber(tolua_S,2,0,&tolua_err))
tolua_error(tolua_S,"#vinvalid type in array indexing.",&tolua_err);
}
#endif
tolua_index = (int)tolua_tonumber(tolua_S,2,0);
#ifndef TOLUA_RELEASE
if (tolua_index<0)
tolua_error(tolua_S,"array indexing out of range.",NULL);
#endif
tolua_pushnumber(tolua_S,(lua_Number)cBlockInfo::GetSpreadLightFalloff(tolua_index));
return 1;
}
#endif //#ifndef TOLUA_DISABLE
/* set function: g_BlockSpreadLightFalloff */
#ifndef TOLUA_DISABLE_tolua_set_AllToLua_g_BlockSpreadLightFalloff
static int tolua_set_AllToLua_g_BlockSpreadLightFalloff(lua_State* tolua_S)
{
int tolua_index;
#ifndef TOLUA_RELEASE
{
tolua_Error tolua_err;
if (!tolua_isnumber(tolua_S,2,0,&tolua_err))
tolua_error(tolua_S,"#vinvalid type in array indexing.",&tolua_err);
}
#endif
tolua_index = (int)tolua_tonumber(tolua_S,2,0);
#ifndef TOLUA_RELEASE
if (tolua_index<0)
tolua_error(tolua_S,"array indexing out of range.",NULL);
#endif
cBlockInfo::Get(tolua_index).m_SpreadLightFalloff = ((unsigned char) tolua_tonumber(tolua_S,3,0));
return 0;
}
#endif //#ifndef TOLUA_DISABLE
/* get function: g_BlockTransparent */
#ifndef TOLUA_DISABLE_tolua_get_AllToLua_g_BlockTransparent
static int tolua_get_AllToLua_g_BlockTransparent(lua_State* tolua_S)
{
int tolua_index;
#ifndef TOLUA_RELEASE
{
tolua_Error tolua_err;
if (!tolua_isnumber(tolua_S,2,0,&tolua_err))
tolua_error(tolua_S,"#vinvalid type in array indexing.",&tolua_err);
}
#endif
tolua_index = (int)tolua_tonumber(tolua_S,2,0);
#ifndef TOLUA_RELEASE
if (tolua_index<0)
tolua_error(tolua_S,"array indexing out of range.",NULL);
#endif
tolua_pushboolean(tolua_S, cBlockInfo::IsTransparent(tolua_index));
return 1;
}
#endif //#ifndef TOLUA_DISABLE
/* set function: g_BlockTransparent */
#ifndef TOLUA_DISABLE_tolua_set_AllToLua_g_BlockTransparent
static int tolua_set_AllToLua_g_BlockTransparent(lua_State* tolua_S)
{
int tolua_index;
#ifndef TOLUA_RELEASE
{
tolua_Error tolua_err;
if (!tolua_isnumber(tolua_S,2,0,&tolua_err))
tolua_error(tolua_S,"#vinvalid type in array indexing.",&tolua_err);
}
#endif
tolua_index = (int)tolua_tonumber(tolua_S,2,0);
#ifndef TOLUA_RELEASE
if (tolua_index<0)
tolua_error(tolua_S,"array indexing out of range.",NULL);
#endif
cBlockInfo::Get(tolua_index).m_Transparent = (tolua_toboolean(tolua_S,3,0) != 0);
return 0;
}
#endif //#ifndef TOLUA_DISABLE
/* get function: g_BlockOneHitDig */
#ifndef TOLUA_DISABLE_tolua_get_AllToLua_g_BlockOneHitDig
static int tolua_get_AllToLua_g_BlockOneHitDig(lua_State* tolua_S)
{
int tolua_index;
#ifndef TOLUA_RELEASE
{
tolua_Error tolua_err;
if (!tolua_isnumber(tolua_S,2,0,&tolua_err))
tolua_error(tolua_S,"#vinvalid type in array indexing.",&tolua_err);
}
#endif
tolua_index = (int)tolua_tonumber(tolua_S,2,0);
#ifndef TOLUA_RELEASE
if (tolua_index<0)
tolua_error(tolua_S,"array indexing out of range.",NULL);
#endif
tolua_pushboolean(tolua_S,(bool)cBlockInfo::IsOneHitDig(tolua_index));
return 1;
}
#endif //#ifndef TOLUA_DISABLE
/* set function: g_BlockOneHitDig */
#ifndef TOLUA_DISABLE_tolua_set_AllToLua_g_BlockOneHitDig
static int tolua_set_AllToLua_g_BlockOneHitDig(lua_State* tolua_S)
{
int tolua_index;
#ifndef TOLUA_RELEASE
{
tolua_Error tolua_err;
if (!tolua_isnumber(tolua_S,2,0,&tolua_err))
tolua_error(tolua_S,"#vinvalid type in array indexing.",&tolua_err);
}
#endif
tolua_index = (int)tolua_tonumber(tolua_S,2,0);
#ifndef TOLUA_RELEASE
if (tolua_index<0)
tolua_error(tolua_S,"array indexing out of range.",NULL);
#endif
cBlockInfo::Get(tolua_index).m_OneHitDig = (tolua_toboolean(tolua_S,3,0) != 0);
return 0;
}
#endif //#ifndef TOLUA_DISABLE
/* get function: g_BlockPistonBreakable */
#ifndef TOLUA_DISABLE_tolua_get_AllToLua_g_BlockPistonBreakable
static int tolua_get_AllToLua_g_BlockPistonBreakable(lua_State* tolua_S)
{
int tolua_index;
#ifndef TOLUA_RELEASE
{
tolua_Error tolua_err;
if (!tolua_isnumber(tolua_S,2,0,&tolua_err))
tolua_error(tolua_S,"#vinvalid type in array indexing.",&tolua_err);
}
#endif
tolua_index = (int)tolua_tonumber(tolua_S,2,0);
#ifndef TOLUA_RELEASE
if (tolua_index<0 || tolua_index>=256)
tolua_error(tolua_S,"array indexing out of range.",NULL);
#endif
tolua_pushboolean(tolua_S,(bool)cBlockInfo::IsPistonBreakable(tolua_index));
return 1;
}
#endif //#ifndef TOLUA_DISABLE
/* set function: g_BlockPistonBreakable */
#ifndef TOLUA_DISABLE_tolua_set_AllToLua_g_BlockPistonBreakable
static int tolua_set_AllToLua_g_BlockPistonBreakable(lua_State* tolua_S)
{
int tolua_index;
#ifndef TOLUA_RELEASE
{
tolua_Error tolua_err;
if (!tolua_isnumber(tolua_S,2,0,&tolua_err))
tolua_error(tolua_S,"#vinvalid type in array indexing.",&tolua_err);
}
#endif
tolua_index = (int)tolua_tonumber(tolua_S,2,0);
#ifndef TOLUA_RELEASE
if (tolua_index<0 || tolua_index>=256)
tolua_error(tolua_S,"array indexing out of range.",NULL);
#endif
cBlockInfo::Get(tolua_index).m_PistonBreakable = (tolua_toboolean(tolua_S,3,0) != 0);
return 0;
}
#endif //#ifndef TOLUA_DISABLE
/* get function: g_BlockIsSnowable */
#ifndef TOLUA_DISABLE_tolua_get_AllToLua_g_BlockIsSnowable
static int tolua_get_AllToLua_g_BlockIsSnowable(lua_State* tolua_S)
{
int tolua_index;
#ifndef TOLUA_RELEASE
{
tolua_Error tolua_err;
if (!tolua_isnumber(tolua_S,2,0,&tolua_err))
tolua_error(tolua_S,"#vinvalid type in array indexing.",&tolua_err);
}
#endif
tolua_index = (int)tolua_tonumber(tolua_S,2,0);
#ifndef TOLUA_RELEASE
if (tolua_index<0 || tolua_index>=256)
tolua_error(tolua_S,"array indexing out of range.",NULL);
#endif
tolua_pushboolean(tolua_S,(bool)cBlockInfo::IsSnowable(tolua_index));
return 1;
}
#endif //#ifndef TOLUA_DISABLE
/* set function: g_BlockIsSnowable */
#ifndef TOLUA_DISABLE_tolua_set_AllToLua_g_BlockIsSnowable
static int tolua_set_AllToLua_g_BlockIsSnowable(lua_State* tolua_S)
{
int tolua_index;
#ifndef TOLUA_RELEASE
{
tolua_Error tolua_err;
if (!tolua_isnumber(tolua_S,2,0,&tolua_err))
tolua_error(tolua_S,"#vinvalid type in array indexing.",&tolua_err);
}
#endif
tolua_index = (int)tolua_tonumber(tolua_S,2,0);
#ifndef TOLUA_RELEASE
if (tolua_index<0 || tolua_index>=256)
tolua_error(tolua_S,"array indexing out of range.",NULL);
#endif
cBlockInfo::Get(tolua_index).m_IsSnowable = (tolua_toboolean(tolua_S,3,0) != 0);
return 0;
}
#endif //#ifndef TOLUA_DISABLE
/* get function: g_BlockRequiresSpecialTool */
#ifndef TOLUA_DISABLE_tolua_get_AllToLua_g_BlockRequiresSpecialTool
static int tolua_get_AllToLua_g_BlockRequiresSpecialTool(lua_State* tolua_S)
{
int tolua_index;
#ifndef TOLUA_RELEASE
{
tolua_Error tolua_err;
if (!tolua_isnumber(tolua_S,2,0,&tolua_err))
tolua_error(tolua_S,"#vinvalid type in array indexing.",&tolua_err);
}
#endif
tolua_index = (int)tolua_tonumber(tolua_S,2,0);
#ifndef TOLUA_RELEASE
if (tolua_index<0 || tolua_index>=256)
tolua_error(tolua_S,"array indexing out of range.",NULL);
#endif
tolua_pushboolean(tolua_S,(bool)cBlockInfo::RequiresSpecialTool(tolua_index));
return 1;
}
#endif //#ifndef TOLUA_DISABLE
/* set function: g_BlockRequiresSpecialTool */
#ifndef TOLUA_DISABLE_tolua_set_AllToLua_g_BlockRequiresSpecialTool
static int tolua_set_AllToLua_g_BlockRequiresSpecialTool(lua_State* tolua_S)
{
int tolua_index;
#ifndef TOLUA_RELEASE
{
tolua_Error tolua_err;
if (!tolua_isnumber(tolua_S,2,0,&tolua_err))
tolua_error(tolua_S,"#vinvalid type in array indexing.",&tolua_err);
}
#endif
tolua_index = (int)tolua_tonumber(tolua_S,2,0);
#ifndef TOLUA_RELEASE
if (tolua_index<0 || tolua_index>=256)
tolua_error(tolua_S,"array indexing out of range.",NULL);
#endif
cBlockInfo::Get(tolua_index).m_RequiresSpecialTool = (tolua_toboolean(tolua_S,3,0) != 0);
return 0;
}
#endif //#ifndef TOLUA_DISABLE
/* get function: g_BlockIsSolid */
#ifndef TOLUA_DISABLE_tolua_get_AllToLua_g_BlockIsSolid
static int tolua_get_AllToLua_g_BlockIsSolid(lua_State* tolua_S)
{
int tolua_index;
#ifndef TOLUA_RELEASE
{
tolua_Error tolua_err;
if (!tolua_isnumber(tolua_S,2,0,&tolua_err))
tolua_error(tolua_S,"#vinvalid type in array indexing.",&tolua_err);
}
#endif
tolua_index = (int)tolua_tonumber(tolua_S,2,0);
#ifndef TOLUA_RELEASE
if (tolua_index<0 || tolua_index>=256)
tolua_error(tolua_S,"array indexing out of range.",NULL);
#endif
tolua_pushboolean(tolua_S,(bool)cBlockInfo::IsSolid(tolua_index));
return 1;
}
#endif //#ifndef TOLUA_DISABLE
/* set function: g_BlockIsSolid */
#ifndef TOLUA_DISABLE_tolua_set_AllToLua_g_BlockIsSolid
static int tolua_set_AllToLua_g_BlockIsSolid(lua_State* tolua_S)
{
int tolua_index;
#ifndef TOLUA_RELEASE
{
tolua_Error tolua_err;
if (!tolua_isnumber(tolua_S,2,0,&tolua_err))
tolua_error(tolua_S,"#vinvalid type in array indexing.",&tolua_err);
}
#endif
tolua_index = (int)tolua_tonumber(tolua_S,2,0);
#ifndef TOLUA_RELEASE
if (tolua_index<0 || tolua_index>=256)
tolua_error(tolua_S,"array indexing out of range.",NULL);
#endif
cBlockInfo::Get(tolua_index).m_IsSolid = (tolua_toboolean(tolua_S,3,0) != 0);
return 0;
}
#endif //#ifndef TOLUA_DISABLE
/* get function: g_BlockFullyOccupiesVoxel */
#ifndef TOLUA_DISABLE_tolua_get_AllToLua_g_BlockFullyOccupiesVoxel
static int tolua_get_AllToLua_g_BlockFullyOccupiesVoxel(lua_State* tolua_S)
{
int tolua_index;
#ifndef TOLUA_RELEASE
{
tolua_Error tolua_err;
if (!tolua_isnumber(tolua_S,2,0,&tolua_err))
tolua_error(tolua_S,"#vinvalid type in array indexing.",&tolua_err);
}
#endif
tolua_index = (int)tolua_tonumber(tolua_S,2,0);
#ifndef TOLUA_RELEASE
if (tolua_index<0 || tolua_index>=256)
tolua_error(tolua_S,"array indexing out of range.",NULL);
#endif
tolua_pushboolean(tolua_S,(bool)cBlockInfo::FullyOccupiesVoxel(tolua_index));
return 1;
}
#endif //#ifndef TOLUA_DISABLE
/* set function: g_BlockFullyOccupiesVoxel */
#ifndef TOLUA_DISABLE_tolua_set_AllToLua_g_BlockFullyOccupiesVoxel
static int tolua_set_AllToLua_g_BlockFullyOccupiesVoxel(lua_State* tolua_S)
{
int tolua_index;
#ifndef TOLUA_RELEASE
{
tolua_Error tolua_err;
if (!tolua_isnumber(tolua_S,2,0,&tolua_err))
tolua_error(tolua_S,"#vinvalid type in array indexing.",&tolua_err);
}
#endif
tolua_index = (int)tolua_tonumber(tolua_S,2,0);
#ifndef TOLUA_RELEASE
if (tolua_index<0 || tolua_index>=256)
tolua_error(tolua_S,"array indexing out of range.",NULL);
#endif
cBlockInfo::Get(tolua_index).m_FullyOccupiesVoxel = (tolua_toboolean(tolua_S,3,0) != 0);
return 0;
}
#endif //#ifndef TOLUA_DISABLE
void DeprecatedBindings::Bind(lua_State * tolua_S)
{
tolua_beginmodule(tolua_S, NULL);
tolua_array(tolua_S, "g_BlockLightValue", tolua_get_AllToLua_g_BlockLightValue, tolua_set_AllToLua_g_BlockLightValue);
tolua_array(tolua_S, "g_BlockSpreadLightFalloff", tolua_get_AllToLua_g_BlockSpreadLightFalloff, tolua_set_AllToLua_g_BlockSpreadLightFalloff);
tolua_array(tolua_S, "g_BlockTransparent", tolua_get_AllToLua_g_BlockTransparent, tolua_set_AllToLua_g_BlockTransparent);
tolua_array(tolua_S, "g_BlockOneHitDig", tolua_get_AllToLua_g_BlockOneHitDig, tolua_set_AllToLua_g_BlockOneHitDig);
tolua_array(tolua_S, "g_BlockPistonBreakable", tolua_get_AllToLua_g_BlockPistonBreakable, tolua_set_AllToLua_g_BlockPistonBreakable);
tolua_array(tolua_S, "g_BlockIsSnowable", tolua_get_AllToLua_g_BlockIsSnowable, tolua_set_AllToLua_g_BlockIsSnowable);
tolua_array(tolua_S, "g_BlockRequiresSpecialTool", tolua_get_AllToLua_g_BlockRequiresSpecialTool, tolua_set_AllToLua_g_BlockRequiresSpecialTool);
tolua_array(tolua_S, "g_BlockIsSolid", tolua_get_AllToLua_g_BlockIsSolid, tolua_set_AllToLua_g_BlockIsSolid);
tolua_array(tolua_S, "g_BlockFullyOccupiesVoxel", tolua_get_AllToLua_g_BlockFullyOccupiesVoxel, tolua_set_AllToLua_g_BlockFullyOccupiesVoxel);
tolua_endmodule(tolua_S);
}

View File

@ -0,0 +1,8 @@
#pragma once
struct lua_State;
class DeprecatedBindings
{
public:
static void Bind( lua_State* tolua_S );
};

View File

@ -14,6 +14,7 @@ extern "C"
#include "tolua++/include/tolua++.h"
#include "Bindings.h"
#include "ManualBindings.h"
#include "DeprecatedBindings.h"
// fwd: SQLite/lsqlite3.c
extern "C"
@ -95,6 +96,7 @@ void cLuaState::Create(void)
luaL_openlibs(m_LuaState);
tolua_AllToLua_open(m_LuaState);
ManualBindings::Bind(m_LuaState);
DeprecatedBindings::Bind(m_LuaState);
luaopen_lsqlite3(m_LuaState);
luaopen_lxp(m_LuaState);
m_IsOwned = true;
@ -714,7 +716,7 @@ void cLuaState::Push(cBlockEntity * a_BlockEntity)
void cLuaState::GetReturn(int a_StackPos, bool & a_ReturnedVal)
void cLuaState::GetStackValue(int a_StackPos, bool & a_ReturnedVal)
{
a_ReturnedVal = (tolua_toboolean(m_LuaState, a_StackPos, a_ReturnedVal ? 1 : 0) > 0);
}
@ -723,11 +725,17 @@ void cLuaState::GetReturn(int a_StackPos, bool & a_ReturnedVal)
void cLuaState::GetReturn(int a_StackPos, AString & a_ReturnedVal)
void cLuaState::GetStackValue(int a_StackPos, AString & a_Value)
{
if (lua_isstring(m_LuaState, a_StackPos))
size_t len = 0;
const char * data = lua_tolstring(m_LuaState, a_StackPos, &len);
if (data != NULL)
{
a_ReturnedVal = tolua_tocppstring(m_LuaState, a_StackPos, a_ReturnedVal.c_str());
a_Value.assign(data, len);
}
else
{
a_Value.clear();
}
}
@ -735,7 +743,7 @@ void cLuaState::GetReturn(int a_StackPos, AString & a_ReturnedVal)
void cLuaState::GetReturn(int a_StackPos, int & a_ReturnedVal)
void cLuaState::GetStackValue(int a_StackPos, int & a_ReturnedVal)
{
if (lua_isnumber(m_LuaState, a_StackPos))
{
@ -747,7 +755,7 @@ void cLuaState::GetReturn(int a_StackPos, int & a_ReturnedVal)
void cLuaState::GetReturn(int a_StackPos, double & a_ReturnedVal)
void cLuaState::GetStackValue(int a_StackPos, double & a_ReturnedVal)
{
if (lua_isnumber(m_LuaState, a_StackPos))
{

View File

@ -197,6 +197,19 @@ public:
void Push(void * a_Ptr);
void Push(cHopperEntity * a_Hopper);
void Push(cBlockEntity * a_BlockEntity);
/** Retrieve value at a_StackPos, if it is a valid bool. If not, a_Value is unchanged */
void GetStackValue(int a_StackPos, bool & a_Value);
/** Retrieve value at a_StackPos, if it is a valid string. If not, a_Value is unchanged */
void GetStackValue(int a_StackPos, AString & a_Value);
/** Retrieve value at a_StackPos, if it is a valid number. If not, a_Value is unchanged */
void GetStackValue(int a_StackPos, int & a_Value);
/** Retrieve value at a_StackPos, if it is a valid number. If not, a_Value is unchanged */
void GetStackValue(int a_StackPos, double & a_Value);
/** Call any 0-param 0-return Lua function in a single line: */
template <typename FnT>
@ -270,7 +283,7 @@ public:
{
return false;
}
GetReturn(-1, a_Ret1);
GetStackValue(-1, a_Ret1);
lua_pop(m_LuaState, 1);
return true;
}
@ -292,7 +305,7 @@ public:
{
return false;
}
GetReturn(-1, a_Ret1);
GetStackValue(-1, a_Ret1);
lua_pop(m_LuaState, 1);
ASSERT(InitialTop == lua_gettop(m_LuaState));
return true;
@ -315,7 +328,7 @@ public:
{
return false;
}
GetReturn(-1, a_Ret1);
GetStackValue(-1, a_Ret1);
lua_pop(m_LuaState, 1);
return true;
}
@ -338,7 +351,7 @@ public:
{
return false;
}
GetReturn(-1, a_Ret1);
GetStackValue(-1, a_Ret1);
lua_pop(m_LuaState, 1);
return true;
}
@ -362,7 +375,7 @@ public:
{
return false;
}
GetReturn(-1, a_Ret1);
GetStackValue(-1, a_Ret1);
lua_pop(m_LuaState, 1);
return true;
}
@ -387,7 +400,7 @@ public:
{
return false;
}
GetReturn(-1, a_Ret1);
GetStackValue(-1, a_Ret1);
lua_pop(m_LuaState, 1);
return true;
}
@ -414,7 +427,7 @@ public:
{
return false;
}
GetReturn(-1, a_Ret1);
GetStackValue(-1, a_Ret1);
lua_pop(m_LuaState, 1);
return true;
}
@ -442,7 +455,7 @@ public:
{
return false;
}
GetReturn(-1, a_Ret1);
GetStackValue(-1, a_Ret1);
lua_pop(m_LuaState, 1);
return true;
}
@ -471,7 +484,7 @@ public:
{
return false;
}
GetReturn(-1, a_Ret1);
GetStackValue(-1, a_Ret1);
lua_pop(m_LuaState, 1);
return true;
}
@ -501,7 +514,7 @@ public:
{
return false;
}
GetReturn(-1, a_Ret1);
GetStackValue(-1, a_Ret1);
lua_pop(m_LuaState, 1);
return true;
}
@ -532,7 +545,7 @@ public:
{
return false;
}
GetReturn(-1, a_Ret1);
GetStackValue(-1, a_Ret1);
lua_pop(m_LuaState, 1);
return true;
}
@ -553,8 +566,8 @@ public:
{
return false;
}
GetReturn(-2, a_Ret1);
GetReturn(-1, a_Ret2);
GetStackValue(-2, a_Ret1);
GetStackValue(-1, a_Ret2);
lua_pop(m_LuaState, 2);
return true;
}
@ -576,8 +589,8 @@ public:
{
return false;
}
GetReturn(-2, a_Ret1);
GetReturn(-1, a_Ret2);
GetStackValue(-2, a_Ret1);
GetStackValue(-1, a_Ret2);
lua_pop(m_LuaState, 2);
return true;
}
@ -601,8 +614,8 @@ public:
{
return false;
}
GetReturn(-2, a_Ret1);
GetReturn(-1, a_Ret2);
GetStackValue(-2, a_Ret1);
GetStackValue(-1, a_Ret2);
lua_pop(m_LuaState, 2);
return true;
}
@ -627,8 +640,8 @@ public:
{
return false;
}
GetReturn(-2, a_Ret1);
GetReturn(-1, a_Ret2);
GetStackValue(-2, a_Ret1);
GetStackValue(-1, a_Ret2);
lua_pop(m_LuaState, 2);
return true;
}
@ -654,8 +667,8 @@ public:
{
return false;
}
GetReturn(-2, a_Ret1);
GetReturn(-1, a_Ret2);
GetStackValue(-2, a_Ret1);
GetStackValue(-1, a_Ret2);
lua_pop(m_LuaState, 2);
return true;
}
@ -683,8 +696,8 @@ public:
{
return false;
}
GetReturn(-2, a_Ret1);
GetReturn(-1, a_Ret2);
GetStackValue(-2, a_Ret1);
GetStackValue(-1, a_Ret2);
lua_pop(m_LuaState, 2);
return true;
}
@ -713,8 +726,8 @@ public:
{
return false;
}
GetReturn(-2, a_Ret1);
GetReturn(-1, a_Ret2);
GetStackValue(-2, a_Ret1);
GetStackValue(-1, a_Ret2);
lua_pop(m_LuaState, 2);
return true;
}
@ -743,9 +756,9 @@ public:
{
return false;
}
GetReturn(-3, a_Ret1);
GetReturn(-2, a_Ret2);
GetReturn(-1, a_Ret3);
GetStackValue(-3, a_Ret1);
GetStackValue(-2, a_Ret2);
GetStackValue(-1, a_Ret3);
lua_pop(m_LuaState, 3);
return true;
}
@ -775,9 +788,9 @@ public:
{
return false;
}
GetReturn(-3, a_Ret1);
GetReturn(-2, a_Ret2);
GetReturn(-1, a_Ret3);
GetStackValue(-3, a_Ret1);
GetStackValue(-2, a_Ret2);
GetStackValue(-1, a_Ret3);
lua_pop(m_LuaState, 3);
return true;
}
@ -808,11 +821,11 @@ public:
{
return false;
}
GetReturn(-5, a_Ret1);
GetReturn(-4, a_Ret2);
GetReturn(-3, a_Ret3);
GetReturn(-2, a_Ret4);
GetReturn(-1, a_Ret5);
GetStackValue(-5, a_Ret1);
GetStackValue(-4, a_Ret2);
GetStackValue(-3, a_Ret3);
GetStackValue(-2, a_Ret4);
GetStackValue(-1, a_Ret5);
lua_pop(m_LuaState, 5);
return true;
}
@ -918,18 +931,6 @@ protected:
/** Pushes a usertype of the specified class type onto the stack */
void PushUserType(void * a_Object, const char * a_Type);
/** Retrieve value returned at a_StackPos, if it is a valid bool. If not, a_ReturnedVal is unchanged */
void GetReturn(int a_StackPos, bool & a_ReturnedVal);
/** Retrieve value returned at a_StackPos, if it is a valid string. If not, a_ReturnedVal is unchanged */
void GetReturn(int a_StackPos, AString & a_ReturnedVal);
/** Retrieve value returned at a_StackPos, if it is a valid number. If not, a_ReturnedVal is unchanged */
void GetReturn(int a_StackPos, int & a_ReturnedVal);
/** Retrieve value returned at a_StackPos, if it is a valid number. If not, a_ReturnedVal is unchanged */
void GetReturn(int a_StackPos, double & a_ReturnedVal);
/**
Calls the function that has been pushed onto the stack by PushFunction(),
with arguments pushed by PushXXX().

View File

@ -23,9 +23,11 @@
#include "../BlockEntities/HopperEntity.h"
#include "../BlockEntities/NoteEntity.h"
#include "../BlockEntities/MobHeadEntity.h"
#include "../BlockEntities/FlowerPotEntity.h"
#include "md5/md5.h"
#include "../LineBlockTracer.h"
#include "../WorldStorage/SchematicFileSerializer.h"
#include "../CompositeChat.h"
@ -2455,7 +2457,7 @@ static int tolua_cBlockArea_GetSize(lua_State * tolua_S)
static int tolua_cBlockArea_LoadFromSchematicFile(lua_State * tolua_S)
{
// function cBlockArea::LoadFromSchematicFile
// Exported manually because function has been moved to SchematicFileSerilizer.cpp
// Exported manually because function has been moved to SchematicFileSerializer.cpp
cLuaState L(tolua_S);
if (
!L.CheckParamUserType(1, "cBlockArea") ||
@ -2482,10 +2484,41 @@ static int tolua_cBlockArea_LoadFromSchematicFile(lua_State * tolua_S)
static int tolua_cBlockArea_LoadFromSchematicString(lua_State * tolua_S)
{
// function cBlockArea::LoadFromSchematicString
// Exported manually because function has been moved to SchematicFileSerializer.cpp
cLuaState L(tolua_S);
if (
!L.CheckParamUserType(1, "cBlockArea") ||
!L.CheckParamString (2) ||
!L.CheckParamEnd (3)
)
{
return 0;
}
cBlockArea * self = (cBlockArea *)tolua_tousertype(tolua_S, 1, NULL);
if (self == NULL)
{
tolua_error(tolua_S, "invalid 'self' in function 'cBlockArea::LoadFromSchematicFile'", NULL);
return 0;
}
AString Data;
L.GetStackValue(2, Data);
bool res = cSchematicFileSerializer::LoadFromSchematicString(*self, Data);
tolua_pushboolean(tolua_S, res);
return 1;
}
static int tolua_cBlockArea_SaveToSchematicFile(lua_State * tolua_S)
{
// function cBlockArea::SaveToSchematicFile
// Exported manually because function has been moved to SchematicFileSerilizer.cpp
// Exported manually because function has been moved to SchematicFileSerializer.cpp
cLuaState L(tolua_S);
if (
!L.CheckParamUserType(1, "cBlockArea") ||
@ -2511,6 +2544,285 @@ static int tolua_cBlockArea_SaveToSchematicFile(lua_State * tolua_S)
static int tolua_cBlockArea_SaveToSchematicString(lua_State * tolua_S)
{
// function cBlockArea::SaveToSchematicString
// Exported manually because function has been moved to SchematicFileSerializer.cpp
cLuaState L(tolua_S);
if (
!L.CheckParamUserType(1, "cBlockArea") ||
!L.CheckParamEnd (2)
)
{
return 0;
}
cBlockArea * self = (cBlockArea *)tolua_tousertype(tolua_S, 1, NULL);
if (self == NULL)
{
tolua_error(tolua_S, "invalid 'self' in function 'cBlockArea::SaveToSchematicFile'", NULL);
return 0;
}
AString Data;
if (cSchematicFileSerializer::SaveToSchematicString(*self, Data))
{
L.Push(Data);
return 1;
}
return 0;
}
static int tolua_cCompositeChat_AddRunCommandPart(lua_State * tolua_S)
{
// function cCompositeChat:AddRunCommandPart(Message, Command, [Style])
// Exported manually to support call-chaining (return *this)
// Check params:
cLuaState L(tolua_S);
if (
!L.CheckParamUserType(1, "cCompositeChat") ||
!L.CheckParamString(2, 3)
)
{
return 0;
}
cCompositeChat * self = (cCompositeChat *)tolua_tousertype(tolua_S, 1, NULL);
if (self == NULL)
{
tolua_error(tolua_S, "invalid 'self' in function 'cCompositeChat:AddRunCommandPart'", NULL);
return 0;
}
// Add the part:
AString Text, Command, Style;
L.GetStackValue(2, Text);
L.GetStackValue(3, Command);
L.GetStackValue(4, Style);
self->AddRunCommandPart(Text, Command, Style);
// Cut away everything from the stack except for the cCompositeChat instance; return that:
lua_settop(L, 1);
return 1;
}
static int tolua_cCompositeChat_AddSuggestCommandPart(lua_State * tolua_S)
{
// function cCompositeChat:AddSuggestCommandPart(Message, Command, [Style])
// Exported manually to support call-chaining (return *this)
// Check params:
cLuaState L(tolua_S);
if (
!L.CheckParamUserType(1, "cCompositeChat") ||
!L.CheckParamString(2, 3)
)
{
return 0;
}
cCompositeChat * self = (cCompositeChat *)tolua_tousertype(tolua_S, 1, NULL);
if (self == NULL)
{
tolua_error(tolua_S, "invalid 'self' in function 'cCompositeChat:AddSuggestCommandPart'", NULL);
return 0;
}
// Add the part:
AString Text, Command, Style;
L.GetStackValue(2, Text);
L.GetStackValue(3, Command);
L.GetStackValue(4, Style);
self->AddSuggestCommandPart(Text, Command, Style);
// Cut away everything from the stack except for the cCompositeChat instance; return that:
lua_settop(L, 1);
return 1;
}
static int tolua_cCompositeChat_AddTextPart(lua_State * tolua_S)
{
// function cCompositeChat:AddTextPart(Message, [Style])
// Exported manually to support call-chaining (return *this)
// Check params:
cLuaState L(tolua_S);
if (
!L.CheckParamUserType(1, "cCompositeChat") ||
!L.CheckParamString(2)
)
{
return 0;
}
cCompositeChat * self = (cCompositeChat *)tolua_tousertype(tolua_S, 1, NULL);
if (self == NULL)
{
tolua_error(tolua_S, "invalid 'self' in function 'cCompositeChat:AddTextPart'", NULL);
return 0;
}
// Add the part:
AString Text, Style;
L.GetStackValue(2, Text);
L.GetStackValue(3, Style);
self->AddTextPart(Text, Style);
// Cut away everything from the stack except for the cCompositeChat instance; return that:
lua_settop(L, 1);
return 1;
}
static int tolua_cCompositeChat_AddUrlPart(lua_State * tolua_S)
{
// function cCompositeChat:AddTextPart(Message, Url, [Style])
// Exported manually to support call-chaining (return *this)
// Check params:
cLuaState L(tolua_S);
if (
!L.CheckParamUserType(1, "cCompositeChat") ||
!L.CheckParamString(2, 3)
)
{
return 0;
}
cCompositeChat * self = (cCompositeChat *)tolua_tousertype(tolua_S, 1, NULL);
if (self == NULL)
{
tolua_error(tolua_S, "invalid 'self' in function 'cCompositeChat:AddUrlPart'", NULL);
return 0;
}
// Add the part:
AString Text, Url, Style;
L.GetStackValue(2, Text);
L.GetStackValue(3, Url);
L.GetStackValue(4, Style);
self->AddUrlPart(Text, Url, Style);
// Cut away everything from the stack except for the cCompositeChat instance; return that:
lua_settop(L, 1);
return 1;
}
static int tolua_cCompositeChat_ParseText(lua_State * tolua_S)
{
// function cCompositeChat:ParseText(TextMessage)
// Exported manually to support call-chaining (return *this)
// Check params:
cLuaState L(tolua_S);
if (
!L.CheckParamUserType(1, "cCompositeChat") ||
!L.CheckParamString(2)
)
{
return 0;
}
cCompositeChat * self = (cCompositeChat *)tolua_tousertype(tolua_S, 1, NULL);
if (self == NULL)
{
tolua_error(tolua_S, "invalid 'self' in function 'cCompositeChat:ParseText'", NULL);
return 0;
}
// Parse the text:
AString Text;
L.GetStackValue(2, Text);
self->ParseText(Text);
// Cut away everything from the stack except for the cCompositeChat instance; return that:
lua_settop(L, 1);
return 1;
}
static int tolua_cCompositeChat_SetMessageType(lua_State * tolua_S)
{
// function cCompositeChat:SetMessageType(MessageType)
// Exported manually to support call-chaining (return *this)
// Check params:
cLuaState L(tolua_S);
if (
!L.CheckParamUserType(1, "cCompositeChat") ||
!L.CheckParamNumber(2)
)
{
return 0;
}
cCompositeChat * self = (cCompositeChat *)tolua_tousertype(tolua_S, 1, NULL);
if (self == NULL)
{
tolua_error(tolua_S, "invalid 'self' in function 'cCompositeChat:SetMessageType'", NULL);
return 0;
}
// Set the type:
int MessageType;
L.GetStackValue(1, MessageType);
self->SetMessageType((eMessageType)MessageType);
// Cut away everything from the stack except for the cCompositeChat instance; return that:
lua_settop(L, 1);
return 1;
}
static int tolua_cCompositeChat_UnderlineUrls(lua_State * tolua_S)
{
// function cCompositeChat:UnderlineUrls()
// Exported manually to support call-chaining (return *this)
// Check params:
cLuaState L(tolua_S);
if (!L.CheckParamUserType(1, "cCompositeChat"))
{
return 0;
}
cCompositeChat * self = (cCompositeChat *)tolua_tousertype(tolua_S, 1, NULL);
if (self == NULL)
{
tolua_error(tolua_S, "invalid 'self' in function 'cCompositeChat:UnderlineUrls'", NULL);
return 0;
}
// Call the processing
self->UnderlineUrls();
// Cut away everything from the stack except for the cCompositeChat instance; return that:
lua_settop(L, 1);
return 1;
}
void ManualBindings::Bind(lua_State * tolua_S)
{
tolua_beginmodule(tolua_S, NULL);
@ -2527,12 +2839,24 @@ void ManualBindings::Bind(lua_State * tolua_S)
tolua_endmodule(tolua_S);
tolua_beginmodule(tolua_S, "cBlockArea");
tolua_function(tolua_S, "GetBlockTypeMeta", tolua_cBlockArea_GetBlockTypeMeta);
tolua_function(tolua_S, "GetOrigin", tolua_cBlockArea_GetOrigin);
tolua_function(tolua_S, "GetRelBlockTypeMeta", tolua_cBlockArea_GetRelBlockTypeMeta);
tolua_function(tolua_S, "GetSize", tolua_cBlockArea_GetSize);
tolua_function(tolua_S, "LoadFromSchematicFile", tolua_cBlockArea_LoadFromSchematicFile);
tolua_function(tolua_S, "SaveToSchematicFile", tolua_cBlockArea_SaveToSchematicFile);
tolua_function(tolua_S, "GetBlockTypeMeta", tolua_cBlockArea_GetBlockTypeMeta);
tolua_function(tolua_S, "GetOrigin", tolua_cBlockArea_GetOrigin);
tolua_function(tolua_S, "GetRelBlockTypeMeta", tolua_cBlockArea_GetRelBlockTypeMeta);
tolua_function(tolua_S, "GetSize", tolua_cBlockArea_GetSize);
tolua_function(tolua_S, "LoadFromSchematicFile", tolua_cBlockArea_LoadFromSchematicFile);
tolua_function(tolua_S, "LoadFromSchematicString", tolua_cBlockArea_LoadFromSchematicString);
tolua_function(tolua_S, "SaveToSchematicFile", tolua_cBlockArea_SaveToSchematicFile);
tolua_function(tolua_S, "SaveToSchematicString", tolua_cBlockArea_SaveToSchematicString);
tolua_endmodule(tolua_S);
tolua_beginmodule(tolua_S, "cCompositeChat");
tolua_function(tolua_S, "AddRunCommandPart", tolua_cCompositeChat_AddRunCommandPart);
tolua_function(tolua_S, "AddSuggestCommandPart", tolua_cCompositeChat_AddSuggestCommandPart);
tolua_function(tolua_S, "AddTextPart", tolua_cCompositeChat_AddTextPart);
tolua_function(tolua_S, "AddUrlPart", tolua_cCompositeChat_AddUrlPart);
tolua_function(tolua_S, "ParseText", tolua_cCompositeChat_ParseText);
tolua_function(tolua_S, "SetMessageType", tolua_cCompositeChat_SetMessageType);
tolua_function(tolua_S, "UnderlineUrls", tolua_cCompositeChat_UnderlineUrls);
tolua_endmodule(tolua_S);
tolua_beginmodule(tolua_S, "cHopperEntity");
@ -2561,7 +2885,8 @@ void ManualBindings::Bind(lua_State * tolua_S)
tolua_function(tolua_S, "DoWithFurnaceAt", tolua_DoWithXYZ<cWorld, cFurnaceEntity, &cWorld::DoWithFurnaceAt>);
tolua_function(tolua_S, "DoWithNoteBlockAt", tolua_DoWithXYZ<cWorld, cNoteEntity, &cWorld::DoWithNoteBlockAt>);
tolua_function(tolua_S, "DoWithCommandBlockAt", tolua_DoWithXYZ<cWorld, cCommandBlockEntity, &cWorld::DoWithCommandBlockAt>);
tolua_function(tolua_S, "DoWithMobHeadBlockAt", tolua_DoWithXYZ<cWorld, cMobHeadEntity, &cWorld::DoWithMobHeadBlockAt>);
tolua_function(tolua_S, "DoWithMobHeadAt", tolua_DoWithXYZ<cWorld, cMobHeadEntity, &cWorld::DoWithMobHeadAt>);
tolua_function(tolua_S, "DoWithFlowerPotAt", tolua_DoWithXYZ<cWorld, cFlowerPotEntity, &cWorld::DoWithFlowerPotAt>);
tolua_function(tolua_S, "DoWithPlayer", tolua_DoWith< cWorld, cPlayer, &cWorld::DoWithPlayer>);
tolua_function(tolua_S, "FindAndDoWithPlayer", tolua_DoWith< cWorld, cPlayer, &cWorld::FindAndDoWithPlayer>);
tolua_function(tolua_S, "ForEachBlockEntityInChunk", tolua_ForEachInChunk<cWorld, cBlockEntity, &cWorld::ForEachBlockEntityInChunk>);
@ -2583,6 +2908,11 @@ void ManualBindings::Bind(lua_State * tolua_S)
tolua_beginmodule(tolua_S, "cMapManager");
tolua_function(tolua_S, "DoWithMap", tolua_DoWithID<cMapManager, cMap, &cMapManager::DoWithMap>);
tolua_endmodule(tolua_S);
tolua_beginmodule(tolua_S, "cScoreboard");
tolua_function(tolua_S, "ForEachObjective", tolua_ForEach<cScoreboard, cObjective, &cScoreboard::ForEachObjective>);
tolua_function(tolua_S, "ForEachTeam", tolua_ForEach<cScoreboard, cTeam, &cScoreboard::ForEachTeam>);
tolua_endmodule(tolua_S);
tolua_beginmodule(tolua_S, "cPlugin");
tolua_function(tolua_S, "Call", tolua_cPlugin_Call);

View File

@ -10,6 +10,7 @@
#include "DispenserEntity.h"
#include "DropperEntity.h"
#include "EnderChestEntity.h"
#include "FlowerPotEntity.h"
#include "FurnaceEntity.h"
#include "HopperEntity.h"
#include "JukeboxEntity.h"
@ -30,6 +31,7 @@ cBlockEntity * cBlockEntity::CreateByBlockType(BLOCKTYPE a_BlockType, NIBBLETYPE
case E_BLOCK_DISPENSER: return new cDispenserEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
case E_BLOCK_DROPPER: return new cDropperEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
case E_BLOCK_ENDER_CHEST: return new cEnderChestEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
case E_BLOCK_FLOWER_POT: return new cFlowerPotEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
case E_BLOCK_HEAD: return new cMobHeadEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
case E_BLOCK_LIT_FURNACE: return new cFurnaceEntity (a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta, a_World);
case E_BLOCK_FURNACE: return new cFurnaceEntity (a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta, a_World);

View File

@ -0,0 +1,134 @@
// FlowerPotEntity.cpp
// Implements the cFlowerPotEntity class representing a single sign in the world
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
#include "json/json.h"
#include "FlowerPotEntity.h"
#include "../Entities/Player.h"
#include "../Item.h"
cFlowerPotEntity::cFlowerPotEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World) :
super(E_BLOCK_FLOWER_POT, a_BlockX, a_BlockY, a_BlockZ, a_World)
{
}
// It don't do anything when 'used'
void cFlowerPotEntity::UsedBy(cPlayer * a_Player)
{
if (IsItemInPot())
{
return;
}
cItem SelectedItem = a_Player->GetInventory().GetEquippedItem();
if (IsFlower(SelectedItem.m_ItemType, SelectedItem.m_ItemDamage))
{
m_Item = SelectedItem.CopyOne();
if (!a_Player->IsGameModeCreative())
{
a_Player->GetInventory().RemoveOneEquippedItem();
}
m_World->BroadcastBlockEntity(m_PosX, m_PosY, m_PosZ, a_Player->GetClientHandle());
}
}
void cFlowerPotEntity::SendTo(cClientHandle & a_Client)
{
a_Client.SendUpdateBlockEntity(*this);
}
void cFlowerPotEntity::Destroy(void)
{
// Drop the contents as pickups:
if (!m_Item.IsEmpty())
{
ASSERT(m_World != NULL);
cItems Pickups;
Pickups.Add(m_Item);
m_World->SpawnItemPickups(Pickups, m_PosX + 0.5, m_PosY + 0.5, m_PosZ + 0.5);
m_Item.Empty();
}
}
bool cFlowerPotEntity::LoadFromJson(const Json::Value & a_Value)
{
m_PosX = a_Value.get("x", 0).asInt();
m_PosY = a_Value.get("y", 0).asInt();
m_PosZ = a_Value.get("z", 0).asInt();
m_Item = cItem();
m_Item.FromJson(a_Value.get("Item", 0));
return true;
}
void cFlowerPotEntity::SaveToJson(Json::Value & a_Value)
{
a_Value["x"] = m_PosX;
a_Value["y"] = m_PosY;
a_Value["z"] = m_PosZ;
Json::Value Item;
m_Item.GetJson(Item);
a_Value["Item"] = Item;
}
bool cFlowerPotEntity::IsFlower(short m_ItemType, short m_ItemData)
{
switch (m_ItemType)
{
case E_BLOCK_DANDELION:
case E_BLOCK_FLOWER:
case E_BLOCK_CACTUS:
case E_BLOCK_BROWN_MUSHROOM:
case E_BLOCK_RED_MUSHROOM:
case E_BLOCK_SAPLING:
case E_BLOCK_DEAD_BUSH:
{
return true;
}
case E_BLOCK_TALL_GRASS:
{
return (m_ItemData == (short) 2);
}
default:
{
return false;
}
}
}

View File

@ -0,0 +1,74 @@
// FlowerPotEntity.h
// Declares the cFlowerPotEntity class representing a single sign in the world
#pragma once
#include "BlockEntity.h"
class cItem;
namespace Json
{
class Value;
}
// tolua_begin
class cFlowerPotEntity :
public cBlockEntity
{
typedef cBlockEntity super;
public:
// tolua_end
/** Creates a new flowerpot entity at the specified block coords. a_World may be NULL */
cFlowerPotEntity(int a_BlocX, int a_BlockY, int a_BlockZ, cWorld * a_World);
bool LoadFromJson( const Json::Value& a_Value );
virtual void SaveToJson(Json::Value& a_Value ) override;
virtual void Destroy(void) override;
// tolua_begin
/** Is a flower in the pot? */
bool IsItemInPot(void) { return !m_Item.IsEmpty(); }
/** Get the item in the flower pot */
cItem GetItem(void) const { return m_Item; }
/** Set the item in the flower pot */
void SetItem(const cItem a_Item) { m_Item = a_Item; }
// tolua_end
virtual void UsedBy(cPlayer * a_Player) override;
virtual void SendTo(cClientHandle & a_Client) override;
static bool IsFlower(short m_ItemType, short m_ItemData);
static const char * GetClassStatic(void) { return "cFlowerPotEntity"; }
private:
cItem m_Item;
} ; // tolua_export

View File

@ -30,48 +30,70 @@ cJukeboxEntity::~cJukeboxEntity()
void cJukeboxEntity::UsedBy(cPlayer * a_Player)
{
if (m_Record == 0)
{
const cItem & HeldItem = a_Player->GetEquippedItem();
if (HeldItem.m_ItemType >= 2256 && HeldItem.m_ItemType <= 2267)
{
m_Record = HeldItem.m_ItemType;
a_Player->GetInventory().RemoveOneEquippedItem();
PlayRecord();
}
}
else
if (IsPlayingRecord())
{
EjectRecord();
}
else
{
const cItem & HeldItem = a_Player->GetEquippedItem();
if (PlayRecord(HeldItem.m_ItemType))
{
a_Player->GetInventory().RemoveOneEquippedItem();
}
}
}
void cJukeboxEntity::PlayRecord(void)
bool cJukeboxEntity::PlayRecord(int a_Record)
{
if (!IsRecordItem(a_Record))
{
// This isn't a Record Item
return false;
}
if (IsPlayingRecord())
{
// A Record is already in the Jukebox.
EjectRecord();
}
m_Record = a_Record;
m_World->BroadcastSoundParticleEffect(1005, m_PosX, m_PosY, m_PosZ, m_Record);
m_World->SetBlockMeta(m_PosX, m_PosY, m_PosZ, E_META_JUKEBOX_ON);
return true;
}
void cJukeboxEntity::EjectRecord(void)
bool cJukeboxEntity::EjectRecord(void)
{
if ((m_Record < E_ITEM_FIRST_DISC) || (m_Record > E_ITEM_LAST_DISC))
if (!IsPlayingRecord())
{
// There's no record here
return;
return false;
}
cItems Drops;
Drops.push_back(cItem(m_Record, 1, 0));
m_Record = 0;
m_World->SpawnItemPickups(Drops, m_PosX + 0.5, m_PosY + 1, m_PosZ + 0.5, 8);
m_World->BroadcastSoundParticleEffect(1005, m_PosX, m_PosY, m_PosZ, 0);
m_Record = 0;
m_World->SetBlockMeta(m_PosX, m_PosY, m_PosZ, E_META_JUKEBOX_OFF);
return true;
}
bool cJukeboxEntity::IsPlayingRecord(void)
{
return (m_Record != 0);
}

View File

@ -37,10 +37,21 @@ public:
int GetRecord(void);
void SetRecord(int a_Record);
void PlayRecord(void);
/// Ejects the currently held record as a pickup. Does nothing when no record inserted.
void EjectRecord(void);
/** Plays the specified Record. Return false if a_Record isn't a playable Record (E_ITEM_XXX_DISC).
If there is a record already playing, ejects it first. */
bool PlayRecord(int a_Record);
/** Ejects the currently held record as a pickup. Return false when no record had been inserted. */
bool EjectRecord(void);
/** Is in the Jukebox a Record? */
bool IsPlayingRecord(void);
static bool IsRecordItem(int a_Item)
{
return ((a_Item >= E_ITEM_FIRST_DISC) && (a_Item <= E_ITEM_LAST_DISC));
}
// tolua_end

View File

@ -12,20 +12,6 @@
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_BlockFullyOccupiesVoxel[256];
class cBlockIDMap
{
// Making the map case-insensitive:
@ -481,389 +467,4 @@ cItem GetIniItemSet(cIniFile & a_IniFile, const char * a_Section, const char * a
// 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_BlockFullyOccupiesVoxel, 0x00, sizeof(g_BlockFullyOccupiesVoxel));
// Setting bools to true must be done manually, see http://forum.mc-server.org/showthread.php?tid=629&pid=5415#pid5415
for (size_t 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 (size_t 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_ENDER_CHEST] = 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_BUTTON] = 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_BUTTON] = 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_HEAVY_WEIGHTED_PRESSURE_PLATE] = 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_LIGHT_WEIGHTED_PRESSURE_PLATE] = 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_HEAVY_WEIGHTED_PRESSURE_PLATE] = 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_LIGHT_WEIGHTED_PRESSURE_PLATE] = 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_POTATOES] = false;
g_BlockIsSolid[E_BLOCK_POWERED_RAIL] = 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_BlockFullyOccupiesVoxel[E_BLOCK_NEW_LOG] = true;
g_BlockFullyOccupiesVoxel[E_BLOCK_BEDROCK] = true;
g_BlockFullyOccupiesVoxel[E_BLOCK_BLOCK_OF_COAL] = true;
g_BlockFullyOccupiesVoxel[E_BLOCK_BLOCK_OF_REDSTONE] = true;
g_BlockFullyOccupiesVoxel[E_BLOCK_BOOKCASE] = true;
g_BlockFullyOccupiesVoxel[E_BLOCK_BRICK] = true;
g_BlockFullyOccupiesVoxel[E_BLOCK_CLAY] = true;
g_BlockFullyOccupiesVoxel[E_BLOCK_COAL_ORE] = true;
g_BlockFullyOccupiesVoxel[E_BLOCK_COBBLESTONE] = true;
g_BlockFullyOccupiesVoxel[E_BLOCK_COMMAND_BLOCK] = true;
g_BlockFullyOccupiesVoxel[E_BLOCK_CRAFTING_TABLE] = true;
g_BlockFullyOccupiesVoxel[E_BLOCK_DIAMOND_BLOCK] = true;
g_BlockFullyOccupiesVoxel[E_BLOCK_DIAMOND_ORE] = true;
g_BlockFullyOccupiesVoxel[E_BLOCK_DIRT] = true;
g_BlockFullyOccupiesVoxel[E_BLOCK_DISPENSER] = true;
g_BlockFullyOccupiesVoxel[E_BLOCK_DOUBLE_STONE_SLAB] = true;
g_BlockFullyOccupiesVoxel[E_BLOCK_DOUBLE_WOODEN_SLAB] = true;
g_BlockFullyOccupiesVoxel[E_BLOCK_DROPPER] = true;
g_BlockFullyOccupiesVoxel[E_BLOCK_EMERALD_BLOCK] = true;
g_BlockFullyOccupiesVoxel[E_BLOCK_EMERALD_ORE] = true;
g_BlockFullyOccupiesVoxel[E_BLOCK_END_STONE] = true;
g_BlockFullyOccupiesVoxel[E_BLOCK_FURNACE] = true;
g_BlockFullyOccupiesVoxel[E_BLOCK_GLOWSTONE] = true;
g_BlockFullyOccupiesVoxel[E_BLOCK_GOLD_BLOCK] = true;
g_BlockFullyOccupiesVoxel[E_BLOCK_GOLD_ORE] = true;
g_BlockFullyOccupiesVoxel[E_BLOCK_GRASS] = true;
g_BlockFullyOccupiesVoxel[E_BLOCK_GRAVEL] = true;
g_BlockFullyOccupiesVoxel[E_BLOCK_HARDENED_CLAY] = true;
g_BlockFullyOccupiesVoxel[E_BLOCK_HAY_BALE] = true;
g_BlockFullyOccupiesVoxel[E_BLOCK_HUGE_BROWN_MUSHROOM] = true;
g_BlockFullyOccupiesVoxel[E_BLOCK_HUGE_RED_MUSHROOM] = true;
g_BlockFullyOccupiesVoxel[E_BLOCK_IRON_BLOCK] = true;
g_BlockFullyOccupiesVoxel[E_BLOCK_IRON_ORE] = true;
g_BlockFullyOccupiesVoxel[E_BLOCK_JACK_O_LANTERN] = true;
g_BlockFullyOccupiesVoxel[E_BLOCK_JUKEBOX] = true;
g_BlockFullyOccupiesVoxel[E_BLOCK_LAPIS_BLOCK] = true;
g_BlockFullyOccupiesVoxel[E_BLOCK_LAPIS_ORE] = true;
g_BlockFullyOccupiesVoxel[E_BLOCK_LOG] = true;
g_BlockFullyOccupiesVoxel[E_BLOCK_MELON] = true;
g_BlockFullyOccupiesVoxel[E_BLOCK_MOSSY_COBBLESTONE] = true;
g_BlockFullyOccupiesVoxel[E_BLOCK_MYCELIUM] = true;
g_BlockFullyOccupiesVoxel[E_BLOCK_NETHERRACK] = true;
g_BlockFullyOccupiesVoxel[E_BLOCK_NETHER_BRICK] = true;
g_BlockFullyOccupiesVoxel[E_BLOCK_NETHER_QUARTZ_ORE] = true;
g_BlockFullyOccupiesVoxel[E_BLOCK_NOTE_BLOCK] = true;
g_BlockFullyOccupiesVoxel[E_BLOCK_OBSIDIAN] = true;
g_BlockFullyOccupiesVoxel[E_BLOCK_PACKED_ICE] = true;
g_BlockFullyOccupiesVoxel[E_BLOCK_PLANKS] = true;
g_BlockFullyOccupiesVoxel[E_BLOCK_PUMPKIN] = true;
g_BlockFullyOccupiesVoxel[E_BLOCK_QUARTZ_BLOCK] = true;
g_BlockFullyOccupiesVoxel[E_BLOCK_REDSTONE_LAMP_OFF] = true;
g_BlockFullyOccupiesVoxel[E_BLOCK_REDSTONE_LAMP_ON] = true;
g_BlockFullyOccupiesVoxel[E_BLOCK_REDSTONE_ORE] = true;
g_BlockFullyOccupiesVoxel[E_BLOCK_REDSTONE_ORE_GLOWING] = true;
g_BlockFullyOccupiesVoxel[E_BLOCK_SANDSTONE] = true;
g_BlockFullyOccupiesVoxel[E_BLOCK_SAND] = true;
g_BlockFullyOccupiesVoxel[E_BLOCK_SILVERFISH_EGG] = true;
g_BlockFullyOccupiesVoxel[E_BLOCK_SPONGE] = true;
g_BlockFullyOccupiesVoxel[E_BLOCK_STAINED_CLAY] = true;
g_BlockFullyOccupiesVoxel[E_BLOCK_WOOL] = true;
g_BlockFullyOccupiesVoxel[E_BLOCK_STONE] = true;
g_BlockFullyOccupiesVoxel[E_BLOCK_STONE_BRICKS] = true;
}
} BlockPropertiesInitializer;

View File

@ -466,6 +466,10 @@ enum
E_META_FLOWER_PINK_TULIP = 7,
E_META_FLOWER_OXEYE_DAISY = 8,
// E_BLOCK_JUKEBOX metas
E_META_JUKEBOX_OFF = 0,
E_META_JUKEBOX_ON = 1,
// E_BLOCK_HOPPER metas:
E_META_HOPPER_FACING_YM = 0,
E_META_HOPPER_UNATTACHED = 1, // Hopper doesn't move items up, there's no YP
@ -905,17 +909,3 @@ extern cItem GetIniItemSet(cIniFile & a_IniFile, const char * a_Section, const c
// Block properties:
extern NIBBLETYPE g_BlockLightValue[256];
extern NIBBLETYPE g_BlockSpreadLightFalloff[256];
extern bool g_BlockTransparent[256];
extern bool g_BlockOneHitDig[256];
extern bool g_BlockPistonBreakable[256];
extern bool g_BlockIsSnowable[256];
extern bool g_BlockRequiresSpecialTool[256];
extern bool g_BlockIsSolid[256];
extern bool g_BlockFullyOccupiesVoxel[256];

451
src/BlockInfo.cpp Normal file
View File

@ -0,0 +1,451 @@
#include "Globals.h"
#include "BlockInfo.h"
#include "Blocks/BlockHandler.h"
cBlockInfo cBlockInfo::ms_Info[256];
cBlockInfo::cBlockInfo()
: m_LightValue(0x00)
, m_SpreadLightFalloff(0x0f)
, m_Transparent(false)
, m_OneHitDig(false)
, m_PistonBreakable(false)
, m_IsSnowable(true)
, m_RequiresSpecialTool(false)
, m_IsSolid(true)
, m_FullyOccupiesVoxel(false)
, m_Handler(NULL)
{}
cBlockInfo::~cBlockInfo()
{
delete m_Handler;
}
cBlockInfo & cBlockInfo::Get(BLOCKTYPE a_Type)
{
ASSERT(a_Type < 256);
return ms_Info[a_Type];
}
void cBlockInfo::Initialize(void)
{
for (unsigned int i = 0; i < 256; ++i)
{
if (ms_Info[i].m_Handler == NULL)
{
ms_Info[i].m_Handler = cBlockHandler::CreateBlockHandler((BLOCKTYPE) i);
}
}
// Emissive blocks
ms_Info[E_BLOCK_FIRE ].m_LightValue = 15;
ms_Info[E_BLOCK_GLOWSTONE ].m_LightValue = 15;
ms_Info[E_BLOCK_JACK_O_LANTERN ].m_LightValue = 15;
ms_Info[E_BLOCK_LAVA ].m_LightValue = 15;
ms_Info[E_BLOCK_STATIONARY_LAVA ].m_LightValue = 15;
ms_Info[E_BLOCK_END_PORTAL ].m_LightValue = 15;
ms_Info[E_BLOCK_REDSTONE_LAMP_ON ].m_LightValue = 15;
ms_Info[E_BLOCK_TORCH ].m_LightValue = 14;
ms_Info[E_BLOCK_BURNING_FURNACE ].m_LightValue = 13;
ms_Info[E_BLOCK_NETHER_PORTAL ].m_LightValue = 11;
ms_Info[E_BLOCK_REDSTONE_ORE_GLOWING].m_LightValue = 9;
ms_Info[E_BLOCK_REDSTONE_REPEATER_ON].m_LightValue = 9;
ms_Info[E_BLOCK_REDSTONE_TORCH_ON ].m_LightValue = 7;
ms_Info[E_BLOCK_BREWING_STAND ].m_LightValue = 1;
ms_Info[E_BLOCK_BROWN_MUSHROOM ].m_LightValue = 1;
ms_Info[E_BLOCK_DRAGON_EGG ].m_LightValue = 1;
// Spread blocks
ms_Info[E_BLOCK_AIR ].m_SpreadLightFalloff = 1;
ms_Info[E_BLOCK_CAKE ].m_SpreadLightFalloff = 1;
ms_Info[E_BLOCK_CHEST ].m_SpreadLightFalloff = 1;
ms_Info[E_BLOCK_COBWEB ].m_SpreadLightFalloff = 1;
ms_Info[E_BLOCK_CROPS ].m_SpreadLightFalloff = 1;
ms_Info[E_BLOCK_FENCE ].m_SpreadLightFalloff = 1;
ms_Info[E_BLOCK_FENCE_GATE ].m_SpreadLightFalloff = 1;
ms_Info[E_BLOCK_FIRE ].m_SpreadLightFalloff = 1;
ms_Info[E_BLOCK_GLASS ].m_SpreadLightFalloff = 1;
ms_Info[E_BLOCK_GLASS_PANE ].m_SpreadLightFalloff = 1;
ms_Info[E_BLOCK_GLOWSTONE ].m_SpreadLightFalloff = 1;
ms_Info[E_BLOCK_IRON_BARS ].m_SpreadLightFalloff = 1;
ms_Info[E_BLOCK_IRON_DOOR ].m_SpreadLightFalloff = 1;
ms_Info[E_BLOCK_LEAVES ].m_SpreadLightFalloff = 1;
ms_Info[E_BLOCK_SIGN_POST ].m_SpreadLightFalloff = 1;
ms_Info[E_BLOCK_TORCH ].m_SpreadLightFalloff = 1;
ms_Info[E_BLOCK_VINES ].m_SpreadLightFalloff = 1;
ms_Info[E_BLOCK_WALLSIGN ].m_SpreadLightFalloff = 1;
ms_Info[E_BLOCK_WOODEN_DOOR ].m_SpreadLightFalloff = 1;
// Light in water and lava dissapears faster:
ms_Info[E_BLOCK_LAVA ].m_SpreadLightFalloff = 3;
ms_Info[E_BLOCK_STATIONARY_LAVA ].m_SpreadLightFalloff = 3;
ms_Info[E_BLOCK_STATIONARY_WATER ].m_SpreadLightFalloff = 3;
ms_Info[E_BLOCK_WATER ].m_SpreadLightFalloff = 3;
// Transparent blocks
ms_Info[E_BLOCK_ACTIVATOR_RAIL ].m_Transparent = true;
ms_Info[E_BLOCK_AIR ].m_Transparent = true;
ms_Info[E_BLOCK_BIG_FLOWER ].m_Transparent = true;
ms_Info[E_BLOCK_BROWN_MUSHROOM ].m_Transparent = true;
ms_Info[E_BLOCK_CARROTS ].m_Transparent = true;
ms_Info[E_BLOCK_CHEST ].m_Transparent = true;
ms_Info[E_BLOCK_COBWEB ].m_Transparent = true;
ms_Info[E_BLOCK_CROPS ].m_Transparent = true;
ms_Info[E_BLOCK_DANDELION ].m_Transparent = true;
ms_Info[E_BLOCK_DETECTOR_RAIL ].m_Transparent = true;
ms_Info[E_BLOCK_ENDER_CHEST ].m_Transparent = true;
ms_Info[E_BLOCK_FENCE ].m_Transparent = true;
ms_Info[E_BLOCK_FENCE_GATE ].m_Transparent = true;
ms_Info[E_BLOCK_FIRE ].m_Transparent = true;
ms_Info[E_BLOCK_FLOWER ].m_Transparent = true;
ms_Info[E_BLOCK_FLOWER_POT ].m_Transparent = true;
ms_Info[E_BLOCK_GLASS ].m_Transparent = true;
ms_Info[E_BLOCK_GLASS_PANE ].m_Transparent = true;
ms_Info[E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE].m_Transparent = true;
ms_Info[E_BLOCK_ICE ].m_Transparent = true;
ms_Info[E_BLOCK_IRON_DOOR ].m_Transparent = true;
ms_Info[E_BLOCK_LAVA ].m_Transparent = true;
ms_Info[E_BLOCK_LEAVES ].m_Transparent = true;
ms_Info[E_BLOCK_LEVER ].m_Transparent = true;
ms_Info[E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE].m_Transparent = true;
ms_Info[E_BLOCK_MELON_STEM ].m_Transparent = true;
ms_Info[E_BLOCK_NETHER_BRICK_FENCE ].m_Transparent = true;
ms_Info[E_BLOCK_NEW_LEAVES ].m_Transparent = true;
ms_Info[E_BLOCK_POTATOES ].m_Transparent = true;
ms_Info[E_BLOCK_POWERED_RAIL ].m_Transparent = true;
ms_Info[E_BLOCK_PISTON_EXTENSION ].m_Transparent = true;
ms_Info[E_BLOCK_PUMPKIN_STEM ].m_Transparent = true;
ms_Info[E_BLOCK_RAIL ].m_Transparent = true;
ms_Info[E_BLOCK_RED_MUSHROOM ].m_Transparent = true;
ms_Info[E_BLOCK_SIGN_POST ].m_Transparent = true;
ms_Info[E_BLOCK_SNOW ].m_Transparent = true;
ms_Info[E_BLOCK_STAINED_GLASS ].m_Transparent = true;
ms_Info[E_BLOCK_STAINED_GLASS_PANE ].m_Transparent = true;
ms_Info[E_BLOCK_STATIONARY_LAVA ].m_Transparent = true;
ms_Info[E_BLOCK_STATIONARY_WATER ].m_Transparent = true;
ms_Info[E_BLOCK_STONE_BUTTON ].m_Transparent = true;
ms_Info[E_BLOCK_STONE_PRESSURE_PLATE].m_Transparent = true;
ms_Info[E_BLOCK_TALL_GRASS ].m_Transparent = true;
ms_Info[E_BLOCK_TORCH ].m_Transparent = true;
ms_Info[E_BLOCK_VINES ].m_Transparent = true;
ms_Info[E_BLOCK_WALLSIGN ].m_Transparent = true;
ms_Info[E_BLOCK_WATER ].m_Transparent = true;
ms_Info[E_BLOCK_WOODEN_BUTTON ].m_Transparent = true;
ms_Info[E_BLOCK_WOODEN_DOOR ].m_Transparent = true;
ms_Info[E_BLOCK_WOODEN_PRESSURE_PLATE].m_Transparent = true;
// TODO: Any other transparent blocks?
// One hit break blocks:
ms_Info[E_BLOCK_ACTIVE_COMPARATOR ].m_OneHitDig = true;
ms_Info[E_BLOCK_BIG_FLOWER ].m_OneHitDig = true;
ms_Info[E_BLOCK_BROWN_MUSHROOM ].m_OneHitDig = true;
ms_Info[E_BLOCK_CARROTS ].m_OneHitDig = true;
ms_Info[E_BLOCK_CROPS ].m_OneHitDig = true;
ms_Info[E_BLOCK_DANDELION ].m_OneHitDig = true;
ms_Info[E_BLOCK_FIRE ].m_OneHitDig = true;
ms_Info[E_BLOCK_FLOWER ].m_OneHitDig = true;
ms_Info[E_BLOCK_FLOWER_POT ].m_OneHitDig = true;
ms_Info[E_BLOCK_INACTIVE_COMPARATOR ].m_OneHitDig = true;
ms_Info[E_BLOCK_MELON_STEM ].m_OneHitDig = true;
ms_Info[E_BLOCK_POTATOES ].m_OneHitDig = true;
ms_Info[E_BLOCK_PUMPKIN_STEM ].m_OneHitDig = true;
ms_Info[E_BLOCK_REDSTONE_REPEATER_OFF].m_OneHitDig = true;
ms_Info[E_BLOCK_REDSTONE_REPEATER_ON].m_OneHitDig = true;
ms_Info[E_BLOCK_REDSTONE_TORCH_OFF ].m_OneHitDig = true;
ms_Info[E_BLOCK_REDSTONE_TORCH_ON ].m_OneHitDig = true;
ms_Info[E_BLOCK_REDSTONE_WIRE ].m_OneHitDig = true;
ms_Info[E_BLOCK_RED_MUSHROOM ].m_OneHitDig = true;
ms_Info[E_BLOCK_REEDS ].m_OneHitDig = true;
ms_Info[E_BLOCK_SAPLING ].m_OneHitDig = true;
ms_Info[E_BLOCK_TNT ].m_OneHitDig = true;
ms_Info[E_BLOCK_TALL_GRASS ].m_OneHitDig = true;
ms_Info[E_BLOCK_TORCH ].m_OneHitDig = true;
// Blocks that break when pushed by piston:
ms_Info[E_BLOCK_ACTIVE_COMPARATOR ].m_PistonBreakable = true;
ms_Info[E_BLOCK_AIR ].m_PistonBreakable = true;
ms_Info[E_BLOCK_BED ].m_PistonBreakable = true;
ms_Info[E_BLOCK_BIG_FLOWER ].m_PistonBreakable = true;
ms_Info[E_BLOCK_BROWN_MUSHROOM ].m_PistonBreakable = true;
ms_Info[E_BLOCK_COBWEB ].m_PistonBreakable = true;
ms_Info[E_BLOCK_CROPS ].m_PistonBreakable = true;
ms_Info[E_BLOCK_DANDELION ].m_PistonBreakable = true;
ms_Info[E_BLOCK_DEAD_BUSH ].m_PistonBreakable = true;
ms_Info[E_BLOCK_FIRE ].m_PistonBreakable = true;
ms_Info[E_BLOCK_FLOWER ].m_PistonBreakable = true;
ms_Info[E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE].m_PistonBreakable = true;
ms_Info[E_BLOCK_INACTIVE_COMPARATOR ].m_PistonBreakable = true;
ms_Info[E_BLOCK_IRON_DOOR ].m_PistonBreakable = true;
ms_Info[E_BLOCK_JACK_O_LANTERN ].m_PistonBreakable = true;
ms_Info[E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE].m_PistonBreakable = true;
ms_Info[E_BLOCK_LADDER ].m_PistonBreakable = true;
ms_Info[E_BLOCK_LAVA ].m_PistonBreakable = true;
ms_Info[E_BLOCK_LEVER ].m_PistonBreakable = true;
ms_Info[E_BLOCK_MELON ].m_PistonBreakable = true;
ms_Info[E_BLOCK_MELON_STEM ].m_PistonBreakable = true;
ms_Info[E_BLOCK_PUMPKIN ].m_PistonBreakable = true;
ms_Info[E_BLOCK_PUMPKIN_STEM ].m_PistonBreakable = true;
ms_Info[E_BLOCK_REDSTONE_REPEATER_OFF].m_PistonBreakable = true;
ms_Info[E_BLOCK_REDSTONE_REPEATER_ON].m_PistonBreakable = true;
ms_Info[E_BLOCK_REDSTONE_TORCH_OFF ].m_PistonBreakable = true;
ms_Info[E_BLOCK_REDSTONE_TORCH_ON ].m_PistonBreakable = true;
ms_Info[E_BLOCK_REDSTONE_WIRE ].m_PistonBreakable = true;
ms_Info[E_BLOCK_RED_MUSHROOM ].m_PistonBreakable = true;
ms_Info[E_BLOCK_REEDS ].m_PistonBreakable = true;
ms_Info[E_BLOCK_SNOW ].m_PistonBreakable = true;
ms_Info[E_BLOCK_STATIONARY_LAVA ].m_PistonBreakable = true;
ms_Info[E_BLOCK_STATIONARY_WATER ].m_PistonBreakable = true;
ms_Info[E_BLOCK_STONE_BUTTON ].m_PistonBreakable = true;
ms_Info[E_BLOCK_STONE_PRESSURE_PLATE].m_PistonBreakable = true;
ms_Info[E_BLOCK_TALL_GRASS ].m_PistonBreakable = true;
ms_Info[E_BLOCK_TORCH ].m_PistonBreakable = true;
ms_Info[E_BLOCK_VINES ].m_PistonBreakable = true;
ms_Info[E_BLOCK_WATER ].m_PistonBreakable = true;
ms_Info[E_BLOCK_WOODEN_BUTTON ].m_PistonBreakable = true;
ms_Info[E_BLOCK_WOODEN_DOOR ].m_PistonBreakable = true;
ms_Info[E_BLOCK_WOODEN_PRESSURE_PLATE].m_PistonBreakable = true;
// Blocks that cannot be snowed over:
ms_Info[E_BLOCK_ACTIVE_COMPARATOR ].m_IsSnowable = false;
ms_Info[E_BLOCK_AIR ].m_IsSnowable = false;
ms_Info[E_BLOCK_BIG_FLOWER ].m_IsSnowable = false;
ms_Info[E_BLOCK_BROWN_MUSHROOM ].m_IsSnowable = false;
ms_Info[E_BLOCK_CACTUS ].m_IsSnowable = false;
ms_Info[E_BLOCK_CHEST ].m_IsSnowable = false;
ms_Info[E_BLOCK_CROPS ].m_IsSnowable = false;
ms_Info[E_BLOCK_DANDELION ].m_IsSnowable = false;
ms_Info[E_BLOCK_FIRE ].m_IsSnowable = false;
ms_Info[E_BLOCK_FLOWER ].m_IsSnowable = false;
ms_Info[E_BLOCK_GLASS ].m_IsSnowable = false;
ms_Info[E_BLOCK_ICE ].m_IsSnowable = false;
ms_Info[E_BLOCK_INACTIVE_COMPARATOR ].m_IsSnowable = false;
ms_Info[E_BLOCK_LAVA ].m_IsSnowable = false;
ms_Info[E_BLOCK_LILY_PAD ].m_IsSnowable = false;
ms_Info[E_BLOCK_REDSTONE_REPEATER_OFF].m_IsSnowable = false;
ms_Info[E_BLOCK_REDSTONE_REPEATER_ON].m_IsSnowable = false;
ms_Info[E_BLOCK_REDSTONE_TORCH_OFF ].m_IsSnowable = false;
ms_Info[E_BLOCK_REDSTONE_TORCH_ON ].m_IsSnowable = false;
ms_Info[E_BLOCK_REDSTONE_WIRE ].m_IsSnowable = false;
ms_Info[E_BLOCK_RED_MUSHROOM ].m_IsSnowable = false;
ms_Info[E_BLOCK_REEDS ].m_IsSnowable = false;
ms_Info[E_BLOCK_SAPLING ].m_IsSnowable = false;
ms_Info[E_BLOCK_SIGN_POST ].m_IsSnowable = false;
ms_Info[E_BLOCK_SNOW ].m_IsSnowable = false;
ms_Info[E_BLOCK_STAINED_GLASS ].m_IsSnowable = false;
ms_Info[E_BLOCK_STAINED_GLASS_PANE ].m_IsSnowable = false;
ms_Info[E_BLOCK_STATIONARY_LAVA ].m_IsSnowable = false;
ms_Info[E_BLOCK_STATIONARY_WATER ].m_IsSnowable = false;
ms_Info[E_BLOCK_TALL_GRASS ].m_IsSnowable = false;
ms_Info[E_BLOCK_TNT ].m_IsSnowable = false;
ms_Info[E_BLOCK_TORCH ].m_IsSnowable = false;
ms_Info[E_BLOCK_VINES ].m_IsSnowable = false;
ms_Info[E_BLOCK_WALLSIGN ].m_IsSnowable = false;
ms_Info[E_BLOCK_WATER ].m_IsSnowable = false;
ms_Info[E_BLOCK_RAIL ].m_IsSnowable = false;
ms_Info[E_BLOCK_ACTIVATOR_RAIL ].m_IsSnowable = false;
ms_Info[E_BLOCK_POWERED_RAIL ].m_IsSnowable = false;
ms_Info[E_BLOCK_DETECTOR_RAIL ].m_IsSnowable = false;
ms_Info[E_BLOCK_COBWEB ].m_IsSnowable = false;
// Blocks that don't drop without a special tool:
ms_Info[E_BLOCK_BRICK ].m_RequiresSpecialTool = true;
ms_Info[E_BLOCK_CAULDRON ].m_RequiresSpecialTool = true;
ms_Info[E_BLOCK_COAL_ORE ].m_RequiresSpecialTool = true;
ms_Info[E_BLOCK_COBBLESTONE ].m_RequiresSpecialTool = true;
ms_Info[E_BLOCK_COBBLESTONE_STAIRS ].m_RequiresSpecialTool = true;
ms_Info[E_BLOCK_COBWEB ].m_RequiresSpecialTool = true;
ms_Info[E_BLOCK_DIAMOND_BLOCK ].m_RequiresSpecialTool = true;
ms_Info[E_BLOCK_DIAMOND_ORE ].m_RequiresSpecialTool = true;
ms_Info[E_BLOCK_DOUBLE_STONE_SLAB ].m_RequiresSpecialTool = true;
ms_Info[E_BLOCK_EMERALD_ORE ].m_RequiresSpecialTool = true;
ms_Info[E_BLOCK_END_STONE ].m_RequiresSpecialTool = true;
ms_Info[E_BLOCK_GOLD_BLOCK ].m_RequiresSpecialTool = true;
ms_Info[E_BLOCK_GOLD_ORE ].m_RequiresSpecialTool = true;
ms_Info[E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE].m_RequiresSpecialTool = true;
ms_Info[E_BLOCK_IRON_BLOCK ].m_RequiresSpecialTool = true;
ms_Info[E_BLOCK_IRON_ORE ].m_RequiresSpecialTool = true;
ms_Info[E_BLOCK_LAPIS_BLOCK ].m_RequiresSpecialTool = true;
ms_Info[E_BLOCK_LAPIS_ORE ].m_RequiresSpecialTool = true;
ms_Info[E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE].m_RequiresSpecialTool = true;
ms_Info[E_BLOCK_MOSSY_COBBLESTONE ].m_RequiresSpecialTool = true;
ms_Info[E_BLOCK_NETHERRACK ].m_RequiresSpecialTool = true;
ms_Info[E_BLOCK_NETHER_BRICK ].m_RequiresSpecialTool = true;
ms_Info[E_BLOCK_NETHER_BRICK_STAIRS ].m_RequiresSpecialTool = true;
ms_Info[E_BLOCK_OBSIDIAN ].m_RequiresSpecialTool = true;
ms_Info[E_BLOCK_REDSTONE_ORE ].m_RequiresSpecialTool = true;
ms_Info[E_BLOCK_REDSTONE_ORE_GLOWING].m_RequiresSpecialTool = true;
ms_Info[E_BLOCK_SANDSTONE ].m_RequiresSpecialTool = true;
ms_Info[E_BLOCK_SANDSTONE_STAIRS ].m_RequiresSpecialTool = true;
ms_Info[E_BLOCK_SNOW ].m_RequiresSpecialTool = true;
ms_Info[E_BLOCK_STONE ].m_RequiresSpecialTool = true;
ms_Info[E_BLOCK_STONE_BRICKS ].m_RequiresSpecialTool = true;
ms_Info[E_BLOCK_STONE_BRICK_STAIRS ].m_RequiresSpecialTool = true;
ms_Info[E_BLOCK_STONE_PRESSURE_PLATE].m_RequiresSpecialTool = true;
ms_Info[E_BLOCK_STONE_SLAB ].m_RequiresSpecialTool = true;
ms_Info[E_BLOCK_VINES ].m_RequiresSpecialTool = true;
ms_Info[E_BLOCK_FURNACE ].m_RequiresSpecialTool = true;
ms_Info[E_BLOCK_LIT_FURNACE ].m_RequiresSpecialTool = true;
ms_Info[E_BLOCK_ANVIL ].m_RequiresSpecialTool = true;
ms_Info[E_BLOCK_ENCHANTMENT_TABLE ].m_RequiresSpecialTool = true;
// Nonsolid blocks:
ms_Info[E_BLOCK_ACTIVATOR_RAIL ].m_IsSolid = false;
ms_Info[E_BLOCK_AIR ].m_IsSolid = false;
ms_Info[E_BLOCK_BIG_FLOWER ].m_IsSolid = false;
ms_Info[E_BLOCK_BROWN_MUSHROOM ].m_IsSolid = false;
ms_Info[E_BLOCK_CARROTS ].m_IsSolid = false;
ms_Info[E_BLOCK_COBWEB ].m_IsSolid = false;
ms_Info[E_BLOCK_CROPS ].m_IsSolid = false;
ms_Info[E_BLOCK_DANDELION ].m_IsSolid = false;
ms_Info[E_BLOCK_DETECTOR_RAIL ].m_IsSolid = false;
ms_Info[E_BLOCK_END_PORTAL ].m_IsSolid = false;
ms_Info[E_BLOCK_FIRE ].m_IsSolid = false;
ms_Info[E_BLOCK_FLOWER ].m_IsSolid = false;
ms_Info[E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE].m_IsSolid = false;
ms_Info[E_BLOCK_LAVA ].m_IsSolid = false;
ms_Info[E_BLOCK_LEVER ].m_IsSolid = false;
ms_Info[E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE].m_IsSolid = false;
ms_Info[E_BLOCK_MELON_STEM ].m_IsSolid = false;
ms_Info[E_BLOCK_NETHER_PORTAL ].m_IsSolid = false;
ms_Info[E_BLOCK_PISTON_EXTENSION ].m_IsSolid = false;
ms_Info[E_BLOCK_POTATOES ].m_IsSolid = false;
ms_Info[E_BLOCK_POWERED_RAIL ].m_IsSolid = false;
ms_Info[E_BLOCK_RAIL ].m_IsSolid = false;
ms_Info[E_BLOCK_REDSTONE_TORCH_OFF ].m_IsSolid = false;
ms_Info[E_BLOCK_REDSTONE_TORCH_ON ].m_IsSolid = false;
ms_Info[E_BLOCK_REDSTONE_WIRE ].m_IsSolid = false;
ms_Info[E_BLOCK_RED_MUSHROOM ].m_IsSolid = false;
ms_Info[E_BLOCK_REEDS ].m_IsSolid = false;
ms_Info[E_BLOCK_SAPLING ].m_IsSolid = false;
ms_Info[E_BLOCK_SIGN_POST ].m_IsSolid = false;
ms_Info[E_BLOCK_SNOW ].m_IsSolid = false;
ms_Info[E_BLOCK_STATIONARY_LAVA ].m_IsSolid = false;
ms_Info[E_BLOCK_STATIONARY_WATER ].m_IsSolid = false;
ms_Info[E_BLOCK_STONE_BUTTON ].m_IsSolid = false;
ms_Info[E_BLOCK_STONE_PRESSURE_PLATE].m_IsSolid = false;
ms_Info[E_BLOCK_TALL_GRASS ].m_IsSolid = false;
ms_Info[E_BLOCK_TORCH ].m_IsSolid = false;
ms_Info[E_BLOCK_TRIPWIRE ].m_IsSolid = false;
ms_Info[E_BLOCK_VINES ].m_IsSolid = false;
ms_Info[E_BLOCK_WALLSIGN ].m_IsSolid = false;
ms_Info[E_BLOCK_WATER ].m_IsSolid = false;
ms_Info[E_BLOCK_WOODEN_BUTTON ].m_IsSolid = false;
ms_Info[E_BLOCK_WOODEN_PRESSURE_PLATE].m_IsSolid = false;
ms_Info[E_BLOCK_WOODEN_SLAB ].m_IsSolid = false;
// Torch placeable blocks:
ms_Info[E_BLOCK_NEW_LOG ].m_FullyOccupiesVoxel = true;
ms_Info[E_BLOCK_BEDROCK ].m_FullyOccupiesVoxel = true;
ms_Info[E_BLOCK_BLOCK_OF_COAL ].m_FullyOccupiesVoxel = true;
ms_Info[E_BLOCK_BLOCK_OF_REDSTONE ].m_FullyOccupiesVoxel = true;
ms_Info[E_BLOCK_BOOKCASE ].m_FullyOccupiesVoxel = true;
ms_Info[E_BLOCK_BRICK ].m_FullyOccupiesVoxel = true;
ms_Info[E_BLOCK_CLAY ].m_FullyOccupiesVoxel = true;
ms_Info[E_BLOCK_COAL_ORE ].m_FullyOccupiesVoxel = true;
ms_Info[E_BLOCK_COBBLESTONE ].m_FullyOccupiesVoxel = true;
ms_Info[E_BLOCK_COMMAND_BLOCK ].m_FullyOccupiesVoxel = true;
ms_Info[E_BLOCK_CRAFTING_TABLE ].m_FullyOccupiesVoxel = true;
ms_Info[E_BLOCK_DIAMOND_BLOCK ].m_FullyOccupiesVoxel = true;
ms_Info[E_BLOCK_DIAMOND_ORE ].m_FullyOccupiesVoxel = true;
ms_Info[E_BLOCK_DIRT ].m_FullyOccupiesVoxel = true;
ms_Info[E_BLOCK_DISPENSER ].m_FullyOccupiesVoxel = true;
ms_Info[E_BLOCK_DOUBLE_STONE_SLAB ].m_FullyOccupiesVoxel = true;
ms_Info[E_BLOCK_DOUBLE_WOODEN_SLAB ].m_FullyOccupiesVoxel = true;
ms_Info[E_BLOCK_DROPPER ].m_FullyOccupiesVoxel = true;
ms_Info[E_BLOCK_EMERALD_BLOCK ].m_FullyOccupiesVoxel = true;
ms_Info[E_BLOCK_EMERALD_ORE ].m_FullyOccupiesVoxel = true;
ms_Info[E_BLOCK_END_STONE ].m_FullyOccupiesVoxel = true;
ms_Info[E_BLOCK_FURNACE ].m_FullyOccupiesVoxel = true;
ms_Info[E_BLOCK_GLOWSTONE ].m_FullyOccupiesVoxel = true;
ms_Info[E_BLOCK_GOLD_BLOCK ].m_FullyOccupiesVoxel = true;
ms_Info[E_BLOCK_GOLD_ORE ].m_FullyOccupiesVoxel = true;
ms_Info[E_BLOCK_GRASS ].m_FullyOccupiesVoxel = true;
ms_Info[E_BLOCK_GRAVEL ].m_FullyOccupiesVoxel = true;
ms_Info[E_BLOCK_HARDENED_CLAY ].m_FullyOccupiesVoxel = true;
ms_Info[E_BLOCK_HAY_BALE ].m_FullyOccupiesVoxel = true;
ms_Info[E_BLOCK_HUGE_BROWN_MUSHROOM ].m_FullyOccupiesVoxel = true;
ms_Info[E_BLOCK_HUGE_RED_MUSHROOM ].m_FullyOccupiesVoxel = true;
ms_Info[E_BLOCK_IRON_BLOCK ].m_FullyOccupiesVoxel = true;
ms_Info[E_BLOCK_IRON_ORE ].m_FullyOccupiesVoxel = true;
ms_Info[E_BLOCK_JACK_O_LANTERN ].m_FullyOccupiesVoxel = true;
ms_Info[E_BLOCK_JUKEBOX ].m_FullyOccupiesVoxel = true;
ms_Info[E_BLOCK_LAPIS_BLOCK ].m_FullyOccupiesVoxel = true;
ms_Info[E_BLOCK_LAPIS_ORE ].m_FullyOccupiesVoxel = true;
ms_Info[E_BLOCK_LOG ].m_FullyOccupiesVoxel = true;
ms_Info[E_BLOCK_MELON ].m_FullyOccupiesVoxel = true;
ms_Info[E_BLOCK_MOSSY_COBBLESTONE ].m_FullyOccupiesVoxel = true;
ms_Info[E_BLOCK_MYCELIUM ].m_FullyOccupiesVoxel = true;
ms_Info[E_BLOCK_NETHERRACK ].m_FullyOccupiesVoxel = true;
ms_Info[E_BLOCK_NETHER_BRICK ].m_FullyOccupiesVoxel = true;
ms_Info[E_BLOCK_NETHER_QUARTZ_ORE ].m_FullyOccupiesVoxel = true;
ms_Info[E_BLOCK_NOTE_BLOCK ].m_FullyOccupiesVoxel = true;
ms_Info[E_BLOCK_OBSIDIAN ].m_FullyOccupiesVoxel = true;
ms_Info[E_BLOCK_PACKED_ICE ].m_FullyOccupiesVoxel = true;
ms_Info[E_BLOCK_PLANKS ].m_FullyOccupiesVoxel = true;
ms_Info[E_BLOCK_PUMPKIN ].m_FullyOccupiesVoxel = true;
ms_Info[E_BLOCK_QUARTZ_BLOCK ].m_FullyOccupiesVoxel = true;
ms_Info[E_BLOCK_REDSTONE_LAMP_OFF ].m_FullyOccupiesVoxel = true;
ms_Info[E_BLOCK_REDSTONE_LAMP_ON ].m_FullyOccupiesVoxel = true;
ms_Info[E_BLOCK_REDSTONE_ORE ].m_FullyOccupiesVoxel = true;
ms_Info[E_BLOCK_REDSTONE_ORE_GLOWING].m_FullyOccupiesVoxel = true;
ms_Info[E_BLOCK_SANDSTONE ].m_FullyOccupiesVoxel = true;
ms_Info[E_BLOCK_SAND ].m_FullyOccupiesVoxel = true;
ms_Info[E_BLOCK_SILVERFISH_EGG ].m_FullyOccupiesVoxel = true;
ms_Info[E_BLOCK_SPONGE ].m_FullyOccupiesVoxel = true;
ms_Info[E_BLOCK_STAINED_CLAY ].m_FullyOccupiesVoxel = true;
ms_Info[E_BLOCK_WOOL ].m_FullyOccupiesVoxel = true;
ms_Info[E_BLOCK_STONE ].m_FullyOccupiesVoxel = true;
ms_Info[E_BLOCK_STONE_BRICKS ].m_FullyOccupiesVoxel = true;
}
// This is actually just some code that needs to run at program startup, so it is wrapped into a global var's constructor:
class cBlockInfoInitializer
{
public:
cBlockInfoInitializer(void)
{
cBlockInfo::Initialize();
}
} BlockInfoInitializer;

103
src/BlockInfo.h Normal file
View File

@ -0,0 +1,103 @@
#pragma once
// fwd:
class cBlockHandler;
// tolua_begin
class cBlockInfo
{
public:
// tolua_end
cBlockInfo();
~cBlockInfo();
/** (Re-)Initializes the internal BlockInfo structures. */
static void Initialize(void);
// tolua_begin
/** Returns the associated BlockInfo structure. */
static cBlockInfo & Get(BLOCKTYPE a_Type);
/** How much light do the blocks emit on their own? */
NIBBLETYPE m_LightValue;
/** How much light do the blocks consume? */
NIBBLETYPE m_SpreadLightFalloff;
/** Is a block completely transparent? (light doesn't get decreased(?)) */
bool m_Transparent;
/** Is a block destroyed after a single hit? */
bool m_OneHitDig;
/** Can a piston break this block? */
bool m_PistonBreakable;
/** Can this block hold snow atop? */
bool m_IsSnowable;
/** Does this block require a tool to drop? */
bool m_RequiresSpecialTool;
/** Is this block solid (player cannot walk through)? */
bool m_IsSolid;
/** Does this block fully occupy its voxel - is it a 'full' block? */
bool m_FullyOccupiesVoxel;
// tolua_end
/** Associated block handler. */
cBlockHandler * m_Handler;
// tolua_begin
inline static NIBBLETYPE GetLightValue (BLOCKTYPE a_Type) { return Get(a_Type).m_LightValue; }
inline static NIBBLETYPE GetSpreadLightFalloff(BLOCKTYPE a_Type) { return Get(a_Type).m_SpreadLightFalloff; }
inline static bool IsTransparent (BLOCKTYPE a_Type) { return Get(a_Type).m_Transparent; }
inline static bool IsOneHitDig (BLOCKTYPE a_Type) { return Get(a_Type).m_OneHitDig; }
inline static bool IsPistonBreakable (BLOCKTYPE a_Type) { return Get(a_Type).m_PistonBreakable; }
inline static bool IsSnowable (BLOCKTYPE a_Type) { return Get(a_Type).m_IsSnowable; }
inline static bool RequiresSpecialTool (BLOCKTYPE a_Type) { return Get(a_Type).m_RequiresSpecialTool; }
inline static bool IsSolid (BLOCKTYPE a_Type) { return Get(a_Type).m_IsSolid; }
inline static bool FullyOccupiesVoxel (BLOCKTYPE a_Type) { return Get(a_Type).m_FullyOccupiesVoxel; }
// tolua_end
inline static cBlockHandler * GetHandler (BLOCKTYPE a_Type) { return Get(a_Type).m_Handler; }
protected:
// TODO xdot: Change to std::vector to support dynamic block IDs
static cBlockInfo ms_Info[256];
}; // tolua_export
// Shortcut to get the blockhandler for a specific block
inline cBlockHandler * BlockHandler(BLOCKTYPE a_BlockType)
{
return cBlockInfo::Get(a_BlockType).m_Handler;
}

View File

@ -4,6 +4,7 @@
#include "BlockHandler.h"
#include "ChunkInterface.h"
#include "WorldInterface.h"
#include "MetaRotater.h"
#include "../Entities/Player.h"
@ -11,11 +12,11 @@
class cBlockBedHandler :
public cBlockHandler
public cMetaRotater<cBlockHandler, 0x3, 0x02, 0x03, 0x00, 0x01, true>
{
public:
cBlockBedHandler(BLOCKTYPE a_BlockType)
: cBlockHandler(a_BlockType)
: cMetaRotater<cBlockHandler, 0x3, 0x02, 0x03, 0x00, 0x01,true>(a_BlockType)
{
}

View File

@ -2,16 +2,17 @@
#include "BlockHandler.h"
#include "Chunk.h"
#include "MetaRotater.h"
class cBlockButtonHandler :
public cBlockHandler
public cMetaRotater<cBlockHandler, 0x07, 0x04, 0x01, 0x03, 0x02, true>
{
public:
cBlockButtonHandler(BLOCKTYPE a_BlockType)
: cBlockHandler(a_BlockType)
: cMetaRotater<cBlockHandler, 0x07, 0x04, 0x01, 0x03, 0x02, true>(a_BlockType)
{
}
@ -101,7 +102,7 @@ public:
AddFaceDirection(a_RelX, a_RelY, a_RelZ, BlockMetaDataToBlockFace(Meta), true);
BLOCKTYPE BlockIsOn; a_Chunk.UnboundedRelGetBlockType(a_RelX, a_RelY, a_RelZ, BlockIsOn);
return (a_RelY > 0) && (g_BlockIsSolid[BlockIsOn]);
return (a_RelY > 0) && (cBlockInfo::IsSolid(BlockIsOn));
}
} ;

View File

@ -54,7 +54,7 @@ public:
NIBBLETYPE BlockMeta;
if (
a_Chunk.UnboundedRelGetBlock(a_RelX + Coords[i].x, a_RelY, a_RelZ + Coords[i].z, BlockType, BlockMeta) &&
(g_BlockIsSolid[BlockType])
cBlockInfo::IsSolid(BlockType)
)
{
return false;

View File

@ -4,17 +4,18 @@
#include "BlockEntity.h"
#include "../BlockArea.h"
#include "../Entities/Player.h"
#include "MetaRotater.h"
class cBlockChestHandler :
public cBlockEntityHandler
public cMetaRotater<cBlockEntityHandler, 0x07, 0x04, 0x01, 0x03, 0x02, true>
{
public:
cBlockChestHandler(BLOCKTYPE a_BlockType)
: cBlockEntityHandler(a_BlockType)
: cMetaRotater<cBlockEntityHandler, 0x07, 0x04, 0x01, 0x03, 0x02, true>(a_BlockType)
{
}

View File

@ -3,17 +3,18 @@
#include "BlockHandler.h"
#include "BlockRedstoneRepeater.h"
#include "MetaRotater.h"
class cBlockComparatorHandler :
public cBlockHandler
public cMetaRotater<cBlockHandler, 0x03, 0x00, 0x01, 0x02, 0x03, true>
{
public:
cBlockComparatorHandler(BLOCKTYPE a_BlockType)
: cBlockHandler(a_BlockType)
: cMetaRotater<cBlockHandler, 0x03, 0x00, 0x01, 0x02, 0x03, true>(a_BlockType)
{
}
@ -26,6 +27,13 @@ public:
}
virtual void OnCancelRightClick(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace) override
{
UNUSED(a_ChunkInterface);
a_WorldInterface.SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, a_Player);
}
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
{
// Reset meta to 0

View File

@ -36,7 +36,7 @@ public:
if (a_RelY < cChunkDef::Height - 1)
{
BLOCKTYPE Above = a_Chunk.GetBlock(a_RelX, a_RelY + 1, a_RelZ);
if ((!g_BlockTransparent[Above] && !g_BlockOneHitDig[Above]) || IsBlockWater(Above))
if ((!cBlockInfo::IsTransparent(Above) && !cBlockInfo::IsOneHitDig(Above)) || IsBlockWater(Above))
{
a_Chunk.FastSetBlock(a_RelX, a_RelY, a_RelZ, E_BLOCK_DIRT, E_META_DIRT_NORMAL);
return;
@ -77,7 +77,7 @@ public:
BLOCKTYPE AboveDest;
NIBBLETYPE AboveMeta;
Chunk->GetBlockTypeMeta(BlockX, BlockY + 1, BlockZ, AboveDest, AboveMeta);
if ((g_BlockOneHitDig[AboveDest] || g_BlockTransparent[AboveDest]) && !IsBlockWater(AboveDest))
if ((cBlockInfo::IsOneHitDig(AboveDest) || cBlockInfo::IsTransparent(AboveDest)) && !IsBlockWater(AboveDest))
{
Chunk->FastSetBlock(BlockX, BlockY, BlockZ, E_BLOCK_GRASS, 0);
}

View File

@ -9,7 +9,7 @@
cBlockDoorHandler::cBlockDoorHandler(BLOCKTYPE a_BlockType)
: cBlockHandler(a_BlockType)
: super(a_BlockType)
{
}
@ -55,6 +55,29 @@ void cBlockDoorHandler::OnUse(cChunkInterface & a_ChunkInterface, cWorldInterfac
void cBlockDoorHandler::OnCancelRightClick(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace)
{
UNUSED(a_ChunkInterface);
a_WorldInterface.SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, a_Player);
NIBBLETYPE Meta = a_ChunkInterface.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ);
if (Meta & 8)
{
// Current block is top of the door
a_WorldInterface.SendBlockTo(a_BlockX, a_BlockY - 1, a_BlockZ, a_Player);
}
else
{
// Current block is bottom of the door
a_WorldInterface.SendBlockTo(a_BlockX, a_BlockY + 1, a_BlockZ, a_Player);
}
}
void cBlockDoorHandler::OnPlacedByPlayer(
cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player,
int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,

View File

@ -4,18 +4,21 @@
#include "BlockHandler.h"
#include "../Entities/Player.h"
#include "Chunk.h"
#include "MetaRotater.h"
class cBlockDoorHandler :
public cBlockHandler
public cMetaRotater<cBlockHandler, 0x03, 0x01, 0x02, 0x03, 0x00, true>
{
typedef cMetaRotater<cBlockHandler, 0x03, 0x01, 0x02, 0x03, 0x00, true> super;
public:
cBlockDoorHandler(BLOCKTYPE a_BlockType);
virtual void OnDestroyed(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, int a_BlockX, int a_BlockY, int a_BlockZ) override;
virtual void OnUse(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) override;
virtual void OnCancelRightClick(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace) override;
virtual const char * GetStepSound(void) override;
@ -167,6 +170,60 @@ public:
}
virtual NIBBLETYPE MetaRotateCCW(NIBBLETYPE a_Meta) override
{
if (a_Meta & 0x08)
{
return a_Meta;
}
else
{
return super::MetaRotateCCW(a_Meta);
}
}
virtual NIBBLETYPE MetaRotateCW(NIBBLETYPE a_Meta) override
{
if (a_Meta & 0x08)
{
return a_Meta;
}
else
{
return super::MetaRotateCW(a_Meta);
}
}
virtual NIBBLETYPE MetaMirrorXY(NIBBLETYPE a_Meta) override
{
if (a_Meta & 0x08)
{
return a_Meta;
}
else
{
return super::MetaMirrorXY(a_Meta);
}
}
virtual NIBBLETYPE MetaMirrorYZ(NIBBLETYPE a_Meta) override
{
if (a_Meta & 0x08)
{
return a_Meta;
}
else
{
return super::MetaMirrorYZ(a_Meta);
}
}
} ;

View File

@ -6,17 +6,18 @@
#pragma once
#include "../Piston.h"
#include "MetaRotater.h"
class cBlockDropSpenserHandler :
public cBlockEntityHandler
public cMetaRotater<cBlockEntityHandler, 0x07, 0x02, 0x05, 0x03, 0x04>
{
public:
cBlockDropSpenserHandler(BLOCKTYPE a_BlockType) :
cBlockEntityHandler(a_BlockType)
cMetaRotater<cBlockEntityHandler, 0x07, 0x02, 0x05, 0x03, 0x04>(a_BlockType)
{
}
@ -34,6 +35,20 @@ public:
a_BlockMeta = cPiston::RotationPitchToMetaData(a_Player->GetYaw(), a_Player->GetPitch());
return true;
}
virtual NIBBLETYPE MetaMirrorXZ(NIBBLETYPE a_Meta) override
{
// Bit 0x08 is a flag. Lowest three bits are position. 0x08 == 1000
NIBBLETYPE OtherMeta = a_Meta & 0x08;
// Mirrors defined by by a table. (Source, mincraft.gamepedia.com) 0x07 == 0111
switch (a_Meta & 0x07)
{
case 0x00: return 0x01 + OtherMeta; // Down -> Up
case 0x01: return 0x00 + OtherMeta; // Up -> Down
}
// Not Facing Up or Down; No change.
return a_Meta;
}
} ;

View File

@ -2,17 +2,17 @@
#pragma once
#include "BlockEntity.h"
#include "MetaRotater.h"
class cBlockEnderchestHandler :
public cBlockEntityHandler
public cMetaRotater<cBlockEntityHandler, 0x07, 0x02, 0x05, 0x03, 0x04>
{
public:
cBlockEnderchestHandler(BLOCKTYPE a_BlockType)
: cBlockEntityHandler(a_BlockType)
: cMetaRotater<cBlockEntityHandler, 0x07, 0x02, 0x05, 0x03, 0x04>(a_BlockType)
{
}

View File

@ -2,17 +2,17 @@
#pragma once
#include "BlockHandler.h"
#include "MetaRotater.h"
class cBlockFenceGateHandler :
public cBlockHandler
public cMetaRotater<cBlockHandler, 0x03, 0x02, 0x03, 0x00, 0x01, true>
{
public:
cBlockFenceGateHandler(BLOCKTYPE a_BlockType) :
cBlockHandler(a_BlockType)
cMetaRotater<cBlockHandler, 0x03, 0x02, 0x03, 0x00, 0x01, true>(a_BlockType)
{
}
@ -48,6 +48,12 @@ public:
}
virtual void OnCancelRightClick(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace) override
{
a_WorldInterface.SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, a_Player);
}
virtual bool IsUseable(void) override
{
return true;

View File

@ -2,101 +2,24 @@
#pragma once
#include "BlockHandler.h"
#include "BlockEntity.h"
class cBlockFlowerPotHandler :
public cBlockHandler
public cBlockEntityHandler
{
public:
cBlockFlowerPotHandler(BLOCKTYPE a_BlockType) :
cBlockHandler(a_BlockType)
cBlockEntityHandler(a_BlockType)
{
}
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
{
a_Pickups.push_back(cItem(E_ITEM_FLOWER_POT, 1, 0));
if (a_BlockMeta == 0)
{
return;
}
cItem Plant;
switch (a_BlockMeta)
{
case 1: Plant = cItem(E_BLOCK_RED_ROSE, 1, 0); break;
case 2: Plant = cItem(E_BLOCK_YELLOW_FLOWER, 1, 0); break;
case 3: Plant = cItem(E_BLOCK_SAPLING, 1, E_META_SAPLING_APPLE); break;
case 4: Plant = cItem(E_BLOCK_SAPLING, 1, E_META_SAPLING_CONIFER); break;
case 5: Plant = cItem(E_BLOCK_SAPLING, 1, E_META_SAPLING_BIRCH); break;
case 6: Plant = cItem(E_BLOCK_SAPLING, 1, E_META_SAPLING_JUNGLE); break;
case 7: Plant = cItem(E_BLOCK_RED_MUSHROOM, 1, 0); break;
case 8: Plant = cItem(E_BLOCK_BROWN_MUSHROOM, 1, 0); break;
case 9: Plant = cItem(E_BLOCK_CACTUS, 1, 0); break;
case 10: Plant = cItem(E_BLOCK_DEAD_BUSH, 1, 0); break;
case 11: Plant = cItem(E_BLOCK_TALL_GRASS, 1, E_META_TALL_GRASS_FERN); break;
default: return;
}
a_Pickups.push_back(Plant);
}
void OnUse(cWorld * a_World, cWorldInterface * a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ)
{
NIBBLETYPE Meta = a_World->GetBlockMeta( a_BlockX, a_BlockY, a_BlockZ );
if (Meta != 0)
{
// Already filled
return;
}
switch (a_Player->GetEquippedItem().m_ItemType)
{
case E_BLOCK_RED_ROSE: Meta = 1; break;
case E_BLOCK_YELLOW_FLOWER: Meta = 2; break;
case E_BLOCK_SAPLING:
{
switch (a_Player->GetEquippedItem().m_ItemDamage)
{
case E_META_SAPLING_APPLE: Meta = 3; break;
case E_META_SAPLING_CONIFER: Meta = 4; break;
case E_META_SAPLING_BIRCH: Meta = 5; break;
case E_META_SAPLING_JUNGLE: Meta = 6; break;
}
break;
}
case E_BLOCK_RED_MUSHROOM: Meta = 7; break;
case E_BLOCK_BROWN_MUSHROOM: Meta = 8; break;
case E_BLOCK_CACTUS: Meta = 9; break;
case E_BLOCK_DEAD_BUSH: Meta = 10; break;
case E_BLOCK_TALL_GRASS:
{
if (a_Player->GetEquippedItem().m_ItemDamage == E_META_TALL_GRASS_FERN)
{
Meta = 11;
}
else
{
return;
}
break;
}
}
if (a_Player->GetGameMode() != gmCreative)
{
a_Player->GetInventory().RemoveOneEquippedItem();
}
a_World->SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, Meta);
}
virtual bool IsUseable(void) override
{
return true;
}
} ;

View File

@ -57,6 +57,7 @@
#include "BlockRedstoneLamp.h"
#include "BlockRedstoneRepeater.h"
#include "BlockRedstoneTorch.h"
#include "BlockTNT.h"
#include "BlockSand.h"
#include "BlockSapling.h"
#include "BlockSideways.h"
@ -77,33 +78,6 @@
bool cBlockHandler::m_HandlerInitialized = false;
cBlockHandler * cBlockHandler::m_BlockHandler[256];
cBlockHandler * cBlockHandler::GetBlockHandler(BLOCKTYPE a_BlockType)
{
if (!m_HandlerInitialized)
{
// We have to initialize
memset(m_BlockHandler, 0, sizeof(m_BlockHandler));
m_HandlerInitialized = true;
}
if (m_BlockHandler[a_BlockType] != NULL)
{
return m_BlockHandler[a_BlockType];
}
return m_BlockHandler[a_BlockType] = CreateBlockHandler(a_BlockType);
}
cBlockHandler * cBlockHandler::CreateBlockHandler(BLOCKTYPE a_BlockType)
{
switch(a_BlockType)
@ -172,6 +146,7 @@ cBlockHandler * cBlockHandler::CreateBlockHandler(BLOCKTYPE a_BlockType)
case E_BLOCK_NETHER_BRICK_STAIRS: return new cBlockStairsHandler (a_BlockType);
case E_BLOCK_NETHER_PORTAL: return new cBlockPortalHandler (a_BlockType);
case E_BLOCK_NETHER_WART: return new cBlockNetherWartHandler (a_BlockType);
case E_BLOCK_NETHER_QUARTZ_ORE: return new cBlockOreHandler (a_BlockType);
case E_BLOCK_NEW_LEAVES: return new cBlockNewLeavesHandler (a_BlockType);
case E_BLOCK_NEW_LOG: return new cBlockSidewaysHandler (a_BlockType);
case E_BLOCK_NOTE_BLOCK: return new cBlockNoteHandler (a_BlockType);
@ -192,7 +167,7 @@ cBlockHandler * cBlockHandler::CreateBlockHandler(BLOCKTYPE a_BlockType)
case E_BLOCK_REDSTONE_REPEATER_ON: return new cBlockRedstoneRepeaterHandler(a_BlockType);
case E_BLOCK_REDSTONE_TORCH_OFF: return new cBlockRedstoneTorchHandler (a_BlockType);
case E_BLOCK_REDSTONE_TORCH_ON: return new cBlockRedstoneTorchHandler (a_BlockType);
case E_BLOCK_REDSTONE_WIRE: return new cBlockRedstoneHandler (a_BlockType);
case E_BLOCK_REDSTONE_WIRE: return new cBlockRedstoneHandler (a_BlockType);
case E_BLOCK_RED_MUSHROOM: return new cBlockMushroomHandler (a_BlockType);
case E_BLOCK_RED_ROSE: return new cBlockFlowerHandler (a_BlockType);
case E_BLOCK_SAND: return new cBlockSandHandler (a_BlockType);
@ -212,6 +187,7 @@ cBlockHandler * cBlockHandler::CreateBlockHandler(BLOCKTYPE a_BlockType)
case E_BLOCK_TALL_GRASS: return new cBlockTallGrassHandler (a_BlockType);
case E_BLOCK_TORCH: return new cBlockTorchHandler (a_BlockType);
case E_BLOCK_TRAPDOOR: return new cBlockTrapdoorHandler (a_BlockType);
case E_BLOCK_TNT: return new cBlockTNTHandler (a_BlockType);
case E_BLOCK_VINES: return new cBlockVineHandler (a_BlockType);
case E_BLOCK_WALLSIGN: return new cBlockSignHandler (a_BlockType);
case E_BLOCK_WATER: return new cBlockFluidHandler (a_BlockType);
@ -231,20 +207,6 @@ cBlockHandler * cBlockHandler::CreateBlockHandler(BLOCKTYPE a_BlockType)
void cBlockHandler::Deinit()
{
for (int i = 0; i < 256; i++)
{
delete m_BlockHandler[i];
}
memset(m_BlockHandler, 0, sizeof(m_BlockHandler)); // Don't leave any dangling pointers around, just in case
m_HandlerInitialized = false;
}
cBlockHandler::cBlockHandler(BLOCKTYPE a_BlockType)
{
m_BlockType = a_BlockType;
@ -329,7 +291,7 @@ void cBlockHandler::NeighborChanged(cChunkInterface & a_ChunkInterface, int a_Bl
{
if ((a_BlockY >= 0) && (a_BlockY < cChunkDef::Height))
{
GetBlockHandler(a_ChunkInterface.GetBlock(a_BlockX, a_BlockY, a_BlockZ))->OnNeighborChanged(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ);
cBlockInfo::GetHandler(a_ChunkInterface.GetBlock(a_BlockX, a_BlockY, a_BlockZ))->OnNeighborChanged(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ);
}
}
@ -361,6 +323,14 @@ void cBlockHandler::OnUse(cChunkInterface & a_ChunkInterface, cWorldInterface &
void cBlockHandler::OnCancelRightClick(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer *a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace)
{
}
void cBlockHandler::ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta)
{
// Setting the meta to a_BlockMeta keeps most textures. The few other blocks have to override this.

View File

@ -69,6 +69,9 @@ public:
/// Called if the user right clicks the block and the block is useable
virtual void OnUse(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ);
/** Called when a Right Click to this Block is cancelled */
virtual void OnCancelRightClick(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace);
/// <summary>Called when the item is mined to convert it into pickups. Pickups may specify multiple items. Appends items to a_Pickups, preserves its original contents</summary>
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta);
@ -136,31 +139,15 @@ public:
/// <returns>Block meta following mirroring</returns>
virtual NIBBLETYPE MetaMirrorYZ(NIBBLETYPE a_Meta) { return a_Meta; }
/// <summary>Get the blockhandler for a specific block id</summary>
static cBlockHandler * GetBlockHandler(BLOCKTYPE a_BlockType);
/// <summary>Deletes all initialised block handlers</summary>
static void Deinit();
protected:
BLOCKTYPE m_BlockType;
// Creates a new blockhandler for the given block type. For internal use only, use ::GetBlockHandler() instead.
static cBlockHandler *CreateBlockHandler(BLOCKTYPE a_BlockType);
static cBlockHandler *m_BlockHandler[256];
static bool m_HandlerInitialized; //used to detect if the blockhandlers are initialized
static cBlockHandler * CreateBlockHandler(BLOCKTYPE a_BlockType);
friend class cBlockInfo;
};
// Shortcut to get the blockhandler for a specific block
inline cBlockHandler * BlockHandler(BLOCKTYPE a_BlockType)
{
return cBlockHandler::GetBlockHandler(a_BlockType);
}

View File

@ -91,7 +91,7 @@ public:
AddFaceDirection( a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, true);
return g_BlockIsSolid[a_ChunkInterface.GetBlock(a_BlockX, a_BlockY, a_BlockZ)];
return cBlockInfo::IsSolid(a_ChunkInterface.GetBlock(a_BlockX, a_BlockY, a_BlockZ));
}

View File

@ -102,7 +102,7 @@ public:
AddFaceDirection(a_RelX, a_RelY, a_RelZ, BlockMetaDataToBlockFace(Meta), true);
BLOCKTYPE BlockIsOn; a_Chunk.UnboundedRelGetBlockType(a_RelX, a_RelY, a_RelZ, BlockIsOn);
return (a_RelY > 0) && (g_BlockIsSolid[BlockIsOn]);
return (a_RelY > 0) && cBlockInfo::IsSolid(BlockIsOn);
}
} ;

View File

@ -29,7 +29,7 @@ public:
BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta
) override
{
class cCallback : public cMobHeadBlockCallback
class cCallback : public cMobHeadCallback
{
cPlayer * m_Player;
NIBBLETYPE m_OldBlockMeta;
@ -45,6 +45,7 @@ public:
a_MobHeadEntity->SetType(static_cast<eMobHeadType>(m_OldBlockMeta));
a_MobHeadEntity->SetRotation(static_cast<eMobHeadRotation>(Rotation));
a_MobHeadEntity->GetWorld()->BroadcastBlockEntity(a_MobHeadEntity->GetPosX(), a_MobHeadEntity->GetPosY(), a_MobHeadEntity->GetPosZ(), m_Player->GetClientHandle());
return false;
}
@ -59,7 +60,7 @@ public:
a_BlockMeta = a_BlockFace;
cWorld * World = (cWorld *) &a_WorldInterface;
World->DoWithMobHeadBlockAt(a_BlockX, a_BlockY, a_BlockZ, Callback);
World->DoWithMobHeadAt(a_BlockX, a_BlockY, a_BlockZ, Callback);
a_ChunkInterface.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, a_BlockMeta);
}
} ;

View File

@ -98,7 +98,7 @@ public:
{
return false;
}
if (!g_BlockIsSolid[a_Chunk.GetBlock(a_RelX, a_RelY - 1, a_RelZ)])
if (!cBlockInfo::IsSolid(a_Chunk.GetBlock(a_RelX, a_RelY - 1, a_RelZ)))
{
return false;
}
@ -130,7 +130,7 @@ public:
// Too close to the edge, cannot simulate
return true;
}
return g_BlockIsSolid[BlockType];
return cBlockInfo::IsSolid(BlockType);
}
}
return true;

View File

@ -20,7 +20,7 @@ public:
virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override
{
return ((a_RelY > 0) && g_BlockFullyOccupiesVoxel[a_Chunk.GetBlock(a_RelX, a_RelY - 1, a_RelZ)]);
return ((a_RelY > 0) && cBlockInfo::FullyOccupiesVoxel(a_Chunk.GetBlock(a_RelX, a_RelY - 1, a_RelZ)));
}

View File

@ -29,7 +29,7 @@ public:
a_BlockMeta = RepeaterRotationToMetaData(a_Player->GetYaw());
return true;
}
virtual void OnUse(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) override
{
@ -37,6 +37,13 @@ public:
}
virtual void OnCancelRightClick(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace) override
{
UNUSED(a_ChunkInterface);
a_WorldInterface.SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, a_Player);
}
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
{
// Reset meta to 0

View File

@ -28,7 +28,7 @@ public:
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
{
a_Pickups.push_back(cItem(m_BlockType, 1, a_BlockMeta));
a_Pickups.push_back(cItem(m_BlockType, 1, a_BlockMeta & 0x7));
}
@ -41,7 +41,7 @@ public:
{
a_BlockType = m_BlockType;
BLOCKTYPE Type = (BLOCKTYPE) (a_Player->GetEquippedItem().m_ItemType);
NIBBLETYPE Meta = (NIBBLETYPE)(a_Player->GetEquippedItem().m_ItemDamage & 0x07);
NIBBLETYPE Meta = (NIBBLETYPE) a_Player->GetEquippedItem().m_ItemDamage;
// HandlePlaceBlock wants a cItemHandler pointer thing, so let's give it one
cItemHandler * ItemHandler = cItemHandler::GetItemHandler(GetDoubleSlabType(Type));
@ -159,21 +159,30 @@ public:
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
{
if (m_BlockType == E_BLOCK_DOUBLE_STONE_SLAB)
{
m_BlockType = E_BLOCK_STONE_SLAB;
}
else
{
m_BlockType = E_BLOCK_WOODEN_SLAB;
}
a_Pickups.push_back(cItem(m_BlockType, 2, a_BlockMeta));
BLOCKTYPE Block = GetSingleSlabType(m_BlockType);
a_Pickups.push_back(cItem(Block, 2, a_BlockMeta & 0x7));
}
inline static BLOCKTYPE GetSingleSlabType(BLOCKTYPE a_BlockType)
{
switch (a_BlockType)
{
case E_BLOCK_DOUBLE_STONE_SLAB: return E_BLOCK_STONE_SLAB;
case E_BLOCK_DOUBLE_WOODEN_SLAB: return E_BLOCK_WOODEN_SLAB;
}
ASSERT(!"Unhandled double slab type!");
return a_BlockType;
}
virtual const char * GetStepSound(void) override
{
return ((m_BlockType == E_BLOCK_DOUBLE_WOODEN_SLAB) || (m_BlockType == E_BLOCK_DOUBLE_WOODEN_SLAB)) ? "step.wood" : "step.stone";
{
switch (m_BlockType)
{
case E_BLOCK_DOUBLE_STONE_SLAB: return "step.stone";
case E_BLOCK_DOUBLE_WOODEN_SLAB: return "step.wood";
}
ASSERT(!"Unhandled double slab type!");
return "";
}
} ;

View File

@ -72,7 +72,7 @@ public:
BLOCKTYPE BlockBelow = a_Chunk.GetBlock(a_RelX, a_RelY - 1, a_RelZ);
NIBBLETYPE MetaBelow = a_Chunk.GetMeta(a_RelX, a_RelY - 1, a_RelZ);
if (g_BlockIsSnowable[BlockBelow] || ((BlockBelow == E_BLOCK_SNOW) && (MetaBelow == 7)))
if (cBlockInfo::IsSnowable(BlockBelow) || ((BlockBelow == E_BLOCK_SNOW) && (MetaBelow == 7)))
{
// If block below is snowable, or it is a thin slow block and has a meta of 7 (full thin snow block), say yay
return true;

View File

@ -2,17 +2,17 @@
#pragma once
#include "BlockHandler.h"
#include "MetaRotater.h"
class cBlockStairsHandler :
public cBlockHandler
public cMetaRotater<cBlockHandler, 0x03, 0x03, 0x00, 0x02, 0x01, true>
{
public:
cBlockStairsHandler(BLOCKTYPE a_BlockType) :
cBlockHandler(a_BlockType)
cMetaRotater<cBlockHandler, 0x03, 0x03, 0x00, 0x02, 0x01, true>(a_BlockType)
{
}
@ -96,54 +96,6 @@ public:
}
virtual NIBBLETYPE MetaRotateCCW(NIBBLETYPE a_Meta) override
{
// Bits 3 and 4 stay, the rest is swapped around according to a table:
NIBBLETYPE TopBits = (a_Meta & 0x0c);
switch (a_Meta & 0x03)
{
case 0x00: return TopBits | 0x03; // East -> North
case 0x01: return TopBits | 0x02; // West -> South
case 0x02: return TopBits | 0x00; // South -> East
case 0x03: return TopBits | 0x01; // North -> West
}
// Not reachable, but to avoid a compiler warning:
return 0;
}
virtual NIBBLETYPE MetaRotateCW(NIBBLETYPE a_Meta) override
{
// Bits 3 and 4 stay, the rest is swapped around according to a table:
NIBBLETYPE TopBits = (a_Meta & 0x0c);
switch (a_Meta & 0x03)
{
case 0x00: return TopBits | 0x02; // East -> South
case 0x01: return TopBits | 0x03; // West -> North
case 0x02: return TopBits | 0x01; // South -> West
case 0x03: return TopBits | 0x00; // North -> East
}
// Not reachable, but to avoid a compiler warning:
return 0;
}
virtual NIBBLETYPE MetaMirrorXY(NIBBLETYPE a_Meta) override
{
// Bits 3 and 4 stay, the rest is swapped around according to a table:
NIBBLETYPE TopBits = (a_Meta & 0x0c);
switch (a_Meta & 0x03)
{
case 0x00: return TopBits | 0x00; // East -> East
case 0x01: return TopBits | 0x01; // West -> West
case 0x02: return TopBits | 0x03; // South -> North
case 0x03: return TopBits | 0x02; // North -> South
}
// Not reachable, but to avoid a compiler warning:
return 0;
}
virtual NIBBLETYPE MetaMirrorXZ(NIBBLETYPE a_Meta) override
{
// Toggle bit 3:
@ -151,20 +103,6 @@ public:
}
virtual NIBBLETYPE MetaMirrorYZ(NIBBLETYPE a_Meta) override
{
// Bits 3 and 4 stay, the rest is swapped around according to a table:
NIBBLETYPE TopBits = (a_Meta & 0x0c);
switch (a_Meta & 0x03)
{
case 0x00: return TopBits | 0x01; // East -> West
case 0x01: return TopBits | 0x00; // West -> East
case 0x02: return TopBits | 0x02; // South -> South
case 0x03: return TopBits | 0x03; // North -> North
}
// Not reachable, but to avoid a compiler warning:
return 0;
}
} ;

32
src/Blocks/BlockTNT.h Normal file
View File

@ -0,0 +1,32 @@
#pragma once
#include "BlockHandler.h"
class cBlockTNTHandler :
public cBlockHandler
{
public:
cBlockTNTHandler(BLOCKTYPE a_BlockType)
: cBlockHandler(a_BlockType)
{
}
virtual const char * GetStepSound(void) override
{
return "step.grass";
}
virtual void OnCancelRightClick(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace) override
{
a_WorldInterface.SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, a_Player);
}
};

View File

@ -2,17 +2,17 @@
#include "BlockHandler.h"
#include "../Chunk.h"
#include "MetaRotater.h"
class cBlockTorchHandler :
public cBlockHandler
public cMetaRotater<cBlockHandler, 0x7, 0x4, 0x1, 0x3, 0x2>
{
public:
cBlockTorchHandler(BLOCKTYPE a_BlockType)
: cBlockHandler(a_BlockType)
: cMetaRotater<cBlockHandler, 0x7, 0x4, 0x1, 0x3, 0x2>(a_BlockType)
{
}
@ -99,7 +99,7 @@ public:
static bool CanBePlacedOn(BLOCKTYPE a_BlockType, eBlockFace a_BlockFace)
{
if ( !g_BlockFullyOccupiesVoxel[a_BlockType] )
if ( !cBlockInfo::FullyOccupiesVoxel(a_BlockType) )
{
return (a_BlockFace == BLOCK_FACE_TOP); // Allow placement only when torch upright (for glass, etc.); exceptions won't even be sent by client, no need to handle
}
@ -129,7 +129,7 @@ public:
{
return Face;
}
else if ((g_BlockFullyOccupiesVoxel[BlockInQuestion]) && (i != BLOCK_FACE_BOTTOM))
else if (cBlockInfo::FullyOccupiesVoxel(BlockInQuestion) && (i != BLOCK_FACE_BOTTOM))
{
// Otherwise, if block in that direction is torch placeable and we haven't gotten to it via the bottom face, return that face
return Face;
@ -163,7 +163,7 @@ public:
// No need to check for upright orientation, it was done when the torch was placed
return true;
}
else if ( !g_BlockFullyOccupiesVoxel[BlockInQuestion] )
else if ( !cBlockInfo::FullyOccupiesVoxel(BlockInQuestion) )
{
return false;
}
@ -185,67 +185,6 @@ public:
{
return "step.wood";
}
virtual NIBBLETYPE MetaRotateCCW(NIBBLETYPE a_Meta) override
{
// Bit 4 stays, the rest is swapped around according to a table:
NIBBLETYPE TopBits = (a_Meta & 0x08);
switch (a_Meta & 0x07)
{
case 0x01: return TopBits | 0x04; // East -> North
case 0x02: return TopBits | 0x03; // West -> South
case 0x03: return TopBits | 0x01; // South -> East
case 0x04: return TopBits | 0x02; // North -> West
default: return a_Meta; // Floor -> Floor
}
}
virtual NIBBLETYPE MetaRotateCW(NIBBLETYPE a_Meta) override
{
// Bit 4 stays, the rest is swapped around according to a table:
NIBBLETYPE TopBits = (a_Meta & 0x08);
switch (a_Meta & 0x07)
{
case 0x01: return TopBits | 0x03; // East -> South
case 0x02: return TopBits | 0x04; // West -> North
case 0x03: return TopBits | 0x02; // South -> West
case 0x04: return TopBits | 0x01; // North -> East
default: return a_Meta; // Floor -> Floor
}
}
virtual NIBBLETYPE MetaMirrorXY(NIBBLETYPE a_Meta) override
{
// Bit 4 stays, the rest is swapped around according to a table:
NIBBLETYPE TopBits = (a_Meta & 0x08);
switch (a_Meta & 0x07)
{
case 0x03: return TopBits | 0x04; // South -> North
case 0x04: return TopBits | 0x03; // North -> South
default: return a_Meta; // Keep the rest
}
}
// Mirroring around the XZ plane doesn't make sense for floor torches,
// the others stay the same, so let's keep all the metas the same.
// The base class does tht for us, no need to override MetaMirrorXZ()
virtual NIBBLETYPE MetaMirrorYZ(NIBBLETYPE a_Meta) override
{
// Bit 4 stays, the rest is swapped around according to a table:
NIBBLETYPE TopBits = (a_Meta & 0x08);
switch (a_Meta & 0x07)
{
case 0x01: return TopBits | 0x02; // East -> West
case 0x02: return TopBits | 0x01; // West -> East
default: return a_Meta; // Keep the rest
}
}
} ;

View File

@ -36,8 +36,16 @@ public:
{
// Flip the ON bit on/off using the XOR bitwise operation
NIBBLETYPE Meta = (a_ChunkInterface.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ) ^ 0x04);
a_ChunkInterface.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, Meta);
cWorld * World = (cWorld *) &a_WorldInterface;
World->BroadcastSoundParticleEffect(1003, a_BlockX, a_BlockY, a_BlockZ, 0, a_Player->GetClientHandle());
}
virtual void OnCancelRightClick(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace) override
{
UNUSED(a_ChunkInterface);
a_WorldInterface.SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, a_Player);
}
virtual bool GetPlacementBlockTypeMeta(
@ -97,7 +105,7 @@ public:
AddFaceDirection(a_RelX, a_RelY, a_RelZ, BlockMetaDataToBlockFace(Meta), true);
BLOCKTYPE BlockIsOn; a_Chunk.UnboundedRelGetBlockType(a_RelX, a_RelY, a_RelZ, BlockIsOn);
return (a_RelY > 0) && (g_BlockIsSolid[BlockIsOn]);
return (a_RelY > 0) && cBlockInfo::IsSolid(BlockIsOn);
}
};

View File

@ -1,8 +1,7 @@
#pragma once
#include "BlockHandler.h"
#include "MetaRotater.h"
@ -70,7 +69,7 @@ public:
/// Returns true if the specified block type is good for vines to attach to
static bool IsBlockAttachable(BLOCKTYPE a_BlockType)
{
return (a_BlockType == E_BLOCK_LEAVES) || g_BlockIsSolid[a_BlockType];
return (a_BlockType == E_BLOCK_LEAVES) || cBlockInfo::IsSolid(a_BlockType);
}
@ -180,8 +179,8 @@ public:
{
return ((a_Meta << 1) | (a_Meta >> 3)) & 0x0f; // Rotate bits to the left
}
virtual NIBBLETYPE MetaMirrorXY(NIBBLETYPE a_Meta) override
{
// Bits 2 and 4 stay, bits 1 and 3 swap
@ -194,6 +193,7 @@ public:
// Bits 1 and 3 stay, bits 2 and 4 swap
return ((a_Meta & 0x05) | ((a_Meta & 0x02) << 2) | ((a_Meta & 0x08) >> 2));
}
} ;

View File

@ -6,7 +6,7 @@
bool cChunkInterface::DigBlock(cWorldInterface & a_WorldInterface, int a_X, int a_Y, int a_Z)
{
cBlockHandler *Handler = cBlockHandler::GetBlockHandler(GetBlock(a_X, a_Y, a_Z));
cBlockHandler * Handler = cBlockInfo::GetHandler(GetBlock(a_X, a_Y, a_Z));
Handler->OnDestroyed(*this, a_WorldInterface, a_X, a_Y, a_Z);
return m_ChunkMap->DigBlock(a_X, a_Y, a_Z);
}

View File

@ -5,31 +5,35 @@
#include "../ForEachChunkProvider.h"
#include "WorldInterface.h"
class cBlockHandler;
class cChunkInterface : public cForEachChunkProvider
class cChunkInterface:
public cForEachChunkProvider
{
public:
cChunkInterface(cChunkMap * a_ChunkMap) : m_ChunkMap(a_ChunkMap) {}
BLOCKTYPE GetBlock (int a_BlockX, int a_BlockY, int a_BlockZ)
BLOCKTYPE GetBlock(int a_BlockX, int a_BlockY, int a_BlockZ)
{
return m_ChunkMap->GetBlock(a_BlockX,a_BlockY,a_BlockZ);
}
BLOCKTYPE GetBlock (const Vector3i & a_Pos )
BLOCKTYPE GetBlock(const Vector3i & a_Pos)
{
return GetBlock( a_Pos.x, a_Pos.y, a_Pos.z );
return GetBlock(a_Pos.x, a_Pos.y, a_Pos.z);
}
NIBBLETYPE GetBlockMeta (int a_BlockX, int a_BlockY, int a_BlockZ)
NIBBLETYPE GetBlockMeta(int a_BlockX, int a_BlockY, int a_BlockZ)
{
return m_ChunkMap->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ);
}
bool GetBlockTypeMeta (int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta)
bool GetBlockTypeMeta(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta)
{
return m_ChunkMap->GetBlockTypeMeta(a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta);
}
/** Sets the block at the specified coords to the specified value.
Full processing, incl. updating neighbors, is performed.
*/
@ -37,7 +41,8 @@ public:
{
m_ChunkMap->SetBlock(a_WorldInterface, a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta);
}
void SetBlockMeta (int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_MetaData)
void SetBlockMeta(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_MetaData)
{
m_ChunkMap->SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, a_MetaData);
}
@ -55,7 +60,11 @@ public:
{
m_ChunkMap->FastSetBlock(a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta);
}
void FastSetBlock(const Vector3i & a_Pos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta ) { FastSetBlock( a_Pos.x, a_Pos.y, a_Pos.z, a_BlockType, a_BlockMeta ); }
void FastSetBlock(const Vector3i & a_Pos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta )
{
FastSetBlock( a_Pos.x, a_Pos.y, a_Pos.z, a_BlockType, a_BlockMeta );
}
void UseBlockEntity(cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ)
{
@ -77,3 +86,7 @@ public:
private:
cChunkMap * m_ChunkMap;
};

99
src/Blocks/MetaRotater.h Normal file
View File

@ -0,0 +1,99 @@
// MetaRotater.h
// Provides a mixin for rotations and reflections
#pragma once
/*
Provides a mixin for rotations and reflections following the standard pattern of apply mask then use case.
Usage:
Inherit from this class providing your base class as Base, the BitMask for the direction bits in bitmask and the masked value for the directions in North, East, South, West. There is also an aptional parameter AssertIfNotMatched. Set this if it is invalid for a block to exist in any other state.
*/
template<class Base, NIBBLETYPE BitMask, NIBBLETYPE North, NIBBLETYPE East, NIBBLETYPE South, NIBBLETYPE West, bool AssertIfNotMatched = false>
class cMetaRotater : public Base
{
public:
cMetaRotater(BLOCKTYPE a_BlockType) :
Base(a_BlockType)
{}
virtual ~cMetaRotater() {}
virtual NIBBLETYPE MetaRotateCCW(NIBBLETYPE a_Meta) override;
virtual NIBBLETYPE MetaRotateCW(NIBBLETYPE a_Meta) override;
virtual NIBBLETYPE MetaMirrorXY(NIBBLETYPE a_Meta) override;
virtual NIBBLETYPE MetaMirrorYZ(NIBBLETYPE a_Meta) override;
};
template<class Base, NIBBLETYPE BitMask, NIBBLETYPE North, NIBBLETYPE East, NIBBLETYPE South, NIBBLETYPE West, bool AssertIfNotMatched>
NIBBLETYPE cMetaRotater<Base, BitMask, North, East, South, West, AssertIfNotMatched>::MetaRotateCW(NIBBLETYPE a_Meta)
{
NIBBLETYPE OtherMeta = a_Meta & (~BitMask);
switch (a_Meta & BitMask)
{
case South: return West | OtherMeta;
case West: return North | OtherMeta;
case North: return East | OtherMeta;
case East: return South | OtherMeta;
}
if (AssertIfNotMatched)
{
ASSERT(!"Invalid Meta value");
}
return a_Meta;
}
template<class Base, NIBBLETYPE BitMask, NIBBLETYPE North, NIBBLETYPE East, NIBBLETYPE South, NIBBLETYPE West, bool AssertIfNotMatched>
NIBBLETYPE cMetaRotater<Base, BitMask, North, East, South, West, AssertIfNotMatched>::MetaRotateCCW(NIBBLETYPE a_Meta)
{
NIBBLETYPE OtherMeta = a_Meta & (~BitMask);
switch (a_Meta & BitMask)
{
case South: return East | OtherMeta;
case East: return North | OtherMeta;
case North: return West | OtherMeta;
case West: return South | OtherMeta;
}
if (AssertIfNotMatched)
{
ASSERT(!"Invalid Meta value");
}
return a_Meta;
}
template<class Base, NIBBLETYPE BitMask, NIBBLETYPE North, NIBBLETYPE East, NIBBLETYPE South, NIBBLETYPE West, bool AssertIfNotMatched>
NIBBLETYPE cMetaRotater<Base, BitMask, North, East, South, West, AssertIfNotMatched>::MetaMirrorXY(NIBBLETYPE a_Meta)
{
NIBBLETYPE OtherMeta = a_Meta & (~BitMask);
switch (a_Meta & BitMask)
{
case South: return North | OtherMeta;
case North: return South | OtherMeta;
}
// Not Facing North or South; No change.
return a_Meta;
}
template<class Base, NIBBLETYPE BitMask, NIBBLETYPE North, NIBBLETYPE East, NIBBLETYPE South, NIBBLETYPE West, bool AssertIfNotMatched>
NIBBLETYPE cMetaRotater<Base, BitMask, North, East, South, West, AssertIfNotMatched>::MetaMirrorYZ(NIBBLETYPE a_Meta)
{
NIBBLETYPE OtherMeta = a_Meta & (~BitMask);
switch (a_Meta & BitMask)
{
case West: return East | OtherMeta;
case East: return West | OtherMeta;
}
// Not Facing East or West; No change.
return a_Meta;
}

View File

@ -27,4 +27,7 @@ public:
/** Spawns a mob of the specified type. Returns the mob's EntityID if recognized and spawned, <0 otherwise */
virtual int SpawnMob(double a_PosX, double a_PosY, double a_PosZ, cMonster::eType a_MonsterType) = 0;
/** Sends the block on those coords to the player */
virtual void SendBlockTo(int a_BlockX, int a_BlockY, int a_BlockZ, cPlayer * a_Player) = 0;
};

View File

@ -40,6 +40,7 @@ if (NOT MSVC)
BlockEntities/NoteEntity.h
BlockEntities/SignEntity.h
BlockEntities/MobHeadEntity.h
BlockEntities/FlowerPotEntity.h
BlockID.h
BoundingBox.h
ChatColor.h
@ -95,6 +96,7 @@ if (NOT MSVC)
#add cpp files here
add_library(Bindings
Bindings/Bindings
Bindings/DeprecatedBindings
Bindings/LuaChunkStay
Bindings/LuaState
Bindings/LuaWindow

View File

@ -20,6 +20,7 @@
#include "BlockEntities/NoteEntity.h"
#include "BlockEntities/SignEntity.h"
#include "BlockEntities/MobHeadEntity.h"
#include "BlockEntities/FlowerPotEntity.h"
#include "Entities/Pickup.h"
#include "Item.h"
#include "Noise.h"
@ -883,7 +884,7 @@ void cChunk::ApplyWeatherToTop()
FastSetBlock(X, Height, Z, E_BLOCK_SNOW, TopMeta - 1);
}
}
else if (g_BlockIsSnowable[TopBlock])
else if (cBlockInfo::IsSnowable(TopBlock))
{
SetBlock(X, Height + 1, Z, E_BLOCK_SNOW, 0);
}
@ -1311,6 +1312,7 @@ void cChunk::CreateBlockEntities(void)
case E_BLOCK_HEAD:
case E_BLOCK_NOTE_BLOCK:
case E_BLOCK_JUKEBOX:
case E_BLOCK_FLOWER_POT:
{
if (!HasBlockEntityAt(x + m_PosX * Width, y + m_PosY * Height, z + m_PosZ * Width))
{
@ -1440,6 +1442,7 @@ void cChunk::SetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType,
case E_BLOCK_HEAD:
case E_BLOCK_NOTE_BLOCK:
case E_BLOCK_JUKEBOX:
case E_BLOCK_FLOWER_POT:
{
AddBlockEntity(cBlockEntity::CreateByBlockType(a_BlockType, a_BlockMeta, WorldPos.x, WorldPos.y, WorldPos.z, m_World));
break;
@ -1540,10 +1543,10 @@ void cChunk::FastSetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockT
SetNibble(m_BlockMeta, index, a_BlockMeta);
// ONLY recalculate lighting if it's necessary!
if(
(g_BlockLightValue[OldBlockType ] != g_BlockLightValue[a_BlockType]) ||
(g_BlockSpreadLightFalloff[OldBlockType] != g_BlockSpreadLightFalloff[a_BlockType]) ||
(g_BlockTransparent[OldBlockType] != g_BlockTransparent[a_BlockType])
if (
(cBlockInfo::GetLightValue (OldBlockType) != cBlockInfo::GetLightValue (a_BlockType)) ||
(cBlockInfo::GetSpreadLightFalloff(OldBlockType) != cBlockInfo::GetSpreadLightFalloff(a_BlockType)) ||
(cBlockInfo::IsTransparent (OldBlockType) != cBlockInfo::IsTransparent (a_BlockType))
)
{
m_IsLightValid = false;
@ -2337,7 +2340,7 @@ bool cChunk::DoWithCommandBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cCom
bool cChunk::DoWithMobHeadBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cMobHeadBlockCallback & a_Callback)
bool cChunk::DoWithMobHeadAt(int a_BlockX, int a_BlockY, int a_BlockZ, cMobHeadCallback & a_Callback)
{
// The blockentity list is locked by the parent chunkmap's CS
for (cBlockEntityList::iterator itr = m_BlockEntities.begin(), itr2 = itr; itr != m_BlockEntities.end(); itr = itr2)
@ -2369,6 +2372,38 @@ bool cChunk::DoWithMobHeadBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cMob
bool cChunk::DoWithFlowerPotAt(int a_BlockX, int a_BlockY, int a_BlockZ, cFlowerPotCallback & a_Callback)
{
// The blockentity list is locked by the parent chunkmap's CS
for (cBlockEntityList::iterator itr = m_BlockEntities.begin(), itr2 = itr; itr != m_BlockEntities.end(); itr = itr2)
{
++itr2;
if (((*itr)->GetPosX() != a_BlockX) || ((*itr)->GetPosY() != a_BlockY) || ((*itr)->GetPosZ() != a_BlockZ))
{
continue;
}
if ((*itr)->GetBlockType() != E_BLOCK_FLOWER_POT)
{
// There is a block entity here, but of different type. No other block entity can be here, so we can safely bail out
return false;
}
// The correct block entity is here,
if (a_Callback.Item((cFlowerPotEntity *)*itr))
{
return false;
}
return true;
} // for itr - m_BlockEntitites[]
// Not found:
return false;
}
bool cChunk::GetSignLines(int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4)
{
// The blockentity list is locked by the parent chunkmap's CS

View File

@ -32,6 +32,7 @@ class cDispenserEntity;
class cFurnaceEntity;
class cNoteEntity;
class cMobHeadEntity;
class cFlowerPotEntity;
class cBlockArea;
class cPawn;
class cPickup;
@ -48,7 +49,8 @@ typedef cItemCallback<cDispenserEntity> cDispenserCallback;
typedef cItemCallback<cFurnaceEntity> cFurnaceCallback;
typedef cItemCallback<cNoteEntity> cNoteBlockCallback;
typedef cItemCallback<cCommandBlockEntity> cCommandBlockCallback;
typedef cItemCallback<cMobHeadEntity> cMobHeadBlockCallback;
typedef cItemCallback<cMobHeadEntity> cMobHeadCallback;
typedef cItemCallback<cFlowerPotEntity> cFlowerPotCallback;
@ -253,8 +255,11 @@ public:
/** Calls the callback for the command block at the specified coords; returns false if there's no command block at those coords or callback returns true, returns true if found */
bool DoWithCommandBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cCommandBlockCallback & a_Callback);
/** Calls the callback for the mob head block at the specified coords; returns false if there's no mob header block at those coords or callback returns true, returns true if found */
bool DoWithMobHeadBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cMobHeadBlockCallback & a_Callback);
/** Calls the callback for the mob head block at the specified coords; returns false if there's no mob head block at those coords or callback returns true, returns true if found */
bool DoWithMobHeadAt(int a_BlockX, int a_BlockY, int a_BlockZ, cMobHeadCallback & a_Callback);
/** Calls the callback for the flower pot at the specified coords; returns false if there's no flower pot at those coords or callback returns true, returns true if found */
bool DoWithFlowerPotAt(int a_BlockX, int a_BlockY, int a_BlockZ, cFlowerPotCallback & a_Callback);
/** Retrieves the test on the sign at the specified coords; returns false if there's no sign at those coords, true if found */
bool GetSignLines (int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4); // Lua-accessible

View File

@ -2182,7 +2182,7 @@ bool cChunkMap::DoWithCommandBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, c
bool cChunkMap::DoWithMobHeadBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cMobHeadBlockCallback & a_Callback)
bool cChunkMap::DoWithMobHeadAt(int a_BlockX, int a_BlockY, int a_BlockZ, cMobHeadCallback & a_Callback)
{
int ChunkX, ChunkZ;
int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ;
@ -2193,7 +2193,25 @@ bool cChunkMap::DoWithMobHeadBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, c
{
return false;
}
return Chunk->DoWithMobHeadBlockAt(a_BlockX, a_BlockY, a_BlockZ, a_Callback);
return Chunk->DoWithMobHeadAt(a_BlockX, a_BlockY, a_BlockZ, a_Callback);
}
bool cChunkMap::DoWithFlowerPotAt(int a_BlockX, int a_BlockY, int a_BlockZ, cFlowerPotCallback & a_Callback)
{
int ChunkX, ChunkZ;
int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ;
cChunkDef::AbsoluteToRelative(BlockX, BlockY, BlockZ, ChunkX, ChunkZ);
cCSLock Lock(m_CSLayers);
cChunkPtr Chunk = GetChunkNoGen(ChunkX, ZERO_CHUNK_Y, ChunkZ);
if ((Chunk == NULL) && !Chunk->IsValid())
{
return false;
}
return Chunk->DoWithFlowerPotAt(a_BlockX, a_BlockY, a_BlockZ, a_Callback);
}

View File

@ -26,6 +26,7 @@ class cFurnaceEntity;
class cNoteEntity;
class cCommandBlockEntity;
class cMobHeadEntity;
class cFlowerPotEntity;
class cPawn;
class cPickup;
class cChunkDataSerializer;
@ -41,10 +42,11 @@ typedef cItemCallback<cChestEntity> cChestCallback;
typedef cItemCallback<cDispenserEntity> cDispenserCallback;
typedef cItemCallback<cDropperEntity> cDropperCallback;
typedef cItemCallback<cDropSpenserEntity> cDropSpenserCallback;
typedef cItemCallback<cFlowerPotEntity> cFlowerPotCallback;
typedef cItemCallback<cFurnaceEntity> cFurnaceCallback;
typedef cItemCallback<cNoteEntity> cNoteBlockCallback;
typedef cItemCallback<cCommandBlockEntity> cCommandBlockCallback;
typedef cItemCallback<cMobHeadEntity> cMobHeadBlockCallback;
typedef cItemCallback<cMobHeadEntity> cMobHeadCallback;
typedef cItemCallback<cChunk> cChunkCallback;
@ -257,7 +259,10 @@ public:
bool DoWithCommandBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cCommandBlockCallback & a_Callback); // Lua-accessible
/** Calls the callback for the mob head block at the specified coords; returns false if there's no mob head block at those coords or callback returns true, returns true if found */
bool DoWithMobHeadBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cMobHeadBlockCallback & a_Callback); // Lua-accessible
bool DoWithMobHeadAt(int a_BlockX, int a_BlockY, int a_BlockZ, cMobHeadCallback & a_Callback); // Lua-accessible
/** Calls the callback for the flower pot at the specified coords; returns false if there's no flower pot at those coords or callback returns true, returns true if found */
bool DoWithFlowerPotAt(int a_BlockX, int a_BlockY, int a_BlockZ, cFlowerPotCallback & a_Callback); // Lua-accessible
/** Retrieves the test on the sign at the specified coords; returns false if there's no sign at those coords, true if found */
bool GetSignLines (int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4); // Lua-accessible

View File

@ -558,12 +558,25 @@ void cClientHandle::HandlePluginMessage(const AString & a_Channel, const AString
}
else if (a_Channel == "REGISTER")
{
if (HasPluginChannel(a_Channel))
{
SendPluginMessage("UNREGISTER", a_Channel);
return; // Can't register again if already taken - kinda defeats the point of plugin messaging!
}
RegisterPluginChannels(BreakApartPluginChannels(a_Message));
}
else if (a_Channel == "UNREGISTER")
{
UnregisterPluginChannels(BreakApartPluginChannels(a_Message));
}
else if (!HasPluginChannel(a_Channel))
{
// Ignore if client sent something but didn't register the channel first
LOGD("Player %s sent a plugin message on channel \"%s\", but didn't REGISTER it first", GetUsername().c_str(), a_Channel.c_str());
SendPluginMessage("UNREGISTER", a_Channel);
return;
}
cPluginManager::Get()->CallHookPluginMessage(*this, a_Channel, a_Message);
}
@ -824,7 +837,7 @@ void cClientHandle::HandleBlockDigStarted(int a_BlockX, int a_BlockY, int a_Bloc
if (
(m_Player->IsGameModeCreative()) || // In creative mode, digging is done immediately
g_BlockOneHitDig[a_OldBlock] // One-hit blocks get destroyed immediately, too
cBlockInfo::IsOneHitDig(a_OldBlock) // One-hit blocks get destroyed immediately, too
)
{
HandleBlockDigFinished(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_OldBlock, a_OldMeta);
@ -843,7 +856,7 @@ void cClientHandle::HandleBlockDigStarted(int a_BlockX, int a_BlockY, int a_Bloc
cWorld * World = m_Player->GetWorld();
cChunkInterface ChunkInterface(World->GetChunkMap());
cBlockHandler * Handler = cBlockHandler::GetBlockHandler(a_OldBlock);
cBlockHandler * Handler = cBlockInfo::GetHandler(a_OldBlock);
Handler->OnDigging(ChunkInterface, *World, m_Player, a_BlockX, a_BlockY, a_BlockZ);
cItemHandler * ItemHandler = cItemHandler::GetItemHandler(m_Player->GetEquippedItem());
@ -857,7 +870,7 @@ void cClientHandle::HandleBlockDigStarted(int a_BlockX, int a_BlockY, int a_Bloc
int pZ = a_BlockZ;
AddFaceDirection(pX, pY, pZ, a_BlockFace); // Get the block in front of the clicked coordinates (m_bInverse defaulted to false)
Handler = cBlockHandler::GetBlockHandler(World->GetBlock(pX, pY, pZ));
Handler = cBlockInfo::GetHandler(World->GetBlock(pX, pY, pZ));
if (Handler->IsClickedThrough())
{
@ -925,14 +938,22 @@ void cClientHandle::HandleRightClick(int a_BlockX, int a_BlockY, int a_BlockZ, e
a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, ItemToFullString(a_HeldItem).c_str()
);
cWorld * World = m_Player->GetWorld();
cPluginManager * PlgMgr = cRoot::Get()->GetPluginManager();
if (PlgMgr->CallHookPlayerRightClick(*m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ))
{
// A plugin doesn't agree with the action, replace the block on the client and quit:
cChunkInterface ChunkInterface(World->GetChunkMap());
BLOCKTYPE BlockType = World->GetBlock(a_BlockX, a_BlockY, a_BlockZ);
cBlockHandler * BlockHandler = cBlockInfo::GetHandler(BlockType);
BlockHandler->OnCancelRightClick(ChunkInterface, *World, m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace);
if (a_BlockFace > BLOCK_FACE_NONE)
{
AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace);
m_Player->GetWorld()->SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, m_Player);
World->SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, m_Player);
World->SendBlockTo(a_BlockX, a_BlockY + 1, a_BlockZ, m_Player); //2 block high things
}
return;
}
@ -958,17 +979,15 @@ void cClientHandle::HandleRightClick(int a_BlockX, int a_BlockY, int a_BlockZ, e
if (a_BlockFace > -1)
{
AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace);
m_Player->GetWorld()->SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, m_Player);
World->SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, m_Player);
}
return;
}
cWorld * World = m_Player->GetWorld();
BLOCKTYPE BlockType;
NIBBLETYPE BlockMeta;
World->GetBlockTypeMeta(a_BlockX, a_BlockY, a_BlockZ, BlockType, BlockMeta);
cBlockHandler * BlockHandler = cBlockHandler::GetBlockHandler(BlockType);
cBlockHandler * BlockHandler = cBlockInfo::GetHandler(BlockType);
if (BlockHandler->IsUseable() && !m_Player->IsCrouched())
{
@ -1048,7 +1067,7 @@ void cClientHandle::HandlePlaceBlock(int a_BlockX, int a_BlockY, int a_BlockZ, e
if (
cBlockSlabHandler::IsAnySlabType(ClickedBlock) && // Is there a slab already?
cBlockSlabHandler::IsAnySlabType(EquippedBlock) && // Is the player placing another slab?
((ClickedBlockMeta & 0x07) == (EquippedBlockDamage & 0x07)) && // Is it the same slab type?
((ClickedBlockMeta & 0x07) == EquippedBlockDamage) && // Is it the same slab type?
(
(a_BlockFace == BLOCK_FACE_TOP) || // Clicking the top of a bottom slab
(a_BlockFace == BLOCK_FACE_BOTTOM) // Clicking the bottom of a top slab

View File

@ -124,14 +124,15 @@ public:
/** Removes all parts from the object. */
void Clear(void);
// tolua_end
// The following are exported in ManualBindings in order to support chaining - they return *this in Lua (#755)
/** Adds a plain text part, with optional style.
The default style is plain white text. */
void AddTextPart(const AString & a_Message, const AString & a_Style = "");
// tolua_end
/** Adds a part that is translated client-side, with the formatting parameters and optional style.
Exported in ManualBindings due to AStringVector usage - Lua uses an array-table of strings. */
/** Adds a part that is translated client-side, with the formatting parameters and optional style. */
void AddClientTranslatedPart(const AString & a_TranslationID, const AStringVector & a_Parameters, const AString & a_Style = "");
// tolua_begin
@ -155,12 +156,14 @@ public:
/** Sets the message type, which is indicated by prefixes added to the message when serializing. */
void SetMessageType(eMessageType a_MessageType);
/** Returns the message type set previously by SetMessageType(). */
eMessageType GetMessageType(void) const { return m_MessageType; }
/** Adds the "underline" style to each part that is an URL. */
void UnderlineUrls(void);
// tolua_begin
/** Returns the message type set previously by SetMessageType(). */
eMessageType GetMessageType(void) const { return m_MessageType; }
// tolua_end
const cParts & GetParts(void) const { return m_Parts; }

View File

@ -17,33 +17,6 @@ typedef std::vector<int> cSlotNums;
// tolua_begin
/// How much light do the blocks emit on their own?
extern unsigned char g_BlockLightValue[];
/// How much light do the block consume?
extern unsigned char g_BlockSpreadLightFalloff[];
/// Is a block completely transparent? (light doesn't get decreased(?))
extern bool g_BlockTransparent[];
/// Is a block destroyed after a single hit?
extern bool g_BlockOneHitDig[];
/// Can a piston break this block?
extern bool g_BlockPistonBreakable[256];
/// Can this block hold snow atop?
extern bool g_BlockIsSnowable[256];
/// Does this block require a tool to drop?
extern bool g_BlockRequiresSpecialTool[256];
/// Is this block solid (player cannot walk through)?
extern bool g_BlockIsSolid[256];
/// Does this block fully occupy it's voxel - is it a 'full' block?
extern bool g_BlockFullyOccupiesVoxel[256];
/// Experience Orb setup
enum
{
@ -253,6 +226,56 @@ inline const char * ClickActionToString(eClickAction a_ClickAction)
/** Returns a blockface mirrored around the Y axis (doesn't change up/down). */
inline eBlockFace MirrorBlockFaceY(eBlockFace a_BlockFace)
{
switch (a_BlockFace)
{
case BLOCK_FACE_XM: return BLOCK_FACE_XP;
case BLOCK_FACE_XP: return BLOCK_FACE_XM;
case BLOCK_FACE_ZM: return BLOCK_FACE_ZP;
case BLOCK_FACE_ZP: return BLOCK_FACE_ZM;
default: return a_BlockFace;
}
}
/** Returns a blockface rotated around the Y axis counter-clockwise. */
inline eBlockFace RotateBlockFaceCCW(eBlockFace a_BlockFace)
{
switch (a_BlockFace)
{
case BLOCK_FACE_XM: return BLOCK_FACE_ZP;
case BLOCK_FACE_XP: return BLOCK_FACE_ZM;
case BLOCK_FACE_ZM: return BLOCK_FACE_XM;
case BLOCK_FACE_ZP: return BLOCK_FACE_XP;
default: return a_BlockFace;
}
}
inline eBlockFace RotateBlockFaceCW(eBlockFace a_BlockFace)
{
switch (a_BlockFace)
{
case BLOCK_FACE_XM: return BLOCK_FACE_ZM;
case BLOCK_FACE_XP: return BLOCK_FACE_ZP;
case BLOCK_FACE_ZM: return BLOCK_FACE_XP;
case BLOCK_FACE_ZP: return BLOCK_FACE_XM;
default: return a_BlockFace;
}
}
inline bool IsValidBlock(int a_BlockType)
{
if (
@ -654,7 +677,7 @@ namespace ItemCategory
inline bool BlockRequiresSpecialTool(BLOCKTYPE a_BlockType)
{
if(!IsValidBlock(a_BlockType)) return false;
return g_BlockRequiresSpecialTool[a_BlockType];
return cBlockInfo::RequiresSpecialTool(a_BlockType);
}

View File

@ -582,11 +582,11 @@ void cEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
int RelBlockZ = BlockZ - (NextChunk->GetPosZ() * cChunkDef::Width);
BLOCKTYPE BlockIn = NextChunk->GetBlock( RelBlockX, BlockY, RelBlockZ );
BLOCKTYPE BlockBelow = (BlockY > 0) ? NextChunk->GetBlock(RelBlockX, BlockY - 1, RelBlockZ) : E_BLOCK_AIR;
if (!g_BlockIsSolid[BlockIn]) // Making sure we are not inside a solid block
if (!cBlockInfo::IsSolid(BlockIn)) // Making sure we are not inside a solid block
{
if (m_bOnGround) // check if it's still on the ground
{
if (!g_BlockIsSolid[BlockBelow]) // Check if block below is air or water.
if (!cBlockInfo::IsSolid(BlockBelow)) // Check if block below is air or water.
{
m_bOnGround = false;
}
@ -616,7 +616,7 @@ void cEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
// The pickup is too close to an unloaded chunk, bail out of any physics handling
return;
}
if (!g_BlockIsSolid[GotBlock])
if (!cBlockInfo::IsSolid(GotBlock))
{
NextPos.x += gCrossCoords[i].x;
NextPos.z += gCrossCoords[i].z;

View File

@ -720,7 +720,7 @@ bool cMinecart::TestBlockCollision(NIBBLETYPE a_RailMeta)
if (GetSpeedZ() > 0)
{
BLOCKTYPE Block = m_World->GetBlock((int)floor(GetPosX()), (int)floor(GetPosY()), (int)ceil(GetPosZ()));
if (!IsBlockRail(Block) && g_BlockIsSolid[Block])
if (!IsBlockRail(Block) && cBlockInfo::IsSolid(Block))
{
// We could try to detect a block in front based purely on coordinates, but xoft made a bounding box system - why not use? :P
cBoundingBox bbBlock(Vector3d((int)floor(GetPosX()), (int)floor(GetPosY()), (int)ceil(GetPosZ())), 0.5, 1);
@ -737,7 +737,7 @@ bool cMinecart::TestBlockCollision(NIBBLETYPE a_RailMeta)
else if (GetSpeedZ() < 0)
{
BLOCKTYPE Block = m_World->GetBlock((int)floor(GetPosX()), (int)floor(GetPosY()), (int)floor(GetPosZ()) - 1);
if (!IsBlockRail(Block) && g_BlockIsSolid[Block])
if (!IsBlockRail(Block) && cBlockInfo::IsSolid(Block))
{
cBoundingBox bbBlock(Vector3d((int)floor(GetPosX()), (int)floor(GetPosY()), (int)floor(GetPosZ()) - 1), 0.5, 1);
cBoundingBox bbMinecart(Vector3d(GetPosX(), floor(GetPosY()), GetPosZ() - 1), GetWidth() / 2, GetHeight());
@ -757,7 +757,7 @@ bool cMinecart::TestBlockCollision(NIBBLETYPE a_RailMeta)
if (GetSpeedX() > 0)
{
BLOCKTYPE Block = m_World->GetBlock((int)ceil(GetPosX()), (int)floor(GetPosY()), (int)floor(GetPosZ()));
if (!IsBlockRail(Block) && g_BlockIsSolid[Block])
if (!IsBlockRail(Block) && cBlockInfo::IsSolid(Block))
{
cBoundingBox bbBlock(Vector3d((int)ceil(GetPosX()), (int)floor(GetPosY()), (int)floor(GetPosZ())), 0.5, 1);
cBoundingBox bbMinecart(Vector3d(GetPosX(), floor(GetPosY()), GetPosZ()), GetWidth() / 2, GetHeight());
@ -773,7 +773,7 @@ bool cMinecart::TestBlockCollision(NIBBLETYPE a_RailMeta)
else if (GetSpeedX() < 0)
{
BLOCKTYPE Block = m_World->GetBlock((int)floor(GetPosX()) - 1, (int)floor(GetPosY()), (int)floor(GetPosZ()));
if (!IsBlockRail(Block) && g_BlockIsSolid[Block])
if (!IsBlockRail(Block) && cBlockInfo::IsSolid(Block))
{
cBoundingBox bbBlock(Vector3d((int)floor(GetPosX()) - 1, (int)floor(GetPosY()), (int)floor(GetPosZ())), 0.5, 1);
cBoundingBox bbMinecart(Vector3d(GetPosX() - 1, floor(GetPosY()), GetPosZ()), GetWidth() / 2, GetHeight());
@ -798,10 +798,10 @@ bool cMinecart::TestBlockCollision(NIBBLETYPE a_RailMeta)
BLOCKTYPE BlockZM = m_World->GetBlock((int)floor(GetPosX()), (int)floor(GetPosY()), (int)floor(GetPosZ()) + 1);
BLOCKTYPE BlockZP = m_World->GetBlock((int)floor(GetPosX()), (int)floor(GetPosY()), (int)floor(GetPosZ()) + 1);
if (
(!IsBlockRail(BlockXM) && g_BlockIsSolid[BlockXM]) ||
(!IsBlockRail(BlockXP) && g_BlockIsSolid[BlockXP]) ||
(!IsBlockRail(BlockZM) && g_BlockIsSolid[BlockZM]) ||
(!IsBlockRail(BlockZP) && g_BlockIsSolid[BlockZP])
(!IsBlockRail(BlockXM) && cBlockInfo::IsSolid(BlockXM)) ||
(!IsBlockRail(BlockXP) && cBlockInfo::IsSolid(BlockXP)) ||
(!IsBlockRail(BlockZM) && cBlockInfo::IsSolid(BlockZM)) ||
(!IsBlockRail(BlockZP) && cBlockInfo::IsSolid(BlockZP))
)
{
SetSpeed(0, 0, 0);

View File

@ -4,6 +4,7 @@
#include "Painting.h"
#include "ClientHandle.h"
#include "Player.h"
#include "../Chunk.h"
@ -30,6 +31,16 @@ void cPainting::SpawnOn(cClientHandle & a_Client)
void cPainting::Tick(float a_Dt, cChunk & a_Chunk)
{
UNUSED(a_Dt);
UNUSED(a_Chunk);
}
void cPainting::GetDrops(cItems & a_Items, cEntity * a_Killer)
{
if ((a_Killer != NULL) && a_Killer->IsPlayer() && !((cPlayer *)a_Killer)->IsGameModeCreative())

View File

@ -24,7 +24,7 @@ public:
private:
virtual void SpawnOn(cClientHandle & a_Client) override;
virtual void Tick(float a_Dt, cChunk & a_Chunk) override {};
virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
virtual void GetDrops(cItems & a_Items, cEntity * a_Killer) override;
virtual void KilledBy(cEntity * a_Killer) override
{

View File

@ -847,6 +847,8 @@ void cPlayer::KilledBy(cEntity * a_Killer)
else if (a_Killer->IsPlayer())
{
GetWorld()->BroadcastChatDeath(Printf("%s was killed by %s", GetName().c_str(), ((cPlayer *)a_Killer)->GetName().c_str()));
m_World->GetScoreBoard().AddPlayerScore(((cPlayer *)a_Killer)->GetName(), cObjective::otPlayerKillCount, 1);
}
else
{
@ -856,24 +858,7 @@ void cPlayer::KilledBy(cEntity * a_Killer)
GetWorld()->BroadcastChatDeath(Printf("%s was killed by a %s", GetName().c_str(), KillerClass.c_str()));
}
class cIncrementCounterCB
: public cObjectiveCallback
{
AString m_Name;
public:
cIncrementCounterCB(const AString & a_Name) : m_Name(a_Name) {}
virtual bool Item(cObjective * a_Objective) override
{
a_Objective->AddScore(m_Name, 1);
return true;
}
} IncrementCounter (GetName());
cScoreboard & Scoreboard = m_World->GetScoreBoard();
// Update scoreboard objectives
Scoreboard.ForEachObjectiveWith(cObjective::E_TYPE_DEATH_COUNT, IncrementCounter);
m_World->GetScoreBoard().AddPlayerScore(GetName(), cObjective::otDeathCount, 1);
}
@ -1497,10 +1482,14 @@ void cPlayer::LoadPermissionsFromDisk()
std::string Groups = IniFile.GetValue(m_PlayerName, "Groups", "");
if (!Groups.empty())
{
AStringVector Split = StringSplit( Groups, "," );
for( unsigned int i = 0; i < Split.size(); i++ )
AStringVector Split = StringSplitAndTrim(Groups, ",");
for (AStringVector::const_iterator itr = Split.begin(), end = Split.end(); itr != end; ++itr)
{
AddToGroup( Split[i].c_str() );
if (!cRoot::Get()->GetGroupManager()->ExistsGroup(*itr))
{
LOGWARNING("The group %s for player %s was not found!", itr->c_str(), m_PlayerName.c_str());
}
AddToGroup(*itr);
}
}
else
@ -1508,16 +1497,15 @@ void cPlayer::LoadPermissionsFromDisk()
AddToGroup("Default");
}
m_Color = IniFile.GetValue(m_PlayerName, "Color", "-")[0];
AString Color = IniFile.GetValue(m_PlayerName, "Color", "-");
if (!Color.empty())
{
m_Color = Color[0];
}
}
else
{
LOGWARN("Regenerating users.ini, player %s will be added to the \"Default\" group", m_PlayerName.c_str());
IniFile.AddHeaderComment(" This is the file in which the group the player belongs to is stored");
IniFile.AddHeaderComment(" The format is: [PlayerName] | Groups=GroupName");
IniFile.SetValue(m_PlayerName, "Groups", "Default");
IniFile.WriteFile("users.ini");
cGroupManager::GenerateDefaultUsersIni(IniFile);
AddToGroup("Default");
}
ResolvePermissions();
@ -1884,7 +1872,7 @@ void cPlayer::Detach()
{
for (int z = PosZ - 2; z <= (PosZ + 2); ++z)
{
if (!g_BlockIsSolid[m_World->GetBlock(x, y, z)] && g_BlockIsSolid[m_World->GetBlock(x, y - 1, z)])
if (!cBlockInfo::IsSolid(m_World->GetBlock(x, y, z)) && cBlockInfo::IsSolid(m_World->GetBlock(x, y - 1, z)))
{
TeleportToCoords(x, y, z);
return;

View File

@ -50,12 +50,12 @@ protected:
LOGD("Hit block %d:%d at {%d, %d, %d} face %d, %s (%s)",
a_BlockType, a_BlockMeta,
a_BlockX, a_BlockY, a_BlockZ, a_EntryFace,
g_BlockIsSolid[a_BlockType] ? "solid" : "non-solid",
cBlockInfo::IsSolid(a_BlockType) ? "solid" : "non-solid",
ItemToString(cItem(a_BlockType, 1, a_BlockMeta)).c_str()
);
*/
if (g_BlockIsSolid[a_BlockType])
if (cBlockInfo::IsSolid(a_BlockType))
{
// The projectile hit a solid block
// Calculate the exact hit coords:

View File

@ -762,7 +762,7 @@ void cStructGenWormNestCaves::ClearCache(void)
void cStructGenWormNestCaves::GenStructures(cChunkDesc & a_ChunkDesc)
void cStructGenWormNestCaves::GenFinish(cChunkDesc & a_ChunkDesc)
{
int ChunkX = a_ChunkDesc.GetChunkX();
int ChunkZ = a_ChunkDesc.GetChunkZ();
@ -902,7 +902,7 @@ static float GetMarbleNoise( float x, float y, float z, cNoise & a_Noise )
void cStructGenMarbleCaves::GenStructures(cChunkDesc & a_ChunkDesc)
void cStructGenMarbleCaves::GenFinish(cChunkDesc & a_ChunkDesc)
{
cNoise Noise(m_Seed);
for (int z = 0; z < cChunkDef::Width; z++)
@ -938,7 +938,7 @@ void cStructGenMarbleCaves::GenStructures(cChunkDesc & a_ChunkDesc)
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// cStructGenDualRidgeCaves:
void cStructGenDualRidgeCaves::GenStructures(cChunkDesc & a_ChunkDesc)
void cStructGenDualRidgeCaves::GenFinish(cChunkDesc & a_ChunkDesc)
{
for (int z = 0; z < cChunkDef::Width; z++)
{

View File

@ -20,7 +20,7 @@
class cStructGenMarbleCaves :
public cStructureGen
public cFinishGen
{
public:
cStructGenMarbleCaves(int a_Seed) : m_Seed(a_Seed) {}
@ -29,8 +29,8 @@ protected:
int m_Seed;
// cStructureGen override:
virtual void GenStructures(cChunkDesc & a_ChunkDesc) override;
// cFinishGen override:
virtual void GenFinish(cChunkDesc & a_ChunkDesc) override;
} ;
@ -38,7 +38,7 @@ protected:
class cStructGenDualRidgeCaves :
public cStructureGen
public cFinishGen
{
public:
cStructGenDualRidgeCaves(int a_Seed, float a_Threshold) :
@ -55,8 +55,8 @@ protected:
int m_Seed;
float m_Threshold;
// cStructureGen override:
virtual void GenStructures(cChunkDesc & a_ChunkDesc) override;
// cFinishGen override:
virtual void GenFinish(cChunkDesc & a_ChunkDesc) override;
} ;
@ -64,7 +64,7 @@ protected:
class cStructGenWormNestCaves :
public cStructureGen
public cFinishGen
{
public:
cStructGenWormNestCaves(int a_Seed, int a_Size = 64, int a_Grid = 96, int a_MaxOffset = 128) :
@ -94,7 +94,7 @@ protected:
void GetCavesForChunk(int a_ChunkX, int a_ChunkZ, cCaveSystems & a_Caves);
// cStructGen override:
virtual void GenStructures(cChunkDesc & a_ChunkDesc) override;
virtual void GenFinish(cChunkDesc & a_ChunkDesc) override;
} ;

View File

@ -209,6 +209,7 @@ bool cChunkDesc::IsUsingDefaultComposition(void) const
void cChunkDesc::SetUseDefaultStructures(bool a_bUseDefaultStructures)
{
LOGWARNING("%s: Structures are no longer accounted for, use Finishers instead", __FUNCTION__);
m_bUseDefaultStructures = a_bUseDefaultStructures;
}
@ -218,6 +219,7 @@ void cChunkDesc::SetUseDefaultStructures(bool a_bUseDefaultStructures)
bool cChunkDesc::IsUsingDefaultStructures(void) const
{
LOGWARNING("%s: Structures are no longer accounted for, use Finishers instead", __FUNCTION__);
return m_bUseDefaultStructures;
}

View File

@ -133,11 +133,6 @@ cComposableGenerator::~cComposableGenerator()
delete *itr;
}
m_FinishGens.clear();
for (cStructureGenList::const_iterator itr = m_StructureGens.begin(); itr != m_StructureGens.end(); ++itr)
{
delete *itr;
}
m_StructureGens.clear();
delete m_CompositionGen;
m_CompositionGen = NULL;
@ -164,7 +159,6 @@ void cComposableGenerator::Initialize(cIniFile & a_IniFile)
InitBiomeGen(a_IniFile);
InitHeightGen(a_IniFile);
InitCompositionGen(a_IniFile);
InitStructureGens(a_IniFile);
InitFinishGens(a_IniFile);
}
@ -201,14 +195,6 @@ void cComposableGenerator::DoGenerate(int a_ChunkX, int a_ChunkZ, cChunkDesc & a
m_CompositionGen->ComposeTerrain(a_ChunkDesc);
}
if (a_ChunkDesc.IsUsingDefaultStructures())
{
for (cStructureGenList::iterator itr = m_StructureGens.begin(); itr != m_StructureGens.end(); ++itr)
{
(*itr)->GenStructures(a_ChunkDesc);
} // for itr - m_StructureGens[]
}
if (a_ChunkDesc.IsUsingDefaultFinish())
{
for (cFinishGenList::iterator itr = m_FinishGens.begin(); itr != m_FinishGens.end(); ++itr)
@ -290,86 +276,26 @@ void cComposableGenerator::InitCompositionGen(cIniFile & a_IniFile)
void cComposableGenerator::InitStructureGens(cIniFile & a_IniFile)
{
AString Structures = a_IniFile.GetValueSet("Generator", "Structures", "Ravines, WormNestCaves, WaterLakes, LavaLakes, OreNests, Trees");
int Seed = m_ChunkGenerator.GetSeed();
AStringVector Str = StringSplitAndTrim(Structures, ",");
for (AStringVector::const_iterator itr = Str.begin(); itr != Str.end(); ++itr)
{
if (NoCaseCompare(*itr, "DualRidgeCaves") == 0)
{
float Threshold = (float)a_IniFile.GetValueSetF("Generator", "DualRidgeCavesThreshold", 0.3);
m_StructureGens.push_back(new cStructGenDualRidgeCaves(Seed, Threshold));
}
else if (NoCaseCompare(*itr, "DirectOverhangs") == 0)
{
m_StructureGens.push_back(new cStructGenDirectOverhangs(Seed));
}
else if (NoCaseCompare(*itr, "DistortedMembraneOverhangs") == 0)
{
m_StructureGens.push_back(new cStructGenDistortedMembraneOverhangs(Seed));
}
else if (NoCaseCompare(*itr, "LavaLakes") == 0)
{
int Probability = a_IniFile.GetValueSetI("Generator", "LavaLakesProbability", 10);
m_StructureGens.push_back(new cStructGenLakes(Seed * 5 + 16873, E_BLOCK_STATIONARY_LAVA, *m_HeightGen, Probability));
}
else if (NoCaseCompare(*itr, "MarbleCaves") == 0)
{
m_StructureGens.push_back(new cStructGenMarbleCaves(Seed));
}
else if (NoCaseCompare(*itr, "MineShafts") == 0)
{
int GridSize = a_IniFile.GetValueSetI("Generator", "MineShaftsGridSize", 512);
int MaxSystemSize = a_IniFile.GetValueSetI("Generator", "MineShaftsMaxSystemSize", 160);
int ChanceCorridor = a_IniFile.GetValueSetI("Generator", "MineShaftsChanceCorridor", 600);
int ChanceCrossing = a_IniFile.GetValueSetI("Generator", "MineShaftsChanceCrossing", 200);
int ChanceStaircase = a_IniFile.GetValueSetI("Generator", "MineShaftsChanceStaircase", 200);
m_StructureGens.push_back(new cStructGenMineShafts(
Seed, GridSize, MaxSystemSize,
ChanceCorridor, ChanceCrossing, ChanceStaircase
));
}
else if (NoCaseCompare(*itr, "OreNests") == 0)
{
m_StructureGens.push_back(new cStructGenOreNests(Seed));
}
else if (NoCaseCompare(*itr, "Ravines") == 0)
{
m_StructureGens.push_back(new cStructGenRavines(Seed, 128));
}
else if (NoCaseCompare(*itr, "Trees") == 0)
{
m_StructureGens.push_back(new cStructGenTrees(Seed, m_BiomeGen, m_HeightGen, m_CompositionGen));
}
else if (NoCaseCompare(*itr, "WaterLakes") == 0)
{
int Probability = a_IniFile.GetValueSetI("Generator", "WaterLakesProbability", 25);
m_StructureGens.push_back(new cStructGenLakes(Seed * 3 + 652, E_BLOCK_STATIONARY_WATER, *m_HeightGen, Probability));
}
else if (NoCaseCompare(*itr, "WormNestCaves") == 0)
{
m_StructureGens.push_back(new cStructGenWormNestCaves(Seed));
}
else
{
LOGWARNING("Unknown structure generator: \"%s\". Ignoring.", itr->c_str());
}
} // for itr - Str[]
}
void cComposableGenerator::InitFinishGens(cIniFile & a_IniFile)
{
int Seed = m_ChunkGenerator.GetSeed();
eDimension Dimension = StringToDimension(a_IniFile.GetValue("General", "Dimension", "Overworld"));
AString Finishers = a_IniFile.GetValueSet("Generator", "Finishers", "SprinkleFoliage,Ice,Snow,Lilypads,BottomLava,DeadBushes,PreSimulator");
// Older configuration used "Structures" in addition to "Finishers"; we don't distinguish between the two anymore (#398)
// Therefore, we load Structures from the ini file for compatibility, but move its contents over to Finishers:
AString Structures = a_IniFile.GetValue("Generator", "Structures", "");
AString Finishers = a_IniFile.GetValueSet("Generator", "Finishers", "Ravines, WormNestCaves, WaterLakes, LavaLakes, OreNests, Trees, SprinkleFoliage, Ice, Snow, Lilypads, BottomLava, DeadBushes, PreSimulator");
if (!Structures.empty())
{
LOGINFO("[Generator].Structures is deprecated, moving the contents to [Generator].Finishers.");
// Structures used to generate before Finishers, so place them first:
Structures.append(", ");
Finishers = Structures + Finishers;
a_IniFile.SetValue("Generator", "Finishers", Finishers);
}
a_IniFile.DeleteValue("Generator", "Structures");
// Create all requested finishers:
AStringVector Str = StringSplitAndTrim(Finishers, ",");
for (AStringVector::const_iterator itr = Str.begin(); itr != Str.end(); ++itr)
{
@ -384,14 +310,48 @@ void cComposableGenerator::InitFinishGens(cIniFile & a_IniFile)
{
m_FinishGens.push_back(new cFinishGenSingleBiomeSingleTopBlock(Seed, E_BLOCK_DEAD_BUSH, biDesert, 2, E_BLOCK_SAND, E_BLOCK_SAND));
}
else if (NoCaseCompare(*itr, "DirectOverhangs") == 0)
{
m_FinishGens.push_back(new cStructGenDirectOverhangs(Seed));
}
else if (NoCaseCompare(*itr, "DistortedMembraneOverhangs") == 0)
{
m_FinishGens.push_back(new cStructGenDistortedMembraneOverhangs(Seed));
}
else if (NoCaseCompare(*itr, "DualRidgeCaves") == 0)
{
float Threshold = (float)a_IniFile.GetValueSetF("Generator", "DualRidgeCavesThreshold", 0.3);
m_FinishGens.push_back(new cStructGenDualRidgeCaves(Seed, Threshold));
}
else if (NoCaseCompare(*itr, "Ice") == 0)
{
m_FinishGens.push_back(new cFinishGenIce);
}
else if (NoCaseCompare(*itr, "LavaLakes") == 0)
{
int Probability = a_IniFile.GetValueSetI("Generator", "LavaLakesProbability", 10);
m_FinishGens.push_back(new cStructGenLakes(Seed * 5 + 16873, E_BLOCK_STATIONARY_LAVA, *m_HeightGen, Probability));
}
else if (NoCaseCompare(*itr, "LavaSprings") == 0)
{
m_FinishGens.push_back(new cFinishGenFluidSprings(Seed, E_BLOCK_LAVA, a_IniFile, Dimension));
}
else if (NoCaseCompare(*itr, "MarbleCaves") == 0)
{
m_FinishGens.push_back(new cStructGenMarbleCaves(Seed));
}
else if (NoCaseCompare(*itr, "MineShafts") == 0)
{
int GridSize = a_IniFile.GetValueSetI("Generator", "MineShaftsGridSize", 512);
int MaxSystemSize = a_IniFile.GetValueSetI("Generator", "MineShaftsMaxSystemSize", 160);
int ChanceCorridor = a_IniFile.GetValueSetI("Generator", "MineShaftsChanceCorridor", 600);
int ChanceCrossing = a_IniFile.GetValueSetI("Generator", "MineShaftsChanceCrossing", 200);
int ChanceStaircase = a_IniFile.GetValueSetI("Generator", "MineShaftsChanceStaircase", 200);
m_FinishGens.push_back(new cStructGenMineShafts(
Seed, GridSize, MaxSystemSize,
ChanceCorridor, ChanceCrossing, ChanceStaircase
));
}
else if (NoCaseCompare(*itr, "Lilypads") == 0)
{
m_FinishGens.push_back(new cFinishGenSingleBiomeSingleTopBlock(Seed, E_BLOCK_LILY_PAD, biSwampland, 4, E_BLOCK_WATER, E_BLOCK_STATIONARY_WATER));
@ -400,10 +360,18 @@ void cComposableGenerator::InitFinishGens(cIniFile & a_IniFile)
{
m_FinishGens.push_back(new cFinishGenNetherClumpFoliage(Seed));
}
else if (NoCaseCompare(*itr, "OreNests") == 0)
{
m_FinishGens.push_back(new cStructGenOreNests(Seed));
}
else if (NoCaseCompare(*itr, "PreSimulator") == 0)
{
m_FinishGens.push_back(new cFinishGenPreSimulator);
}
else if (NoCaseCompare(*itr, "Ravines") == 0)
{
m_FinishGens.push_back(new cStructGenRavines(Seed, 128));
}
else if (NoCaseCompare(*itr, "Snow") == 0)
{
m_FinishGens.push_back(new cFinishGenSnow);
@ -412,10 +380,27 @@ void cComposableGenerator::InitFinishGens(cIniFile & a_IniFile)
{
m_FinishGens.push_back(new cFinishGenSprinkleFoliage(Seed));
}
else if (NoCaseCompare(*itr, "Trees") == 0)
{
m_FinishGens.push_back(new cStructGenTrees(Seed, m_BiomeGen, m_HeightGen, m_CompositionGen));
}
else if (NoCaseCompare(*itr, "WaterLakes") == 0)
{
int Probability = a_IniFile.GetValueSetI("Generator", "WaterLakesProbability", 25);
m_FinishGens.push_back(new cStructGenLakes(Seed * 3 + 652, E_BLOCK_STATIONARY_WATER, *m_HeightGen, Probability));
}
else if (NoCaseCompare(*itr, "WaterSprings") == 0)
{
m_FinishGens.push_back(new cFinishGenFluidSprings(Seed, E_BLOCK_WATER, a_IniFile, Dimension));
}
else if (NoCaseCompare(*itr, "WormNestCaves") == 0)
{
m_FinishGens.push_back(new cStructGenWormNestCaves(Seed));
}
else
{
LOGWARNING("Unknown Finisher in the [Generator] section: \"%s\". Ignoring.", itr->c_str());
}
} // for itr - Str[]
}

View File

@ -43,16 +43,16 @@ class cBiomeGen
public:
virtual ~cBiomeGen() {} // Force a virtual destructor in descendants
/// Generates biomes for the given chunk
/** Generates biomes for the given chunk */
virtual void GenBiomes(int a_ChunkX, int a_ChunkZ, cChunkDef::BiomeMap & a_BiomeMap) = 0;
/// Reads parameters from the ini file, prepares generator for use.
/** Reads parameters from the ini file, prepares generator for use. */
virtual void InitializeBiomeGen(cIniFile & a_IniFile) {}
/// Creates the correct BiomeGen descendant based on the ini file settings and the seed provided.
/// a_CacheOffByDefault gets set to whether the cache should be disabled by default
/// Used in BiomeVisualiser, too.
/// Implemented in BioGen.cpp!
/** Creates the correct BiomeGen descendant based on the ini file settings and the seed provided.
a_CacheOffByDefault gets set to whether the cache should be disabled by default.
Used in BiomeVisualiser, too.
Implemented in BioGen.cpp! */
static cBiomeGen * CreateBiomeGen(cIniFile & a_IniFile, int a_Seed, bool & a_CacheOffByDefault);
} ;
@ -72,10 +72,10 @@ class cTerrainHeightGen
public:
virtual ~cTerrainHeightGen() {} // Force a virtual destructor in descendants
/// Generates heightmap for the given chunk
/** Generates heightmap for the given chunk */
virtual void GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMap & a_HeightMap) = 0;
/// Reads parameters from the ini file, prepares generator for use.
/** Reads parameters from the ini file, prepares generator for use. */
virtual void InitializeHeightGen(cIniFile & a_IniFile) {}
/** Creates the correct TerrainHeightGen descendant based on the ini file settings and the seed provided.
@ -102,7 +102,7 @@ public:
virtual void ComposeTerrain(cChunkDesc & a_ChunkDesc) = 0;
/// Reads parameters from the ini file, prepares generator for use.
/** Reads parameters from the ini file, prepares generator for use. */
virtual void InitializeCompoGen(cIniFile & a_IniFile) {}
/** Creates the correct TerrainCompositionGen descendant based on the ini file settings and the seed provided.
@ -116,28 +116,12 @@ public:
/** The interface that a structure generator must implement
Structures are generated after the terrain composition took place. It should modify the blocktype data to account
for whatever structures the generator is generating.
Note that ores are considered structures too, at least from the interface point of view.
Also note that a worldgenerator may contain multiple structure generators, one for each type of structure
*/
class cStructureGen
{
public:
virtual ~cStructureGen() {} // Force a virtual destructor in descendants
virtual void GenStructures(cChunkDesc & a_ChunkDesc) = 0;
} ;
typedef std::list<cStructureGen *> cStructureGenList;
/** The interface that a finisher must implement
Finisher implements small additions after all structures have been generated.
Finisher implements changes to the chunk after the rough terrain has been generated.
Examples of finishers are trees, snow, ore, lilypads and others.
Note that a worldgenerator may contain multiple finishers.
Also note that previously we used to distinguish between a structuregen and a finisher; this distinction is
no longer relevant, all structure generators are considered finishers now (#398)
*/
class cFinishGen
{
@ -171,7 +155,6 @@ protected:
cBiomeGen * m_BiomeGen;
cTerrainHeightGen * m_HeightGen;
cTerrainCompositionGen * m_CompositionGen;
cStructureGenList m_StructureGens;
cFinishGenList m_FinishGens;
// Generators underlying the caches:
@ -180,19 +163,16 @@ protected:
cTerrainCompositionGen * m_UnderlyingCompositionGen;
/// Reads the biome gen settings from the ini and initializes m_BiomeGen accordingly
/** Reads the biome gen settings from the ini and initializes m_BiomeGen accordingly */
void InitBiomeGen(cIniFile & a_IniFile);
/// Reads the HeightGen settings from the ini and initializes m_HeightGen accordingly
/** Reads the HeightGen settings from the ini and initializes m_HeightGen accordingly */
void InitHeightGen(cIniFile & a_IniFile);
/// Reads the CompositionGen settings from the ini and initializes m_CompositionGen accordingly
/** Reads the CompositionGen settings from the ini and initializes m_CompositionGen accordingly */
void InitCompositionGen(cIniFile & a_IniFile);
/// Reads the structures to generate from the ini and initializes m_StructureGens accordingly
void InitStructureGens(cIniFile & a_IniFile);
/// Reads the finishers from the ini and initializes m_FinishGens accordingly
/** Reads the finishers from the ini and initializes m_FinishGens accordingly */
void InitFinishGens(cIniFile & a_IniFile);
} ;

View File

@ -88,7 +88,7 @@ void cFinishGenNetherClumpFoliage::GenFinish(cChunkDesc & a_ChunkDesc)
{
continue;
}
if (!g_BlockIsSolid[a_ChunkDesc.GetBlockType(PosX, y - 1, PosZ)]) // Only place on solid blocks
if (!cBlockInfo::IsSolid(a_ChunkDesc.GetBlockType(PosX, y - 1, PosZ))) // Only place on solid blocks
{
continue;
}
@ -131,7 +131,7 @@ void cFinishGenNetherClumpFoliage::TryPlaceClump(cChunkDesc & a_ChunkDesc, int a
}
BLOCKTYPE BlockBelow = a_ChunkDesc.GetBlockType(x, y - 1, z);
if (!g_BlockIsSolid[BlockBelow]) // Only place on solid blocks
if (!cBlockInfo::IsSolid(BlockBelow)) // Only place on solid blocks
{
continue;
}
@ -329,7 +329,7 @@ void cFinishGenSnow::GenFinish(cChunkDesc & a_ChunkDesc)
case biFrozenOcean:
{
int Height = a_ChunkDesc.GetHeight(x, z);
if (g_BlockIsSnowable[a_ChunkDesc.GetBlockType(x, Height, z)])
if (cBlockInfo::IsSnowable(a_ChunkDesc.GetBlockType(x, Height, z)))
{
a_ChunkDesc.SetBlockType(x, Height + 1, z, E_BLOCK_SNOW);
a_ChunkDesc.SetHeight(x, z, Height + 1);

View File

@ -1407,7 +1407,7 @@ void cStructGenMineShafts::GetMineShaftSystemsForChunk(
void cStructGenMineShafts::GenStructures(cChunkDesc & a_ChunkDesc)
void cStructGenMineShafts::GenFinish(cChunkDesc & a_ChunkDesc)
{
int ChunkX = a_ChunkDesc.GetChunkX();
int ChunkZ = a_ChunkDesc.GetChunkZ();

View File

@ -17,7 +17,7 @@
class cStructGenMineShafts :
public cStructureGen
public cFinishGen
{
public:
cStructGenMineShafts(
@ -52,8 +52,8 @@ protected:
*/
void GetMineShaftSystemsForChunk(int a_ChunkX, int a_ChunkZ, cMineShaftSystems & a_MineShaftSystems);
// cStructureGen overrides:
virtual void GenStructures(cChunkDesc & a_ChunkDesc) override;
// cFinishGen overrides:
virtual void GenFinish(cChunkDesc & a_ChunkDesc) override;
} ;

View File

@ -117,7 +117,7 @@ void cStructGenRavines::ClearCache(void)
void cStructGenRavines::GenStructures(cChunkDesc & a_ChunkDesc)
void cStructGenRavines::GenFinish(cChunkDesc & a_ChunkDesc)
{
int ChunkX = a_ChunkDesc.GetChunkX();
int ChunkZ = a_ChunkDesc.GetChunkZ();

View File

@ -17,7 +17,7 @@
class cStructGenRavines :
public cStructureGen
public cFinishGen
{
public:
cStructGenRavines(int a_Seed, int a_Size);
@ -37,8 +37,8 @@ protected:
/// Returns all ravines that *may* intersect the given chunk. All the ravines are valid until the next call to this function.
void GetRavinesForChunk(int a_ChunkX, int a_ChunkZ, cRavines & a_Ravines);
// cStructureGen override:
virtual void GenStructures(cChunkDesc & a_ChunkDesc) override;
// cFinishGen override:
virtual void GenFinish(cChunkDesc & a_ChunkDesc) override;
} ;

View File

@ -54,7 +54,7 @@ const int NEST_SIZE_GRAVEL = 32;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// cStructGenTrees:
void cStructGenTrees::GenStructures(cChunkDesc & a_ChunkDesc)
void cStructGenTrees::GenFinish(cChunkDesc & a_ChunkDesc)
{
int ChunkX = a_ChunkDesc.GetChunkX();
int ChunkZ = a_ChunkDesc.GetChunkZ();
@ -306,7 +306,7 @@ int cStructGenTrees::GetNumTrees(
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// cStructGenOreNests:
void cStructGenOreNests::GenStructures(cChunkDesc & a_ChunkDesc)
void cStructGenOreNests::GenFinish(cChunkDesc & a_ChunkDesc)
{
int ChunkX = a_ChunkDesc.GetChunkX();
int ChunkZ = a_ChunkDesc.GetChunkZ();
@ -413,7 +413,7 @@ void cStructGenOreNests::GenerateOre(int a_ChunkX, int a_ChunkZ, BLOCKTYPE a_Ore
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// cStructGenLakes:
void cStructGenLakes::GenStructures(cChunkDesc & a_ChunkDesc)
void cStructGenLakes::GenFinish(cChunkDesc & a_ChunkDesc)
{
int ChunkX = a_ChunkDesc.GetChunkX();
int ChunkZ = a_ChunkDesc.GetChunkZ();
@ -545,7 +545,7 @@ cStructGenDirectOverhangs::cStructGenDirectOverhangs(int a_Seed) :
void cStructGenDirectOverhangs::GenStructures(cChunkDesc & a_ChunkDesc)
void cStructGenDirectOverhangs::GenFinish(cChunkDesc & a_ChunkDesc)
{
// If there is no column of the wanted biome, bail out:
if (!HasWantedBiome(a_ChunkDesc))
@ -665,7 +665,7 @@ cStructGenDistortedMembraneOverhangs::cStructGenDistortedMembraneOverhangs(int a
void cStructGenDistortedMembraneOverhangs::GenStructures(cChunkDesc & a_ChunkDesc)
void cStructGenDistortedMembraneOverhangs::GenFinish(cChunkDesc & a_ChunkDesc)
{
const NOISE_DATATYPE Frequency = (NOISE_DATATYPE)16;
const NOISE_DATATYPE Amount = (NOISE_DATATYPE)1;

View File

@ -21,7 +21,7 @@
class cStructGenTrees :
public cStructureGen
public cFinishGen
{
public:
cStructGenTrees(int a_Seed, cBiomeGen * a_BiomeGen, cTerrainHeightGen * a_HeightGen, cTerrainCompositionGen * a_CompositionGen) :
@ -64,8 +64,8 @@ protected:
const cChunkDef::BiomeMap & a_Biomes
);
// cStructureGen override:
virtual void GenStructures(cChunkDesc & a_ChunkDesc) override;
// cFinishGen override:
virtual void GenFinish(cChunkDesc & a_ChunkDesc) override;
} ;
@ -73,7 +73,7 @@ protected:
class cStructGenOreNests :
public cStructureGen
public cFinishGen
{
public:
cStructGenOreNests(int a_Seed) : m_Noise(a_Seed), m_Seed(a_Seed) {}
@ -82,8 +82,8 @@ protected:
cNoise m_Noise;
int m_Seed;
// cStructureGen override:
virtual void GenStructures(cChunkDesc & a_ChunkDesc) override;
// cFinishGen override:
virtual void GenFinish(cChunkDesc & a_ChunkDesc) override;
void GenerateOre(int a_ChunkX, int a_ChunkZ, BLOCKTYPE a_OreType, int a_MaxHeight, int a_NumNests, int a_NestSize, cChunkDef::BlockTypes & a_BlockTypes, int a_Seq);
} ;
@ -93,7 +93,7 @@ protected:
class cStructGenLakes :
public cStructureGen
public cFinishGen
{
public:
cStructGenLakes(int a_Seed, BLOCKTYPE a_Fluid, cTerrainHeightGen & a_HeiGen, int a_Probability) :
@ -112,8 +112,8 @@ protected:
cTerrainHeightGen & m_HeiGen;
int m_Probability; ///< Chance, 0 .. 100, of a chunk having the lake
// cStructureGen override:
virtual void GenStructures(cChunkDesc & a_ChunkDesc) override;
// cFinishGen override:
virtual void GenFinish(cChunkDesc & a_ChunkDesc) override;
/// Creates a lake image for the specified chunk into a_Lake
void CreateLakeImage(int a_ChunkX, int a_ChunkZ, cBlockArea & a_Lake);
@ -125,7 +125,7 @@ protected:
class cStructGenDirectOverhangs :
public cStructureGen
public cFinishGen
{
public:
cStructGenDirectOverhangs(int a_Seed);
@ -134,8 +134,8 @@ protected:
cNoise m_Noise1;
cNoise m_Noise2;
// cStructureGen override:
virtual void GenStructures(cChunkDesc & a_ChunkDesc) override;
// cFinishGen override:
virtual void GenFinish(cChunkDesc & a_ChunkDesc) override;
bool HasWantedBiome(cChunkDesc & a_ChunkDesc) const;
} ;
@ -145,7 +145,7 @@ protected:
class cStructGenDistortedMembraneOverhangs :
public cStructureGen
public cFinishGen
{
public:
cStructGenDistortedMembraneOverhangs(int a_Seed);
@ -156,8 +156,8 @@ protected:
cNoise m_NoiseZ;
cNoise m_NoiseH;
// cStructureGen override:
virtual void GenStructures(cChunkDesc & a_ChunkDesc) override;
// cFinishGen override:
virtual void GenFinish(cChunkDesc & a_ChunkDesc) override;
} ;

View File

@ -250,6 +250,7 @@ T Clamp(T a_Value, T a_Min, T a_Max)
#include "ChunkDef.h"
#include "BiomeDef.h"
#include "BlockID.h"
#include "BlockInfo.h"
#include "Entities/Effects.h"

View File

@ -46,6 +46,7 @@ cGroupManager::cGroupManager()
LOGD("-- Loading Groups --");
LoadGroups();
CheckUsers();
LOGD("-- Groups Successfully Loaded --");
}
@ -54,6 +55,53 @@ cGroupManager::cGroupManager()
void cGroupManager::GenerateDefaultUsersIni(cIniFile & a_IniFile)
{
LOGWARN("Regenerating users.ini, all users will be reset");
a_IniFile.AddHeaderComment(" This file stores the players' groups.");
a_IniFile.AddHeaderComment(" The format is:");
a_IniFile.AddHeaderComment(" [PlayerName]");
a_IniFile.AddHeaderComment(" Groups = GroupName1, GroupName2, ...");
a_IniFile.WriteFile("users.ini");
}
void cGroupManager::CheckUsers(void)
{
cIniFile IniFile;
if (!IniFile.ReadFile("users.ini"))
{
GenerateDefaultUsersIni(IniFile);
return;
}
unsigned int NumKeys = IniFile.GetNumKeys();
for (size_t i = 0; i < NumKeys; i++)
{
AString Player = IniFile.GetKeyName( i );
AString Groups = IniFile.GetValue(Player, "Groups", "");
if (!Groups.empty())
{
AStringVector Split = StringSplit( Groups, "," );
for( unsigned int i = 0; i < Split.size(); i++ )
{
if (!ExistsGroup(Split[i]))
{
LOGWARNING("The group %s for player %s was not found!", Split[i].c_str(), Player.c_str());
}
}
}
}
}
void cGroupManager::LoadGroups()
{
cIniFile IniFile;
@ -137,6 +185,16 @@ void cGroupManager::LoadGroups()
bool cGroupManager::ExistsGroup( const AString & a_Name )
{
GroupMap::iterator itr = m_pState->Groups.find( a_Name );
return ( itr != m_pState->Groups.end() );
}
cGroup* cGroupManager::GetGroup( const AString & a_Name )
{
GroupMap::iterator itr = m_pState->Groups.find( a_Name );

View File

@ -14,8 +14,13 @@ class cGroup;
class cGroupManager
{
public:
bool ExistsGroup(const AString & a_Name);
cGroup * GetGroup(const AString & a_Name);
void LoadGroups(void);
void CheckUsers(void);
/** Writes the default header to the specified ini file, and saves it as "users.ini". */
static void GenerateDefaultUsersIni(cIniFile & a_IniFile);
private:
friend class cRoot;

View File

@ -29,6 +29,8 @@ class cDebugCallbacks :
{
virtual void OnRequestBegun(cHTTPConnection & a_Connection, cHTTPRequest & a_Request) override
{
UNUSED(a_Connection);
if (cHTTPFormParser::HasFormData(a_Request))
{
a_Request.SetUserData(new cHTTPFormParser(a_Request, *this));
@ -38,6 +40,8 @@ class cDebugCallbacks :
virtual void OnRequestBody(cHTTPConnection & a_Connection, cHTTPRequest & a_Request, const char * a_Data, int a_Size) override
{
UNUSED(a_Connection);
cHTTPFormParser * FormParser = (cHTTPFormParser *)(a_Request.GetUserData());
if (FormParser != NULL)
{

View File

@ -204,6 +204,12 @@ void cInventory::SetSlot(int a_SlotNum, const cItem & a_Item)
return;
}
Grid->SetSlot(GridSlotNum, a_Item);
// Broadcast the Equipped Item, if the Slot is changed.
if ((Grid == &m_HotbarSlots) && (m_EquippedSlotNum == (a_SlotNum - invHotbarOffset)))
{
m_Owner.GetWorld()->BroadcastEntityEquipment(m_Owner, 0, a_Item, m_Owner.GetClientHandle());
}
}

View File

@ -36,10 +36,10 @@ public:
// The map center is fixed at the central point of the 8x8 block of chunks you are standing in when you right-click it.
const int RegionWidth = cChunkDef::Width * 8 * pow(2.0, (double) DEFAULT_SCALE);
const int RegionWidth = cChunkDef::Width * 8;
int CenterX = floor(a_Player->GetPosX() / (float) RegionWidth) * RegionWidth;
int CenterZ = floor(a_Player->GetPosZ() / (float) RegionWidth) * RegionWidth;
int CenterX = (int)(floor(a_Player->GetPosX() / (float) RegionWidth) * RegionWidth);
int CenterZ = (int)(floor(a_Player->GetPosZ() / (float) RegionWidth) * RegionWidth);
cMap * NewMap = a_World->GetMapManager().CreateMap(CenterX, CenterZ, DEFAULT_SCALE);

View File

@ -248,6 +248,14 @@ cItemHandler::cItemHandler(int a_ItemType)
bool cItemHandler::OnItemUse(cWorld * a_World, cPlayer * a_Player, const cItem & a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_Dir)
{
UNUSED(a_World);
UNUSED(a_Player);
UNUSED(a_Item);
UNUSED(a_BlockX);
UNUSED(a_BlockY);
UNUSED(a_BlockZ);
UNUSED(a_Dir);
return false;
}
@ -257,6 +265,14 @@ bool cItemHandler::OnItemUse(cWorld * a_World, cPlayer * a_Player, const cItem &
bool cItemHandler::OnDiggingBlock(cWorld * a_World, cPlayer * a_Player, const cItem & a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_Dir)
{
UNUSED(a_World);
UNUSED(a_Player);
UNUSED(a_Item);
UNUSED(a_BlockX);
UNUSED(a_BlockY);
UNUSED(a_BlockZ);
UNUSED(a_Dir);
return false;
}
@ -266,8 +282,10 @@ bool cItemHandler::OnDiggingBlock(cWorld * a_World, cPlayer * a_Player, const cI
void cItemHandler::OnBlockDestroyed(cWorld * a_World, cPlayer * a_Player, const cItem & a_Item, int a_BlockX, int a_BlockY, int a_BlockZ)
{
UNUSED(a_Item);
BLOCKTYPE Block = a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ);
cBlockHandler * Handler = cBlockHandler::GetBlockHandler(Block);
cBlockHandler * Handler = cBlockInfo::GetHandler(Block);
if (a_Player->IsGameModeSurvival())
{
@ -288,7 +306,9 @@ void cItemHandler::OnBlockDestroyed(cWorld * a_World, cPlayer * a_Player, const
void cItemHandler::OnFoodEaten(cWorld * a_World, cPlayer * a_Player, cItem * a_Item)
{
UNUSED(a_World);
UNUSED(a_Player);
UNUSED(a_Item);
}
@ -461,6 +481,8 @@ bool cItemHandler::IsPlaceable(void)
bool cItemHandler::CanHarvestBlock(BLOCKTYPE a_BlockType)
{
UNUSED(a_BlockType);
return false;
}
@ -499,6 +521,8 @@ bool cItemHandler::GetPlacementBlockTypeMeta(
bool cItemHandler::EatItem(cPlayer * a_Player, cItem * a_Item)
{
UNUSED(a_Item);
FoodInfo Info = GetFoodInfo();
if ((Info.FoodLevel > 0) || (Info.Saturation > 0.f))

View File

@ -19,17 +19,13 @@ public:
{
switch(m_ItemType)
{
case E_ITEM_WOODEN_PICKAXE:
case E_ITEM_GOLD_PICKAXE:
return 1;
case E_ITEM_STONE_PICKAXE:
return 2;
case E_ITEM_IRON_PICKAXE:
return 3;
case E_ITEM_DIAMOND_PICKAXE:
return 4;
default:
return 0;
case E_ITEM_WOODEN_PICKAXE: return 1;
case E_ITEM_GOLD_PICKAXE: return 1;
case E_ITEM_STONE_PICKAXE: return 2;
case E_ITEM_IRON_PICKAXE: return 3;
case E_ITEM_DIAMOND_PICKAXE: return 4;
default: return 0;
}
}
@ -61,6 +57,10 @@ public:
return PickaxeLevel() >= 2;
}
case E_BLOCK_ANVIL:
case E_BLOCK_ENCHANTMENT_TABLE:
case E_BLOCK_FURNACE:
case E_BLOCK_LIT_FURNACE:
case E_BLOCK_COAL_ORE:
case E_BLOCK_STONE:
case E_BLOCK_COBBLESTONE:

View File

@ -27,7 +27,7 @@ public:
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
) override
{
if (!g_BlockFullyOccupiesVoxel[a_World->GetBlock(a_BlockX, a_BlockY - 1, a_BlockZ)]) // Some solid blocks, such as cocoa beans, are not suitable for dust
if (!cBlockInfo::FullyOccupiesVoxel(a_World->GetBlock(a_BlockX, a_BlockY - 1, a_BlockZ))) // Some solid blocks, such as cocoa beans, are not suitable for dust
{
return false;
}

View File

@ -391,7 +391,7 @@ void cLightingThread::PrepareBlockLight(void)
int idx = BaseZ + x;
for (int y = m_HeightMap[idx], Index = idx + y * BlocksPerYLayer; y >= 0; y--, Index -= BlocksPerYLayer)
{
if (g_BlockLightValue[m_BlockTypes[Index]] == 0)
if (cBlockInfo::GetLightValue(m_BlockTypes[Index]) == 0)
{
continue;
}
@ -401,7 +401,7 @@ void cLightingThread::PrepareBlockLight(void)
m_SeedIdx1[m_NumSeeds++] = Index;
// Light it up:
m_BlockLight[Index] = g_BlockLightValue[m_BlockTypes[Index]];
m_BlockLight[Index] = cBlockInfo::GetLightValue(m_BlockTypes[Index]);
}
}
}

View File

@ -169,13 +169,13 @@ protected:
ASSERT(a_DstIdx >= 0);
ASSERT(a_DstIdx < (int)ARRAYCOUNT(m_BlockTypes));
if (a_Light[a_SrcIdx] <= a_Light[a_DstIdx] + g_BlockSpreadLightFalloff[m_BlockTypes[a_DstIdx]])
if (a_Light[a_SrcIdx] <= a_Light[a_DstIdx] + cBlockInfo::GetSpreadLightFalloff(m_BlockTypes[a_DstIdx]))
{
// We're not offering more light than the dest block already has
return;
}
a_Light[a_DstIdx] = a_Light[a_SrcIdx] - g_BlockSpreadLightFalloff[m_BlockTypes[a_DstIdx]];
a_Light[a_DstIdx] = a_Light[a_SrcIdx] - cBlockInfo::GetSpreadLightFalloff(m_BlockTypes[a_DstIdx]);
if (!a_IsSeedOut[a_DstIdx])
{
a_IsSeedOut[a_DstIdx] = true;

View File

@ -42,7 +42,7 @@ cLog::~cLog()
cLog* cLog::GetInstance()
cLog * cLog::GetInstance()
{
if (s_Log != NULL)
{
@ -92,7 +92,7 @@ void cLog::ClearLog()
if( m_File )
fclose (m_File);
#endif
m_File = 0;
m_File = NULL;
}

View File

@ -357,6 +357,8 @@ void cMap::AddPlayer(cPlayer * a_Player, Int64 a_WorldAge)
MapClient.m_LastUpdate = a_WorldAge;
MapClient.m_SendInfo = true;
MapClient.m_Handle = Handle;
MapClient.m_DataUpdate = 0;
MapClient.m_NextDecoratorUpdate = 0;
m_Clients.push_back(MapClient);

View File

@ -145,7 +145,7 @@ bool cMobSpawner::CanSpawnHere(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_R
case cMonster::mtBat:
{
return (a_RelY <= 63) && (BlockLight <= 4) && (SkyLight <= 4) && (TargetBlock == E_BLOCK_AIR) && (!g_BlockTransparent[BlockAbove]);
return (a_RelY <= 63) && (BlockLight <= 4) && (SkyLight <= 4) && (TargetBlock == E_BLOCK_AIR) && !cBlockInfo::IsTransparent(BlockAbove);
}
case cMonster::mtChicken:
@ -157,7 +157,7 @@ bool cMobSpawner::CanSpawnHere(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_R
return (
(TargetBlock == E_BLOCK_AIR) &&
(BlockAbove == E_BLOCK_AIR) &&
(!g_BlockTransparent[BlockBelow]) &&
(!cBlockInfo::IsTransparent(BlockBelow)) &&
(BlockBelow == E_BLOCK_GRASS) &&
(SkyLight >= 9)
);
@ -188,7 +188,7 @@ bool cMobSpawner::CanSpawnHere(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_R
(TargetBlock == E_BLOCK_AIR) &&
(BlockAbove == E_BLOCK_AIR) &&
(BlockTop == E_BLOCK_AIR) &&
(!g_BlockTransparent[BlockBelow]) &&
(!cBlockInfo::IsTransparent(BlockBelow)) &&
(SkyLight <= 7) &&
(BlockLight <= 7)
);
@ -215,7 +215,7 @@ bool cMobSpawner::CanSpawnHere(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_R
HaveFloor ||
(
a_Chunk->UnboundedRelGetBlockType(a_RelX + x, a_RelY - 1, a_RelZ + z, TargetBlock) &&
!g_BlockTransparent[TargetBlock]
!cBlockInfo::IsTransparent(TargetBlock)
)
);
}
@ -230,7 +230,7 @@ bool cMobSpawner::CanSpawnHere(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_R
return (
(TargetBlock == E_BLOCK_AIR) &&
(BlockAbove == E_BLOCK_AIR) &&
(!g_BlockTransparent[BlockBelow]) &&
(!cBlockInfo::IsTransparent(BlockBelow)) &&
(SkyLight <= 7) &&
(BlockLight <= 7) &&
(m_Random.NextInt(2, a_Biome) == 0)
@ -242,7 +242,7 @@ bool cMobSpawner::CanSpawnHere(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_R
return (
(TargetBlock == E_BLOCK_AIR) &&
(BlockAbove == E_BLOCK_AIR) &&
(!g_BlockTransparent[BlockBelow]) &&
(!cBlockInfo::IsTransparent(BlockBelow)) &&
(
(a_RelY <= 40) || (a_Biome == biSwampland)
)
@ -255,7 +255,7 @@ bool cMobSpawner::CanSpawnHere(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_R
return (
(TargetBlock == E_BLOCK_AIR) &&
(BlockAbove == E_BLOCK_AIR) &&
(!g_BlockTransparent[BlockBelow]) &&
(!cBlockInfo::IsTransparent(BlockBelow)) &&
(m_Random.NextInt(20, a_Biome) == 0)
);
}

View File

@ -4,6 +4,7 @@
#include "Creeper.h"
#include "../World.h"
#include "../Entities/ProjectileEntity.h"
#include "../Entities/Player.h"
@ -13,6 +14,7 @@ cCreeper::cCreeper(void) :
super("Creeper", mtCreeper, "mob.creeper.say", "mob.creeper.say", 0.6, 1.8),
m_bIsBlowing(false),
m_bIsCharged(false),
m_BurnedWithFlintAndSteel(false),
m_ExplodingTimer(0)
{
}
@ -25,12 +27,25 @@ void cCreeper::Tick(float a_Dt, cChunk & a_Chunk)
{
super::Tick(a_Dt, a_Chunk);
if (!ReachedFinalDestination())
if (!ReachedFinalDestination() && !m_BurnedWithFlintAndSteel)
{
m_ExplodingTimer = 0;
m_bIsBlowing = false;
m_World->BroadcastEntityMetadata(*this);
}
else
{
if (m_bIsBlowing)
{
m_ExplodingTimer += 1;
}
if (m_ExplodingTimer == 30)
{
m_World->DoExplosionAt((m_bIsCharged ? 5 : 3), GetPosX(), GetPosY(), GetPosZ(), false, esMonster, this);
Destroy();
}
}
}
@ -80,22 +95,30 @@ void cCreeper::Attack(float a_Dt)
{
UNUSED(a_Dt);
m_ExplodingTimer += 1;
if (!m_bIsBlowing)
{
m_World->BroadcastSoundEffect("game.tnt.primed", (int)GetPosX() * 8, (int)GetPosY() * 8, (int)GetPosZ() * 8, 1.f, (float)(0.75 + ((float)((GetUniqueID() * 23) % 32)) / 64));
m_bIsBlowing = true;
m_World->BroadcastEntityMetadata(*this);
}
if (m_ExplodingTimer == 20)
{
m_World->DoExplosionAt((m_bIsCharged ? 5 : 3), GetPosX(), GetPosY(), GetPosZ(), false, esMonster, this);
Destroy();
}
}
void cCreeper::OnRightClicked(cPlayer & a_Player)
{
if ((a_Player.GetEquippedItem().m_ItemType == E_ITEM_FLINT_AND_STEEL))
{
if (!a_Player.IsGameModeCreative())
{
a_Player.UseEquippedItem();
}
m_World->BroadcastSoundEffect("game.tnt.primed", (int)GetPosX() * 8, (int)GetPosY() * 8, (int)GetPosZ() * 8, 1.f, (float)(0.75 + ((float)((GetUniqueID() * 23) % 32)) / 64));
m_bIsBlowing = true;
m_World->BroadcastEntityMetadata(*this);
m_BurnedWithFlintAndSteel = true;
}
}

Some files were not shown because too many files have changed in this diff Show More