1
0
Fork 0

Merge branch 'master' of github.com:mc-server/MCServer

This commit is contained in:
Alexander Harkness 2013-08-07 18:37:03 +01:00
commit be7a6d7a66
36 changed files with 3312 additions and 1586 deletions

8
MCServer/.gitignore vendored
View File

@ -1,11 +1,8 @@
*.exe
ChunkWorx.ini
ChunkWorxSave.ini
*.ini
MCServer
banned.ini
logs
players
whitelist.ini
world*
API.txt
*.dat
@ -15,9 +12,6 @@ schematics
*.pdb
memdump.xml
*.grab
ProtectionAreas.ini
ProtectionAreas.sqlite
helgrind.log
settings.ini
webadmin.ini
motd.txt

View File

@ -23,17 +23,18 @@ function Initialize(Plugin)
PluginManager:AddHook(Plugin, cPluginManager.HOOK_CHAT);
PluginManager:AddHook(Plugin, cPluginManager.HOOK_PLAYER_RIGHT_CLICKING_ENTITY);
PluginManager:BindCommand("/le", "debuggers", HandleListEntitiesCmd, "Shows a list of all the loaded entities");
PluginManager:BindCommand("/ke", "debuggers", HandleKillEntitiesCmd, "Kills all the loaded entities");
PluginManager:BindCommand("/wool", "debuggers", HandleWoolCmd, "Sets all your armor to blue wool");
PluginManager:BindCommand("/testwnd", "debuggers", HandleTestWndCmd, "Opens up a window using plugin API");
PluginManager:BindCommand("/gc", "debuggers", HandleGCCmd, "Activates the Lua garbage collector");
PluginManager:BindCommand("/fast", "debuggers", HandleFastCmd, "Switches between fast and normal movement speed");
PluginManager:BindCommand("/dash", "debuggers", HandleDashCmd, "Switches between fast and normal sprinting speed");
PluginManager:BindCommand("/hunger", "debuggers", HandleHungerCmd, "Lists the current hunger-related variables");
PluginManager:BindCommand("/poison", "debuggers", HandlePoisonCmd, "Sets food-poisoning for 15 seconds");
PluginManager:BindCommand("/starve", "debuggers", HandleStarveCmd, "Sets the food level to zero");
PluginManager:BindCommand("/fl", "debuggers", HandleFoodLevelCmd, "Sets the food level to the given value");
PluginManager:BindCommand("/le", "debuggers", HandleListEntitiesCmd, "- Shows a list of all the loaded entities");
PluginManager:BindCommand("/ke", "debuggers", HandleKillEntitiesCmd, "- Kills all the loaded entities");
PluginManager:BindCommand("/wool", "debuggers", HandleWoolCmd, "- Sets all your armor to blue wool");
PluginManager:BindCommand("/testwnd", "debuggers", HandleTestWndCmd, "- Opens up a window using plugin API");
PluginManager:BindCommand("/gc", "debuggers", HandleGCCmd, "- Activates the Lua garbage collector");
PluginManager:BindCommand("/fast", "debuggers", HandleFastCmd, "- Switches between fast and normal movement speed");
PluginManager:BindCommand("/dash", "debuggers", HandleDashCmd, "- Switches between fast and normal sprinting speed");
PluginManager:BindCommand("/hunger", "debuggers", HandleHungerCmd, "- Lists the current hunger-related variables");
PluginManager:BindCommand("/poison", "debuggers", HandlePoisonCmd, "- Sets food-poisoning for 15 seconds");
PluginManager:BindCommand("/starve", "debuggers", HandleStarveCmd, "- Sets the food level to zero");
PluginManager:BindCommand("/fl", "debuggers", HandleFoodLevelCmd, "- Sets the food level to the given value");
PluginManager:BindCommand("/spidey", "debuggers", HandleSpideyCmd, "- Shoots a line of web blocks until it hits non-air");
-- Enable the following line for BlockArea / Generator interface testing:
-- PluginManager:AddHook(Plugin, cPluginManager.HOOK_CHUNK_GENERATED);
@ -707,3 +708,34 @@ end
function HandleSpideyCmd(a_Split, a_Player)
-- Place a line of cobwebs from the player's eyes until non-air block, in the line-of-sight of the player
local World = a_Player:GetWorld();
local Callbacks = {
OnNextBlock = function(a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta)
if (a_BlockType ~= E_BLOCK_AIR) then
-- abort the trace
return true;
end
World:SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_COBWEB, 0);
end
};
local EyePos = a_Player:GetEyePosition();
local LookVector = a_Player:GetLookVector();
LookVector:Normalize();
-- Start cca 2 blocks away from the eyes
local Start = EyePos + LookVector + LookVector;
local End = EyePos + LookVector * 50;
cLineBlockTracer.Trace(World, Callbacks, Start.x, Start.y, Start.z, End.x, End.y, End.z);
return true;
end

View File

@ -1,9 +1,9 @@
[Spider]
AttackRange=5.0
AttackRate=1
AttackDamage=1.0
AttackDamage=2.0
SightDistance=25.0
MaxHealth=10
MaxHealth=16
[Chicken]
AttackRange=5.0
@ -50,7 +50,7 @@ MaxHealth=40
[Zombiepigman]
AttackRange=5.0
AttackRate=1
AttackDamage=5.0
AttackDamage=7.0
SightDistance=25.0
MaxHealth=20
@ -85,21 +85,14 @@ MaxHealth=8
[Skeleton]
AttackRange=5.0
AttackRate=1
AttackDamage=4.0
AttackDamage=3.0
SightDistance=25.0
MaxHealth=20
[Slime]
AttackRange=5.0
AttackRate=1
AttackDamage=10.0
SightDistance=25.0
MaxHealth=32
[Spider]
AttackRange=5.0
AttackRate=1
AttackDamage=2.0
AttackDamage=4.0
SightDistance=25.0
MaxHealth=16
@ -108,4 +101,54 @@ AttackRange=5.0
AttackRate=1
AttackDamage=4.0
SightDistance=25.0
MaxHealth=20
MaxHealth=20
[Wolf]
AttackRange=5.0
AttackRate=1
AttackDamage=4.0
SightDistance=25.0
MaxHealth=20
[Blaze]
AttackRange=5.0
AttackRate=1
AttackDamage=6.0
SightDistance=25.0
MaxHealth=20
[Villager]
AttackRange=5.0
AttackRate=1
AttackDamage=0.0
SightDistance=25.0
MaxHealth=20
[Witch]
AttackRange=5.0
AttackRate=1
AttackDamage=0.0
SightDistance=25.0
MaxHealth=26
[Ocelot]
AttackRange=5.0
AttackRate=1
AttackDamage=0.0
SightDistance=25.0
MaxHealth=10
[Mooshroom]
AttackRange=5.0
AttackRate=1
AttackDamage=0.0
SightDistance=25.0
MaxHealth=10
[Magmacube]
AttackRange=5.0
AttackRate=1
AttackDamage=6.0
SightDistance=25.0
MaxHealth=16

View File

@ -4,6 +4,10 @@ function Output(String)
table.insert(SiteContent, String)
end
function GetTableSize(Table)
local Size = 0
for key,value in pairs(Table) do
@ -12,6 +16,10 @@ function GetTableSize(Table)
return Size
end
function GetDefaultPage()
local PM = cRoot:Get():GetPluginManager()
@ -42,11 +50,15 @@ function GetDefaultPage()
return Content, SubTitle
end
function ShowPage(WebAdmin, TemplateRequest)
SiteContent = {}
local BaseURL = WebAdmin:GetBaseURL(TemplateRequest.Request.Path)
local Title = "MCServer"
local MemoryUsage = WebAdmin:GetMemoryUsage()
local MemoryUsage = cWebAdmin:GetMemoryUsage()
local NumChunks = cRoot:Get():GetTotalChunkCount()
local PluginPage = WebAdmin:GetPage(TemplateRequest.Request)
local PageContent = PluginPage.Content
@ -408,6 +420,7 @@ function ShowPage(WebAdmin, TemplateRequest)
<div id="sidebar">
<ul class="sideNav">
]])
local AllPlugins = WebAdmin:GetPlugins()
for key,value in pairs(AllPlugins) do
@ -421,6 +434,7 @@ function ShowPage(WebAdmin, TemplateRequest)
end
end
end
Output([[
</ul>

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<?xml version="1.0" encoding="UTF-8"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9,00"
@ -306,6 +306,10 @@
RelativePath="..\source\BlockID.h"
>
</File>
<File
RelativePath="..\source\BlockTracer.h"
>
</File>
<File
RelativePath="..\source\ByteBuffer.cpp"
>
@ -545,6 +549,14 @@
RelativePath="..\source\LinearUpscale.h"
>
</File>
<File
RelativePath="..\source\LineBlockTracer.cpp"
>
</File>
<File
RelativePath="..\source\LineBlockTracer.h"
>
</File>
<File
RelativePath="..\source\Log.cpp"
>
@ -1485,6 +1497,14 @@
RelativePath="..\source\LuaScript.h"
>
</File>
<File
RelativePath="..\source\LuaState.cpp"
>
</File>
<File
RelativePath="..\source\LuaState.h"
>
</File>
<File
RelativePath="..\source\LuaWindow.cpp"
>
@ -1832,6 +1852,10 @@
RelativePath="..\source\blocks\BlockCactus.h"
>
</File>
<File
RelativePath="..\source\Blocks\BlockCarpet.h"
>
</File>
<File
RelativePath="..\source\Blocks\BlockCauldron.h"
>

File diff suppressed because it is too large Load Diff

View File

@ -30,135 +30,160 @@
class cIniFile // tolua_export
{ // tolua_export
// tolua_begin
class cIniFile
{
private:
bool caseInsensitive;
std::string path;
struct key {
bool m_IsCaseInsensitive;
std::string m_Path;
struct key
{
std::vector<std::string> names;
std::vector<std::string> values;
std::vector<std::string> comments;
};
std::vector<key> keys;
std::vector<std::string> names;
} ;
std::vector<key> keys;
std::vector<std::string> names;
std::vector<std::string> comments;
std::string CheckCase( std::string s) const;
/// If the object is case-insensitive, returns s as lowercase; otherwise returns s as-is
std::string CheckCase(const std::string & s) const;
public:
enum errors{ noID = -1}; // tolua_export
cIniFile( const std::string iniPath = ""); // tolua_export
virtual ~cIniFile() {}
enum errors
{
noID = -1,
};
/// Creates a new instance; sets m_Path to a_Path, but doesn't read the file
cIniFile(const std::string & a_Path = "");
// Sets whether or not keynames and valuenames should be case sensitive.
// The default is case insensitive.
void CaseSensitive() {caseInsensitive = false;} // tolua_export
void CaseInsensitive() {caseInsensitive = true;} // tolua_export
void CaseSensitive (void) { m_IsCaseInsensitive = false; }
void CaseInsensitive(void) { m_IsCaseInsensitive = true; }
// Sets path of ini file to read and write from.
void Path(const std::string & newPath) {path = newPath;} // tolua_export
std::string Path() const {return path;} // tolua_export
void SetPath(const std::string & newPath) {Path( newPath);} // tolua_export
void Path(const std::string & newPath) {m_Path = newPath;}
const std::string & Path(void) const {return m_Path;}
void SetPath(const std::string & newPath) {Path(newPath);}
// Reads ini file specified using path.
// Returns true if successful, false otherwise.
bool ReadFile(); // tolua_export
/** Reads the ini file specified in m_Path
If the file doesn't exist and a_AllowExampleRedirect is true, tries to read <basename>.example.ini, and
writes its contents as <basename>.ini, if successful.
Returns true if successful, false otherwise.
*/
bool ReadFile(bool a_AllowExampleRedirect = true);
// Writes data stored in class to ini file.
bool WriteFile(); // tolua_export
/// Writes data stored in class to ini file specified in m_Path
bool WriteFile(void) const;
// Deletes all stored ini data.
void Erase(); // tolua_export
void Clear() {Erase();} // tolua_export
void Reset() {Erase();} // tolua_export
/// Deletes all stored ini data (but doesn't touch the file)
void Clear(void);
void Reset(void) { Clear(); }
void Erase(void) { Clear(); } // OBSOLETE, this name is misguiding and will be removed from the interface
// Returns index of specified key, or noID if not found.
long FindKey( const std::string & keyname) const; // tolua_export
/// Returns index of specified key, or noID if not found
long FindKey(const std::string & keyname) const;
// Returns index of specified value, in the specified key, or noID if not found.
long FindValue( const unsigned keyID, const std::string & valuename) const; // tolua_export
/// Returns index of specified value, in the specified key, or noID if not found
long FindValue(const unsigned keyID, const std::string & valuename) const;
// Returns number of keys currently in the ini.
unsigned NumKeys() const {return names.size();} // tolua_export
unsigned GetNumKeys() const {return NumKeys();} // tolua_export
/// Returns number of keys currently in the ini
unsigned NumKeys (void) const {return names.size();}
unsigned GetNumKeys(void) const {return NumKeys();}
// Add a key name.
unsigned AddKeyName( const std::string & keyname); // tolua_export
/// Add a key name
unsigned AddKeyName(const std::string & keyname);
// Returns key names by index.
std::string KeyName( const unsigned keyID) const; // tolua_export
std::string GetKeyName( const unsigned keyID) const {return KeyName(keyID);} // tolua_export
std::string KeyName(const unsigned keyID) const;
std::string GetKeyName(const unsigned keyID) const {return KeyName(keyID);}
// Returns number of values stored for specified key.
unsigned NumValues( const std::string & keyname); // tolua_export
unsigned GetNumValues( const std::string & keyname) {return NumValues( keyname);} // tolua_export
unsigned NumValues( const unsigned keyID); // tolua_export
unsigned GetNumValues( const unsigned keyID) {return NumValues( keyID);} // tolua_export
unsigned NumValues (const std::string & keyname);
unsigned GetNumValues(const std::string & keyname) {return NumValues(keyname);}
unsigned NumValues (const unsigned keyID);
unsigned GetNumValues(const unsigned keyID) {return NumValues(keyID);}
// Returns value name by index for a given keyname or keyID.
std::string ValueName( const std::string & keyname, const unsigned valueID) const; // tolua_export
std::string GetValueName( const std::string & keyname, const unsigned valueID) const { // tolua_export
return ValueName( keyname, valueID);
} // tolua_export
std::string ValueName( const unsigned keyID, const unsigned valueID) const; // tolua_export
std::string GetValueName( const unsigned keyID, const unsigned valueID) const { // tolua_export
return ValueName( keyID, valueID);
} // tolua_export
std::string ValueName( const std::string & keyname, const unsigned valueID) const;
std::string GetValueName( const std::string & keyname, const unsigned valueID) const
{
return ValueName(keyname, valueID);
}
std::string ValueName (const unsigned keyID, const unsigned valueID) const;
std::string GetValueName(const unsigned keyID, const unsigned valueID) const
{
return ValueName(keyID, valueID);
}
// Gets value of [keyname] valuename =.
// Overloaded to return string, int, and double.
// Returns defValue if key/value not found.
AString GetValue (const AString & keyname, const AString & valuename, const AString & defValue = "") const; // tolua_export
AString GetValue (const unsigned keyID, const unsigned valueID, const AString & defValue = "") const; // tolua_export
double GetValueF(const AString & keyname, const AString & valuename, const double defValue = 0) const; // tolua_export
int GetValueI(const AString & keyname, const AString & valuename, const int defValue = 0) const; // tolua_export
bool GetValueB(const AString & keyname, const AString & valuename, const bool defValue = false) const { // tolua_export
return ( GetValueI( keyname, valuename, int( defValue)) > 0);
} // tolua_export
AString GetValue (const AString & keyname, const AString & valuename, const AString & defValue = "") const;
AString GetValue (const unsigned keyID, const unsigned valueID, const AString & defValue = "") const;
double GetValueF(const AString & keyname, const AString & valuename, const double defValue = 0) const;
int GetValueI(const AString & keyname, const AString & valuename, const int defValue = 0) const;
bool GetValueB(const AString & keyname, const AString & valuename, const bool defValue = false) const
{
return (GetValueI(keyname, valuename, int(defValue)) > 0);
}
// Gets the value; if not found, write the default to the INI file
AString GetValueSet (const AString & keyname, const AString & valuename, const AString & defValue = ""); // tolua_export
double GetValueSetF(const AString & keyname, const AString & valuename, const double defValue = 0.0); // tolua_export
int GetValueSetI(const AString & keyname, const AString & valuename, const int defValue = 0); // tolua_export
bool GetValueSetB(const AString & keyname, const AString & valuename, const bool defValue = false) { // tolua_export
AString GetValueSet (const AString & keyname, const AString & valuename, const AString & defValue = "");
double GetValueSetF(const AString & keyname, const AString & valuename, const double defValue = 0.0);
int GetValueSetI(const AString & keyname, const AString & valuename, const int defValue = 0);
bool GetValueSetB(const AString & keyname, const AString & valuename, const bool defValue = false)
{
return (GetValueSetI(keyname, valuename, defValue ? 1 : 0) > 0);
} // tolua_export
}
// Sets value of [keyname] valuename =.
// Specify the optional paramter as false (0) if you do not want it to create
// the key if it doesn't exist. Returns true if data entered, false otherwise.
// Overloaded to accept string, int, and double.
bool SetValue( const unsigned keyID, const unsigned valueID, const std::string & value); // tolua_export
bool SetValue( const std::string & keyname, const std::string & valuename, const std::string & value, const bool create = true); // tolua_export
bool SetValueI( const std::string & keyname, const std::string & valuename, const int value, const bool create = true); // tolua_export
bool SetValueB( const std::string & keyname, const std::string & valuename, const bool value, const bool create = true) { // tolua_export
bool SetValue( const unsigned keyID, const unsigned valueID, const std::string & value);
bool SetValue( const std::string & keyname, const std::string & valuename, const std::string & value, const bool create = true);
bool SetValueI( const std::string & keyname, const std::string & valuename, const int value, const bool create = true);
bool SetValueB( const std::string & keyname, const std::string & valuename, const bool value, const bool create = true)
{
return SetValueI( keyname, valuename, int(value), create);
} // tolua_export
bool SetValueF( const std::string & keyname, const std::string & valuename, const double value, const bool create = true); // tolua_export
}
bool SetValueF( const std::string & keyname, const std::string & valuename, const double value, const bool create = true);
// tolua_end
bool SetValueV( const std::string & keyname, const std::string & valuename, char *format, ...);
// tolua_begin
// Deletes specified value.
// Returns true if value existed and deleted, false otherwise.
bool DeleteValueByID( const unsigned keyID, const unsigned valueID ); // tolua_export
bool DeleteValue( const std::string & keyname, const std::string & valuename); // tolua_export
bool DeleteValueByID( const unsigned keyID, const unsigned valueID );
bool DeleteValue( const std::string & keyname, const std::string & valuename);
// Deletes specified key and all values contained within.
// Returns true if key existed and deleted, false otherwise.
bool DeleteKey(const std::string & keyname); // tolua_export
bool DeleteKey(const std::string & keyname);
// Header comment functions.
// Header comments are those comments before the first key.
//
// Number of header comments.
unsigned NumHeaderComments() {return comments.size();} // tolua_export
unsigned NumHeaderComments(void) {return comments.size();}
// Add a header comment.
void HeaderComment( const std::string & comment); // tolua_export
void HeaderComment(const std::string & comment);
// Return a header comment.
std::string HeaderComment( const unsigned commentID) const; // tolua_export
std::string HeaderComment(const unsigned commentID) const;
// Delete a header comment.
bool DeleteHeaderComment( unsigned commentID); // tolua_export
bool DeleteHeaderComment(unsigned commentID);
// Delete all header comments.
void DeleteHeaderComments() {comments.clear();} // tolua_export
void DeleteHeaderComments(void) {comments.clear();}
// Key comment functions.
// Key comments are those comments within a key. Any comments
@ -167,20 +192,26 @@ public:
// the CIniFile::WriteFile() is called.
//
// Number of key comments.
unsigned NumKeyComments( const unsigned keyID) const; // tolua_export
unsigned NumKeyComments( const std::string & keyname) const; // tolua_export
unsigned NumKeyComments( const unsigned keyID) const;
unsigned NumKeyComments( const std::string & keyname) const;
// Add a key comment.
bool KeyComment( const unsigned keyID, const std::string & comment); // tolua_export
bool KeyComment( const std::string & keyname, const std::string & comment); // tolua_export
bool KeyComment(const unsigned keyID, const std::string & comment);
bool KeyComment(const std::string & keyname, const std::string & comment);
// Return a key comment.
std::string KeyComment( const unsigned keyID, const unsigned commentID) const; // tolua_export
std::string KeyComment( const std::string & keyname, const unsigned commentID) const; // tolua_export
std::string KeyComment(const unsigned keyID, const unsigned commentID) const;
std::string KeyComment(const std::string & keyname, const unsigned commentID) const;
// Delete a key comment.
bool DeleteKeyComment( const unsigned keyID, const unsigned commentID); // tolua_export
bool DeleteKeyComment( const std::string & keyname, const unsigned commentID); // tolua_export
bool DeleteKeyComment(const unsigned keyID, const unsigned commentID);
bool DeleteKeyComment(const std::string & keyname, const unsigned commentID);
// Delete all comments for a key.
bool DeleteKeyComments( const unsigned keyID); // tolua_export
bool DeleteKeyComments( const std::string & keyname); // tolua_export
}; // tolua_export
bool DeleteKeyComments(const unsigned keyID);
bool DeleteKeyComments(const std::string & keyname);
};
// tolua_end
#endif

View File

@ -63,3 +63,11 @@ $cfile "LuaWindow.h"
// Need to declare this class so that the usertype is properly registered in Bindings.cpp -
// it seems impossible to register a usertype in ManualBindings.cpp
class cLineBlockTracer;

View File

@ -1,6 +1,6 @@
/*
** Lua binding: AllToLua
** Generated automatically by tolua++-1.0.92 on 08/02/13 08:41:18.
** Generated automatically by tolua++-1.0.92 on 08/07/13 12:06:03.
*/
#ifndef __cplusplus
@ -202,8 +202,11 @@ static int tolua_collect_Vector3d (lua_State* tolua_S)
static void tolua_reg_types (lua_State* tolua_S)
{
tolua_usertype(tolua_S,"TakeDamageInfo");
tolua_usertype(tolua_S,"cCraftingRecipe");
tolua_usertype(tolua_S,"cPlugin_NewLua");
tolua_usertype(tolua_S,"cCraftingGrid");
tolua_usertype(tolua_S,"cCraftingRecipe");
tolua_usertype(tolua_S,"cPlugin");
tolua_usertype(tolua_S,"cWindow");
tolua_usertype(tolua_S,"cStringMap");
tolua_usertype(tolua_S,"cItemGrid");
tolua_usertype(tolua_S,"cBlockArea");
@ -211,42 +214,42 @@ static void tolua_reg_types (lua_State* tolua_S)
tolua_usertype(tolua_S,"cLuaWindow");
tolua_usertype(tolua_S,"cInventory");
tolua_usertype(tolua_S,"cRoot");
tolua_usertype(tolua_S,"cWindow");
tolua_usertype(tolua_S,"cCraftingGrid");
tolua_usertype(tolua_S,"cTracer");
tolua_usertype(tolua_S,"cPickup");
tolua_usertype(tolua_S,"cItems");
tolua_usertype(tolua_S,"cCuboid");
tolua_usertype(tolua_S,"std::vector<cIniFile::key>");
tolua_usertype(tolua_S,"cGroup");
tolua_usertype(tolua_S,"cPickup");
tolua_usertype(tolua_S,"std::vector<std::string>");
tolua_usertype(tolua_S,"cTracer");
tolua_usertype(tolua_S,"cClientHandle");
tolua_usertype(tolua_S,"cChunkDesc");
tolua_usertype(tolua_S,"cFurnaceRecipe");
tolua_usertype(tolua_S,"cCuboid");
tolua_usertype(tolua_S,"cChatColor");
tolua_usertype(tolua_S,"Vector3i");
tolua_usertype(tolua_S,"cEntity");
tolua_usertype(tolua_S,"cChatColor");
tolua_usertype(tolua_S,"cWorld");
tolua_usertype(tolua_S,"Lua__cPickup");
tolua_usertype(tolua_S,"Lua__cWebPlugin");
tolua_usertype(tolua_S,"cPlugin");
tolua_usertype(tolua_S,"cCraftingRecipes");
tolua_usertype(tolua_S,"cEntity");
tolua_usertype(tolua_S,"cItem");
tolua_usertype(tolua_S,"Vector3f");
tolua_usertype(tolua_S,"Lua__cPickup");
tolua_usertype(tolua_S,"cWebPlugin");
tolua_usertype(tolua_S,"cDropSpenserEntity");
tolua_usertype(tolua_S,"Lua__cPlayer");
tolua_usertype(tolua_S,"cWebPlugin");
tolua_usertype(tolua_S,"cWebAdmin");
tolua_usertype(tolua_S,"cChestEntity");
tolua_usertype(tolua_S,"cDispenserEntity");
tolua_usertype(tolua_S,"cWebAdmin");
tolua_usertype(tolua_S,"sWebAdminPage");
tolua_usertype(tolua_S,"cBlockEntity");
tolua_usertype(tolua_S,"cCriticalSection");
tolua_usertype(tolua_S,"HTTPTemplateRequest");
tolua_usertype(tolua_S,"sWebAdminPage");
tolua_usertype(tolua_S,"HTTPRequest");
tolua_usertype(tolua_S,"HTTPFormData");
tolua_usertype(tolua_S,"cFurnaceEntity");
tolua_usertype(tolua_S,"cPluginManager");
tolua_usertype(tolua_S,"cDropperEntity");
tolua_usertype(tolua_S,"cLineBlockTracer");
tolua_usertype(tolua_S,"cPluginManager");
tolua_usertype(tolua_S,"cIniFile");
tolua_usertype(tolua_S,"cWorld");
tolua_usertype(tolua_S,"cBlockEntityWithItems");
tolua_usertype(tolua_S,"cListeners");
tolua_usertype(tolua_S,"cPawn");
tolua_usertype(tolua_S,"cPlayer");
@ -254,7 +257,7 @@ static void tolua_reg_types (lua_State* tolua_S)
tolua_usertype(tolua_S,"cBlockEntityWindowOwner");
tolua_usertype(tolua_S,"cItemGrid::cListener");
tolua_usertype(tolua_S,"cServer");
tolua_usertype(tolua_S,"cBlockEntityWithItems");
tolua_usertype(tolua_S,"cItems");
tolua_usertype(tolua_S,"Lua__cEntity");
tolua_usertype(tolua_S,"Vector3d");
}
@ -267,16 +270,14 @@ static int tolua_AllToLua_cIniFile_new00(lua_State* tolua_S)
tolua_Error tolua_err;
if (
!tolua_isusertable(tolua_S,1,"cIniFile",0,&tolua_err) ||
!tolua_iscppstring(tolua_S,2,1,&tolua_err) ||
!tolua_isnoobj(tolua_S,3,&tolua_err)
!tolua_isnoobj(tolua_S,2,&tolua_err)
)
goto tolua_lerror;
else
#endif
{
const std::string iniPath = ((const std::string) tolua_tocppstring(tolua_S,2,""));
{
cIniFile* tolua_ret = (cIniFile*) Mtolua_new((cIniFile)(iniPath));
cIniFile* tolua_ret = (cIniFile*) Mtolua_new((cIniFile)());
tolua_pushusertype(tolua_S,(void*)tolua_ret,"cIniFile");
}
}
@ -297,16 +298,14 @@ static int tolua_AllToLua_cIniFile_new00_local(lua_State* tolua_S)
tolua_Error tolua_err;
if (
!tolua_isusertable(tolua_S,1,"cIniFile",0,&tolua_err) ||
!tolua_iscppstring(tolua_S,2,1,&tolua_err) ||
!tolua_isnoobj(tolua_S,3,&tolua_err)
!tolua_isnoobj(tolua_S,2,&tolua_err)
)
goto tolua_lerror;
else
#endif
{
const std::string iniPath = ((const std::string) tolua_tocppstring(tolua_S,2,""));
{
cIniFile* tolua_ret = (cIniFile*) Mtolua_new((cIniFile)(iniPath));
cIniFile* tolua_ret = (cIniFile*) Mtolua_new((cIniFile)());
tolua_pushusertype(tolua_S,(void*)tolua_ret,"cIniFile");
tolua_register_gc(tolua_S,lua_gettop(tolua_S));
}
@ -320,6 +319,59 @@ static int tolua_AllToLua_cIniFile_new00_local(lua_State* tolua_S)
}
#endif //#ifndef TOLUA_DISABLE
/* method: new of class cIniFile */
#ifndef TOLUA_DISABLE_tolua_AllToLua_cIniFile_new01
static int tolua_AllToLua_cIniFile_new01(lua_State* tolua_S)
{
tolua_Error tolua_err;
if (
!tolua_isusertable(tolua_S,1,"cIniFile",0,&tolua_err) ||
!tolua_iscppstring(tolua_S,2,0,&tolua_err) ||
!tolua_isnoobj(tolua_S,3,&tolua_err)
)
goto tolua_lerror;
else
{
const std::string a_Path = ((const std::string) tolua_tocppstring(tolua_S,2,0));
{
cIniFile* tolua_ret = (cIniFile*) Mtolua_new((cIniFile)(a_Path));
tolua_pushusertype(tolua_S,(void*)tolua_ret,"cIniFile");
tolua_pushcppstring(tolua_S,(const char*)a_Path);
}
}
return 2;
tolua_lerror:
return tolua_AllToLua_cIniFile_new00(tolua_S);
}
#endif //#ifndef TOLUA_DISABLE
/* method: new_local of class cIniFile */
#ifndef TOLUA_DISABLE_tolua_AllToLua_cIniFile_new01_local
static int tolua_AllToLua_cIniFile_new01_local(lua_State* tolua_S)
{
tolua_Error tolua_err;
if (
!tolua_isusertable(tolua_S,1,"cIniFile",0,&tolua_err) ||
!tolua_iscppstring(tolua_S,2,0,&tolua_err) ||
!tolua_isnoobj(tolua_S,3,&tolua_err)
)
goto tolua_lerror;
else
{
const std::string a_Path = ((const std::string) tolua_tocppstring(tolua_S,2,0));
{
cIniFile* tolua_ret = (cIniFile*) Mtolua_new((cIniFile)(a_Path));
tolua_pushusertype(tolua_S,(void*)tolua_ret,"cIniFile");
tolua_register_gc(tolua_S,lua_gettop(tolua_S));
tolua_pushcppstring(tolua_S,(const char*)a_Path);
}
}
return 2;
tolua_lerror:
return tolua_AllToLua_cIniFile_new00_local(tolua_S);
}
#endif //#ifndef TOLUA_DISABLE
/* method: CaseSensitive of class cIniFile */
#ifndef TOLUA_DISABLE_tolua_AllToLua_cIniFile_CaseSensitive00
static int tolua_AllToLua_cIniFile_CaseSensitive00(lua_State* tolua_S)
@ -433,7 +485,7 @@ static int tolua_AllToLua_cIniFile_Path01(lua_State* tolua_S)
if (!self) tolua_error(tolua_S,"invalid 'self' in function 'Path'", NULL);
#endif
{
std::string tolua_ret = (std::string) self->Path();
const std::string tolua_ret = (const std::string) self->Path();
tolua_pushcppstring(tolua_S,(const char*)tolua_ret);
}
}
@ -485,18 +537,20 @@ static int tolua_AllToLua_cIniFile_ReadFile00(lua_State* tolua_S)
tolua_Error tolua_err;
if (
!tolua_isusertype(tolua_S,1,"cIniFile",0,&tolua_err) ||
!tolua_isnoobj(tolua_S,2,&tolua_err)
!tolua_isboolean(tolua_S,2,1,&tolua_err) ||
!tolua_isnoobj(tolua_S,3,&tolua_err)
)
goto tolua_lerror;
else
#endif
{
cIniFile* self = (cIniFile*) tolua_tousertype(tolua_S,1,0);
bool a_AllowExampleRedirect = ((bool) tolua_toboolean(tolua_S,2,true));
#ifndef TOLUA_RELEASE
if (!self) tolua_error(tolua_S,"invalid 'self' in function 'ReadFile'", NULL);
#endif
{
bool tolua_ret = (bool) self->ReadFile();
bool tolua_ret = (bool) self->ReadFile(a_AllowExampleRedirect);
tolua_pushboolean(tolua_S,(bool)tolua_ret);
}
}
@ -516,14 +570,14 @@ static int tolua_AllToLua_cIniFile_WriteFile00(lua_State* tolua_S)
#ifndef TOLUA_RELEASE
tolua_Error tolua_err;
if (
!tolua_isusertype(tolua_S,1,"cIniFile",0,&tolua_err) ||
!tolua_isusertype(tolua_S,1,"const cIniFile",0,&tolua_err) ||
!tolua_isnoobj(tolua_S,2,&tolua_err)
)
goto tolua_lerror;
else
#endif
{
cIniFile* self = (cIniFile*) tolua_tousertype(tolua_S,1,0);
const cIniFile* self = (const cIniFile*) tolua_tousertype(tolua_S,1,0);
#ifndef TOLUA_RELEASE
if (!self) tolua_error(tolua_S,"invalid 'self' in function 'WriteFile'", NULL);
#endif
@ -541,37 +595,6 @@ static int tolua_AllToLua_cIniFile_WriteFile00(lua_State* tolua_S)
}
#endif //#ifndef TOLUA_DISABLE
/* method: Erase of class cIniFile */
#ifndef TOLUA_DISABLE_tolua_AllToLua_cIniFile_Erase00
static int tolua_AllToLua_cIniFile_Erase00(lua_State* tolua_S)
{
#ifndef TOLUA_RELEASE
tolua_Error tolua_err;
if (
!tolua_isusertype(tolua_S,1,"cIniFile",0,&tolua_err) ||
!tolua_isnoobj(tolua_S,2,&tolua_err)
)
goto tolua_lerror;
else
#endif
{
cIniFile* self = (cIniFile*) tolua_tousertype(tolua_S,1,0);
#ifndef TOLUA_RELEASE
if (!self) tolua_error(tolua_S,"invalid 'self' in function 'Erase'", NULL);
#endif
{
self->Erase();
}
}
return 0;
#ifndef TOLUA_RELEASE
tolua_lerror:
tolua_error(tolua_S,"#ferror in function 'Erase'.",&tolua_err);
return 0;
#endif
}
#endif //#ifndef TOLUA_DISABLE
/* method: Clear of class cIniFile */
#ifndef TOLUA_DISABLE_tolua_AllToLua_cIniFile_Clear00
static int tolua_AllToLua_cIniFile_Clear00(lua_State* tolua_S)
@ -634,6 +657,37 @@ static int tolua_AllToLua_cIniFile_Reset00(lua_State* tolua_S)
}
#endif //#ifndef TOLUA_DISABLE
/* method: Erase of class cIniFile */
#ifndef TOLUA_DISABLE_tolua_AllToLua_cIniFile_Erase00
static int tolua_AllToLua_cIniFile_Erase00(lua_State* tolua_S)
{
#ifndef TOLUA_RELEASE
tolua_Error tolua_err;
if (
!tolua_isusertype(tolua_S,1,"cIniFile",0,&tolua_err) ||
!tolua_isnoobj(tolua_S,2,&tolua_err)
)
goto tolua_lerror;
else
#endif
{
cIniFile* self = (cIniFile*) tolua_tousertype(tolua_S,1,0);
#ifndef TOLUA_RELEASE
if (!self) tolua_error(tolua_S,"invalid 'self' in function 'Erase'", NULL);
#endif
{
self->Erase();
}
}
return 0;
#ifndef TOLUA_RELEASE
tolua_lerror:
tolua_error(tolua_S,"#ferror in function 'Erase'.",&tolua_err);
return 0;
#endif
}
#endif //#ifndef TOLUA_DISABLE
/* method: FindKey of class cIniFile */
#ifndef TOLUA_DISABLE_tolua_AllToLua_cIniFile_FindKey00
static int tolua_AllToLua_cIniFile_FindKey00(lua_State* tolua_S)
@ -28476,6 +28530,9 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S)
tolua_function(tolua_S,"new",tolua_AllToLua_cIniFile_new00);
tolua_function(tolua_S,"new_local",tolua_AllToLua_cIniFile_new00_local);
tolua_function(tolua_S,".call",tolua_AllToLua_cIniFile_new00_local);
tolua_function(tolua_S,"new",tolua_AllToLua_cIniFile_new01);
tolua_function(tolua_S,"new_local",tolua_AllToLua_cIniFile_new01_local);
tolua_function(tolua_S,".call",tolua_AllToLua_cIniFile_new01_local);
tolua_function(tolua_S,"CaseSensitive",tolua_AllToLua_cIniFile_CaseSensitive00);
tolua_function(tolua_S,"CaseInsensitive",tolua_AllToLua_cIniFile_CaseInsensitive00);
tolua_function(tolua_S,"Path",tolua_AllToLua_cIniFile_Path00);
@ -28483,9 +28540,9 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S)
tolua_function(tolua_S,"SetPath",tolua_AllToLua_cIniFile_SetPath00);
tolua_function(tolua_S,"ReadFile",tolua_AllToLua_cIniFile_ReadFile00);
tolua_function(tolua_S,"WriteFile",tolua_AllToLua_cIniFile_WriteFile00);
tolua_function(tolua_S,"Erase",tolua_AllToLua_cIniFile_Erase00);
tolua_function(tolua_S,"Clear",tolua_AllToLua_cIniFile_Clear00);
tolua_function(tolua_S,"Reset",tolua_AllToLua_cIniFile_Reset00);
tolua_function(tolua_S,"Erase",tolua_AllToLua_cIniFile_Erase00);
tolua_function(tolua_S,"FindKey",tolua_AllToLua_cIniFile_FindKey00);
tolua_function(tolua_S,"FindValue",tolua_AllToLua_cIniFile_FindValue00);
tolua_function(tolua_S,"NumKeys",tolua_AllToLua_cIniFile_NumKeys00);
@ -28699,6 +28756,7 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S)
tolua_constant(tolua_S,"E_BLOCK_QUARTZ_BLOCK",E_BLOCK_QUARTZ_BLOCK);
tolua_constant(tolua_S,"E_BLOCK_ACTIVATOR_RAIL",E_BLOCK_ACTIVATOR_RAIL);
tolua_constant(tolua_S,"E_BLOCK_DROPPER",E_BLOCK_DROPPER);
tolua_constant(tolua_S,"E_BLOCK_CARPET",E_BLOCK_CARPET);
tolua_constant(tolua_S,"E_BLOCK_NUMBER_OF_TYPES",E_BLOCK_NUMBER_OF_TYPES);
tolua_constant(tolua_S,"E_BLOCK_MAX_TYPE_ID",E_BLOCK_MAX_TYPE_ID);
tolua_constant(tolua_S,"E_ITEM_EMPTY",E_ITEM_EMPTY);
@ -30283,6 +30341,9 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S)
tolua_function(tolua_S,"GetContents",tolua_AllToLua_cLuaWindow_GetContents00);
tolua_variable(tolua_S,"__cItemGrid__cListener__",tolua_get_cLuaWindow___cItemGrid__cListener__,NULL);
tolua_endmodule(tolua_S);
tolua_cclass(tolua_S,"cLineBlockTracer","cLineBlockTracer","",NULL);
tolua_beginmodule(tolua_S,"cLineBlockTracer");
tolua_endmodule(tolua_S);
tolua_endmodule(tolua_S);
return 1;
}

View File

@ -1,6 +1,6 @@
/*
** Lua binding: AllToLua
** Generated automatically by tolua++-1.0.92 on 08/02/13 08:41:19.
** Generated automatically by tolua++-1.0.92 on 08/07/13 12:06:04.
*/
/* Exported function */

View File

@ -123,7 +123,7 @@ void cChestEntity::UsedBy(cPlayer * a_Player)
// We cannot properly detect contents change, but such a change doesn't happen without a player opening the chest first.
// The few false positives aren't much to worry about
int ChunkX, ChunkZ;
cChunkDef::BlockToChunk(m_PosX, m_PosY, m_PosZ, ChunkX, ChunkZ);
cChunkDef::BlockToChunk(m_PosX, m_PosZ, ChunkX, ChunkZ);
m_World->MarkChunkDirty(ChunkX, ChunkZ);
}

View File

@ -125,7 +125,7 @@ void cHopperEntity::UsedBy(cPlayer * a_Player)
// We cannot properly detect contents change, but such a change doesn't happen without a player opening the chest first.
// The few false positives aren't much to worry about
int ChunkX, ChunkZ;
cChunkDef::BlockToChunk(m_PosX, m_PosY, m_PosZ, ChunkX, ChunkZ);
cChunkDef::BlockToChunk(m_PosX, m_PosZ, ChunkX, ChunkZ);
m_World->MarkChunkDirty(ChunkX, ChunkZ);
}

View File

@ -169,6 +169,8 @@ enum ENUM_BLOCK_ID
E_BLOCK_DROPPER = 158,
E_BLOCK_CARPET = 171,
// Keep these two as the last values, without a number - they will get their correct number assigned automagically by C++
// IsValidBlock() depends on this
E_BLOCK_NUMBER_OF_TYPES, ///< Number of individual (different) blocktypes

104
source/BlockTracer.h Normal file
View File

@ -0,0 +1,104 @@
// BlockTracer.h
// Declares the classes common for all blocktracers
#pragma once
// fwd: World.h
class cWorld;
class cBlockTracer abstract
{
public:
/** The callback class is used to notify the caller of individual events that are being traced.
*/
class cCallbacks abstract
{
public:
/** Called on each block encountered along the path, including the first block (path start)
When this callback returns true, the tracing is aborted.
*/
virtual bool OnNextBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) = 0;
/** Called on each block encountered along the path, including the first block (path start), if chunk data is not loaded
When this callback returns true, the tracing is aborted.
*/
virtual bool OnNextBlockNoData(int a_BlockX, int a_BlockY, int a_BlockZ) { return false; }
/** Called when the path goes out of world, either below (a_BlockY < 0) or above (a_BlockY >= cChunkDef::Height)
The coords specify the exact point at which the path exited the world.
If this callback returns true, the tracing is aborted.
Note that some paths can go out of the world and come back again (parabola),
in such a case this callback is followed by OnIntoWorld() and further OnNextBlock() calls
*/
virtual bool OnOutOfWorld(double a_BlockX, double a_BlockY, double a_BlockZ) { return false; }
/** Called when the path goes into the world, from either below (a_BlockY < 0) or above (a_BlockY >= cChunkDef::Height)
The coords specify the exact point at which the path entered the world.
If this callback returns true, the tracing is aborted.
Note that some paths can go out of the world and come back again (parabola),
in such a case this callback is followed by further OnNextBlock() calls
*/
virtual bool OnIntoWorld(double a_BlockX, double a_BlockY, double a_BlockZ) { return false; }
/** Called when the path is sure not to hit any more blocks.
Note that for some shapes this might never happen (line with constant Y)
*/
virtual void OnNoMoreHits(void) {}
/** Called when the block tracing walks into a chunk that is not allocated.
This usually means that the tracing is aborted.
*/
virtual void OnNoChunk(void) {}
} ;
/// Creates the BlockTracer parent with the specified callbacks
cBlockTracer(cWorld & a_World, cCallbacks & a_Callbacks) :
m_World(&a_World),
m_Callbacks(&a_Callbacks)
{
}
/// Sets new world, returns the old one. Note that both need to be valid
cWorld & SetWorld(cWorld & a_World)
{
cWorld & Old = *m_World;
m_World = &a_World;
return Old;
}
/// Sets new callbacks, returns the old ones. Note that both need to be valid
cCallbacks & SetCallbacks(cCallbacks & a_NewCallbacks)
{
cCallbacks & Old = *m_Callbacks;
m_Callbacks = &a_NewCallbacks;
return Old;
}
protected:
/// The world upon which to operate
cWorld * m_World;
/// The callback to use for reporting
cCallbacks * m_Callbacks;
} ;

View File

@ -0,0 +1,54 @@
// BlockCarpet.h
// Declares the cBlockCarpetHandler class representing the handler for the carpet block
#pragma once
class cBlockCarpetHandler :
public cBlockHandler
{
public:
cBlockCarpetHandler(BLOCKTYPE a_BlockType);
virtual const char * GetStepSound(void) override
{
return "step.cloth";
}
virtual bool GetPlacementBlockTypeMeta(
cWorld * a_World, cPlayer * a_Player,
int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
) override
{
a_BlockType = m_BlockType;
a_BlockMeta = a_Player->GetEquippedItem().m_ItemDamage & 0x0f;
return true;
}
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
{
a_Pickups.push_back(cItem(E_BLOCK_CARPET, a_BlockMeta));
}
virtual bool CanBeAt(int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override
{
return ((a_RelY > 0) && (a_Chunk.GetBlock(a_RelX, a_RelY - 1, a_RelZ) != E_BLOCK_AIR));
}
} ;

View File

@ -3,6 +3,7 @@
#include "BlockEntity.h"
#include "../World.h"
#include "../BlockArea.h"
#include "../Player.h"

View File

@ -5,6 +5,8 @@
#pragma once
#include "../Piston.h"

View File

@ -5,59 +5,60 @@
#include "../World.h"
#include "../Root.h"
#include "../PluginManager.h"
#include "BlockSand.h"
#include "BlockGravel.h"
#include "BlockDoor.h"
#include "BlockFire.h"
#include "BlockRedstone.h"
#include "BlockRedstoneTorch.h"
#include "BlockRedstoneRepeater.h"
#include "BlockPiston.h"
#include "BlockWorkbench.h"
#include "BlockEntity.h"
#include "BlockVine.h"
#include "BlockTallGrass.h"
#include "BlockSnow.h"
#include "BlockCloth.h"
#include "BlockSlab.h"
#include "BlockDirt.h"
#include "BlockTorch.h"
#include "BlockWood.h"
#include "BlockLeaves.h"
#include "BlockSapling.h"
#include "BlockFluid.h"
#include "BlockChest.h"
#include "BlockFurnace.h"
#include "BlockDropSpenser.h"
#include "BlockStairs.h"
#include "BlockLadder.h"
#include "BlockLever.h"
#include "BlockSign.h"
#include "BlockCrops.h"
#include "BlockSugarcane.h"
#include "BlockFlower.h"
#include "BlockMushroom.h"
#include "BlockCactus.h"
#include "BlockStems.h"
#include "BlockGlowstone.h"
#include "BlockStone.h"
#include "BlockMelon.h"
#include "BlockIce.h"
#include "BlockOre.h"
#include "BlockNote.h"
#include "BlockBed.h"
#include "BlockFarmland.h"
#include "BlockMycelium.h"
#include "BlockRail.h"
#include "BlockGlass.h"
#include "BlockEnderchest.h"
#include "BlockFenceGate.h"
#include "BlockFlowerPot.h"
#include "BlockCauldron.h"
#include "BlockBrewingStand.h"
#include "BlockCactus.h"
#include "BlockCarpet.h"
#include "BlockCauldron.h"
#include "BlockChest.h"
#include "BlockCloth.h"
#include "BlockCobWeb.h"
#include "BlockCrops.h"
#include "BlockDeadBush.h"
#include "BlockDirt.h"
#include "BlockDoor.h"
#include "BlockDropSpenser.h"
#include "BlockEnderchest.h"
#include "BlockEntity.h"
#include "BlockFarmland.h"
#include "BlockFenceGate.h"
#include "BlockFire.h"
#include "BlockFlower.h"
#include "BlockFlowerPot.h"
#include "BlockFluid.h"
#include "BlockFurnace.h"
#include "BlockGlass.h"
#include "BlockGlowstone.h"
#include "BlockGravel.h"
#include "BlockHopper.h"
#include "BlockIce.h"
#include "BlockLadder.h"
#include "BlockLeaves.h"
#include "BlockLever.h"
#include "BlockMelon.h"
#include "BlockMushroom.h"
#include "BlockMycelium.h"
#include "BlockNote.h"
#include "BlockOre.h"
#include "BlockPiston.h"
#include "BlockRail.h"
#include "BlockRedstone.h"
#include "BlockRedstoneRepeater.h"
#include "BlockRedstoneTorch.h"
#include "BlockSand.h"
#include "BlockSapling.h"
#include "BlockSign.h"
#include "BlockSlab.h"
#include "BlockSnow.h"
#include "BlockStairs.h"
#include "BlockStems.h"
#include "BlockStone.h"
#include "BlockSugarcane.h"
#include "BlockTallGrass.h"
#include "BlockTorch.h"
#include "BlockVine.h"
#include "BlockWood.h"
#include "BlockWorkbench.h"

View File

@ -137,7 +137,7 @@ public:
/// Converts absolute block coords into relative (chunk + block) coords:
inline static void AbsoluteToRelative(/* in-out */ int & a_X, int & a_Y, int & a_Z, /* out */ int & a_ChunkX, int & a_ChunkZ )
{
BlockToChunk(a_X, a_Y, a_Z, a_ChunkX, a_ChunkZ);
BlockToChunk(a_X, a_Z, a_ChunkX, a_ChunkZ);
a_X = a_X - a_ChunkX * Width;
a_Z = a_Z - a_ChunkZ * Width;
@ -145,9 +145,8 @@ public:
/// Converts absolute block coords to chunk coords:
inline static void BlockToChunk( int a_X, int a_Y, int a_Z, int & a_ChunkX, int & a_ChunkZ )
inline static void BlockToChunk(int a_X, int a_Z, int & a_ChunkX, int & a_ChunkZ)
{
(void)a_Y;
a_ChunkX = a_X / Width;
if ((a_X < 0) && (a_X % Width != 0))
{

View File

@ -345,7 +345,7 @@ void cChunkMap::BroadcastBlockAction(int a_BlockX, int a_BlockY, int a_BlockZ, c
x = a_BlockX;
y = a_BlockY;
z = a_BlockZ;
cChunkDef::BlockToChunk(x, y, z, ChunkX, ChunkZ);
cChunkDef::BlockToChunk(x, z, ChunkX, ChunkZ);
cChunkPtr Chunk = GetChunkNoGen(ChunkX, ZERO_CHUNK_Y, ChunkZ);
if (Chunk == NULL)
{
@ -364,7 +364,7 @@ void cChunkMap::BroadcastBlockBreakAnimation(int a_entityID, int a_blockX, int a
cCSLock Lock(m_CSLayers);
int ChunkX, ChunkZ;
cChunkDef::BlockToChunk(a_blockX, a_blockY, a_blockZ, ChunkX, ChunkZ);
cChunkDef::BlockToChunk(a_blockX, a_blockZ, ChunkX, ChunkZ);
cChunkPtr Chunk = GetChunkNoGen(ChunkX, 0, ChunkZ);
if (Chunk == NULL)
{
@ -382,7 +382,7 @@ void cChunkMap::BroadcastBlockEntity(int a_BlockX, int a_BlockY, int a_BlockZ, c
{
cCSLock Lock(m_CSLayers);
int ChunkX, ChunkZ;
cChunkDef::BlockToChunk(a_BlockX, a_BlockY, a_BlockZ, ChunkX, ChunkZ);
cChunkDef::BlockToChunk(a_BlockX, a_BlockZ, ChunkX, ChunkZ);
cChunkPtr Chunk = GetChunkNoGen(ChunkX, 0, ChunkZ);
if ((Chunk == NULL) || !Chunk->IsValid())
{
@ -592,7 +592,7 @@ void cChunkMap::BroadcastSoundEffect(const AString & a_SoundName, int a_SrcX, in
cCSLock Lock(m_CSLayers);
int ChunkX, ChunkZ;
cChunkDef::BlockToChunk(a_SrcX / 8, a_SrcY / 8, a_SrcZ / 8, ChunkX, ChunkZ);
cChunkDef::BlockToChunk(a_SrcX / 8, a_SrcZ / 8, ChunkX, ChunkZ);
cChunkPtr Chunk = GetChunkNoGen(ChunkX, 0, ChunkZ);
if (Chunk == NULL)
{
@ -611,7 +611,7 @@ void cChunkMap::BroadcastSoundParticleEffect(int a_EffectID, int a_SrcX, int a_S
cCSLock Lock(m_CSLayers);
int ChunkX, ChunkZ;
cChunkDef::BlockToChunk(a_SrcX / 8, a_SrcY / 8, a_SrcZ / 8, ChunkX, ChunkZ);
cChunkDef::BlockToChunk(a_SrcX / 8, a_SrcZ / 8, ChunkX, ChunkZ);
cChunkPtr Chunk = GetChunkNoGen(ChunkX, 0, ChunkZ);
if (Chunk == NULL)
{
@ -645,7 +645,7 @@ void cChunkMap::BroadcastThunderbolt(int a_BlockX, int a_BlockY, int a_BlockZ, c
{
cCSLock Lock(m_CSLayers);
int ChunkX, ChunkZ;
cChunkDef::BlockToChunk(a_BlockX, a_BlockY, a_BlockZ, ChunkX, ChunkZ);
cChunkDef::BlockToChunk(a_BlockX, a_BlockZ, ChunkX, ChunkZ);
cChunkPtr Chunk = GetChunkNoGen(ChunkX, 0, ChunkZ);
if (Chunk == NULL)
{
@ -664,7 +664,7 @@ void cChunkMap::BroadcastUseBed(const cEntity & a_Entity, int a_BlockX, int a_Bl
cCSLock Lock(m_CSLayers);
int ChunkX, ChunkZ;
cChunkDef::BlockToChunk(a_BlockX, a_BlockY, a_BlockZ, ChunkX, ChunkZ);
cChunkDef::BlockToChunk(a_BlockX, a_BlockZ, ChunkX, ChunkZ);
cChunkPtr Chunk = GetChunkNoGen(ChunkX, 0, ChunkZ);
if (Chunk == NULL)
{
@ -682,7 +682,7 @@ void cChunkMap::SendBlockEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cClien
{
cCSLock Lock(m_CSLayers);
int ChunkX, ChunkZ;
cChunkDef::BlockToChunk(a_BlockX, a_BlockY, a_BlockZ, ChunkX, ChunkZ);
cChunkDef::BlockToChunk(a_BlockX, a_BlockZ, ChunkX, ChunkZ);
cChunkPtr Chunk = GetChunkNoGen(ChunkX, 0, ChunkZ);
if ((Chunk == NULL) || !Chunk->IsValid())
{
@ -700,7 +700,7 @@ void cChunkMap::UseBlockEntity(cPlayer * a_Player, int a_BlockX, int a_BlockY, i
// a_Player rclked block entity at the coords specified, handle it
cCSLock Lock(m_CSLayers);
int ChunkX, ChunkZ;
cChunkDef::BlockToChunk(a_BlockX, a_BlockY, a_BlockZ, ChunkX, ChunkZ);
cChunkDef::BlockToChunk(a_BlockX, a_BlockZ, ChunkX, ChunkZ);
cChunkPtr Chunk = GetChunkNoGen(ChunkX, 0, ChunkZ);
if ((Chunk == NULL) || !Chunk->IsValid())
{
@ -713,11 +713,26 @@ void cChunkMap::UseBlockEntity(cPlayer * a_Player, int a_BlockX, int a_BlockY, i
bool cChunkMap::DoWithChunk(int a_ChunkX, int a_ChunkZ, cChunkCallback & a_Callback)
{
cCSLock Lock(m_CSLayers);
cChunkPtr Chunk = GetChunkNoLoad(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ);
if (Chunk == NULL)
{
return false;
}
return a_Callback.Item(Chunk);
}
void cChunkMap::WakeUpSimulators(int a_BlockX, int a_BlockY, int a_BlockZ)
{
cCSLock Lock(m_CSLayers);
int ChunkX, ChunkZ;
cChunkDef::BlockToChunk(a_BlockX, a_BlockY, a_BlockZ, ChunkX, ChunkZ);
cChunkDef::BlockToChunk(a_BlockX, a_BlockZ, ChunkX, ChunkZ);
cChunkPtr Chunk = GetChunkNoGen(ChunkX, 0, ChunkZ);
if ((Chunk == NULL) || !Chunk->IsValid())
{
@ -735,8 +750,8 @@ void cChunkMap::WakeUpSimulatorsInArea(int a_MinBlockX, int a_MaxBlockX, int a_M
{
cSimulatorManager * SimMgr = m_World->GetSimulatorManager();
int MinChunkX, MinChunkZ, MaxChunkX, MaxChunkZ;
cChunkDef::BlockToChunk(a_MinBlockX, ZERO_CHUNK_Y, a_MinBlockZ, MinChunkX, MinChunkZ);
cChunkDef::BlockToChunk(a_MaxBlockX, ZERO_CHUNK_Y, a_MaxBlockZ, MaxChunkX, MaxChunkZ);
cChunkDef::BlockToChunk(a_MinBlockX, a_MinBlockZ, MinChunkX, MinChunkZ);
cChunkDef::BlockToChunk(a_MaxBlockX, a_MaxBlockZ, MaxChunkX, MaxChunkZ);
for (int z = MinChunkZ; z <= MaxChunkZ; z++)
{
int MinZ = std::max(a_MinBlockZ, z * cChunkDef::Width);
@ -1903,7 +1918,7 @@ bool cChunkMap::SetSignLines(int a_BlockX, int a_BlockY, int a_BlockZ, const ASt
{
cCSLock Lock(m_CSLayers);
int ChunkX, ChunkZ;
cChunkDef::BlockToChunk(a_BlockX, a_BlockY, a_BlockZ, ChunkX, ChunkZ);
cChunkDef::BlockToChunk(a_BlockX, a_BlockZ, ChunkX, ChunkZ);
cChunkPtr Chunk = GetChunkNoGen(ChunkX, ZERO_CHUNK_Y, ChunkZ);
if ((Chunk == NULL) || !Chunk->IsValid())
{

View File

@ -35,6 +35,7 @@ typedef cItemCallback<cDispenserEntity> cDispenserCallback;
typedef cItemCallback<cDropperEntity> cDropperCallback;
typedef cItemCallback<cDropSpenserEntity> cDropSpenserCallback;
typedef cItemCallback<cFurnaceEntity> cFurnaceCallback;
typedef cItemCallback<cChunk> cChunkCallback;
@ -79,6 +80,9 @@ public:
/// a_Player rclked block entity at the coords specified, handle it
void UseBlockEntity(cPlayer * a_Player, int a_X, int a_Y, int a_Z);
/// Calls the callback for the chunk specified, with ChunkMapCS locked; returns false if the chunk doesn't exist, otherwise returns the same value as the callback
bool DoWithChunk(int a_ChunkX, int a_ChunkZ, cChunkCallback & a_Callback);
/// Wakes up simulators for the specified block
void WakeUpSimulators(int a_BlockX, int a_BlockY, int a_BlockZ);

View File

@ -47,11 +47,8 @@ cGroupManager::cGroupManager()
cIniFile IniFile("groups.ini");
if (!IniFile.ReadFile())
{
LOGINFO("groups.ini inaccessible, using groups.example.ini for defaults!");
IniFile.Path("groups.example.ini");
IniFile.ReadFile();
IniFile.Path("groups.ini");
IniFile.WriteFile();
LOGWARNING("groups.ini inaccessible, no groups are defined");
return;
}
unsigned int NumKeys = IniFile.GetNumKeys();

View File

@ -55,7 +55,10 @@ public:
{
if (!IsValidItem(m_ItemType))
{
LOGWARNING("%s: creating an invalid item type (%d), resetting to empty.", __FUNCTION__, a_ItemType);
if (m_ItemType != E_BLOCK_AIR)
{
LOGWARNING("%s: creating an invalid item type (%d), resetting to empty.", __FUNCTION__, a_ItemType);
}
Empty();
}
}

261
source/LineBlockTracer.cpp Normal file
View File

@ -0,0 +1,261 @@
// LineBlockTracer.cpp
// Implements the cLineBlockTracer class representing a cBlockTracer that traces along a straight line between two points
#include "Globals.h"
#include "LineBlockTracer.h"
#include "Vector3d.h"
#include "World.h"
#include "Chunk.h"
cLineBlockTracer::cLineBlockTracer(cWorld & a_World, cCallbacks & a_Callbacks) :
super(a_World, a_Callbacks)
{
}
bool cLineBlockTracer::Trace(cWorld & a_World, cBlockTracer::cCallbacks & a_Callbacks, const Vector3d & a_Start, const Vector3d & a_End)
{
cLineBlockTracer Tracer(a_World, a_Callbacks);
return Tracer.Trace(a_Start.x, a_Start.y, a_Start.z, a_End.x, a_End.y, a_End.z);
}
bool cLineBlockTracer::Trace(cWorld & a_World, cBlockTracer::cCallbacks &a_Callbacks, double a_StartX, double a_StartY, double a_StartZ, double a_EndX, double a_EndY, double a_EndZ)
{
cLineBlockTracer Tracer(a_World, a_Callbacks);
return Tracer.Trace(a_StartX, a_StartY, a_StartZ, a_EndX, a_EndY, a_EndZ);
}
bool cLineBlockTracer::Trace(double a_StartX, double a_StartY, double a_StartZ, double a_EndX, double a_EndY, double a_EndZ)
{
// Initialize the member veriables:
m_StartX = a_StartX;
m_StartY = a_StartY;
m_StartZ = a_StartZ;
m_EndX = a_EndX;
m_EndY = a_EndY;
m_EndZ = a_EndZ;
m_DirX = (m_StartX < m_EndX) ? 1 : -1;
m_DirY = (m_StartY < m_EndY) ? 1 : -1;
m_DirZ = (m_StartZ < m_EndZ) ? 1 : -1;
// Check the start coords, adjust into the world:
if (m_StartY < 0)
{
if (m_EndY < 0)
{
// Nothing to trace
m_Callbacks->OnNoMoreHits();
return true;
}
FixStartBelowWorld();
m_Callbacks->OnIntoWorld(m_StartX, m_StartY, m_StartZ);
}
else if (m_StartY >= cChunkDef::Height)
{
if (m_EndY >= cChunkDef::Height)
{
m_Callbacks->OnNoMoreHits();
return true;
}
FixStartAboveWorld();
m_Callbacks->OnIntoWorld(m_StartX, m_StartY, m_StartZ);
}
m_CurrentX = (int)floor(m_StartX);
m_CurrentY = (int)floor(m_StartY);
m_CurrentZ = (int)floor(m_StartZ);
m_DiffX = m_EndX - m_StartX;
m_DiffY = m_EndY - m_StartY;
m_DiffZ = m_EndZ - m_StartZ;
// The actual trace is handled with ChunkMapCS locked by calling our Item() for the specified chunk
int BlockX = (int)floor(m_StartX);
int BlockZ = (int)floor(m_StartZ);
int ChunkX, ChunkZ;
cChunkDef::BlockToChunk(BlockX, BlockZ, ChunkX, ChunkZ);
return m_World->DoWithChunk(ChunkX, ChunkZ, *this);
}
void cLineBlockTracer::FixStartAboveWorld(void)
{
// We must set the start Y to less than cChunkDef::Height so that it is considered inside the world later on
// Therefore we use an EPS-offset from the height, as small as reasonably possible.
const double Height = (double)cChunkDef::Height - 0.00001;
CalcXZIntersection(Height, m_StartX, m_StartZ);
m_StartY = Height;
}
void cLineBlockTracer::FixStartBelowWorld(void)
{
CalcXZIntersection(0, m_StartX, m_StartZ);
m_StartY = 0;
}
void cLineBlockTracer::CalcXZIntersection(double a_Y, double & a_IntersectX, double & a_IntersectZ)
{
double Ratio = (m_StartY - a_Y) / (m_StartY - m_EndY);
a_IntersectX = m_StartX + (m_EndX - m_StartX) * Ratio;
a_IntersectZ = m_StartZ + (m_EndZ - m_StartZ) * Ratio;
}
bool cLineBlockTracer::MoveToNextBlock(void)
{
// Find out which of the current block's walls gets hit by the path:
static const double EPS = 0.00001;
double Coeff = 1;
enum eDirection
{
dirNONE,
dirX,
dirY,
dirZ,
} Direction = dirNONE;
if (abs(m_DiffX) > EPS)
{
double DestX = (m_DirX > 0) ? (m_CurrentX + 1) : m_CurrentX;
Coeff = (DestX - m_StartX) / m_DiffX;
if (Coeff <= 1)
{
Direction = dirX;
}
}
if (abs(m_DiffY) > EPS)
{
double DestY = (m_DirY > 0) ? (m_CurrentY + 1) : m_CurrentY;
double CoeffY = (DestY - m_StartY) / m_DiffY;
if (CoeffY < Coeff)
{
Coeff = CoeffY;
Direction = dirY;
}
}
if (abs(m_DiffZ) > EPS)
{
double DestZ = (m_DirZ > 0) ? (m_CurrentZ + 1) : m_CurrentZ;
double CoeffZ = (DestZ - m_StartZ) / m_DiffZ;
if (CoeffZ < Coeff)
{
Coeff = CoeffZ;
Direction = dirZ;
}
}
// Based on the wall hit, adjust the current coords
switch (Direction)
{
case dirX: m_CurrentX += m_DirX; break;
case dirY: m_CurrentY += m_DirY; break;
case dirZ: m_CurrentZ += m_DirZ; break;
case dirNONE: return false;
}
return true;
}
bool cLineBlockTracer::Item(cChunk * a_Chunk)
{
ASSERT((m_CurrentY >= 0) && (m_CurrentY < cChunkDef::Height)); // This should be provided by FixStartAboveWorld() / FixStartBelowWorld()
// This is the actual line tracing loop.
bool Finished = false;
while (true)
{
// Report the current block through the callbacks:
if (a_Chunk == NULL)
{
m_Callbacks->OnNoChunk();
return false;
}
if (a_Chunk->IsValid())
{
BLOCKTYPE BlockType;
NIBBLETYPE BlockMeta;
int RelX = m_CurrentX - a_Chunk->GetPosX() * cChunkDef::Width;
int RelZ = m_CurrentZ - a_Chunk->GetPosZ() * cChunkDef::Width;
a_Chunk->GetBlockTypeMeta(RelX, m_CurrentY, RelZ, BlockType, BlockMeta);
if (m_Callbacks->OnNextBlock(m_CurrentX, m_CurrentY, m_CurrentZ, BlockType, BlockMeta))
{
// The callback terminated the trace
return false;
}
}
else
{
if (m_Callbacks->OnNextBlockNoData(m_CurrentX, m_CurrentY, m_CurrentZ))
{
// The callback terminated the trace
return false;
}
}
// Move to next block
if (!MoveToNextBlock())
{
// We've reached the end
m_Callbacks->OnNoMoreHits();
return true;
}
// Update the current chunk
if (a_Chunk != NULL)
{
a_Chunk = a_Chunk->GetNeighborChunk(m_CurrentX, m_CurrentZ);
}
if ((m_CurrentY < 0) || (m_CurrentY >= cChunkDef::Height))
{
// We've gone out of the world, that's the end of this trace
double IntersectX, IntersectZ;
CalcXZIntersection(m_CurrentY, IntersectX, IntersectZ);
if (m_Callbacks->OnOutOfWorld(IntersectX, m_CurrentY, IntersectZ))
{
// The callback terminated the trace
return false;
}
m_Callbacks->OnNoMoreHits();
return true;
}
}
}

84
source/LineBlockTracer.h Normal file
View File

@ -0,0 +1,84 @@
// LineBlockTracer.h
// Declares the cLineBlockTracer class representing a cBlockTracer that traces along a straight line between two points
#pragma once
#include "BlockTracer.h"
// fwd: Chunk.h
class cChunk;
// fwd: cChunkMap.h
typedef cItemCallback<cChunk> cChunkCallback;
class cLineBlockTracer :
public cBlockTracer,
public cChunkCallback
{
typedef cBlockTracer super;
public:
cLineBlockTracer(cWorld & a_World, cCallbacks & a_Callbacks);
/// Traces one line between Start and End; returns true if the entire line was traced (until OnNoMoreHits())
bool Trace(double a_StartX, double a_StartY, double a_StartZ, double a_EndX, double a_EndY, double a_EndZ);
// Utility functions for simple one-line usage:
/// Traces one line between Start and End; returns true if the entire line was traced (until OnNoMoreHits())
static bool Trace(cWorld & a_World, cCallbacks & a_Callbacks, double a_StartX, double a_StartY, double a_StartZ, double a_EndX, double a_EndY, double a_EndZ);
/// Traces one line between Start and End; returns true if the entire line was traced (until OnNoMoreHits())
static bool Trace(cWorld & a_World, cCallbacks & a_Callbacks, const Vector3d & a_Start, const Vector3d & a_End);
protected:
// The start point of the trace
double m_StartX, m_StartY, m_StartZ;
// The end point of the trace
double m_EndX, m_EndY, m_EndZ;
// The difference in coords, End - Start
double m_DiffX, m_DiffY, m_DiffZ;
// The increment at which the block coords are going from Start to End; either +1 or -1
int m_DirX, m_DirY, m_DirZ;
// The current block
int m_CurrentX, m_CurrentY, m_CurrentZ;
/// Adjusts the start point above the world to just at the world's top
void FixStartAboveWorld(void);
/// Adjusts the start point below the world to just at the world's bottom
void FixStartBelowWorld(void);
/// Calculates the XZ coords of an intersection with the specified Yconst plane; assumes that such an intersection exists
void CalcXZIntersection(double a_Y, double & a_IntersectX, double & a_IntersectZ);
/// Moves m_Current to the next block on the line; returns false if no move is possible (reached the end)
bool MoveToNextBlock(void);
// cChunkCallback overrides:
virtual bool Item(cChunk * a_Chunk) override;
} ;

View File

@ -6,34 +6,14 @@
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
#include "LuaScript.h"
extern "C"
{
#include "lualib.h"
}
#include "tolua++.h"
#include "Bindings.h"
#include "ManualBindings.h"
// fwd: SQLite/lsqlite3.c
extern "C"
{
LUALIB_API int luaopen_lsqlite3(lua_State * L);
}
// fwd: LuaExpat/lxplib.c:
extern "C"
{
int luaopen_lxp(lua_State * L);
}
cLuaScript::cLuaScript()
: m_LuaState(NULL)
: m_LuaState("cLuaScript")
{
}
@ -42,166 +22,45 @@ cLuaScript::cLuaScript()
cLuaScript::~cLuaScript()
{
if( m_LuaState )
{
lua_close( m_LuaState );
m_LuaState = 0;
}
}
void cLuaScript::Initialize()
{
// Check to see if this script has not been initialized before
ASSERT(!m_LuaState);
ASSERT(!m_LuaState.IsValid());
// Create a Lua state and bind all libraries to it
m_LuaState = lua_open();
luaL_openlibs(m_LuaState);
tolua_AllToLua_open(m_LuaState);
ManualBindings::Bind(m_LuaState);
luaopen_lsqlite3(m_LuaState);
luaopen_lxp(m_LuaState);
m_LuaState.Create();
}
bool cLuaScript::LoadFile( const char* a_FilePath )
bool cLuaScript::LoadFile(const char * a_FilePath)
{
// Make sure the plugin is initialized
ASSERT(m_LuaState);
ASSERT(m_LuaState.IsValid());
// Load the file into the Lua state
int s = luaL_loadfile(m_LuaState, a_FilePath );
if (ReportErrors(s))
{
return false;
}
return true;
return m_LuaState.LoadFile(a_FilePath);
}
bool cLuaScript::Execute()
bool cLuaScript::CallShowPage(cWebAdmin & a_WebAdmin, HTTPTemplateRequest & a_Request, AString & a_ReturnedString)
{
// Make sure we got a Lua state
ASSERT(m_LuaState);
// Execute the script as it is right now
int s = lua_pcall(m_LuaState, 0, LUA_MULTRET, 0);
if( ReportErrors( s ) )
ASSERT(m_LuaState.IsValid());
m_LuaState.PushFunction("ShowPage");
m_LuaState.PushUserType(&a_WebAdmin, "cWebAdmin");
m_LuaState.PushUserType(&a_Request, "HTTPTemplateRequest");
if (!m_LuaState.CallFunction(1))
{
return false;
}
return true;
}
bool cLuaScript::ReportErrors( int a_Status )
{
if (a_Status == 0)
{
// No error to report
return false;
}
// Status was set to error so get the error from the Lua state and log it
LOGERROR("LUA: %s", lua_tostring(m_LuaState, -1));
lua_pop(m_LuaState, 1);
// Return true to indicate that an error was returned
return true;
}
bool cLuaScript::LuaPushFunction( const char * a_FunctionName, bool a_bLogError /*= true*/ )
{
ASSERT(m_LuaState);
// Find and push the function on the Lua stack
lua_getglobal(m_LuaState, a_FunctionName);
// Make sure we found a function
if (!lua_isfunction(m_LuaState, -1))
{
if (a_bLogError)
{
LOGWARN("LUA: Could not find function %s()", a_FunctionName);
}
// Pop the pushed 'object' back
lua_pop(m_LuaState, 1);
return false;
}
// Successfully pushed a function to the Lua stack
return true;
}
bool cLuaScript::LuaCallFunction( int a_NumArgs, int a_NumResults, const char * a_FunctionName )
{
ASSERT(m_LuaState);
// Make sure there's a lua function on the stack
ASSERT(lua_isfunction(m_LuaState, -a_NumArgs - 1));
// Call the desired function
int s = lua_pcall(m_LuaState, a_NumArgs, a_NumResults, 0);
// Check for errors
if (ReportErrors(s))
{
LOGWARN("LUA: Error calling function %s()", a_FunctionName);
return false;
}
// Successfully executed function
return true;
}
bool cLuaScript::CallFunction( const char* a_Function, AString& ReturnedString )
{
// Make sure we have the required things to call a function
ASSERT(m_LuaState);
ASSERT(a_Function);
// Push the desired function on the stack
if (!LuaPushFunction(a_Function))
{
return false;
}
if (!LuaCallFunction(0, 1, a_Function))
{
return false;
}
if (lua_isstring(m_LuaState, -1))
{
ReturnedString = tolua_tostring(m_LuaState, -1, "");
a_ReturnedString.assign(tolua_tostring(m_LuaState, -1, ""));
}
lua_pop(m_LuaState, 1);
return true;
@ -210,69 +69,3 @@ bool cLuaScript::CallFunction( const char* a_Function, AString& ReturnedString )
bool cLuaScript::CallFunction( const char* a_Function, const sLuaUsertype& a_UserType, AString& ReturnedString )
{
// Make sure we have the required things to call a function
ASSERT(m_LuaState);
ASSERT(a_Function);
// Push the desired function on the stack
if (!LuaPushFunction(a_Function))
{
return false;
}
tolua_pushusertype(m_LuaState, a_UserType.Object, a_UserType.ClassName);
if (!LuaCallFunction(1, 1, a_Function))
{
return false;
}
if (lua_isstring(m_LuaState, -1))
{
ReturnedString = tolua_tostring(m_LuaState, -1, "");
}
lua_pop(m_LuaState, 1);
return true;
}
bool cLuaScript::CallFunction( const char* a_Function, const sLuaUsertype& a_UserType1, const sLuaUsertype& a_UserType2, AString& ReturnedString )
{
// Make sure we have the required things to call a function
ASSERT(m_LuaState);
ASSERT(a_Function);
// Push the desired function on the stack
if (!LuaPushFunction(a_Function))
{
return false;
}
tolua_pushusertype(m_LuaState, a_UserType1.Object, a_UserType1.ClassName);
tolua_pushusertype(m_LuaState, a_UserType2.Object, a_UserType2.ClassName);
if (!LuaCallFunction(2, 1, a_Function))
{
return false;
}
if (lua_isstring(m_LuaState, -1))
{
ReturnedString = tolua_tostring(m_LuaState, -1, "");
}
lua_pop(m_LuaState, 1);
return true;
}

View File

@ -9,19 +9,15 @@
#pragma once
struct lua_State;
#include "LuaState.h"
struct sLuaUsertype
{
sLuaUsertype(void* a_pObject, const char* a_pClassName) : Object(a_pObject), ClassName(a_pClassName) {}
//
void* Object;
const char* ClassName;
} ;
// fwd:
class cWebAdmin;
struct HTTPTemplateRequest;
@ -30,32 +26,18 @@ struct sLuaUsertype
class cLuaScript
{
public:
cLuaScript();
~cLuaScript();
cLuaScript(void);
/// Prepares a Lua state
void Initialize();
void Initialize();
/// Load a Lua script on the given path
bool LoadFile(const char* a_FilePath);
bool LoadFile(const char * a_FilePath);
/// Execute the loaded Lua script
bool Execute();
/// Call a function on the Lua script. Put all overloads here
bool CallFunction(const char* a_Function, AString& ReturnedString);
bool CallFunction(const char* a_Function, const sLuaUsertype& a_UserType, AString& ReturnedString);
bool CallFunction(const char* a_Function, const sLuaUsertype& a_UserType1, const sLuaUsertype& a_UserType2, AString& ReturnedString);
bool CallShowPage(cWebAdmin & a_WebAdmin, HTTPTemplateRequest & a_Request, AString & a_ReturnedString);
protected:
/// Reports an error in the log if a_Status is flagged as an error. Returns true when a_Status is flagged as error, returns false when no error occured.
bool ReportErrors(int a_Status);
/// Helper functions for calling functions in Lua
bool LuaPushFunction(const char * a_FunctionName, bool a_bLogError = true);
bool LuaCallFunction(int a_NumArgs, int a_NumResults, const char * a_FunctionName ); // a_FunctionName is only used for error messages, nothing else
private:
lua_State* m_LuaState;
cLuaState m_LuaState;
} ;

646
source/LuaState.cpp Normal file
View File

@ -0,0 +1,646 @@
// LuaState.cpp
// Implements the cLuaState class representing the wrapper over lua_State *, provides associated helper functions
#include "Globals.h"
#include "LuaState.h"
extern "C"
{
#include "lualib.h"
}
#include "tolua++.h"
#include "Bindings.h"
#include "ManualBindings.h"
// fwd: SQLite/lsqlite3.c
extern "C"
{
LUALIB_API int luaopen_lsqlite3(lua_State * L);
}
// fwd: LuaExpat/lxplib.c:
extern "C"
{
int luaopen_lxp(lua_State * L);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// cLuaState:
cLuaState::cLuaState(const AString & a_SubsystemName) :
m_LuaState(NULL),
m_IsOwned(false),
m_SubsystemName(a_SubsystemName),
m_NumCurrentFunctionArgs(-1)
{
}
cLuaState::cLuaState(lua_State * a_AttachState) :
m_LuaState(a_AttachState),
m_IsOwned(false),
m_SubsystemName("<attached>"),
m_NumCurrentFunctionArgs(-1)
{
}
cLuaState::~cLuaState()
{
if (IsValid())
{
if (m_IsOwned)
{
Close();
}
else
{
Detach();
}
}
}
void cLuaState::Create(void)
{
if (m_LuaState != NULL)
{
LOGWARNING("%s: Trying to create an already-existing LuaState, ignoring.", __FUNCTION__);
return;
}
m_LuaState = lua_open();
luaL_openlibs(m_LuaState);
tolua_AllToLua_open(m_LuaState);
ManualBindings::Bind(m_LuaState);
luaopen_lsqlite3(m_LuaState);
luaopen_lxp(m_LuaState);
m_IsOwned = true;
}
void cLuaState::Close(void)
{
if (m_LuaState == NULL)
{
LOGWARNING("%s: Trying to close an invalid LuaState, ignoring.", __FUNCTION__);
return;
}
if (!m_IsOwned)
{
LOGWARNING(
"%s: Detected mis-use, calling Close() on an attached state (0x%p). Detaching instead.",
__FUNCTION__, m_LuaState
);
Detach();
return;
}
lua_close(m_LuaState);
m_LuaState = NULL;
m_IsOwned = false;
}
void cLuaState::Attach(lua_State * a_State)
{
if (m_LuaState != NULL)
{
LOGINFO("%s: Already contains a LuaState (0x%p), will be closed / detached.", __FUNCTION__, m_LuaState);
if (m_IsOwned)
{
Close();
}
else
{
Detach();
}
}
m_LuaState = a_State;
m_IsOwned = false;
}
void cLuaState::Detach(void)
{
if (m_LuaState == NULL)
{
return;
}
if (m_IsOwned)
{
LOGWARNING(
"%s: Detected a mis-use, calling Detach() when the state is owned. Closing the owned state (0x%p).",
__FUNCTION__, m_LuaState
);
Close();
return;
}
m_LuaState = NULL;
}
bool cLuaState::LoadFile(const AString & a_FileName)
{
ASSERT(IsValid());
// Load the file:
int s = luaL_loadfile(m_LuaState, a_FileName.c_str());
if (ReportErrors(s))
{
LOGWARNING("Can't load %s because of an error in file %s", m_SubsystemName.c_str(), a_FileName.c_str());
return false;
}
// Execute the globals:
s = lua_pcall(m_LuaState, 0, LUA_MULTRET, 0);
if (ReportErrors(s))
{
LOGWARNING("Error in %s in file %s", m_SubsystemName.c_str(), a_FileName.c_str());
return false;
}
return true;
}
bool cLuaState::PushFunction(const char * a_FunctionName, bool a_ShouldLogFailure /* = true */)
{
ASSERT(m_NumCurrentFunctionArgs == -1); // If not, there's already something pushed onto the stack
if (!IsValid())
{
// This happens if cPlugin::Initialize() fails with an error
return false;
}
lua_getglobal(m_LuaState, a_FunctionName);
if (!lua_isfunction(m_LuaState, -1))
{
if (a_ShouldLogFailure)
{
LOGWARNING("Error in %s: Could not find function %s()", m_SubsystemName.c_str(), a_FunctionName);
}
lua_pop(m_LuaState, 1);
return false;
}
m_CurrentFunctionName.assign(a_FunctionName);
m_NumCurrentFunctionArgs = 0;
return true;
}
bool cLuaState::PushFunctionFromRegistry(int a_FnRef)
{
ASSERT(IsValid());
ASSERT(m_NumCurrentFunctionArgs == -1); // If not, there's already something pushed onto the stack
lua_rawgeti(m_LuaState, LUA_REGISTRYINDEX, a_FnRef); // same as lua_getref()
if (!lua_isfunction(m_LuaState, -1))
{
lua_pop(m_LuaState, 1);
return false;
}
m_CurrentFunctionName = "<callback>";
m_NumCurrentFunctionArgs = 0;
return true;
}
bool cLuaState::PushFunctionFromRefTable(cRef & a_TableRef, const char * a_FnName)
{
ASSERT(IsValid());
ASSERT(m_NumCurrentFunctionArgs == -1); // If not, there's already something pushed onto the stack
lua_rawgeti(m_LuaState, LUA_REGISTRYINDEX, a_TableRef); // Get the table ref
if (!lua_istable(m_LuaState, -1))
{
// Not a table, bail out
lua_pop(m_LuaState, 1);
return false;
}
lua_getfield(m_LuaState, -1, a_FnName);
if (lua_isnil(m_LuaState, -1) || !lua_isfunction(m_LuaState, -1))
{
// Not a valid function, bail out
lua_pop(m_LuaState, 2);
return false;
}
lua_remove(m_LuaState, -2); // Remove the table ref from the stack
m_CurrentFunctionName = "<table_callback>";
m_NumCurrentFunctionArgs = 0;
return true;
}
void cLuaState::PushStringVector(const AStringVector & a_Vector)
{
ASSERT(IsValid());
ASSERT(m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first
lua_createtable(m_LuaState, a_Vector.size(), 0);
int newTable = lua_gettop(m_LuaState);
int index = 1;
for (AStringVector::const_iterator itr = a_Vector.begin(), end = a_Vector.end(); itr != end; ++itr, ++index)
{
tolua_pushstring(m_LuaState, itr->c_str());
lua_rawseti(m_LuaState, newTable, index);
}
m_NumCurrentFunctionArgs += 1;
}
void cLuaState::PushUserType(void * a_Object, const char * a_Type)
{
ASSERT(IsValid());
ASSERT(m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first
tolua_pushusertype(m_LuaState, a_Object, a_Type);
m_NumCurrentFunctionArgs += 1;
}
void cLuaState::PushNumber(int a_Value)
{
ASSERT(IsValid());
ASSERT(m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first
tolua_pushnumber(m_LuaState, a_Value);
m_NumCurrentFunctionArgs += 1;
}
void cLuaState::PushNumber(double a_Value)
{
ASSERT(IsValid());
ASSERT(m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first
tolua_pushnumber(m_LuaState, a_Value);
m_NumCurrentFunctionArgs += 1;
}
void cLuaState::PushString(const char * a_Value)
{
ASSERT(IsValid());
ASSERT(m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first
tolua_pushstring(m_LuaState, a_Value);
m_NumCurrentFunctionArgs += 1;
}
void cLuaState::PushBool(bool a_Value)
{
ASSERT(IsValid());
ASSERT(m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first
tolua_pushboolean(m_LuaState, a_Value ? 1 : 0);
m_NumCurrentFunctionArgs += 1;
}
void cLuaState::PushObject(cWorld * a_World)
{
ASSERT(IsValid());
ASSERT(m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first
tolua_pushusertype(m_LuaState, a_World, "cWorld");
m_NumCurrentFunctionArgs += 1;
}
void cLuaState::PushObject(cPlayer * a_Player)
{
ASSERT(IsValid());
ASSERT(m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first
tolua_pushusertype(m_LuaState, a_Player, "cPlayer");
m_NumCurrentFunctionArgs += 1;
}
void cLuaState::PushObject(cEntity * a_Entity)
{
ASSERT(IsValid());
ASSERT(m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first
tolua_pushusertype(m_LuaState, a_Entity, "cEntity");
m_NumCurrentFunctionArgs += 1;
}
void cLuaState::PushObject(cItem * a_Item)
{
ASSERT(IsValid());
ASSERT(m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first
tolua_pushusertype(m_LuaState, a_Item, "cItem");
m_NumCurrentFunctionArgs += 1;
}
void cLuaState::PushObject(cItems * a_Items)
{
ASSERT(IsValid());
ASSERT(m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first
tolua_pushusertype(m_LuaState, a_Items, "cItems");
m_NumCurrentFunctionArgs += 1;
}
void cLuaState::PushObject(cClientHandle * a_Client)
{
ASSERT(IsValid());
ASSERT(m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first
tolua_pushusertype(m_LuaState, a_Client, "cClientHandle");
m_NumCurrentFunctionArgs += 1;
}
void cLuaState::PushObject(cPickup * a_Pickup)
{
ASSERT(IsValid());
ASSERT(m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first
tolua_pushusertype(m_LuaState, a_Pickup, "cPickup");
m_NumCurrentFunctionArgs += 1;
}
bool cLuaState::CallFunction(int a_NumResults)
{
ASSERT (m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first
ASSERT(lua_isfunction(m_LuaState, -m_NumCurrentFunctionArgs - 1));
int s = lua_pcall(m_LuaState, m_NumCurrentFunctionArgs, a_NumResults, 0);
if (ReportErrors(s))
{
LOGWARNING("Error in %s calling function %s()", m_SubsystemName.c_str(), m_CurrentFunctionName.c_str());
m_NumCurrentFunctionArgs = -1;
m_CurrentFunctionName.clear();
return false;
}
m_NumCurrentFunctionArgs = -1;
m_CurrentFunctionName.clear();
return true;
}
bool cLuaState::CheckParamUserType(int a_StartParam, const char * a_UserType, int a_EndParam)
{
ASSERT(IsValid());
if (a_EndParam < 0)
{
a_EndParam = a_StartParam;
}
tolua_Error tolua_err;
for (int i = a_StartParam; i <= a_EndParam; i++)
{
if (tolua_isusertype(m_LuaState, i, a_UserType, 0, &tolua_err))
{
continue;
}
// Not the correct parameter
lua_Debug entry;
VERIFY(lua_getstack(m_LuaState, 0, &entry));
VERIFY(lua_getinfo (m_LuaState, "n", &entry));
AString ErrMsg = Printf("#ferror in function '%s'.", (entry.name != NULL) ? entry.name : "?");
tolua_error(m_LuaState, ErrMsg.c_str(), &tolua_err);
return false;
} // for i - Param
// All params checked ok
return true;
}
bool cLuaState::CheckParamTable(int a_StartParam, int a_EndParam)
{
ASSERT(IsValid());
if (a_EndParam < 0)
{
a_EndParam = a_StartParam;
}
tolua_Error tolua_err;
for (int i = a_StartParam; i <= a_EndParam; i++)
{
if (tolua_istable(m_LuaState, i, 0, &tolua_err))
{
continue;
}
// Not the correct parameter
lua_Debug entry;
VERIFY(lua_getstack(m_LuaState, 0, &entry));
VERIFY(lua_getinfo (m_LuaState, "n", &entry));
AString ErrMsg = Printf("#ferror in function '%s'.", (entry.name != NULL) ? entry.name : "?");
tolua_error(m_LuaState, ErrMsg.c_str(), &tolua_err);
return false;
} // for i - Param
// All params checked ok
return true;
}
bool cLuaState::CheckParamNumber(int a_StartParam, int a_EndParam)
{
ASSERT(IsValid());
if (a_EndParam < 0)
{
a_EndParam = a_StartParam;
}
tolua_Error tolua_err;
for (int i = a_StartParam; i <= a_EndParam; i++)
{
if (tolua_isnumber(m_LuaState, i, 0, &tolua_err))
{
continue;
}
// Not the correct parameter
lua_Debug entry;
VERIFY(lua_getstack(m_LuaState, 0, &entry));
VERIFY(lua_getinfo (m_LuaState, "n", &entry));
AString ErrMsg = Printf("#ferror in function '%s'.", (entry.name != NULL) ? entry.name : "?");
tolua_error(m_LuaState, ErrMsg.c_str(), &tolua_err);
return false;
} // for i - Param
// All params checked ok
return true;
}
bool cLuaState::CheckParamEnd(int a_Param)
{
tolua_Error tolua_err;
if (tolua_isnoobj(m_LuaState, a_Param, &tolua_err))
{
return true;
}
// Not the correct parameter
lua_Debug entry;
VERIFY(lua_getstack(m_LuaState, 0, &entry));
VERIFY(lua_getinfo (m_LuaState, "n", &entry));
AString ErrMsg = Printf("#ferror in function '%s': Too many arguments.", (entry.name != NULL) ? entry.name : "?");
tolua_error(m_LuaState, ErrMsg.c_str(), &tolua_err);
return false;
}
bool cLuaState::ReportErrors(int a_Status)
{
return ReportErrors(m_LuaState, a_Status);
}
bool cLuaState::ReportErrors(lua_State * a_LuaState, int a_Status)
{
if (a_Status == 0)
{
// No error to report
return false;
}
LOGWARNING("LUA: %d - %s", a_Status, lua_tostring(a_LuaState, -1));
lua_pop(a_LuaState, 1);
return true;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// cLuaState::cRef:
cLuaState::cRef::cRef(cLuaState & a_LuaState, int a_StackPos) :
m_LuaState(a_LuaState)
{
ASSERT(m_LuaState.IsValid());
lua_pushvalue(m_LuaState, a_StackPos); // Push a copy of the value at a_StackPos onto the stack
m_Ref = luaL_ref(m_LuaState, LUA_REGISTRYINDEX);
}
cLuaState::cRef::~cRef()
{
ASSERT(m_LuaState.IsValid());
if (IsValid())
{
luaL_unref(m_LuaState, LUA_REGISTRYINDEX, m_Ref);
}
}

198
source/LuaState.h Normal file
View File

@ -0,0 +1,198 @@
// LuaState.h
// Declares the cLuaState class representing the wrapper over lua_State *, provides associated helper functions
/*
The contained lua_State can be either owned or attached.
Owned lua_State is created by calling Create() and the cLuaState automatically closes the state
Or, lua_State can be attached by calling Attach(), the cLuaState doesn't close such a state
Attaching a state will automatically close an owned state.
Calling a Lua function is done by pushing the function, either by PushFunction() or PushFunctionFromRegistry(),
then pushing the arguments (PushString(), PushNumber(), PushUserData() etc.) and finally
executing CallFunction(). cLuaState automatically keeps track of the number of arguments and the name of the
function (for logging purposes), which makes the call less error-prone.
Reference management is provided by the cLuaState::cRef class. This is used when you need to hold a reference to
any Lua object across several function calls; usually this is used for callbacks. The class is RAII-like, with
automatic resource management.
*/
#pragma once
extern "C"
{
#include "lauxlib.h"
}
class cWorld;
class cPlayer;
class cEntity;
class cItem;
class cItems;
class cClientHandle;
class cPickup;
/// Encapsulates a Lua state and provides some syntactic sugar for common operations
class cLuaState
{
public:
/// Used for storing references to object in the global registry
class cRef
{
public:
/// Creates a reference in the specified LuaState for object at the specified StackPos
cRef(cLuaState & a_LuaState, int a_StackPos);
~cRef();
/// Returns true if the reference is valid
bool IsValid(void) const {return (m_Ref != LUA_REFNIL); }
/// Allows to use this class wherever an int (i. e. ref) is to be used
operator int(void) { return m_Ref; }
protected:
cLuaState & m_LuaState;
int m_Ref;
} ;
/** Creates a new instance. The LuaState is not initialized.
a_SubsystemName is used for reporting problems in the console, it is "plugin %s" for plugins,
or "LuaScript" for the cLuaScript template
*/
cLuaState(const AString & a_SubsystemName);
/** Creates a new instance. The a_AttachState is attached.
Subsystem name is set to "<attached>".
*/
explicit cLuaState(lua_State * a_AttachState);
~cLuaState();
/// Allows this object to be used in the same way as a lua_State *, for example in the LuaLib functions
operator lua_State * (void) { return m_LuaState; }
/// Creates the m_LuaState, if not closed already. This state will be automatically closed in the destructor
void Create(void);
/// Closes the m_LuaState, if not closed already
void Close(void);
/// Attaches the specified state. Operations will be carried out on this state, but it will not be closed in the destructor
void Attach(lua_State * a_State);
/// Detaches a previously attached state.
void Detach(void);
/// Returns true if the m_LuaState is valid
bool IsValid(void) const { return (m_LuaState != NULL); }
/** Loads the specified file
Returns false and logs a warning to the console if not successful (but the LuaState is kept open).
m_SubsystemName is displayed in the warning log message.
*/
bool LoadFile(const AString & a_FileName);
/** Pushes the function of the specified name onto the stack.
Returns true if successful.
If a_ShouldLogFail is true, logs a warning on failure (incl. m_SubsystemName)
*/
bool PushFunction(const char * a_FunctionName, bool a_ShouldLogFailure = true);
/** Pushes a function that has been saved into the global registry, identified by a_FnRef.
Returns true if successful. Logs a warning on failure
*/
bool PushFunctionFromRegistry(int a_FnRef);
/** Pushes a function that is stored in a table ref.
Returns true if successful, false on failure. Doesn't log failure.
*/
bool PushFunctionFromRefTable(cRef & a_TableRef, const char * a_FnName);
/// Pushes a string vector, as a table, onto the stack
void PushStringVector(const AStringVector & a_Vector);
/// Pushes a usertype of the specified class type onto the stack
void PushUserType(void * a_Object, const char * a_Type);
/// Pushes an integer onto the stack
void PushNumber(int a_Value);
/// Pushes a double onto the stack
void PushNumber(double a_Value);
/// Pushes a string onto the stack
void PushString(const char * a_Value);
/// Pushes a bool onto the stack
void PushBool(bool a_Value);
// Special family of functions that do PushUserType internally, but require one less parameter
void PushObject(cWorld * a_World);
void PushObject(cPlayer * a_Player);
void PushObject(cEntity * a_Entity);
void PushObject(cItem * a_Item);
void PushObject(cItems * a_Items);
void PushObject(cClientHandle * a_ClientHandle);
void PushObject(cPickup * a_Pickup);
/**
Calls the function that has been pushed onto the stack by PushFunction(),
with arguments pushed by PushXXX().
Returns true if successful, logs a warning on failure.
*/
bool CallFunction(int a_NumReturnValues);
/// Returns true if the specified parameters on the stack are of the specified usertype; also logs warning if not
bool CheckParamUserType(int a_StartParam, const char * a_UserType, int a_EndParam = -1);
/// Returns true if the specified parameters on the stack are a table; also logs warning if not
bool CheckParamTable(int a_StartParam, int a_EndParam = -1);
/// Returns true if the specified parameters on the stack are a number; also logs warning if not
bool CheckParamNumber(int a_StartParam, int a_EndParam = -1);
/// Returns true if the specified parameter on the stack is nil (indicating an end-of-parameters)
bool CheckParamEnd(int a_Param);
/// If the status is nonzero, prints the text on the top of Lua stack and returns true
bool ReportErrors(int status);
/// If the status is nonzero, prints the text on the top of Lua stack and returns true
static bool ReportErrors(lua_State * a_LuaState, int status);
protected:
lua_State * m_LuaState;
/// If true, the state is owned by this object and will be auto-Closed. False => attached state
bool m_IsOwned;
/** The subsystem name is used for reporting errors to the console, it is either "plugin %s" or "LuaScript"
whatever is given to the constructor
*/
AString m_SubsystemName;
/// Name of the currently pushed function (for the Push / Call chain)
AString m_CurrentFunctionName;
/// Number of arguments currently pushed (for the Push / Call chain)
int m_NumCurrentFunctionArgs;
} ;

View File

@ -19,13 +19,8 @@
#include "BlockEntities/FurnaceEntity.h"
#include "md5/md5.h"
#include "LuaWindow.h"
// fwd: LuaCommandBinder.cpp
bool report_errors(lua_State* lua, int status);
#include "LuaState.h"
#include "LineBlockTracer.h"
@ -83,23 +78,14 @@ int lua_do_error(lua_State* L, const char * a_pFormat, ...)
* Lua bound functions with special return types
**/
static int tolua_StringSplit(lua_State* tolua_S)
static int tolua_StringSplit(lua_State * tolua_S)
{
std::string str = ((std::string) tolua_tocppstring(tolua_S,1,0));
std::string delim = ((std::string) tolua_tocppstring(tolua_S,2,0));
cLuaState LuaState(tolua_S);
std::string str = (std::string)tolua_tocppstring(LuaState, 1, 0);
std::string delim = (std::string)tolua_tocppstring(LuaState, 2, 0);
AStringVector Split = StringSplit( str, delim );
lua_createtable(tolua_S, Split.size(), 0);
int newTable = lua_gettop(tolua_S);
int index = 1;
std::vector<std::string>::const_iterator iter = Split.begin();
while(iter != Split.end()) {
tolua_pushstring( tolua_S, (*iter).c_str() );
lua_rawseti(tolua_S, newTable, index);
++iter;
++index;
}
AStringVector Split = StringSplit(str, delim);
LuaState.PushStringVector(Split);
return 1;
}
@ -157,7 +143,8 @@ cPlugin_NewLua * GetLuaPlugin(lua_State * L)
lua_getglobal(L, LUA_PLUGIN_INSTANCE_VAR_NAME);
if (!lua_islightuserdata(L, -1))
{
LOGERROR("%s: cannot get plugin instance, what have you done to my Lua state?", __FUNCTION__);
LOGWARNING("%s: cannot get plugin instance, what have you done to my Lua state?", __FUNCTION__);
lua_pop(L, 1);
return NULL;
}
cPlugin_NewLua * Plugin = (cPlugin_NewLua *)lua_topointer(L, -1);
@ -169,7 +156,7 @@ cPlugin_NewLua * GetLuaPlugin(lua_State * L)
template<
class Ty1,
class Ty2,
@ -177,181 +164,273 @@ template<
>
static int tolua_DoWith(lua_State* tolua_S)
{
int NumArgs = lua_gettop(tolua_S) - 1; /* This includes 'self' */
if ((NumArgs != 2) && (NumArgs != 3))
int NumArgs = lua_gettop(tolua_S) - 1; /* This includes 'self' */
if ((NumArgs != 2) && (NumArgs != 3))
{
return lua_do_error(tolua_S, "Error in function call '#funcname#': Requires 2 or 3 arguments, got %i", NumArgs);
}
}
Ty1 * self = (Ty1 *) tolua_tousertype(tolua_S, 1, 0);
Ty1 * self = (Ty1 *) tolua_tousertype(tolua_S, 1, 0);
const char * ItemName = tolua_tocppstring(tolua_S, 2, "");
if ((ItemName == NULL) || (ItemName[0] == 0))
{
return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a non-empty string for parameter #1", NumArgs);
}
if (!lua_isfunction( tolua_S, 3))
{
return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a function for parameter #2", NumArgs);
}
/* luaL_ref gets reference to value on top of the stack, the table is the last argument and therefore on the top */
int TableRef = LUA_REFNIL;
if (NumArgs == 3)
{
TableRef = luaL_ref(tolua_S, LUA_REGISTRYINDEX);
if (TableRef == LUA_REFNIL)
{
return lua_do_error(tolua_S, "Error in function call '#funcname#': Could not get value reference of parameter #3", NumArgs);
}
}
/* table value is popped, and now function is on top of the stack */
int FuncRef = luaL_ref(tolua_S, LUA_REGISTRYINDEX);
if (FuncRef == LUA_REFNIL)
{
return lua_do_error(tolua_S, "Error in function call '#funcname#': Could not get function reference of parameter #2", NumArgs);
}
class cLuaCallback : public cItemCallback<Ty2>
const char * ItemName = tolua_tocppstring(tolua_S, 2, "");
if ((ItemName == NULL) || (ItemName[0] == 0))
{
public:
cLuaCallback(lua_State* a_LuaState, int a_FuncRef, int a_TableRef)
: LuaState( a_LuaState )
, FuncRef( a_FuncRef )
, TableRef( a_TableRef )
{}
return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a non-empty string for parameter #1", NumArgs);
}
if (!lua_isfunction( tolua_S, 3))
{
return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a function for parameter #2", NumArgs);
}
private:
virtual bool Item(Ty2 * a_Item) override
{
lua_rawgeti( LuaState, LUA_REGISTRYINDEX, FuncRef); /* Push function reference */
/* luaL_ref gets reference to value on top of the stack, the table is the last argument and therefore on the top */
int TableRef = LUA_REFNIL;
if (NumArgs == 3)
{
TableRef = luaL_ref(tolua_S, LUA_REGISTRYINDEX);
if (TableRef == LUA_REFNIL)
{
return lua_do_error(tolua_S, "Error in function call '#funcname#': Could not get value reference of parameter #3", NumArgs);
}
}
/* table value is popped, and now function is on top of the stack */
int FuncRef = luaL_ref(tolua_S, LUA_REGISTRYINDEX);
if (FuncRef == LUA_REFNIL)
{
return lua_do_error(tolua_S, "Error in function call '#funcname#': Could not get function reference of parameter #2", NumArgs);
}
class cLuaCallback : public cItemCallback<Ty2>
{
public:
cLuaCallback(lua_State* a_LuaState, int a_FuncRef, int a_TableRef)
: LuaState( a_LuaState )
, FuncRef( a_FuncRef )
, TableRef( a_TableRef )
{}
private:
virtual bool Item(Ty2 * a_Item) override
{
lua_rawgeti( LuaState, LUA_REGISTRYINDEX, FuncRef); /* Push function reference */
tolua_pushusertype(LuaState, a_Item, Ty2::GetClassStatic());
if (TableRef != LUA_REFNIL)
{
lua_rawgeti( LuaState, LUA_REGISTRYINDEX, TableRef); /* Push table reference */
}
if (TableRef != LUA_REFNIL)
{
lua_rawgeti( LuaState, LUA_REGISTRYINDEX, TableRef); /* Push table reference */
}
int s = lua_pcall(LuaState, (TableRef == LUA_REFNIL ? 1 : 2), 1, 0);
if (report_errors(LuaState, s))
int s = lua_pcall(LuaState, (TableRef == LUA_REFNIL ? 1 : 2), 1, 0);
if (cLuaState::ReportErrors(LuaState, s))
{
return true; // Abort enumeration
}
if (lua_isboolean(LuaState, -1))
{
return (tolua_toboolean(LuaState, -1, 0) > 0);
}
return false; /* Continue enumeration */
}
lua_State * LuaState;
int FuncRef;
int TableRef;
} Callback(tolua_S, FuncRef, TableRef);
if (lua_isboolean(LuaState, -1))
{
return (tolua_toboolean(LuaState, -1, 0) > 0);
}
return false; /* Continue enumeration */
}
lua_State * LuaState;
int FuncRef;
int TableRef;
} Callback(tolua_S, FuncRef, TableRef);
bool bRetVal = (self->*Func1)(ItemName, Callback);
/* Unreference the values again, so the LUA_REGISTRYINDEX can make place for other references */
luaL_unref(tolua_S, LUA_REGISTRYINDEX, TableRef);
luaL_unref(tolua_S, LUA_REGISTRYINDEX, FuncRef);
/* Unreference the values again, so the LUA_REGISTRYINDEX can make place for other references */
luaL_unref(tolua_S, LUA_REGISTRYINDEX, TableRef);
luaL_unref(tolua_S, LUA_REGISTRYINDEX, FuncRef);
/* Push return value on stack */
tolua_pushboolean(tolua_S, bRetVal );
return 1;
/* Push return value on stack */
tolua_pushboolean(tolua_S, bRetVal );
return 1;
}
template< class Ty1,
class Ty2,
bool (Ty1::*Func1)(int, int, int, cItemCallback<Ty2> &) >
static int tolua_DoWithXYZ(lua_State* tolua_S)
template<
class Ty1,
class Ty2,
bool (Ty1::*Func1)(int, cItemCallback<Ty2> &)
>
static int tolua_DoWithID(lua_State* tolua_S)
{
int NumArgs = lua_gettop(tolua_S) - 1; /* This includes 'self' */
if ((NumArgs != 4) && (NumArgs != 5))
{
return lua_do_error(tolua_S, "Error in function call '#funcname#': Requires 4 or 5 arguments, got %i", NumArgs);
}
int NumArgs = lua_gettop(tolua_S) - 1; /* This includes 'self' */
if ((NumArgs != 2) && (NumArgs != 3))
{
return lua_do_error(tolua_S, "Error in function call '#funcname#': Requires 2 or 3 arguments, got %i", NumArgs);
}
Ty1 * self = (Ty1 *) tolua_tousertype(tolua_S, 1, 0);
if (!lua_isnumber(tolua_S, 2) || !lua_isnumber(tolua_S, 3) || !lua_isnumber(tolua_S, 4))
{
return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a number for parameters #1, #2 and #3");
}
Ty1 * self = (Ty1 *)tolua_tousertype(tolua_S, 1, 0);
int ItemX = ((int)tolua_tonumber(tolua_S, 2, 0));
int ItemY = ((int)tolua_tonumber(tolua_S, 3, 0));
int ItemZ = ((int)tolua_tonumber(tolua_S, 4, 0));
LOG("x %i y %i z %i", ItemX, ItemY, ItemZ );
if (!lua_isfunction( tolua_S, 5))
{
return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a function for parameter #4");
}
int ItemID = (int)tolua_tonumber(tolua_S, 2, 0);
if (!lua_isfunction(tolua_S, 3))
{
return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a function for parameter #2", NumArgs);
}
/* luaL_ref gets reference to value on top of the stack, the table is the last argument and therefore on the top */
int TableRef = LUA_REFNIL;
if (NumArgs == 5)
{
TableRef = luaL_ref(tolua_S, LUA_REGISTRYINDEX);
if (TableRef == LUA_REFNIL)
{
return lua_do_error(tolua_S, "Error in function call '#funcname#': Could not get value reference of parameter #5");
}
}
/* luaL_ref gets reference to value on top of the stack, the table is the last argument and therefore on the top */
int TableRef = LUA_REFNIL;
if (NumArgs == 3)
{
TableRef = luaL_ref(tolua_S, LUA_REGISTRYINDEX);
if (TableRef == LUA_REFNIL)
{
return lua_do_error(tolua_S, "Error in function call '#funcname#': Could not get value reference of parameter #3", NumArgs);
}
}
/* table value is popped, and now function is on top of the stack */
int FuncRef = luaL_ref(tolua_S, LUA_REGISTRYINDEX);
if (FuncRef == LUA_REFNIL)
{
return lua_do_error(tolua_S, "Error in function call '#funcname#': Could not get function reference of parameter #4");
}
/* table value is popped, and now function is on top of the stack */
int FuncRef = luaL_ref(tolua_S, LUA_REGISTRYINDEX);
if (FuncRef == LUA_REFNIL)
{
return lua_do_error(tolua_S, "Error in function call '#funcname#': Could not get function reference of parameter #2", NumArgs);
}
class cLuaCallback : public cItemCallback<Ty2>
{
public:
cLuaCallback(lua_State* a_LuaState, int a_FuncRef, int a_TableRef)
: LuaState( a_LuaState )
, FuncRef( a_FuncRef )
, TableRef( a_TableRef )
{}
class cLuaCallback : public cItemCallback<Ty2>
{
public:
cLuaCallback(lua_State * a_LuaState, int a_FuncRef, int a_TableRef) :
LuaState(a_LuaState),
FuncRef(a_FuncRef),
TableRef(a_TableRef)
{}
private:
virtual bool Item(Ty2 * a_Item) override
{
lua_rawgeti( LuaState, LUA_REGISTRYINDEX, FuncRef); /* Push function reference */
tolua_pushusertype(LuaState, a_Item, Ty2::GetClassStatic());
if (TableRef != LUA_REFNIL)
{
lua_rawgeti( LuaState, LUA_REGISTRYINDEX, TableRef); /* Push table reference */
}
private:
virtual bool Item(Ty2 * a_Item) override
{
lua_rawgeti(LuaState, LUA_REGISTRYINDEX, FuncRef); // Push function to call
tolua_pushusertype(LuaState, a_Item, Ty2::GetClassStatic()); // Push the item
if (TableRef != LUA_REFNIL)
{
lua_rawgeti(LuaState, LUA_REGISTRYINDEX, TableRef); // Push the optional callbackdata param
}
int s = lua_pcall(LuaState, (TableRef == LUA_REFNIL ? 1 : 2), 1, 0);
if (report_errors(LuaState, s))
int s = lua_pcall(LuaState, (TableRef == LUA_REFNIL ? 1 : 2), 1, 0);
if (cLuaState::ReportErrors(LuaState, s))
{
return true; // Abort enumeration
}
if (lua_isboolean(LuaState, -1))
{
return (tolua_toboolean(LuaState, -1, 0) > 0);
}
return false; /* Continue enumeration */
}
lua_State * LuaState;
int FuncRef;
int TableRef;
} Callback(tolua_S, FuncRef, TableRef);
if (lua_isboolean(LuaState, -1))
{
return (tolua_toboolean(LuaState, -1, 0) > 0);
}
return false; /* Continue enumeration */
}
lua_State * LuaState;
int FuncRef;
int TableRef;
} Callback(tolua_S, FuncRef, TableRef);
bool bRetVal = (self->*Func1)(ItemID, Callback);
/* Unreference the values again, so the LUA_REGISTRYINDEX can make place for other references */
luaL_unref(tolua_S, LUA_REGISTRYINDEX, TableRef);
luaL_unref(tolua_S, LUA_REGISTRYINDEX, FuncRef);
/* Push return value on stack */
tolua_pushboolean(tolua_S, bRetVal );
return 1;
}
template<
class Ty1,
class Ty2,
bool (Ty1::*Func1)(int, int, int, cItemCallback<Ty2> &)
>
static int tolua_DoWithXYZ(lua_State* tolua_S)
{
int NumArgs = lua_gettop(tolua_S) - 1; /* This includes 'self' */
if ((NumArgs != 4) && (NumArgs != 5))
{
return lua_do_error(tolua_S, "Error in function call '#funcname#': Requires 4 or 5 arguments, got %i", NumArgs);
}
Ty1 * self = (Ty1 *) tolua_tousertype(tolua_S, 1, 0);
if (!lua_isnumber(tolua_S, 2) || !lua_isnumber(tolua_S, 3) || !lua_isnumber(tolua_S, 4))
{
return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a number for parameters #1, #2 and #3");
}
int ItemX = ((int)tolua_tonumber(tolua_S, 2, 0));
int ItemY = ((int)tolua_tonumber(tolua_S, 3, 0));
int ItemZ = ((int)tolua_tonumber(tolua_S, 4, 0));
LOG("x %i y %i z %i", ItemX, ItemY, ItemZ );
if (!lua_isfunction( tolua_S, 5))
{
return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a function for parameter #4");
}
/* luaL_ref gets reference to value on top of the stack, the table is the last argument and therefore on the top */
int TableRef = LUA_REFNIL;
if (NumArgs == 5)
{
TableRef = luaL_ref(tolua_S, LUA_REGISTRYINDEX);
if (TableRef == LUA_REFNIL)
{
return lua_do_error(tolua_S, "Error in function call '#funcname#': Could not get value reference of parameter #5");
}
}
/* table value is popped, and now function is on top of the stack */
int FuncRef = luaL_ref(tolua_S, LUA_REGISTRYINDEX);
if (FuncRef == LUA_REFNIL)
{
return lua_do_error(tolua_S, "Error in function call '#funcname#': Could not get function reference of parameter #4");
}
class cLuaCallback : public cItemCallback<Ty2>
{
public:
cLuaCallback(lua_State* a_LuaState, int a_FuncRef, int a_TableRef)
: LuaState( a_LuaState )
, FuncRef( a_FuncRef )
, TableRef( a_TableRef )
{}
private:
virtual bool Item(Ty2 * a_Item) override
{
lua_rawgeti( LuaState, LUA_REGISTRYINDEX, FuncRef); /* Push function reference */
tolua_pushusertype(LuaState, a_Item, Ty2::GetClassStatic());
if (TableRef != LUA_REFNIL)
{
lua_rawgeti( LuaState, LUA_REGISTRYINDEX, TableRef); /* Push table reference */
}
int s = lua_pcall(LuaState, (TableRef == LUA_REFNIL ? 1 : 2), 1, 0);
if (cLuaState::ReportErrors(LuaState, s))
{
return true; // Abort enumeration
}
if (lua_isboolean(LuaState, -1))
{
return (tolua_toboolean(LuaState, -1, 0) > 0);
}
return false; /* Continue enumeration */
}
lua_State * LuaState;
int FuncRef;
int TableRef;
} Callback(tolua_S, FuncRef, TableRef);
bool bRetVal = (self->*Func1)(ItemX, ItemY, ItemZ, Callback);
/* Unreference the values again, so the LUA_REGISTRYINDEX can make place for other references */
luaL_unref(tolua_S, LUA_REGISTRYINDEX, TableRef);
luaL_unref(tolua_S, LUA_REGISTRYINDEX, FuncRef);
/* Unreference the values again, so the LUA_REGISTRYINDEX can make place for other references */
luaL_unref(tolua_S, LUA_REGISTRYINDEX, TableRef);
luaL_unref(tolua_S, LUA_REGISTRYINDEX, FuncRef);
/* Push return value on stack */
tolua_pushboolean(tolua_S, bRetVal );
return 1;
/* Push return value on stack */
tolua_pushboolean(tolua_S, bRetVal );
return 1;
}
@ -363,89 +442,89 @@ template< class Ty1,
bool (Ty1::*Func1)(int, int, cItemCallback<Ty2> &) >
static int tolua_ForEachInChunk(lua_State* tolua_S)
{
int NumArgs = lua_gettop(tolua_S) - 1; /* This includes 'self' */
if ((NumArgs != 3) && (NumArgs != 4))
{
int NumArgs = lua_gettop(tolua_S) - 1; /* This includes 'self' */
if ((NumArgs != 3) && (NumArgs != 4))
{
return lua_do_error(tolua_S, "Error in function call '#funcname#': Requires 3 or 4 arguments, got %i", NumArgs);
}
}
Ty1 * self = (Ty1 *) tolua_tousertype(tolua_S, 1, 0);
if (!lua_isnumber(tolua_S, 2) || !lua_isnumber(tolua_S, 3))
{
Ty1 * self = (Ty1 *) tolua_tousertype(tolua_S, 1, 0);
if (!lua_isnumber(tolua_S, 2) || !lua_isnumber(tolua_S, 3))
{
return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a number for parameters #1 and #2");
}
}
int ChunkX = ((int)tolua_tonumber(tolua_S, 2, 0));
int ChunkZ = ((int)tolua_tonumber(tolua_S, 3, 0));
int ChunkX = ((int)tolua_tonumber(tolua_S, 2, 0));
int ChunkZ = ((int)tolua_tonumber(tolua_S, 3, 0));
if (!lua_isfunction( tolua_S, 4))
{
if (!lua_isfunction( tolua_S, 4))
{
return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a function for parameter #3");
}
}
/* luaL_ref gets reference to value on top of the stack, the table is the last argument and therefore on the top */
int TableRef = LUA_REFNIL;
if (NumArgs == 4)
{
TableRef = luaL_ref(tolua_S, LUA_REGISTRYINDEX);
if (TableRef == LUA_REFNIL)
{
/* luaL_ref gets reference to value on top of the stack, the table is the last argument and therefore on the top */
int TableRef = LUA_REFNIL;
if (NumArgs == 4)
{
TableRef = luaL_ref(tolua_S, LUA_REGISTRYINDEX);
if (TableRef == LUA_REFNIL)
{
return lua_do_error(tolua_S, "Error in function call '#funcname#': Could not get value reference of parameter #4");
}
}
}
}
/* table value is popped, and now function is on top of the stack */
int FuncRef = luaL_ref(tolua_S, LUA_REGISTRYINDEX);
if (FuncRef == LUA_REFNIL)
{
/* table value is popped, and now function is on top of the stack */
int FuncRef = luaL_ref(tolua_S, LUA_REGISTRYINDEX);
if (FuncRef == LUA_REFNIL)
{
return lua_do_error(tolua_S, "Error in function call '#funcname#': Could not get function reference of parameter #3");
}
}
class cLuaCallback : public cItemCallback<Ty2>
{
public:
cLuaCallback(lua_State* a_LuaState, int a_FuncRef, int a_TableRef)
: LuaState( a_LuaState )
, FuncRef( a_FuncRef )
, TableRef( a_TableRef )
{}
class cLuaCallback : public cItemCallback<Ty2>
{
public:
cLuaCallback(lua_State* a_LuaState, int a_FuncRef, int a_TableRef)
: LuaState( a_LuaState )
, FuncRef( a_FuncRef )
, TableRef( a_TableRef )
{}
private:
virtual bool Item(Ty2 * a_Item) override
{
lua_rawgeti( LuaState, LUA_REGISTRYINDEX, FuncRef); /* Push function reference */
tolua_pushusertype(LuaState, a_Item, Ty2::GetClassStatic());
if (TableRef != LUA_REFNIL)
{
lua_rawgeti( LuaState, LUA_REGISTRYINDEX, TableRef); /* Push table reference */
}
private:
virtual bool Item(Ty2 * a_Item) override
{
lua_rawgeti( LuaState, LUA_REGISTRYINDEX, FuncRef); /* Push function reference */
tolua_pushusertype(LuaState, a_Item, Ty2::GetClassStatic());
if (TableRef != LUA_REFNIL)
{
lua_rawgeti( LuaState, LUA_REGISTRYINDEX, TableRef); /* Push table reference */
}
int s = lua_pcall(LuaState, (TableRef == LUA_REFNIL ? 1 : 2), 1, 0);
if (report_errors(LuaState, s))
{
return true; /* Abort enumeration */
}
int s = lua_pcall(LuaState, (TableRef == LUA_REFNIL ? 1 : 2), 1, 0);
if (cLuaState::ReportErrors(LuaState, s))
{
return true; /* Abort enumeration */
}
if (lua_isboolean(LuaState, -1))
{
return (tolua_toboolean(LuaState, -1, 0) > 0);
}
return false; /* Continue enumeration */
}
lua_State * LuaState;
int FuncRef;
int TableRef;
} Callback(tolua_S, FuncRef, TableRef);
if (lua_isboolean(LuaState, -1))
{
return (tolua_toboolean(LuaState, -1, 0) > 0);
}
return false; /* Continue enumeration */
}
lua_State * LuaState;
int FuncRef;
int TableRef;
} Callback(tolua_S, FuncRef, TableRef);
bool bRetVal = (self->*Func1)(ChunkX, ChunkZ, Callback);
/* Unreference the values again, so the LUA_REGISTRYINDEX can make place for other references */
luaL_unref(tolua_S, LUA_REGISTRYINDEX, TableRef);
luaL_unref(tolua_S, LUA_REGISTRYINDEX, FuncRef);
/* Unreference the values again, so the LUA_REGISTRYINDEX can make place for other references */
luaL_unref(tolua_S, LUA_REGISTRYINDEX, TableRef);
luaL_unref(tolua_S, LUA_REGISTRYINDEX, FuncRef);
/* Push return value on stack */
tolua_pushboolean(tolua_S, bRetVal );
return 1;
/* Push return value on stack */
tolua_pushboolean(tolua_S, bRetVal );
return 1;
}
@ -453,7 +532,7 @@ static int tolua_ForEachInChunk(lua_State* tolua_S)
template< class Ty1,
class Ty2,
class Ty2,
bool (Ty1::*Func1)(cItemCallback<Ty2> &) >
static int tolua_ForEach(lua_State * tolua_S)
{
@ -512,7 +591,7 @@ static int tolua_ForEach(lua_State * tolua_S)
}
int s = lua_pcall(LuaState, (TableRef == LUA_REFNIL ? 1 : 2), 1, 0);
if (report_errors(LuaState, s))
if (cLuaState::ReportErrors(LuaState, s))
{
return true; /* Abort enumeration */
}
@ -596,6 +675,52 @@ tolua_lerror:
static int tolua_cWorld_TryGetHeight(lua_State * tolua_S)
{
// Exported manually, because tolua would require the out-only param a_Height to be used when calling
// Takes (a_World,) a_BlockX, a_BlockZ
// Returns Height, IsValid
#ifndef TOLUA_RELEASE
tolua_Error tolua_err;
if (
!tolua_isusertype (tolua_S, 1, "cWorld", 0, &tolua_err) ||
!tolua_isnumber (tolua_S, 2, 0, &tolua_err) ||
!tolua_isnumber (tolua_S, 3, 0, &tolua_err) ||
!tolua_isnoobj (tolua_S, 4, &tolua_err)
)
goto tolua_lerror;
else
#endif
{
cWorld * self = (cWorld *) tolua_tousertype (tolua_S, 1, 0);
int BlockX = (int) tolua_tonumber (tolua_S, 2, 0);
int BlockZ = (int) tolua_tonumber (tolua_S, 3, 0);
#ifndef TOLUA_RELEASE
if (self == NULL)
{
tolua_error(tolua_S, "Invalid 'self' in function 'TryGetHeight'", NULL);
}
#endif
{
int Height = 0;
bool res = self->TryGetHeight(BlockX, BlockZ, Height);
tolua_pushnumber(tolua_S, Height);
tolua_pushboolean(tolua_S, res ? 1 : 0);
}
}
return 1;
#ifndef TOLUA_RELEASE
tolua_lerror:
tolua_error(tolua_S, "#ferror in function 'TryGetHeight'.", &tolua_err);
return 0;
#endif
}
static int tolua_cPluginManager_GetAllPlugins(lua_State * tolua_S)
{
cPluginManager* self = (cPluginManager*) tolua_tousertype(tolua_S,1,0);
@ -677,7 +802,7 @@ static int tolua_cPluginManager_ForEachCommand(lua_State * tolua_S)
tolua_pushcppstring(LuaState, a_HelpString);
int s = lua_pcall(LuaState, 3, 1, 0);
if (report_errors(LuaState, s))
if (cLuaState::ReportErrors(LuaState, s))
{
return true; /* Abort enumeration */
}
@ -751,7 +876,7 @@ static int tolua_cPluginManager_ForEachConsoleCommand(lua_State * tolua_S)
tolua_pushcppstring(LuaState, a_HelpString);
int s = lua_pcall(LuaState, 2, 1, 0);
if (report_errors(LuaState, s))
if (cLuaState::ReportErrors(LuaState, s))
{
return true; /* Abort enumeration */
}
@ -1171,8 +1296,8 @@ static int tolua_cPlugin_Call(lua_State* tolua_S)
return 0;
}
int s = lua_pcall(targetState, top-2, LUA_MULTRET, 0);
if( report_errors( targetState, s ) )
int s = lua_pcall(targetState, top - 2, LUA_MULTRET, 0);
if (cLuaState::ReportErrors(targetState, s))
{
LOGWARN("Error while calling function '%s' in plugin '%s'", funcName.c_str(), self->GetName().c_str() );
return 0;
@ -1361,9 +1486,174 @@ tolua_lerror:
/// Provides interface between a Lua table of callbacks and the cBlockTracer::cCallbacks
class cLuaBlockTracerCallbacks :
public cBlockTracer::cCallbacks
{
public:
cLuaBlockTracerCallbacks(cLuaState & a_LuaState, int a_ParamNum) :
m_LuaState(a_LuaState),
m_TableRef(a_LuaState, a_ParamNum)
{
}
virtual bool OnNextBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) override
{
if (!m_LuaState.PushFunctionFromRefTable(m_TableRef, "OnNextBlock"))
{
// No such function in the table, skip the callback
return false;
}
m_LuaState.PushNumber(a_BlockX);
m_LuaState.PushNumber(a_BlockY);
m_LuaState.PushNumber(a_BlockZ);
m_LuaState.PushNumber(a_BlockType);
m_LuaState.PushNumber(a_BlockMeta);
if (!m_LuaState.CallFunction(1))
{
return false;
}
bool res = false;
if (lua_isboolean(m_LuaState, -1))
{
res = (lua_toboolean(m_LuaState, -1) != 0);
}
lua_pop(m_LuaState, 1);
return res;
}
virtual bool OnNextBlockNoData(int a_BlockX, int a_BlockY, int a_BlockZ) override
{
if (!m_LuaState.PushFunctionFromRefTable(m_TableRef, "OnNextBlockNoData"))
{
// No such function in the table, skip the callback
return false;
}
m_LuaState.PushNumber(a_BlockX);
m_LuaState.PushNumber(a_BlockY);
m_LuaState.PushNumber(a_BlockZ);
if (!m_LuaState.CallFunction(1))
{
return false;
}
bool res = false;
if (lua_isboolean(m_LuaState, -1))
{
res = (lua_toboolean(m_LuaState, -1) != 0);
}
lua_pop(m_LuaState, 1);
return res;
}
virtual bool OnOutOfWorld(double a_BlockX, double a_BlockY, double a_BlockZ) override
{
if (!m_LuaState.PushFunctionFromRefTable(m_TableRef, "OnOutOfWorld"))
{
// No such function in the table, skip the callback
return false;
}
m_LuaState.PushNumber(a_BlockX);
m_LuaState.PushNumber(a_BlockY);
m_LuaState.PushNumber(a_BlockZ);
if (!m_LuaState.CallFunction(1))
{
return false;
}
bool res = false;
if (lua_isboolean(m_LuaState, -1))
{
res = (lua_toboolean(m_LuaState, -1) != 0);
}
lua_pop(m_LuaState, 1);
return res;
}
virtual bool OnIntoWorld(double a_BlockX, double a_BlockY, double a_BlockZ) override
{
if (!m_LuaState.PushFunctionFromRefTable(m_TableRef, "OnIntoWorld"))
{
// No such function in the table, skip the callback
return false;
}
m_LuaState.PushNumber(a_BlockX);
m_LuaState.PushNumber(a_BlockY);
m_LuaState.PushNumber(a_BlockZ);
if (!m_LuaState.CallFunction(1))
{
return false;
}
bool res = false;
if (lua_isboolean(m_LuaState, -1))
{
res = (lua_toboolean(m_LuaState, -1) != 0);
}
lua_pop(m_LuaState, 1);
return res;
}
virtual void OnNoMoreHits(void) override
{
if (!m_LuaState.PushFunctionFromRefTable(m_TableRef, "OnNoMoreHits"))
{
// No such function in the table, skip the callback
return;
}
m_LuaState.CallFunction(0);
}
virtual void OnNoChunk(void) override
{
if (!m_LuaState.PushFunctionFromRefTable(m_TableRef, "OnNoChunk"))
{
// No such function in the table, skip the callback
return;
}
m_LuaState.CallFunction(0);
}
protected:
cLuaState & m_LuaState;
cLuaState::cRef m_TableRef;
} ;
static int tolua_cLineBlockTracer_Trace(lua_State * tolua_S)
{
// cLineBlockTracer.Trace(World, Callbacks, StartX, StartY, StartZ, EndX, EndY, EndZ)
cLuaState L(tolua_S);
if (
!L.CheckParamUserType(1, "cWorld") ||
!L.CheckParamTable (2) ||
!L.CheckParamNumber (3, 8) ||
!L.CheckParamEnd (9)
)
{
return 0;
}
cWorld * World = (cWorld *)tolua_tousertype(L, 1, NULL);
cLuaBlockTracerCallbacks Callbacks(L, 2);
double StartX = tolua_tonumber(L, 3, 0);
double StartY = tolua_tonumber(L, 4, 0);
double StartZ = tolua_tonumber(L, 5, 0);
double EndX = tolua_tonumber(L, 6, 0);
double EndY = tolua_tonumber(L, 7, 0);
double EndZ = tolua_tonumber(L, 8, 0);
bool res = cLineBlockTracer::Trace(*World, Callbacks, StartX, StartY, StartZ, EndX, EndY, EndZ);
tolua_pushboolean(L, res ? 1 : 0);
return 1;
}
void ManualBindings::Bind(lua_State * tolua_S)
{
tolua_beginmodule(tolua_S,NULL);
tolua_beginmodule(tolua_S, NULL);
tolua_function(tolua_S, "StringSplit", tolua_StringSplit);
tolua_function(tolua_S, "LOG", tolua_LOG);
tolua_function(tolua_S, "LOGINFO", tolua_LOGINFO);
@ -1371,26 +1661,32 @@ void ManualBindings::Bind(lua_State * tolua_S)
tolua_function(tolua_S, "LOGWARNING", tolua_LOGWARN);
tolua_function(tolua_S, "LOGERROR", tolua_LOGERROR);
tolua_beginmodule(tolua_S, "cLineBlockTracer");
tolua_function(tolua_S, "Trace", tolua_cLineBlockTracer_Trace);
tolua_endmodule(tolua_S);
tolua_beginmodule(tolua_S, "cRoot");
tolua_function(tolua_S, "ForEachWorld", tolua_ForEach<cRoot, cWorld, &cRoot::ForEachWorld>);
tolua_function(tolua_S, "FindAndDoWithPlayer", tolua_DoWith <cRoot, cPlayer, &cRoot::FindAndDoWithPlayer>);
tolua_function(tolua_S, "ForEachPlayer", tolua_ForEach<cRoot, cPlayer, &cRoot::ForEachPlayer>);
tolua_function(tolua_S, "ForEachWorld", tolua_ForEach<cRoot, cWorld, &cRoot::ForEachWorld>);
tolua_endmodule(tolua_S);
tolua_beginmodule(tolua_S, "cWorld");
tolua_function(tolua_S, "ForEachPlayer", tolua_ForEach<cWorld, cPlayer, &cWorld::ForEachPlayer>);
tolua_function(tolua_S, "ForEachEntity", tolua_ForEach<cWorld, cEntity, &cWorld::ForEachEntity>);
tolua_function(tolua_S, "ForEachEntityInChunk", tolua_ForEachInChunk<cWorld, cEntity, &cWorld::ForEachEntityInChunk>);
tolua_function(tolua_S, "ForEachChestInChunk", tolua_ForEachInChunk<cWorld, cChestEntity, &cWorld::ForEachChestInChunk>);
tolua_function(tolua_S, "ForEachFurnaceInChunk", tolua_ForEachInChunk<cWorld, cFurnaceEntity, &cWorld::ForEachFurnaceInChunk>);
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, "DoWithChestAt", tolua_DoWithXYZ<cWorld, cChestEntity, &cWorld::DoWithChestAt>);
tolua_function(tolua_S, "DoWithDispenserAt", tolua_DoWithXYZ<cWorld, cDispenserEntity, &cWorld::DoWithDispenserAt>);
tolua_function(tolua_S, "DoWithDropperAt", tolua_DoWithXYZ<cWorld, cDropperEntity, &cWorld::DoWithDropperAt>);
tolua_function(tolua_S, "DoWithDropSpenserAt", tolua_DoWithXYZ<cWorld, cDropSpenserEntity, &cWorld::DoWithDropSpenserAt>);
tolua_function(tolua_S, "DoWithDropperAt", tolua_DoWithXYZ<cWorld, cDropperEntity, &cWorld::DoWithDropperAt>);
tolua_function(tolua_S, "DoWithEntityByID", tolua_DoWithID< cWorld, cEntity, &cWorld::DoWithEntityByID>);
tolua_function(tolua_S, "DoWithFurnaceAt", tolua_DoWithXYZ<cWorld, cFurnaceEntity, &cWorld::DoWithFurnaceAt>);
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, "ForEachChestInChunk", tolua_ForEachInChunk<cWorld, cChestEntity, &cWorld::ForEachChestInChunk>);
tolua_function(tolua_S, "ForEachEntity", tolua_ForEach< cWorld, cEntity, &cWorld::ForEachEntity>);
tolua_function(tolua_S, "ForEachEntityInChunk", tolua_ForEachInChunk<cWorld, cEntity, &cWorld::ForEachEntityInChunk>);
tolua_function(tolua_S, "ForEachFurnaceInChunk", tolua_ForEachInChunk<cWorld, cFurnaceEntity, &cWorld::ForEachFurnaceInChunk>);
tolua_function(tolua_S, "ForEachPlayer", tolua_ForEach< cWorld, cPlayer, &cWorld::ForEachPlayer>);
tolua_function(tolua_S, "SetSignLines", tolua_cWorld_SetSignLines);
tolua_function(tolua_S, "TryGetHeight", tolua_cWorld_TryGetHeight);
tolua_function(tolua_S, "UpdateSign", tolua_cWorld_SetSignLines);
tolua_endmodule(tolua_S);
@ -1399,11 +1695,11 @@ void ManualBindings::Bind(lua_State * tolua_S)
tolua_endmodule(tolua_S);
tolua_beginmodule(tolua_S, "cPluginManager");
tolua_function(tolua_S, "GetAllPlugins", tolua_cPluginManager_GetAllPlugins);
tolua_function(tolua_S, "BindCommand", tolua_cPluginManager_BindCommand);
tolua_function(tolua_S, "BindConsoleCommand", tolua_cPluginManager_BindConsoleCommand);
tolua_function(tolua_S, "ForEachCommand", tolua_cPluginManager_ForEachCommand);
tolua_function(tolua_S, "ForEachConsoleCommand", tolua_cPluginManager_ForEachConsoleCommand);
tolua_function(tolua_S, "GetAllPlugins", tolua_cPluginManager_GetAllPlugins);
tolua_endmodule(tolua_S);
tolua_beginmodule(tolua_S, "cPlayer");
@ -1418,17 +1714,17 @@ void ManualBindings::Bind(lua_State * tolua_S)
tolua_endmodule(tolua_S);
tolua_beginmodule(tolua_S, "cPlugin_NewLua");
tolua_function(tolua_S, "AddWebTab", tolua_cPlugin_NewLua_AddWebTab);
tolua_function(tolua_S, "AddTab", tolua_cPlugin_NewLua_AddTab);
tolua_function(tolua_S, "AddWebTab", tolua_cPlugin_NewLua_AddWebTab);
tolua_endmodule(tolua_S);
tolua_cclass(tolua_S,"HTTPRequest","HTTPRequest","",NULL);
tolua_beginmodule(tolua_S,"HTTPRequest");
// tolua_variable(tolua_S,"Method",tolua_get_HTTPRequest_Method,tolua_set_HTTPRequest_Method);
// tolua_variable(tolua_S,"Path",tolua_get_HTTPRequest_Path,tolua_set_HTTPRequest_Path);
tolua_variable(tolua_S,"FormData",tolua_get_HTTPRequest_FormData,0);
tolua_variable(tolua_S,"Params",tolua_get_HTTPRequest_Params,0);
tolua_variable(tolua_S,"PostParams",tolua_get_HTTPRequest_PostParams,0);
tolua_variable(tolua_S,"FormData",tolua_get_HTTPRequest_FormData,0);
tolua_endmodule(tolua_S);
tolua_beginmodule(tolua_S, "cWebAdmin");
@ -1440,8 +1736,8 @@ void ManualBindings::Bind(lua_State * tolua_S)
tolua_endmodule(tolua_S);
tolua_beginmodule(tolua_S, "cClientHandle");
tolua_constant(tolua_S, "MIN_VIEW_DISTANCE", cClientHandle::MIN_VIEW_DISTANCE);
tolua_constant(tolua_S, "MAX_VIEW_DISTANCE", cClientHandle::MAX_VIEW_DISTANCE);
tolua_constant(tolua_S, "MIN_VIEW_DISTANCE", cClientHandle::MIN_VIEW_DISTANCE);
tolua_endmodule(tolua_S);
tolua_beginmodule(tolua_S, "cItemGrid");

File diff suppressed because it is too large Load Diff

View File

@ -3,6 +3,7 @@
#include "Plugin.h"
#include "WebPlugin.h"
#include "LuaState.h"
// Names for the global variables through which the plugin is identified in its LuaState
#define LUA_PLUGIN_NAME_VAR_NAME "_MCServerInternal_PluginName"
@ -11,9 +12,6 @@
// fwd: Lua
typedef struct lua_State lua_State;
// fwd: UI/Window.h
class cWindow;
@ -99,7 +97,7 @@ public:
/// Binds the console command to call the function specified by a Lua function reference. Simply adds to CommandMap.
void BindConsoleCommand(const AString & a_Command, int a_FnRef);
lua_State * GetLuaState(void) { return m_LuaState; }
cLuaState & GetLuaState(void) { return m_LuaState; }
cCriticalSection & GetCriticalSection(void) { return m_CriticalSection; }
@ -114,7 +112,7 @@ public:
protected:
cCriticalSection m_CriticalSection;
lua_State * m_LuaState;
cLuaState m_LuaState;
/// Maps command name into Lua function reference
typedef std::map<AString, int> CommandMap;
@ -122,9 +120,6 @@ protected:
CommandMap m_Commands;
CommandMap m_ConsoleCommands;
bool PushFunction(const char * a_FunctionName, bool a_bLogError = true);
bool CallFunction(int a_NumArgs, int a_NumResults, const char * a_FunctionName ); // a_FunctionName is only used for error messages, nothing else
/// Returns the name of Lua function that should handle the specified hook
const char * GetHookFnName(cPluginManager::PluginHook a_Hook);
} ; // tolua_export

View File

@ -112,10 +112,7 @@ void cRoot::Start(void)
cIniFile IniFile("settings.ini");
if (!IniFile.ReadFile())
{
LOGINFO("settings.ini inaccessible, using settings.example.ini for defaults!");
IniFile.Path("settings.example.ini");
IniFile.ReadFile();
IniFile.Path("settings.ini");
LOGWARNING("settings.ini inaccessible, all settings are reset to default values");
}
m_PrimaryServerVersion = IniFile.GetValueI("Server", "PrimaryServerVersion", 0);
if (m_PrimaryServerVersion == 0)
@ -139,23 +136,19 @@ void cRoot::Start(void)
cIniFile WebIniFile("webadmin.ini");
if (!WebIniFile.ReadFile())
{
LOGINFO("webadmin.ini inaccessible, using webadmin.example.ini for defaults!");
WebIniFile.Path("webadmin.example.ini");
WebIniFile.ReadFile();
WebIniFile.Path("webadmin.ini");
WebIniFile.WriteFile();
LOGWARNING("webadmin.ini inaccessible, wabadmin is disabled");
}
if (WebIniFile.GetValueB("WebAdmin", "Enabled", false ))
if (WebIniFile.GetValueB("WebAdmin", "Enabled", false))
{
LOG("Creating WebAdmin...");
m_WebAdmin = new cWebAdmin(8080);
}
LOG("Loading settings...");
m_GroupManager = new cGroupManager();
m_GroupManager = new cGroupManager();
m_CraftingRecipes = new cCraftingRecipes;
m_FurnaceRecipe = new cFurnaceRecipe();
m_FurnaceRecipe = new cFurnaceRecipe();
LOG("Loading worlds...");
LoadWorlds();

View File

@ -178,7 +178,7 @@ void cWebAdmin::Request_Handler(webserver::http_request* r)
if (!bDontShowTemplate)
{
// New Lua web template
bLuaTemplateSuccessful = WebAdmin->m_pTemplate->CallFunction("ShowPage", sLuaUsertype(WebAdmin, "cWebAdmin"), sLuaUsertype(&TemplateRequest, "HTTPTemplateRequest"), Template);
bLuaTemplateSuccessful = WebAdmin->m_pTemplate->CallShowPage(*WebAdmin, TemplateRequest, Template);
}
if (!bLuaTemplateSuccessful)
@ -274,14 +274,14 @@ bool cWebAdmin::Init( int a_Port )
m_Port = a_Port;
m_IniFile = new cIniFile("webadmin.ini");
if( m_IniFile->ReadFile() )
if (m_IniFile->ReadFile())
{
m_Port = m_IniFile->GetValueI("WebAdmin", "Port", 8080 );
m_Port = m_IniFile->GetValueI("WebAdmin", "Port", 8080);
}
// Initialize the WebAdmin template script and load the file
m_pTemplate->Initialize();
if (!m_pTemplate->LoadFile( FILE_IO_PREFIX "webadmin/template.lua") || !m_pTemplate->Execute())
if (!m_pTemplate->LoadFile(FILE_IO_PREFIX "webadmin/template.lua"))
{
LOGWARN("Could not load WebAdmin template.");
}

View File

@ -1,4 +1,3 @@
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
#include "BlockID.h"
@ -59,6 +58,9 @@
#include "tolua++.h"
// DEBUG: Test out the cLineBlockTracer class by tracing a few lines:
#include "LineBlockTracer.h"
#ifndef _WIN32
#include <stdlib.h>
#endif
@ -278,7 +280,7 @@ cWorld::cWorld(const AString & a_WorldName) :
m_LastSave = 0;
m_LastUnload = 0;
// preallocate some memory for ticking blocks so we don´t need to allocate that often
// preallocate some memory for ticking blocks so we don<EFBFBD>t need to allocate that often
m_BlockTickQueue.reserve(1000);
m_BlockTickQueueCopy.reserve(1000);
@ -442,6 +444,60 @@ void cWorld::InitializeSpawn(void)
// TODO: Better spawn detection - move spawn out of the water if it isn't set in the INI already
m_SpawnY = (double)GetHeight((int)m_SpawnX, (int)m_SpawnZ) + 1.6f; // +1.6f eye height
#ifdef TEST_LINEBLOCKTRACER
// DEBUG: Test out the cLineBlockTracer class by tracing a few lines:
class cTracerCallbacks :
public cBlockTracer::cCallbacks
{
virtual bool OnNextBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) override
{
LOGD("Block {%d, %d, %d}: %d:%d (%s)",
a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta,
ItemToString(cItem(a_BlockType, 1, a_BlockMeta)).c_str()
);
return false;
}
virtual bool OnNextBlockNoData(int a_BlockX, int a_BlockY, int a_BlockZ) override
{
LOGD("Block {%d, %d, %d}: no data available",
a_BlockX, a_BlockY, a_BlockZ
);
return false;
}
virtual bool OnOutOfWorld(double a_BlockX, double a_BlockY, double a_BlockZ) override
{
LOGD("Out of world at {%f, %f, %f}", a_BlockX, a_BlockY, a_BlockZ);
return false;
}
virtual bool OnIntoWorld(double a_BlockX, double a_BlockY, double a_BlockZ) override
{
LOGD("Into world at {%f, %f, %f}", a_BlockX, a_BlockY, a_BlockZ);
return false;
}
virtual void OnNoMoreHits(void) override
{
LOGD("No more hits");
}
} Callbacks;
LOGD("Spawn is at {%f, %f, %f}", m_SpawnX, m_SpawnY, m_SpawnZ);
LOGD("Tracing a line along +X:");
cLineBlockTracer::Trace(*this, Callbacks, m_SpawnX - 10, m_SpawnY, m_SpawnZ, m_SpawnX + 10, m_SpawnY, m_SpawnZ);
LOGD("Tracing a line along -Z:");
cLineBlockTracer::Trace(*this, Callbacks, m_SpawnX, m_SpawnY, m_SpawnZ + 10, m_SpawnX, m_SpawnY, m_SpawnZ - 10);
LOGD("Tracing a line along -Y, out of world:");
cLineBlockTracer::Trace(*this, Callbacks, m_SpawnX, 260, m_SpawnZ, m_SpawnX, -5, m_SpawnZ);
LOGD("Tracing a line along XY:");
cLineBlockTracer::Trace(*this, Callbacks, m_SpawnX - 10, m_SpawnY - 10, m_SpawnZ, m_SpawnX + 10, m_SpawnY + 10, m_SpawnZ);
LOGD("Tracing a line in generic direction:");
cLineBlockTracer::Trace(*this, Callbacks, m_SpawnX - 15, m_SpawnY - 5, m_SpawnZ + 7.5, m_SpawnX + 13, m_SpawnY - 10, m_SpawnZ + 8.5);
LOGD("Tracing tests done");
#endif // TEST_LINEBLOCKTRACER
}
@ -634,7 +690,6 @@ void cWorld::TickSpawnMobs(float a_Dt)
{
switch (nightRand)
{
case 1: MobType = E_ENTITY_TYPE_ZOMBIE; break; // _X 2013_06_25: Really? Zombies in the Nether?
case 5: MobType = E_ENTITY_TYPE_GHAST; break;
case 6: MobType = E_ENTITY_TYPE_ZOMBIE_PIGMAN; break;
}
@ -642,8 +697,9 @@ void cWorld::TickSpawnMobs(float a_Dt)
else
{
switch (nightRand)
{
{
case 0: MobType = E_ENTITY_TYPE_SPIDER; break;
case 1: MobType = E_ENTITY_TYPE_ZOMBIE; break;
case 2: MobType = E_ENTITY_TYPE_ENDERMAN; break;
case 3: MobType = E_ENTITY_TYPE_CREEPER; break;
case 4: MobType = E_ENTITY_TYPE_CAVE_SPIDER; break;
@ -832,6 +888,15 @@ bool cWorld::GetSignLines(int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_
bool cWorld::DoWithChunk(int a_ChunkX, int a_ChunkZ, cChunkCallback & a_Callback)
{
return m_ChunkMap->DoWithChunk(a_ChunkX, a_ChunkZ, a_Callback);
}
void cWorld::GrowTree(int a_X, int a_Y, int a_Z)
{
if (GetBlock(a_X, a_Y, a_Z) == E_BLOCK_SAPLING)

View File

@ -129,7 +129,7 @@ public:
// tolua_end
/// Retrieves the world height at the specified coords; returns false if chunk not loaded / generated
bool TryGetHeight(int a_BlockX, int a_BlockZ, int & a_Height); // TODO: Export in ManualBindings.cpp
bool TryGetHeight(int a_BlockX, int a_BlockZ, int & a_Height); // Exported in ManualBindings.cpp
// Broadcast respective packets to all clients of the chunk where the event is taking place
// (Please keep these alpha-sorted)
@ -174,7 +174,7 @@ public:
If a_MarkDirty is set, the chunk is set as dirty (used after generating)
*/
void SetChunkData(
int a_ChunkX, int a_ChunkZ,
int a_ChunkX, int a_ChunkZ,
const BLOCKTYPE * a_BlockTypes,
const NIBBLETYPE * a_BlockMeta,
const NIBBLETYPE * a_BlockLight,
@ -245,7 +245,7 @@ public:
bool ForEachEntityInChunk(int a_ChunkX, int a_ChunkZ, cEntityCallback & a_Callback); // Exported in ManualBindings.cpp
/// Calls the callback if the entity with the specified ID is found, with the entity object as the callback param. Returns true if entity found and callback returned false.
bool DoWithEntityByID(int a_UniqueID, cEntityCallback & a_Callback); // TODO: Exported in ManualBindings.cpp
bool DoWithEntityByID(int a_UniqueID, cEntityCallback & a_Callback); // Exported in ManualBindings.cpp
/// Compares clients of two chunks, calls the callback accordingly
void CompareChunkClients(int a_ChunkX1, int a_ChunkZ1, int a_ChunkX2, int a_ChunkZ2, cClientDiffCallback & a_Callback);
@ -319,8 +319,8 @@ public:
void SetBlockMeta(const Vector3i & a_Pos, NIBBLETYPE a_MetaData ) { SetBlockMeta( a_Pos.x, a_Pos.y, a_Pos.z, a_MetaData ); }
// tolua_end
/** Writes the block area into the specified coords.
Returns true if all chunks have been processed.
/** Writes the block area into the specified coords.
Returns true if all chunks have been processed.
Prefer cBlockArea::Write() instead, this is the internal implementation; cBlockArea does error checking, too.
a_DataTypes is a bitmask of cBlockArea::baXXX constants ORed together.
*/
@ -404,6 +404,9 @@ public:
/// a_Player is using block entity at [x, y, z], handle that:
void UseBlockEntity(cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ) {m_ChunkMap->UseBlockEntity(a_Player, a_BlockX, a_BlockY, a_BlockZ); }
/// Calls the callback for the chunk specified, with ChunkMapCS locked; returns false if the chunk doesn't exist, otherwise returns the same value as the callback
bool DoWithChunk(int a_ChunkX, int a_ChunkZ, cChunkCallback & a_Callback);
void GrowTree (int a_BlockX, int a_BlockY, int a_BlockZ); // tolua_export
void GrowTreeFromSapling(int a_BlockX, int a_BlockY, int a_BlockZ, char a_SaplingMeta); // tolua_export