summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--MCServer/Plugins/APIDump/APIDesc.lua16
-rw-r--r--MCServer/Plugins/APIDump/main_APIDump.lua11
-rw-r--r--Tools/ProtoProxy/Connection.cpp5
-rw-r--r--src/Bindings/AllToLua.pkg1
-rw-r--r--src/Bindings/Bindings.cpp345
-rw-r--r--src/Bindings/Bindings.h2
-rw-r--r--src/Bindings/LuaWindow.h8
-rw-r--r--src/Bindings/ManualBindings.cpp2
-rw-r--r--src/Bindings/Plugin.h2
-rw-r--r--src/Bindings/PluginLua.cpp8
-rw-r--r--src/Bindings/PluginLua.h2
-rw-r--r--src/Bindings/PluginManager.cpp6
-rw-r--r--src/Bindings/PluginManager.h4
-rw-r--r--src/Bindings/tolua++.h13
-rw-r--r--src/BlockArea.cpp6
-rw-r--r--src/BlockEntities/ChestEntity.h8
-rw-r--r--src/BlockEntities/DropSpenserEntity.h8
-rw-r--r--src/BlockEntities/EnderChestEntity.h8
-rw-r--r--src/BlockEntities/FurnaceEntity.h8
-rw-r--r--src/BlockEntities/HopperEntity.h8
-rw-r--r--src/Blocks/BlockHandler.cpp2
-rw-r--r--src/Blocks/BlockNetherWart.h52
-rw-r--r--src/Chunk.cpp64
-rw-r--r--src/Chunk.h8
-rw-r--r--src/ChunkMap.cpp50
-rw-r--r--src/ChunkMap.h7
-rw-r--r--src/ClientHandle.cpp100
-rw-r--r--src/ClientHandle.h9
-rw-r--r--src/Entities/Boat.cpp33
-rw-r--r--src/Entities/Boat.h3
-rw-r--r--src/Entities/Effects.h30
-rw-r--r--src/Entities/Entity.cpp18
-rw-r--r--src/Entities/Entity.h1
-rw-r--r--src/Entities/ExpOrb.cpp2
-rw-r--r--src/Entities/Player.cpp78
-rw-r--r--src/Entities/Player.h19
-rw-r--r--src/Globals.h4
-rw-r--r--src/Items/ItemBoat.h39
-rw-r--r--src/Items/ItemBucket.h120
-rw-r--r--src/Items/ItemHandler.cpp2
-rw-r--r--src/Items/ItemNetherWart.h54
-rw-r--r--src/Protocol/Protocol.h2
-rw-r--r--src/Protocol/Protocol125.cpp30
-rw-r--r--src/Protocol/Protocol125.h2
-rw-r--r--src/Protocol/Protocol17x.cpp64
-rw-r--r--src/Protocol/Protocol17x.h2
-rw-r--r--src/Protocol/ProtocolRecognizer.cpp20
-rw-r--r--src/Protocol/ProtocolRecognizer.h2
-rw-r--r--src/Server.cpp2
-rw-r--r--src/Simulator/RedstoneSimulator.cpp307
-rw-r--r--src/Simulator/RedstoneSimulator.h5
-rw-r--r--src/World.cpp51
-rw-r--r--src/World.h12
53 files changed, 1355 insertions, 310 deletions
diff --git a/MCServer/Plugins/APIDump/APIDesc.lua b/MCServer/Plugins/APIDump/APIDesc.lua
index b7dddec05..5bc4a5f39 100644
--- a/MCServer/Plugins/APIDump/APIDesc.lua
+++ b/MCServer/Plugins/APIDump/APIDesc.lua
@@ -1567,12 +1567,14 @@ a_Player:OpenWindow(Window);
AddFoodExhaustion = { Params = "Exhaustion", Return = "", Notes = "Adds the specified number to the food exhaustion. Only positive numbers expected." },
AddToGroup = { Params = "GroupName", Return = "", Notes = "Temporarily adds the player to the specified group. The assignment is lost when the player disconnects." },
CalcLevelFromXp = { Params = "XPAmount", Return = "number", Notes = "Returns the level which is reached with the specified amount of XP. Inverse of XpForLevel()." },
+ CanFly = { Return = "bool", Notes = "Returns if the player is able to fly." },
CanUseCommand = { Params = "Command", Return = "bool", Notes = "Returns true if the player is allowed to use the specified command." },
CloseWindow = { Params = "[CanRefuse]", Return = "", Notes = "Closes the currently open UI window. If CanRefuse is true (default), the window may refuse the closing." },
CloseWindowIfID = { Params = "WindowID, [CanRefuse]", Return = "", Notes = "Closes the currently open UI window if its ID matches the given ID. If CanRefuse is true (default), the window may refuse the closing." },
DeltaExperience = { Params = "DeltaXP", Return = "", Notes = "Adds or removes XP from the current XP amount. Won't allow XP to go negative. Returns the new experience, -1 on error (XP overflow)." },
Feed = { Params = "AddFood, AddSaturation", Return = "bool", Notes = "Tries to add the specified amounts to food level and food saturation level (only positive amounts expected). Returns true if player was hungry and the food was consumed, false if too satiated." },
FoodPoison = { Params = "NumTicks", Return = "", Notes = "Starts the food poisoning for the specified amount of ticks; if already foodpoisoned, sets FoodPoisonedTicksRemaining to the larger of the two" },
+ ForceSetSpeed = { Params = "{{Vector3d|Direction}}", Notes = "Forces the player to move to the given direction." },
GetAirLevel = { Params = "", Return = "number", Notes = "Returns the air level (number of ticks of air left)." },
GetClientHandle = { Params = "", Return = "{{cClientHandle}}", Notes = "Returns the client handle representing the player's connection. May be nil (AI players)." },
GetColor = { Return = "string", Notes = "Returns the full color code to be used for this player (based on the first group). Prefix player messages with this code." },
@@ -1605,6 +1607,7 @@ a_Player:OpenWindow(Window);
HasPermission = { Params = "PermissionString", Return = "bool", Notes = "Returns true if the player has the specified permission" },
Heal = { Params = "HitPoints", Return = "", Notes = "Heals the player by the specified amount of HPs. Only positive amounts are expected. Sends a health update to the client." },
IsEating = { Params = "", Return = "bool", Notes = "Returns true if the player is currently eating the item in their hand." },
+ IsFlying = { Return = "bool", Notes = "Returns true if the player is flying." },
IsGameModeAdventure = { Params = "", Return = "bool", Notes = "Returns true if the player is in the gmAdventure gamemode, or has their gamemode unset and the world is a gmAdventure world." },
IsGameModeCreative = { Params = "", Return = "bool", Notes = "Returns true if the player is in the gmCreative gamemode, or has their gamemode unset and the world is a gmCreative world." },
IsGameModeSurvival = { Params = "", Return = "bool", Notes = "Returns true if the player is in the gmSurvival gamemode, or has their gamemode unset and the world is a gmSurvival world." },
@@ -1621,8 +1624,10 @@ a_Player:OpenWindow(Window);
RemoveFromGroup = { Params = "GroupName", Return = "", Notes = "Temporarily removes the player from the specified group. This change is lost when the player disconnects." },
Respawn = { Params = "", Return = "", Notes = "Restores the health, extinguishes fire, makes visible and sends the Respawn packet." },
SendMessage = { Params = "MessageString", Return = "", Notes = "Sends the specified message to the player." },
+ SetCanFly = { Params = "CanFly", Notes = "Sets if the player can fly or not." },
SetCrouch = { Params = "IsCrouched", Return = "", Notes = "Sets the crouch state, broadcasts the change to other players." },
SetCurrentExperience = { Params = "XPAmount", Return = "", Notes = "Sets the current amount of experience (and indirectly, the XP level)." },
+ SetFlying = { Params = "IsFlying", Notes = "Sets if the player is flying or not." },
SetFoodExhaustionLevel = { Params = "ExhaustionLevel", Return = "", Notes = "Sets the food exhaustion to the specified level." },
SetFoodLevel = { Params = "FoodLevel", Return = "", Notes = "Sets the food level (number of half-drumsticks on-screen)" },
SetFoodPoisonedTicksRemaining = { Params = "FoodPoisonedTicksRemaining", Return = "", Notes = "Sets the number of ticks remaining for food poisoning. Doesn't send foodpoisoning effect to the client, use FoodPoison() for that." },
@@ -2708,8 +2713,8 @@ end
"os",
"string",
"table",
- "g_TrackedPages",
"g_Stats",
+ "g_TrackedPages",
},
IgnoreFunctions =
@@ -2742,6 +2747,15 @@ end
"WriteStats",
},
+ IgnoreConstants =
+ {
+ "cChestEntity.__cBlockEntityWindowOwner__",
+ "cDropSpenserEntity.__cBlockEntityWindowOwner__",
+ "cFurnaceEntity.__cBlockEntityWindowOwner__",
+ "cHopperEntity.__cBlockEntityWindowOwner__",
+ "cLuaWindow.__cItemGrid__cListener__",
+ },
+
IgnoreVariables =
{
"__.*__", -- tolua exports multiple inheritance this way
diff --git a/MCServer/Plugins/APIDump/main_APIDump.lua b/MCServer/Plugins/APIDump/main_APIDump.lua
index de4239f7e..ec5569f55 100644
--- a/MCServer/Plugins/APIDump/main_APIDump.lua
+++ b/MCServer/Plugins/APIDump/main_APIDump.lua
@@ -700,6 +700,15 @@ function ReadDescriptions(a_API)
end
);
+ -- Remove ignored constants:
+ local NewConstants = {};
+ for j, cn in ipairs(cls.Constants) do
+ if (not(IsFunctionIgnored(cls.Name, cn.Name))) then
+ table.insert(NewConstants, cn);
+ end
+ end -- for j, cn
+ cls.Constants = NewConstants;
+
-- Sort the constants:
table.sort(cls.Constants,
function(c1, c2)
@@ -707,7 +716,7 @@ function ReadDescriptions(a_API)
end
);
- -- Remove ignored functions:
+ -- Remove ignored member variables:
local NewVariables = {};
for j, var in ipairs(cls.Variables) do
if (not(IsVariableIgnored(cls.Name .. "." .. var.Name))) then
diff --git a/Tools/ProtoProxy/Connection.cpp b/Tools/ProtoProxy/Connection.cpp
index 0b49859cb..10f2b4073 100644
--- a/Tools/ProtoProxy/Connection.cpp
+++ b/Tools/ProtoProxy/Connection.cpp
@@ -2384,10 +2384,11 @@ bool cConnection::HandleServerStatusResponse(void)
Log(" Response: %s", Response.c_str());
// Modify the response to show that it's being proto-proxied:
- size_t idx = Response.find("\"description\":\"");
+ const char DescSearch[] = "\"description\":{\"text\":\"";
+ size_t idx = Response.find(DescSearch);
if (idx != AString::npos)
{
- Response.assign(Response.substr(0, idx + 15) + "ProtoProxy: " + Response.substr(idx + 15));
+ Response.assign(Response.substr(0, idx + sizeof(DescSearch) - 1) + "ProtoProxy: " + Response.substr(idx + sizeof(DescSearch) - 1));
}
cByteBuffer Packet(1000);
Packet.WriteVarInt(0); // Packet type - status response
diff --git a/src/Bindings/AllToLua.pkg b/src/Bindings/AllToLua.pkg
index 6db7b2b0e..e9a5ea0c6 100644
--- a/src/Bindings/AllToLua.pkg
+++ b/src/Bindings/AllToLua.pkg
@@ -37,6 +37,7 @@ $cfile "../Entities/Player.h"
$cfile "../Entities/Pickup.h"
$cfile "../Entities/ProjectileEntity.h"
$cfile "../Entities/TNTEntity.h"
+$cfile "../Entities/Effects.h"
$cfile "../Server.h"
$cfile "../World.h"
$cfile "../Inventory.h"
diff --git a/src/Bindings/Bindings.cpp b/src/Bindings/Bindings.cpp
index 090d8047a..b53b78853 100644
--- a/src/Bindings/Bindings.cpp
+++ b/src/Bindings/Bindings.cpp
@@ -1,6 +1,6 @@
/*
** Lua binding: AllToLua
-** Generated automatically by tolua++-1.0.92 on 12/14/13 16:22:45.
+** Generated automatically by tolua++-1.0.92 on 12/18/13 16:09:11.
*/
#ifndef __cplusplus
@@ -8,7 +8,7 @@
#endif
#include "string.h"
-#include "tolua++/include/tolua++.h"
+#include "tolua++.h"
/* Exported function */
TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S);
@@ -35,6 +35,7 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S);
#include "../Entities/Pickup.h"
#include "../Entities/ProjectileEntity.h"
#include "../Entities/TNTEntity.h"
+#include "../Entities/Effects.h"
#include "../Server.h"
#include "../World.h"
#include "../Inventory.h"
@@ -219,45 +220,46 @@ static void tolua_reg_types (lua_State* tolua_S)
tolua_usertype(tolua_S,"cItemGrid");
tolua_usertype(tolua_S,"cHTTPServer::cCallbacks");
tolua_usertype(tolua_S,"cLuaWindow");
- tolua_usertype(tolua_S,"cInventory");
+ tolua_usertype(tolua_S,"cServer");
tolua_usertype(tolua_S,"cHopperEntity");
tolua_usertype(tolua_S,"std::vector<AString>");
- tolua_usertype(tolua_S,"cBlockEntityWithItems");
tolua_usertype(tolua_S,"cWindow");
+ tolua_usertype(tolua_S,"cBlockEntityWithItems");
tolua_usertype(tolua_S,"cCraftingGrid");
tolua_usertype(tolua_S,"cBlockArea");
tolua_usertype(tolua_S,"cGroup");
tolua_usertype(tolua_S,"cTracer");
- tolua_usertype(tolua_S,"cItem");
tolua_usertype(tolua_S,"cBoundingBox");
+ tolua_usertype(tolua_S,"cItem");
+ tolua_usertype(tolua_S,"cCuboid");
tolua_usertype(tolua_S,"cArrowEntity");
tolua_usertype(tolua_S,"cDropSpenserEntity");
- tolua_usertype(tolua_S,"cCuboid");
tolua_usertype(tolua_S,"Vector3i");
tolua_usertype(tolua_S,"Vector3d");
+ tolua_usertype(tolua_S,"cTNTEntity");
tolua_usertype(tolua_S,"cNoteEntity");
- tolua_usertype(tolua_S,"cServer");
+ tolua_usertype(tolua_S,"cWebAdmin");
tolua_usertype(tolua_S,"cBlockEntity");
tolua_usertype(tolua_S,"cCriticalSection");
tolua_usertype(tolua_S,"HTTPTemplateRequest");
tolua_usertype(tolua_S,"cPickup");
tolua_usertype(tolua_S,"cItems");
tolua_usertype(tolua_S,"cClientHandle");
- tolua_usertype(tolua_S,"cWebAdmin");
- tolua_usertype(tolua_S,"cChatColor");
tolua_usertype(tolua_S,"HTTPRequest");
- tolua_usertype(tolua_S,"cIniFile");
+ tolua_usertype(tolua_S,"cChatColor");
tolua_usertype(tolua_S,"HTTPFormData");
+ tolua_usertype(tolua_S,"cIniFile");
tolua_usertype(tolua_S,"cSignEntity");
+ tolua_usertype(tolua_S,"cDropperEntity");
tolua_usertype(tolua_S,"cPawn");
tolua_usertype(tolua_S,"cThrownEggEntity");
tolua_usertype(tolua_S,"cGroupManager");
+ tolua_usertype(tolua_S,"cBlockEntityWindowOwner");
tolua_usertype(tolua_S,"cPluginManager");
- tolua_usertype(tolua_S,"cDropperEntity");
tolua_usertype(tolua_S,"cProjectileEntity");
tolua_usertype(tolua_S,"cItemGrid::cListener");
+ tolua_usertype(tolua_S,"cInventory");
tolua_usertype(tolua_S,"cPlayer");
- tolua_usertype(tolua_S,"cTNTEntity");
}
/* method: new of class cIniFile */
@@ -3278,6 +3280,23 @@ static int tolua_AllToLua_cLuaWindow_GetContents00(lua_State* tolua_S)
}
#endif //#ifndef TOLUA_DISABLE
+/* get function: __cItemGrid of class cLuaWindow */
+#ifndef TOLUA_DISABLE_tolua_get_cLuaWindow___cItemGrid__cListener__
+static int tolua_get_cLuaWindow___cItemGrid__cListener__(lua_State* tolua_S)
+{
+ cLuaWindow* self = (cLuaWindow*) tolua_tousertype(tolua_S,1,0);
+#ifndef TOLUA_RELEASE
+ if (!self) tolua_error(tolua_S,"invalid 'self' in accessing variable '__cItemGrid'",NULL);
+#endif
+#ifdef __cplusplus
+ tolua_pushusertype(tolua_S,(void*)static_cast<cItemGrid::cListener*>(self), "cItemGrid::cListener");
+#else
+ tolua_pushusertype(tolua_S,(void*)((cItemGrid::cListener*)self), "cItemGrid::cListener");
+#endif
+ return 1;
+}
+#endif //#ifndef TOLUA_DISABLE
+
/* function: BlockStringToType */
#ifndef TOLUA_DISABLE_tolua_AllToLua_BlockStringToType00
static int tolua_AllToLua_BlockStringToType00(lua_State* tolua_S)
@@ -7425,6 +7444,41 @@ static int tolua_AllToLua_cEntity_AddSpeedZ00(lua_State* tolua_S)
}
#endif //#ifndef TOLUA_DISABLE
+/* method: HandleSpeedFromAttachee of class cEntity */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_cEntity_HandleSpeedFromAttachee00
+static int tolua_AllToLua_cEntity_HandleSpeedFromAttachee00(lua_State* tolua_S)
+{
+#ifndef TOLUA_RELEASE
+ tolua_Error tolua_err;
+ if (
+ !tolua_isusertype(tolua_S,1,"cEntity",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
+ {
+ cEntity* self = (cEntity*) tolua_tousertype(tolua_S,1,0);
+ float a_Forward = ((float) tolua_tonumber(tolua_S,2,0));
+ float a_Sideways = ((float) tolua_tonumber(tolua_S,3,0));
+#ifndef TOLUA_RELEASE
+ if (!self) tolua_error(tolua_S,"invalid 'self' in function 'HandleSpeedFromAttachee'", NULL);
+#endif
+ {
+ self->HandleSpeedFromAttachee(a_Forward,a_Sideways);
+ }
+ }
+ return 0;
+#ifndef TOLUA_RELEASE
+ tolua_lerror:
+ tolua_error(tolua_S,"#ferror in function 'HandleSpeedFromAttachee'.",&tolua_err);
+ return 0;
+#endif
+}
+#endif //#ifndef TOLUA_DISABLE
+
/* method: SteerVehicle of class cEntity */
#ifndef TOLUA_DISABLE_tolua_AllToLua_cEntity_SteerVehicle00
static int tolua_AllToLua_cEntity_SteerVehicle00(lua_State* tolua_S)
@@ -9394,6 +9448,39 @@ static int tolua_AllToLua_cPlayer_GetIP00(lua_State* tolua_S)
}
#endif //#ifndef TOLUA_DISABLE
+/* method: ForceSetSpeed of class cPlayer */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_cPlayer_ForceSetSpeed00
+static int tolua_AllToLua_cPlayer_ForceSetSpeed00(lua_State* tolua_S)
+{
+#ifndef TOLUA_RELEASE
+ tolua_Error tolua_err;
+ if (
+ !tolua_isusertype(tolua_S,1,"cPlayer",0,&tolua_err) ||
+ (tolua_isvaluenil(tolua_S,2,&tolua_err) || !tolua_isusertype(tolua_S,2,"Vector3d",0,&tolua_err)) ||
+ !tolua_isnoobj(tolua_S,3,&tolua_err)
+ )
+ goto tolua_lerror;
+ else
+#endif
+ {
+ cPlayer* self = (cPlayer*) tolua_tousertype(tolua_S,1,0);
+ Vector3d a_Direction = *((Vector3d*) tolua_tousertype(tolua_S,2,0));
+#ifndef TOLUA_RELEASE
+ if (!self) tolua_error(tolua_S,"invalid 'self' in function 'ForceSetSpeed'", NULL);
+#endif
+ {
+ self->ForceSetSpeed(a_Direction);
+ }
+ }
+ return 0;
+#ifndef TOLUA_RELEASE
+ tolua_lerror:
+ tolua_error(tolua_S,"#ferror in function 'ForceSetSpeed'.",&tolua_err);
+ return 0;
+#endif
+}
+#endif //#ifndef TOLUA_DISABLE
+
/* method: MoveTo of class cPlayer */
#ifndef TOLUA_DISABLE_tolua_AllToLua_cPlayer_MoveTo00
static int tolua_AllToLua_cPlayer_MoveTo00(lua_State* tolua_S)
@@ -10459,6 +10546,38 @@ static int tolua_AllToLua_cPlayer_IsEating00(lua_State* tolua_S)
}
#endif //#ifndef TOLUA_DISABLE
+/* method: IsFlying of class cPlayer */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_cPlayer_IsFlying00
+static int tolua_AllToLua_cPlayer_IsFlying00(lua_State* tolua_S)
+{
+#ifndef TOLUA_RELEASE
+ tolua_Error tolua_err;
+ if (
+ !tolua_isusertype(tolua_S,1,"const cPlayer",0,&tolua_err) ||
+ !tolua_isnoobj(tolua_S,2,&tolua_err)
+ )
+ goto tolua_lerror;
+ else
+#endif
+ {
+ const cPlayer* self = (const cPlayer*) tolua_tousertype(tolua_S,1,0);
+#ifndef TOLUA_RELEASE
+ if (!self) tolua_error(tolua_S,"invalid 'self' in function 'IsFlying'", NULL);
+#endif
+ {
+ bool tolua_ret = (bool) self->IsFlying();
+ tolua_pushboolean(tolua_S,(bool)tolua_ret);
+ }
+ }
+ return 1;
+#ifndef TOLUA_RELEASE
+ tolua_lerror:
+ tolua_error(tolua_S,"#ferror in function 'IsFlying'.",&tolua_err);
+ return 0;
+#endif
+}
+#endif //#ifndef TOLUA_DISABLE
+
/* method: Respawn of class cPlayer */
#ifndef TOLUA_DISABLE_tolua_AllToLua_cPlayer_Respawn00
static int tolua_AllToLua_cPlayer_Respawn00(lua_State* tolua_S)
@@ -10848,6 +10967,72 @@ static int tolua_AllToLua_cPlayer_SetSprint00(lua_State* tolua_S)
}
#endif //#ifndef TOLUA_DISABLE
+/* method: SetFlying of class cPlayer */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_cPlayer_SetFlying00
+static int tolua_AllToLua_cPlayer_SetFlying00(lua_State* tolua_S)
+{
+#ifndef TOLUA_RELEASE
+ tolua_Error tolua_err;
+ if (
+ !tolua_isusertype(tolua_S,1,"cPlayer",0,&tolua_err) ||
+ !tolua_isboolean(tolua_S,2,0,&tolua_err) ||
+ !tolua_isnoobj(tolua_S,3,&tolua_err)
+ )
+ goto tolua_lerror;
+ else
+#endif
+ {
+ cPlayer* self = (cPlayer*) tolua_tousertype(tolua_S,1,0);
+ bool a_IsFlying = ((bool) tolua_toboolean(tolua_S,2,0));
+#ifndef TOLUA_RELEASE
+ if (!self) tolua_error(tolua_S,"invalid 'self' in function 'SetFlying'", NULL);
+#endif
+ {
+ self->SetFlying(a_IsFlying);
+ }
+ }
+ return 0;
+#ifndef TOLUA_RELEASE
+ tolua_lerror:
+ tolua_error(tolua_S,"#ferror in function 'SetFlying'.",&tolua_err);
+ return 0;
+#endif
+}
+#endif //#ifndef TOLUA_DISABLE
+
+/* method: SetCanFly of class cPlayer */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_cPlayer_SetCanFly00
+static int tolua_AllToLua_cPlayer_SetCanFly00(lua_State* tolua_S)
+{
+#ifndef TOLUA_RELEASE
+ tolua_Error tolua_err;
+ if (
+ !tolua_isusertype(tolua_S,1,"cPlayer",0,&tolua_err) ||
+ !tolua_isboolean(tolua_S,2,0,&tolua_err) ||
+ !tolua_isnoobj(tolua_S,3,&tolua_err)
+ )
+ goto tolua_lerror;
+ else
+#endif
+ {
+ cPlayer* self = (cPlayer*) tolua_tousertype(tolua_S,1,0);
+ bool a_CanFly = ((bool) tolua_toboolean(tolua_S,2,0));
+#ifndef TOLUA_RELEASE
+ if (!self) tolua_error(tolua_S,"invalid 'self' in function 'SetCanFly'", NULL);
+#endif
+ {
+ self->SetCanFly(a_CanFly);
+ }
+ }
+ return 0;
+#ifndef TOLUA_RELEASE
+ tolua_lerror:
+ tolua_error(tolua_S,"#ferror in function 'SetCanFly'.",&tolua_err);
+ return 0;
+#endif
+}
+#endif //#ifndef TOLUA_DISABLE
+
/* method: IsSwimming of class cPlayer */
#ifndef TOLUA_DISABLE_tolua_AllToLua_cPlayer_IsSwimming00
static int tolua_AllToLua_cPlayer_IsSwimming00(lua_State* tolua_S)
@@ -10912,6 +11097,38 @@ static int tolua_AllToLua_cPlayer_IsSubmerged00(lua_State* tolua_S)
}
#endif //#ifndef TOLUA_DISABLE
+/* method: CanFly of class cPlayer */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_cPlayer_CanFly00
+static int tolua_AllToLua_cPlayer_CanFly00(lua_State* tolua_S)
+{
+#ifndef TOLUA_RELEASE
+ tolua_Error tolua_err;
+ if (
+ !tolua_isusertype(tolua_S,1,"const cPlayer",0,&tolua_err) ||
+ !tolua_isnoobj(tolua_S,2,&tolua_err)
+ )
+ goto tolua_lerror;
+ else
+#endif
+ {
+ const cPlayer* self = (const cPlayer*) tolua_tousertype(tolua_S,1,0);
+#ifndef TOLUA_RELEASE
+ if (!self) tolua_error(tolua_S,"invalid 'self' in function 'CanFly'", NULL);
+#endif
+ {
+ bool tolua_ret = (bool) self->CanFly();
+ tolua_pushboolean(tolua_S,(bool)tolua_ret);
+ }
+ }
+ return 1;
+#ifndef TOLUA_RELEASE
+ tolua_lerror:
+ tolua_error(tolua_S,"#ferror in function 'CanFly'.",&tolua_err);
+ return 0;
+#endif
+}
+#endif //#ifndef TOLUA_DISABLE
+
/* method: new of class cPickup */
#ifndef TOLUA_DISABLE_tolua_AllToLua_cPickup_new00
static int tolua_AllToLua_cPickup_new00(lua_State* tolua_S)
@@ -18627,6 +18844,23 @@ static int tolua_AllToLua_cBlockEntityWithItems_GetContents00(lua_State* tolua_S
}
#endif //#ifndef TOLUA_DISABLE
+/* get function: __cBlockEntityWindowOwner__ of class cChestEntity */
+#ifndef TOLUA_DISABLE_tolua_get_cChestEntity___cBlockEntityWindowOwner__
+static int tolua_get_cChestEntity___cBlockEntityWindowOwner__(lua_State* tolua_S)
+{
+ cChestEntity* self = (cChestEntity*) tolua_tousertype(tolua_S,1,0);
+#ifndef TOLUA_RELEASE
+ if (!self) tolua_error(tolua_S,"invalid 'self' in accessing variable '__cBlockEntityWindowOwner__'",NULL);
+#endif
+#ifdef __cplusplus
+ tolua_pushusertype(tolua_S,(void*)static_cast<cBlockEntityWindowOwner*>(self), "cBlockEntityWindowOwner");
+#else
+ tolua_pushusertype(tolua_S,(void*)((cBlockEntityWindowOwner*)self), "cBlockEntityWindowOwner");
+#endif
+ return 1;
+}
+#endif //#ifndef TOLUA_DISABLE
+
/* method: AddDropSpenserDir of class cDropSpenserEntity */
#ifndef TOLUA_DISABLE_tolua_AllToLua_cDropSpenserEntity_AddDropSpenserDir00
static int tolua_AllToLua_cDropSpenserEntity_AddDropSpenserDir00(lua_State* tolua_S)
@@ -18733,6 +18967,23 @@ static int tolua_AllToLua_cDropSpenserEntity_SetRedstonePower00(lua_State* tolua
}
#endif //#ifndef TOLUA_DISABLE
+/* get function: __cBlockEntityWindowOwner__ of class cDropSpenserEntity */
+#ifndef TOLUA_DISABLE_tolua_get_cDropSpenserEntity___cBlockEntityWindowOwner__
+static int tolua_get_cDropSpenserEntity___cBlockEntityWindowOwner__(lua_State* tolua_S)
+{
+ cDropSpenserEntity* self = (cDropSpenserEntity*) tolua_tousertype(tolua_S,1,0);
+#ifndef TOLUA_RELEASE
+ if (!self) tolua_error(tolua_S,"invalid 'self' in accessing variable '__cBlockEntityWindowOwner__'",NULL);
+#endif
+#ifdef __cplusplus
+ tolua_pushusertype(tolua_S,(void*)static_cast<cBlockEntityWindowOwner*>(self), "cBlockEntityWindowOwner");
+#else
+ tolua_pushusertype(tolua_S,(void*)((cBlockEntityWindowOwner*)self), "cBlockEntityWindowOwner");
+#endif
+ return 1;
+}
+#endif //#ifndef TOLUA_DISABLE
+
/* method: GetInputSlot of class cFurnaceEntity */
#ifndef TOLUA_DISABLE_tolua_AllToLua_cFurnaceEntity_GetInputSlot00
static int tolua_AllToLua_cFurnaceEntity_GetInputSlot00(lua_State* tolua_S)
@@ -19056,6 +19307,40 @@ static int tolua_AllToLua_cFurnaceEntity_HasFuelTimeLeft00(lua_State* tolua_S)
}
#endif //#ifndef TOLUA_DISABLE
+/* get function: __cBlockEntityWindowOwner__ of class cFurnaceEntity */
+#ifndef TOLUA_DISABLE_tolua_get_cFurnaceEntity___cBlockEntityWindowOwner__
+static int tolua_get_cFurnaceEntity___cBlockEntityWindowOwner__(lua_State* tolua_S)
+{
+ cFurnaceEntity* self = (cFurnaceEntity*) tolua_tousertype(tolua_S,1,0);
+#ifndef TOLUA_RELEASE
+ if (!self) tolua_error(tolua_S,"invalid 'self' in accessing variable '__cBlockEntityWindowOwner__'",NULL);
+#endif
+#ifdef __cplusplus
+ tolua_pushusertype(tolua_S,(void*)static_cast<cBlockEntityWindowOwner*>(self), "cBlockEntityWindowOwner");
+#else
+ tolua_pushusertype(tolua_S,(void*)((cBlockEntityWindowOwner*)self), "cBlockEntityWindowOwner");
+#endif
+ return 1;
+}
+#endif //#ifndef TOLUA_DISABLE
+
+/* get function: __cBlockEntityWindowOwner__ of class cHopperEntity */
+#ifndef TOLUA_DISABLE_tolua_get_cHopperEntity___cBlockEntityWindowOwner__
+static int tolua_get_cHopperEntity___cBlockEntityWindowOwner__(lua_State* tolua_S)
+{
+ cHopperEntity* self = (cHopperEntity*) tolua_tousertype(tolua_S,1,0);
+#ifndef TOLUA_RELEASE
+ if (!self) tolua_error(tolua_S,"invalid 'self' in accessing variable '__cBlockEntityWindowOwner__'",NULL);
+#endif
+#ifdef __cplusplus
+ tolua_pushusertype(tolua_S,(void*)static_cast<cBlockEntityWindowOwner*>(self), "cBlockEntityWindowOwner");
+#else
+ tolua_pushusertype(tolua_S,(void*)((cBlockEntityWindowOwner*)self), "cBlockEntityWindowOwner");
+#endif
+ return 1;
+}
+#endif //#ifndef TOLUA_DISABLE
+
/* method: GetRecord of class cJukeboxEntity */
#ifndef TOLUA_DISABLE_tolua_AllToLua_cJukeboxEntity_GetRecord00
static int tolua_AllToLua_cJukeboxEntity_GetRecord00(lua_State* tolua_S)
@@ -29860,7 +30145,7 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S)
tolua_constant(tolua_S,"HOOK_COLLECTING_PICKUP",cPluginManager::HOOK_COLLECTING_PICKUP);
tolua_constant(tolua_S,"HOOK_CRAFTING_NO_RECIPE",cPluginManager::HOOK_CRAFTING_NO_RECIPE);
tolua_constant(tolua_S,"HOOK_DISCONNECT",cPluginManager::HOOK_DISCONNECT);
- tolua_constant(tolua_S,"HOOK_ENTITY_ANIMATION",cPluginManager::HOOK_ENTITY_ANIMATION);
+ tolua_constant(tolua_S,"HOOK_PLAYER_ANIMATION",cPluginManager::HOOK_PLAYER_ANIMATION);
tolua_constant(tolua_S,"HOOK_EXECUTE_COMMAND",cPluginManager::HOOK_EXECUTE_COMMAND);
tolua_constant(tolua_S,"HOOK_EXPLODED",cPluginManager::HOOK_EXPLODED);
tolua_constant(tolua_S,"HOOK_EXPLODING",cPluginManager::HOOK_EXPLODING);
@@ -29946,6 +30231,7 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S)
tolua_function(tolua_S,".call",tolua_AllToLua_cLuaWindow_new00_local);
tolua_function(tolua_S,"delete",tolua_AllToLua_cLuaWindow_delete00);
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_constant(tolua_S,"E_BLOCK_AIR",E_BLOCK_AIR);
tolua_constant(tolua_S,"E_BLOCK_STONE",E_BLOCK_STONE);
@@ -30876,6 +31162,7 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S)
tolua_function(tolua_S,"AddSpeedX",tolua_AllToLua_cEntity_AddSpeedX00);
tolua_function(tolua_S,"AddSpeedY",tolua_AllToLua_cEntity_AddSpeedY00);
tolua_function(tolua_S,"AddSpeedZ",tolua_AllToLua_cEntity_AddSpeedZ00);
+ tolua_function(tolua_S,"HandleSpeedFromAttachee",tolua_AllToLua_cEntity_HandleSpeedFromAttachee00);
tolua_function(tolua_S,"SteerVehicle",tolua_AllToLua_cEntity_SteerVehicle00);
tolua_function(tolua_S,"GetUniqueID",tolua_AllToLua_cEntity_GetUniqueID00);
tolua_function(tolua_S,"IsDestroyed",tolua_AllToLua_cEntity_IsDestroyed00);
@@ -30945,6 +31232,7 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S)
tolua_function(tolua_S,"IsGameModeSurvival",tolua_AllToLua_cPlayer_IsGameModeSurvival00);
tolua_function(tolua_S,"IsGameModeAdventure",tolua_AllToLua_cPlayer_IsGameModeAdventure00);
tolua_function(tolua_S,"GetIP",tolua_AllToLua_cPlayer_GetIP00);
+ tolua_function(tolua_S,"ForceSetSpeed",tolua_AllToLua_cPlayer_ForceSetSpeed00);
tolua_function(tolua_S,"MoveTo",tolua_AllToLua_cPlayer_MoveTo00);
tolua_function(tolua_S,"GetWindow",tolua_AllToLua_cPlayer_GetWindow00);
tolua_function(tolua_S,"CloseWindow",tolua_AllToLua_cPlayer_CloseWindow00);
@@ -30977,6 +31265,7 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S)
tolua_function(tolua_S,"AddFoodExhaustion",tolua_AllToLua_cPlayer_AddFoodExhaustion00);
tolua_function(tolua_S,"FoodPoison",tolua_AllToLua_cPlayer_FoodPoison00);
tolua_function(tolua_S,"IsEating",tolua_AllToLua_cPlayer_IsEating00);
+ tolua_function(tolua_S,"IsFlying",tolua_AllToLua_cPlayer_IsFlying00);
tolua_function(tolua_S,"Respawn",tolua_AllToLua_cPlayer_Respawn00);
tolua_function(tolua_S,"SetVisible",tolua_AllToLua_cPlayer_SetVisible00);
tolua_function(tolua_S,"IsVisible",tolua_AllToLua_cPlayer_IsVisible00);
@@ -30989,8 +31278,11 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S)
tolua_function(tolua_S,"SetSprintingMaxSpeed",tolua_AllToLua_cPlayer_SetSprintingMaxSpeed00);
tolua_function(tolua_S,"SetCrouch",tolua_AllToLua_cPlayer_SetCrouch00);
tolua_function(tolua_S,"SetSprint",tolua_AllToLua_cPlayer_SetSprint00);
+ tolua_function(tolua_S,"SetFlying",tolua_AllToLua_cPlayer_SetFlying00);
+ tolua_function(tolua_S,"SetCanFly",tolua_AllToLua_cPlayer_SetCanFly00);
tolua_function(tolua_S,"IsSwimming",tolua_AllToLua_cPlayer_IsSwimming00);
tolua_function(tolua_S,"IsSubmerged",tolua_AllToLua_cPlayer_IsSubmerged00);
+ tolua_function(tolua_S,"CanFly",tolua_AllToLua_cPlayer_CanFly00);
tolua_endmodule(tolua_S);
#ifdef __cplusplus
tolua_cclass(tolua_S,"cPickup","cPickup","cEntity",tolua_collect_cPickup);
@@ -31064,6 +31356,29 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S)
tolua_function(tolua_S,"GetCounterTime",tolua_AllToLua_cTNTEntity_GetCounterTime00);
tolua_function(tolua_S,"GetMaxFuseTime",tolua_AllToLua_cTNTEntity_GetMaxFuseTime00);
tolua_endmodule(tolua_S);
+ tolua_constant(tolua_S,"E_EFFECT_SPEED",E_EFFECT_SPEED);
+ tolua_constant(tolua_S,"E_EFFECT_SLOWNESS",E_EFFECT_SLOWNESS);
+ tolua_constant(tolua_S,"E_EFFECT_HASTE",E_EFFECT_HASTE);
+ tolua_constant(tolua_S,"E_EFFECT_MINING_FATIGUE",E_EFFECT_MINING_FATIGUE);
+ tolua_constant(tolua_S,"E_EFFECT_STENGTH",E_EFFECT_STENGTH);
+ tolua_constant(tolua_S,"E_EFFECT_INSTANT_HEALTH",E_EFFECT_INSTANT_HEALTH);
+ tolua_constant(tolua_S,"E_EFFECT_INSTANT_DAMAGE",E_EFFECT_INSTANT_DAMAGE);
+ tolua_constant(tolua_S,"E_EFFECT_JUMP_BOOST",E_EFFECT_JUMP_BOOST);
+ tolua_constant(tolua_S,"E_EFFECT_NAUSEA",E_EFFECT_NAUSEA);
+ tolua_constant(tolua_S,"E_EFFECT_REGENERATION",E_EFFECT_REGENERATION);
+ tolua_constant(tolua_S,"E_EFFECT_RESISTANCE",E_EFFECT_RESISTANCE);
+ tolua_constant(tolua_S,"E_EFFECT_FIRE_RESISTANCE",E_EFFECT_FIRE_RESISTANCE);
+ tolua_constant(tolua_S,"E_EFFECT_WATER_BREATHING",E_EFFECT_WATER_BREATHING);
+ tolua_constant(tolua_S,"E_EFFECT_INVISIBILITY",E_EFFECT_INVISIBILITY);
+ tolua_constant(tolua_S,"E_EFFECT_BLINDNESS",E_EFFECT_BLINDNESS);
+ tolua_constant(tolua_S,"E_EFFECT_NIGHT_VISION",E_EFFECT_NIGHT_VISION);
+ tolua_constant(tolua_S,"E_EFFECT_HUNGER",E_EFFECT_HUNGER);
+ tolua_constant(tolua_S,"E_EFFECT_WEAKNESS",E_EFFECT_WEAKNESS);
+ tolua_constant(tolua_S,"E_EFFECT_POISON",E_EFFECT_POISON);
+ tolua_constant(tolua_S,"E_EFFECT_WITHER",E_EFFECT_WITHER);
+ tolua_constant(tolua_S,"E_EFFECT_HEALTH_BOOST",E_EFFECT_HEALTH_BOOST);
+ tolua_constant(tolua_S,"E_EFFECT_ABSORPTION",E_EFFECT_ABSORPTION);
+ tolua_constant(tolua_S,"E_EFFECT_SATURATION",E_EFFECT_SATURATION);
tolua_cclass(tolua_S,"cServer","cServer","",NULL);
tolua_beginmodule(tolua_S,"cServer");
tolua_function(tolua_S,"GetDescription",tolua_AllToLua_cServer_GetDescription00);
@@ -31357,6 +31672,7 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S)
tolua_beginmodule(tolua_S,"cChestEntity");
tolua_constant(tolua_S,"ContentsHeight",cChestEntity::ContentsHeight);
tolua_constant(tolua_S,"ContentsWidth",cChestEntity::ContentsWidth);
+ tolua_variable(tolua_S,"__cBlockEntityWindowOwner__",tolua_get_cChestEntity___cBlockEntityWindowOwner__,NULL);
tolua_endmodule(tolua_S);
tolua_cclass(tolua_S,"cDropSpenserEntity","cDropSpenserEntity","cBlockEntityWithItems",NULL);
tolua_beginmodule(tolua_S,"cDropSpenserEntity");
@@ -31365,6 +31681,7 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S)
tolua_function(tolua_S,"AddDropSpenserDir",tolua_AllToLua_cDropSpenserEntity_AddDropSpenserDir00);
tolua_function(tolua_S,"Activate",tolua_AllToLua_cDropSpenserEntity_Activate00);
tolua_function(tolua_S,"SetRedstonePower",tolua_AllToLua_cDropSpenserEntity_SetRedstonePower00);
+ tolua_variable(tolua_S,"__cBlockEntityWindowOwner__",tolua_get_cDropSpenserEntity___cBlockEntityWindowOwner__,NULL);
tolua_endmodule(tolua_S);
tolua_cclass(tolua_S,"cDispenserEntity","cDispenserEntity","cDropSpenserEntity",NULL);
tolua_beginmodule(tolua_S,"cDispenserEntity");
@@ -31389,12 +31706,14 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S)
tolua_function(tolua_S,"GetCookTimeLeft",tolua_AllToLua_cFurnaceEntity_GetCookTimeLeft00);
tolua_function(tolua_S,"GetFuelBurnTimeLeft",tolua_AllToLua_cFurnaceEntity_GetFuelBurnTimeLeft00);
tolua_function(tolua_S,"HasFuelTimeLeft",tolua_AllToLua_cFurnaceEntity_HasFuelTimeLeft00);
+ tolua_variable(tolua_S,"__cBlockEntityWindowOwner__",tolua_get_cFurnaceEntity___cBlockEntityWindowOwner__,NULL);
tolua_endmodule(tolua_S);
tolua_cclass(tolua_S,"cHopperEntity","cHopperEntity","cBlockEntityWithItems",NULL);
tolua_beginmodule(tolua_S,"cHopperEntity");
tolua_constant(tolua_S,"ContentsHeight",cHopperEntity::ContentsHeight);
tolua_constant(tolua_S,"ContentsWidth",cHopperEntity::ContentsWidth);
tolua_constant(tolua_S,"TICKS_PER_TRANSFER",cHopperEntity::TICKS_PER_TRANSFER);
+ tolua_variable(tolua_S,"__cBlockEntityWindowOwner__",tolua_get_cHopperEntity___cBlockEntityWindowOwner__,NULL);
tolua_endmodule(tolua_S);
tolua_cclass(tolua_S,"cJukeboxEntity","cJukeboxEntity","cBlockEntity",NULL);
tolua_beginmodule(tolua_S,"cJukeboxEntity");
diff --git a/src/Bindings/Bindings.h b/src/Bindings/Bindings.h
index 73cf3c7d8..2fbd53dcc 100644
--- a/src/Bindings/Bindings.h
+++ b/src/Bindings/Bindings.h
@@ -1,6 +1,6 @@
/*
** Lua binding: AllToLua
-** Generated automatically by tolua++-1.0.92 on 12/14/13 16:22:46.
+** Generated automatically by tolua++-1.0.92 on 12/18/13 16:09:11.
*/
/* Exported function */
diff --git a/src/Bindings/LuaWindow.h b/src/Bindings/LuaWindow.h
index 58d26ef96..dab99a2e2 100644
--- a/src/Bindings/LuaWindow.h
+++ b/src/Bindings/LuaWindow.h
@@ -33,10 +33,10 @@ Additionally, to forbid Lua from deleting this object while it is used by player
cPlayer:OpenWindow check if the window is of this class, and if so, make a global Lua reference for this object.
This reference needs to be unreferenced in the Destroy() function.
*/
-class cLuaWindow : // tolua_export
- public cItemGrid::cListener,
- // tolua_begin
- public cWindow
+// tolua_begin
+class cLuaWindow :
+ public cWindow,
+ public cItemGrid::cListener
{
typedef cWindow super;
diff --git a/src/Bindings/ManualBindings.cpp b/src/Bindings/ManualBindings.cpp
index 4f7e1470a..2e19c2581 100644
--- a/src/Bindings/ManualBindings.cpp
+++ b/src/Bindings/ManualBindings.cpp
@@ -18,6 +18,7 @@
#include "../BlockEntities/DropperEntity.h"
#include "../BlockEntities/FurnaceEntity.h"
#include "../BlockEntities/HopperEntity.h"
+#include "../BlockEntities/NoteEntity.h"
#include "md5/md5.h"
#include "../LineBlockTracer.h"
@@ -2217,6 +2218,7 @@ void ManualBindings::Bind(lua_State * tolua_S)
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, "DoWithNoteBlockAt", tolua_DoWithXYZ<cWorld, cNoteEntity, &cWorld::DoWithNoteBlockAt>);
tolua_function(tolua_S, "DoWithPlayer", tolua_DoWith< cWorld, cPlayer, &cWorld::DoWithPlayer>);
tolua_function(tolua_S, "FindAndDoWithPlayer", tolua_DoWith< cWorld, cPlayer, &cWorld::FindAndDoWithPlayer>);
tolua_function(tolua_S, "ForEachBlockEntityInChunk", tolua_ForEachInChunk<cWorld, cBlockEntity, &cWorld::ForEachBlockEntityInChunk>);
diff --git a/src/Bindings/Plugin.h b/src/Bindings/Plugin.h
index 5cb35ac5a..9a3c2383e 100644
--- a/src/Bindings/Plugin.h
+++ b/src/Bindings/Plugin.h
@@ -64,7 +64,7 @@ public:
virtual bool OnHopperPushingItem (cWorld & a_World, cHopperEntity & a_Hopper, int a_SrcSlotNum, cBlockEntityWithItems & a_DstEntity, int a_DstSlotNum) = 0;
virtual bool OnKilling (cEntity & a_Victim, cEntity * a_Killer) = 0;
virtual bool OnLogin (cClientHandle * a_Client, int a_ProtocolVersion, const AString & a_Username) = 0;
- virtual bool OnEntityAnimation (cEntity & a_Entity, int a_Animation) = 0;
+ virtual bool OnPlayerAnimation (cPlayer & a_Player, int a_Animation) = 0;
virtual bool OnPlayerBreakingBlock (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) = 0;
virtual bool OnPlayerBrokenBlock (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) = 0;
virtual bool OnPlayerEating (cPlayer & a_Player) = 0;
diff --git a/src/Bindings/PluginLua.cpp b/src/Bindings/PluginLua.cpp
index f27cee76e..0d17c9ce2 100644
--- a/src/Bindings/PluginLua.cpp
+++ b/src/Bindings/PluginLua.cpp
@@ -550,14 +550,14 @@ bool cPluginLua::OnLogin(cClientHandle * a_Client, int a_ProtocolVersion, const
-bool cPluginLua::OnEntityAnimation(cEntity & a_Entity, int a_Animation)
+bool cPluginLua::OnPlayerAnimation(cPlayer & a_Player, int a_Animation)
{
cCSLock Lock(m_CriticalSection);
bool res = false;
- cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_ENTITY_ANIMATION];
+ cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_PLAYER_ANIMATION];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
{
- m_LuaState.Call((int)(**itr), &a_Entity, a_Animation, cLuaState::Return, res);
+ m_LuaState.Call((int)(**itr), &a_Player, a_Animation, cLuaState::Return, res);
if (res)
{
return true;
@@ -1302,7 +1302,7 @@ const char * cPluginLua::GetHookFnName(int a_HookType)
case cPluginManager::HOOK_COLLECTING_PICKUP: return "OnCollectingPickup";
case cPluginManager::HOOK_CRAFTING_NO_RECIPE: return "OnCraftingNoRecipe";
case cPluginManager::HOOK_DISCONNECT: return "OnDisconnect";
- case cPluginManager::HOOK_ENTITY_ANIMATION: return "OnEntityAnimation";
+ case cPluginManager::HOOK_PLAYER_ANIMATION: return "OnPlayerAnimation";
case cPluginManager::HOOK_EXECUTE_COMMAND: return "OnExecuteCommand";
case cPluginManager::HOOK_HANDSHAKE: return "OnHandshake";
case cPluginManager::HOOK_KILLING: return "OnKilling";
diff --git a/src/Bindings/PluginLua.h b/src/Bindings/PluginLua.h
index 188d202e0..e1e274c72 100644
--- a/src/Bindings/PluginLua.h
+++ b/src/Bindings/PluginLua.h
@@ -61,7 +61,7 @@ public:
virtual bool OnHopperPushingItem (cWorld & a_World, cHopperEntity & a_Hopper, int a_SrcSlotNum, cBlockEntityWithItems & a_DstEntity, int a_DstSlotNum) override;
virtual bool OnKilling (cEntity & a_Victim, cEntity * a_Killer) override;
virtual bool OnLogin (cClientHandle * a_Client, int a_ProtocolVersion, const AString & a_Username) override;
- virtual bool OnEntityAnimation (cEntity & a_Entity, int a_Animation) override;
+ virtual bool OnPlayerAnimation (cPlayer & a_Player, int a_Animation) override;
virtual bool OnPlayerBreakingBlock (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) override;
virtual bool OnPlayerBrokenBlock (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) override;
virtual bool OnPlayerEating (cPlayer & a_Player) override;
diff --git a/src/Bindings/PluginManager.cpp b/src/Bindings/PluginManager.cpp
index 12263605f..732da24fa 100644
--- a/src/Bindings/PluginManager.cpp
+++ b/src/Bindings/PluginManager.cpp
@@ -602,16 +602,16 @@ bool cPluginManager::CallHookLogin(cClientHandle * a_Client, int a_ProtocolVersi
-bool cPluginManager::CallHookEntityAnimation(cEntity & a_Entity, int a_Animation)
+bool cPluginManager::CallHookPlayerAnimation(cPlayer & a_Player, int a_Animation)
{
- HookMap::iterator Plugins = m_Hooks.find(HOOK_ENTITY_ANIMATION);
+ HookMap::iterator Plugins = m_Hooks.find(HOOK_PLAYER_ANIMATION);
if (Plugins == m_Hooks.end())
{
return false;
}
for (PluginList::iterator itr = Plugins->second.begin(); itr != Plugins->second.end(); ++itr)
{
- if ((*itr)->OnEntityAnimation(a_Entity, a_Animation))
+ if ((*itr)->OnPlayerAnimation(a_Player, a_Animation))
{
return true;
}
diff --git a/src/Bindings/PluginManager.h b/src/Bindings/PluginManager.h
index 09f230475..b69f402c0 100644
--- a/src/Bindings/PluginManager.h
+++ b/src/Bindings/PluginManager.h
@@ -68,7 +68,7 @@ public: // tolua_export
HOOK_COLLECTING_PICKUP,
HOOK_CRAFTING_NO_RECIPE,
HOOK_DISCONNECT,
- HOOK_ENTITY_ANIMATION,
+ HOOK_PLAYER_ANIMATION,
HOOK_EXECUTE_COMMAND,
HOOK_EXPLODED,
HOOK_EXPLODING,
@@ -163,7 +163,7 @@ public: // tolua_export
bool CallHookHopperPushingItem (cWorld & a_World, cHopperEntity & a_Hopper, int a_SrcSlotNum, cBlockEntityWithItems & a_DstEntity, int a_DstSlotNum);
bool CallHookKilling (cEntity & a_Victim, cEntity * a_Killer);
bool CallHookLogin (cClientHandle * a_Client, int a_ProtocolVersion, const AString & a_Username);
- bool CallHookEntityAnimation (cEntity & a_Entity, int a_Animation);
+ bool CallHookPlayerAnimation (cPlayer & a_Player, int a_Animation);
bool CallHookPlayerBreakingBlock (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta);
bool CallHookPlayerBrokenBlock (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta);
bool CallHookPlayerEating (cPlayer & a_Player);
diff --git a/src/Bindings/tolua++.h b/src/Bindings/tolua++.h
new file mode 100644
index 000000000..4dfd06318
--- /dev/null
+++ b/src/Bindings/tolua++.h
@@ -0,0 +1,13 @@
+
+// tolua++.h
+
+// Redirection file, needed because ToLua++ generates the Bindings.cpp file with >> #include "tolua++.h" <<
+
+
+
+
+#include "tolua++/include/tolua++.h"
+
+
+
+
diff --git a/src/BlockArea.cpp b/src/BlockArea.cpp
index 5c15adfef..c9443c702 100644
--- a/src/BlockArea.cpp
+++ b/src/BlockArea.cpp
@@ -161,6 +161,9 @@ static void MergeCombinatorLake(BLOCKTYPE & a_DstType, BLOCKTYPE a_SrcType, NIBB
// cBlockArea:
cBlockArea::cBlockArea(void) :
+ m_OriginX(0),
+ m_OriginY(0),
+ m_OriginZ(0),
m_SizeX(0),
m_SizeY(0),
m_SizeZ(0),
@@ -190,6 +193,9 @@ void cBlockArea::Clear(void)
delete[] m_BlockMetas; m_BlockMetas = NULL;
delete[] m_BlockLight; m_BlockLight = NULL;
delete[] m_BlockSkyLight; m_BlockSkyLight = NULL;
+ m_OriginX = 0;
+ m_OriginY = 0;
+ m_OriginZ = 0;
m_SizeX = 0;
m_SizeY = 0;
m_SizeZ = 0;
diff --git a/src/BlockEntities/ChestEntity.h b/src/BlockEntities/ChestEntity.h
index 4f2c21e91..4110de1f3 100644
--- a/src/BlockEntities/ChestEntity.h
+++ b/src/BlockEntities/ChestEntity.h
@@ -21,10 +21,10 @@ class cNBTData;
-class cChestEntity : // tolua_export
- public cBlockEntityWindowOwner,
- // tolua_begin
- public cBlockEntityWithItems
+// tolua_begin
+class cChestEntity :
+ public cBlockEntityWithItems,
+ public cBlockEntityWindowOwner
{
typedef cBlockEntityWithItems super;
diff --git a/src/BlockEntities/DropSpenserEntity.h b/src/BlockEntities/DropSpenserEntity.h
index 0e9039915..f2f1eba36 100644
--- a/src/BlockEntities/DropSpenserEntity.h
+++ b/src/BlockEntities/DropSpenserEntity.h
@@ -29,10 +29,10 @@ class cServer;
-class cDropSpenserEntity : // tolua_export
- public cBlockEntityWindowOwner,
- // tolua_begin
- public cBlockEntityWithItems
+// tolua_begin
+class cDropSpenserEntity :
+ public cBlockEntityWithItems,
+ public cBlockEntityWindowOwner
{
typedef cBlockEntityWithItems super;
diff --git a/src/BlockEntities/EnderChestEntity.h b/src/BlockEntities/EnderChestEntity.h
index 683b652b2..0ee3cab3b 100644
--- a/src/BlockEntities/EnderChestEntity.h
+++ b/src/BlockEntities/EnderChestEntity.h
@@ -21,10 +21,10 @@ class cNBTData;
-class cEnderChestEntity : // tolua_export
- public cBlockEntityWindowOwner,
- // tolua_begin
- public cBlockEntityWithItems
+// tolua_begin
+class cEnderChestEntity :
+ public cBlockEntityWithItems,
+ public cBlockEntityWindowOwner
{
typedef cBlockEntityWithItems super;
diff --git a/src/BlockEntities/FurnaceEntity.h b/src/BlockEntities/FurnaceEntity.h
index 9464fd175..8b695d61a 100644
--- a/src/BlockEntities/FurnaceEntity.h
+++ b/src/BlockEntities/FurnaceEntity.h
@@ -21,10 +21,10 @@ class cServer;
-class cFurnaceEntity : // tolua_export
- public cBlockEntityWindowOwner,
- // tolua_begin
- public cBlockEntityWithItems
+// tolua_begin
+class cFurnaceEntity :
+ public cBlockEntityWithItems,
+ public cBlockEntityWindowOwner
{
typedef cBlockEntityWithItems super;
diff --git a/src/BlockEntities/HopperEntity.h b/src/BlockEntities/HopperEntity.h
index 3eaa05b7c..2c8b301fe 100644
--- a/src/BlockEntities/HopperEntity.h
+++ b/src/BlockEntities/HopperEntity.h
@@ -16,10 +16,10 @@
-class cHopperEntity : // tolua_export
- public cBlockEntityWindowOwner,
- // tolua_begin
- public cBlockEntityWithItems
+// tolua_begin
+class cHopperEntity :
+ public cBlockEntityWithItems,
+ public cBlockEntityWindowOwner
{
typedef cBlockEntityWithItems super;
diff --git a/src/Blocks/BlockHandler.cpp b/src/Blocks/BlockHandler.cpp
index d377823f7..ff1022e12 100644
--- a/src/Blocks/BlockHandler.cpp
+++ b/src/Blocks/BlockHandler.cpp
@@ -40,6 +40,7 @@
#include "BlockMelon.h"
#include "BlockMushroom.h"
#include "BlockMycelium.h"
+#include "BlockNetherWart.h"
#include "BlockNote.h"
#include "BlockOre.h"
#include "BlockPiston.h"
@@ -160,6 +161,7 @@ cBlockHandler * cBlockHandler::CreateBlockHandler(BLOCKTYPE a_BlockType)
case E_BLOCK_MYCELIUM: return new cBlockMyceliumHandler (a_BlockType);
case E_BLOCK_NETHER_BRICK_STAIRS: return new cBlockStairsHandler (a_BlockType);
case E_BLOCK_NETHER_PORTAL: return new cBlockPortalHandler (a_BlockType);
+ case E_BLOCK_NETHER_WART: return new cBlockNetherWartHandler (a_BlockType);
case E_BLOCK_NOTE_BLOCK: return new cBlockNoteHandler (a_BlockType);
case E_BLOCK_PISTON: return new cBlockPistonHandler (a_BlockType);
case E_BLOCK_PISTON_EXTENSION: return new cBlockPistonHeadHandler ( );
diff --git a/src/Blocks/BlockNetherWart.h b/src/Blocks/BlockNetherWart.h
new file mode 100644
index 000000000..4cc3d989a
--- /dev/null
+++ b/src/Blocks/BlockNetherWart.h
@@ -0,0 +1,52 @@
+
+#pragma once
+
+#include "BlockHandler.h"
+#include "../MersenneTwister.h"
+#include "../World.h"
+
+
+
+
+
+/// Common class that takes care of carrots, potatoes and wheat
+class cBlockNetherWartHandler :
+ public cBlockHandler
+{
+public:
+ cBlockNetherWartHandler(BLOCKTYPE a_BlockType)
+ : cBlockHandler(a_BlockType)
+ {
+ }
+
+
+ virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_Meta) override
+ {
+ MTRand rand;
+
+ if (a_Meta == 0x7)
+ {
+ // Is fully grown, drop the entire produce:
+ a_Pickups.push_back(cItem(E_ITEM_NETHER_WART, 1 + (int)(rand.randInt(2) + rand.randInt(2)) / 2, 0));
+ }
+ else
+ {
+ a_Pickups.push_back(cItem(E_ITEM_NETHER_WART));
+ }
+ }
+
+ void OnUpdate(cChunk & a_Chunk, int a_RelX, int a_RelY, int a_RelZ) override
+ {
+ NIBBLETYPE Meta = a_Chunk.GetMeta (a_RelX, a_RelY, a_RelZ);
+
+ if (Meta < 7)
+ {
+ a_Chunk.FastSetBlock(a_RelX, a_RelY, a_RelZ, E_BLOCK_NETHER_WART, ++Meta);
+ }
+ }
+
+ 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_SOULSAND));
+ }
+} ; \ No newline at end of file
diff --git a/src/Chunk.cpp b/src/Chunk.cpp
index 42969bf6d..3eb46213c 100644
--- a/src/Chunk.cpp
+++ b/src/Chunk.cpp
@@ -2225,6 +2225,38 @@ bool cChunk::DoWithFurnaceAt(int a_BlockX, int a_BlockY, int a_BlockZ, cFurnaceC
+bool cChunk::DoWithNoteBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cNoteBlockCallback & a_Callback)
+{
+ // The blockentity list is locked by the parent chunkmap's CS
+ for (cBlockEntityList::iterator itr = m_BlockEntities.begin(), itr2 = itr; itr != m_BlockEntities.end(); itr = itr2)
+ {
+ ++itr2;
+ if (((*itr)->GetPosX() != a_BlockX) || ((*itr)->GetPosY() != a_BlockY) || ((*itr)->GetPosZ() != a_BlockZ))
+ {
+ continue;
+ }
+ if ((*itr)->GetBlockType() != E_BLOCK_NOTE_BLOCK)
+ {
+ // There is a block entity here, but of different type. No other block entity can be here, so we can safely bail out
+ return false;
+ }
+
+ // The correct block entity is here,
+ if (a_Callback.Item((cNoteEntity *)*itr))
+ {
+ return false;
+ }
+ return true;
+ } // for itr - m_BlockEntitites[]
+
+ // Not found:
+ return false;
+}
+
+
+
+
+
bool cChunk::GetSignLines(int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4)
{
// The blockentity list is locked by the parent chunkmap's CS
@@ -2557,6 +2589,22 @@ void cChunk::BroadcastDestroyEntity(const cEntity & a_Entity, const cClientHandl
+void cChunk::BroadcastEntityEffect(const cEntity & a_Entity, int a_EffectID, int a_Amplifier, short a_Duration, const cClientHandle * a_Exclude)
+{
+ for (cClientHandleList::const_iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr )
+ {
+ if (*itr == a_Exclude)
+ {
+ continue;
+ }
+ (*itr)->SendEntityEffect(a_Entity, a_EffectID, a_Amplifier, a_Duration);
+ } // for itr - LoadedByClient[]
+}
+
+
+
+
+
void cChunk::BroadcastEntityEquipment(const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item, const cClientHandle * a_Exclude)
{
for (cClientHandleList::const_iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr )
@@ -2701,6 +2749,22 @@ void cChunk::BroadcastEntityAnimation(const cEntity & a_Entity, char a_Animation
+void cChunk::BroadcastRemoveEntityEffect(const cEntity & a_Entity, int a_EffectID, const cClientHandle * a_Exclude)
+{
+ for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr )
+ {
+ if (*itr == a_Exclude)
+ {
+ continue;
+ }
+ (*itr)->SendRemoveEntityEffect(a_Entity, a_EffectID);
+ } // for itr - LoadedByClient[]
+}
+
+
+
+
+
void cChunk::BroadcastSoundEffect(const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch, const cClientHandle * a_Exclude)
{
for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr )
diff --git a/src/Chunk.h b/src/Chunk.h
index 9e5d117c5..1d762c0ca 100644
--- a/src/Chunk.h
+++ b/src/Chunk.h
@@ -35,7 +35,6 @@ namespace Json
class cWorld;
-class cFurnaceEntity;
class cClientHandle;
class cServer;
class MTRand;
@@ -44,6 +43,7 @@ class cChunkMap;
class cChestEntity;
class cDispenserEntity;
class cFurnaceEntity;
+class cNoteEntity;
class cBlockArea;
class cPawn;
class cPickup;
@@ -58,6 +58,7 @@ typedef cItemCallback<cEntity> cEntityCallback;
typedef cItemCallback<cChestEntity> cChestCallback;
typedef cItemCallback<cDispenserEntity> cDispenserCallback;
typedef cItemCallback<cFurnaceEntity> cFurnaceCallback;
+typedef cItemCallback<cNoteEntity> cNoteBlockCallback;
@@ -246,6 +247,9 @@ public:
/// Calls the callback for the furnace at the specified coords; returns false if there's no furnace at those coords or callback returns true, returns true if found
bool DoWithFurnaceAt(int a_BlockX, int a_BlockY, int a_BlockZ, cFurnaceCallback & a_Callback); // Lua-accessible
+ /// Calls the callback for the noteblock at the specified coords; returns false if there's no noteblock at those coords or callback returns true, returns true if found
+ bool DoWithNoteBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cNoteBlockCallback & a_Callback);
+
/// Retrieves the test on the sign at the specified coords; returns false if there's no sign at those coords, true if found
bool GetSignLines (int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4); // Lua-accessible
@@ -263,6 +267,7 @@ public:
void BroadcastChunkData (cChunkDataSerializer & a_Serializer, const cClientHandle * a_Exclude = NULL);
void BroadcastCollectPickup (const cPickup & a_Pickup, const cPlayer & a_Player, const cClientHandle * a_Exclude = NULL);
void BroadcastDestroyEntity (const cEntity & a_Entity, const cClientHandle * a_Exclude = NULL);
+ void BroadcastEntityEffect (const cEntity & a_Entity, int a_EffectID, int a_Amplifier, short a_Duration, const cClientHandle * a_Exclude = NULL);
void BroadcastEntityEquipment (const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item, const cClientHandle * a_Exclude = NULL);
void BroadcastEntityHeadLook (const cEntity & a_Entity, const cClientHandle * a_Exclude = NULL);
void BroadcastEntityLook (const cEntity & a_Entity, const cClientHandle * a_Exclude = NULL);
@@ -272,6 +277,7 @@ public:
void BroadcastEntityStatus (const cEntity & a_Entity, char a_Status, const cClientHandle * a_Exclude = NULL);
void BroadcastEntityVelocity (const cEntity & a_Entity, const cClientHandle * a_Exclude = NULL);
void BroadcastEntityAnimation (const cEntity & a_Entity, char a_Animation, const cClientHandle * a_Exclude = NULL);
+ void BroadcastRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID, const cClientHandle * a_Exclude = NULL);
void BroadcastSoundEffect (const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch, const cClientHandle * a_Exclude = NULL); // a_Src coords are Block * 8
void BroadcastSoundParticleEffect(int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data, const cClientHandle * a_Exclude = NULL);
void BroadcastSpawnEntity (cEntity & a_Entity, const cClientHandle * a_Exclude = NULL);
diff --git a/src/ChunkMap.cpp b/src/ChunkMap.cpp
index cb722af3b..53b595545 100644
--- a/src/ChunkMap.cpp
+++ b/src/ChunkMap.cpp
@@ -445,6 +445,22 @@ void cChunkMap::BroadcastDestroyEntity(const cEntity & a_Entity, const cClientHa
+void cChunkMap::BroadcastEntityEffect(const cEntity & a_Entity, int a_EffectID, int a_Amplifier, short a_Duration, const cClientHandle * a_Exclude)
+{
+ cCSLock Lock(m_CSLayers);
+ cChunkPtr Chunk = GetChunkNoGen(a_Entity.GetChunkX(), ZERO_CHUNK_Y, a_Entity.GetChunkZ());
+ if (Chunk == NULL)
+ {
+ return;
+ }
+ // It's perfectly legal to broadcast packets even to invalid chunks!
+ Chunk->BroadcastEntityEffect(a_Entity, a_EffectID, a_Amplifier, a_Duration);
+}
+
+
+
+
+
void cChunkMap::BroadcastEntityEquipment(const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item, const cClientHandle * a_Exclude)
{
cCSLock Lock(m_CSLayers);
@@ -589,6 +605,23 @@ void cChunkMap::BroadcastEntityAnimation(const cEntity & a_Entity, char a_Animat
+void cChunkMap::BroadcastRemoveEntityEffect(const cEntity & a_Entity, int a_EffectID, const cClientHandle * a_Exclude)
+{
+ cCSLock Lock(m_CSLayers);
+
+ cChunkPtr Chunk = GetChunkNoGen(a_Entity.GetChunkX(), ZERO_CHUNK_Y, a_Entity.GetChunkZ());
+ if (Chunk == NULL)
+ {
+ return;
+ }
+ // It's perfectly legal to broadcast packets even to invalid chunks!
+ Chunk->BroadcastRemoveEntityEffect(a_Entity, a_EffectID, a_Exclude);
+}
+
+
+
+
+
void cChunkMap::BroadcastSoundEffect(const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch, const cClientHandle * a_Exclude)
{
cCSLock Lock(m_CSLayers);
@@ -1899,6 +1932,23 @@ bool cChunkMap::DoWithFurnaceAt(int a_BlockX, int a_BlockY, int a_BlockZ, cFurna
+bool cChunkMap::DoWithNoteBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cNoteBlockCallback & a_Callback)
+{
+ int ChunkX, ChunkZ;
+ int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ;
+ cChunkDef::AbsoluteToRelative(BlockX, BlockY, BlockZ, ChunkX, ChunkZ);
+ cCSLock Lock(m_CSLayers);
+ cChunkPtr Chunk = GetChunkNoGen(ChunkX, ZERO_CHUNK_Y, ChunkZ);
+ if ((Chunk == NULL) && !Chunk->IsValid())
+ {
+ return false;
+ }
+ return Chunk->DoWithNoteBlockAt(a_BlockX, a_BlockY, a_BlockZ, a_Callback);
+}
+
+
+
+
bool cChunkMap::GetSignLines(int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4)
{
diff --git a/src/ChunkMap.h b/src/ChunkMap.h
index ef070194b..dcc6abdc3 100644
--- a/src/ChunkMap.h
+++ b/src/ChunkMap.h
@@ -22,6 +22,7 @@ class cDispenserEntity;
class cDropperEntity;
class cDropSpenserEntity;
class cFurnaceEntity;
+class cNoteEntity;
class cPawn;
class cPickup;
class cChunkDataSerializer;
@@ -38,6 +39,7 @@ typedef cItemCallback<cDispenserEntity> cDispenserCallback;
typedef cItemCallback<cDropperEntity> cDropperCallback;
typedef cItemCallback<cDropSpenserEntity> cDropSpenserCallback;
typedef cItemCallback<cFurnaceEntity> cFurnaceCallback;
+typedef cItemCallback<cNoteEntity> cNoteBlockCallback;
typedef cItemCallback<cChunk> cChunkCallback;
@@ -62,6 +64,7 @@ public:
void BroadcastChunkData(int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer, const cClientHandle * a_Exclude = NULL);
void BroadcastCollectPickup(const cPickup & a_Pickup, const cPlayer & a_Player, const cClientHandle * a_Exclude = NULL);
void BroadcastDestroyEntity(const cEntity & a_Entity, const cClientHandle * a_Exclude = NULL);
+ void BroadcastEntityEffect(const cEntity & a_Entity, int a_EffectID, int a_Amplifier, short a_Duration, const cClientHandle * a_Exclude = NULL);
void BroadcastEntityEquipment(const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item, const cClientHandle * a_Exclude = NULL);
void BroadcastEntityHeadLook(const cEntity & a_Entity, const cClientHandle * a_Exclude = NULL);
void BroadcastEntityLook(const cEntity & a_Entity, const cClientHandle * a_Exclude = NULL);
@@ -71,6 +74,7 @@ public:
void BroadcastEntityStatus(const cEntity & a_Entity, char a_Status, const cClientHandle * a_Exclude = NULL);
void BroadcastEntityVelocity(const cEntity & a_Entity, const cClientHandle * a_Exclude = NULL);
void BroadcastEntityAnimation(const cEntity & a_Entity, char a_Animation, const cClientHandle * a_Exclude = NULL);
+ void BroadcastRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID, const cClientHandle * a_Exclude = NULL);
void BroadcastSoundEffect(const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch, const cClientHandle * a_Exclude = NULL); // a_Src coords are Block * 8
void BroadcastSoundParticleEffect(int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data, const cClientHandle * a_Exclude = NULL);
void BroadcastSpawnEntity(cEntity & a_Entity, const cClientHandle * a_Exclude = NULL);
@@ -228,6 +232,9 @@ public:
/// Calls the callback for the furnace at the specified coords; returns false if there's no furnace at those coords or callback returns true, returns true if found
bool DoWithFurnaceAt(int a_BlockX, int a_BlockY, int a_BlockZ, cFurnaceCallback & a_Callback); // Lua-accessible
+ /// Calls the callback for the noteblock at the specified coords; returns false if there's no noteblock at those coords or callback returns true, returns true if found
+ bool DoWithNoteBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cNoteBlockCallback & a_Callback); // Lua-accessible
+
/// Retrieves the test on the sign at the specified coords; returns false if there's no sign at those coords, true if found
bool GetSignLines (int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4); // Lua-accessible
diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp
index f7e18974f..9565fc41f 100644
--- a/src/ClientHandle.cpp
+++ b/src/ClientHandle.cpp
@@ -270,9 +270,6 @@ void cClientHandle::Authenticate(void)
m_Player->Initialize(World);
m_State = csAuthenticated;
- // Broadcast this player's spawning to all other players in the same chunk
- m_Player->GetWorld()->BroadcastSpawnEntity(*m_Player, this);
-
cRoot::Get()->GetPluginManager()->CallHookPlayerSpawned(*m_Player);
}
@@ -490,6 +487,16 @@ void cClientHandle::HandleCreativeInventory(short a_SlotNum, const cItem & a_Hel
+void cClientHandle::HandlePlayerAbilities(bool a_CanFly, bool a_IsFlying, float FlyingSpeed, float WalkingSpeed)
+{
+ m_Player->SetCanFly(a_CanFly);
+ m_Player->SetFlying(a_IsFlying);
+}
+
+
+
+
+
void cClientHandle::HandlePlayerPos(double a_PosX, double a_PosY, double a_PosZ, double a_Stance, bool a_IsOnGround)
{
if ((m_Player == NULL) || (m_State != csPlaying))
@@ -1053,7 +1060,7 @@ void cClientHandle::HandlePlayerMoveLook(double a_PosX, double a_PosY, double a_
void cClientHandle::HandleAnimation(char a_Animation)
{
- if (cPluginManager::Get()->CallHookEntityAnimation(*m_Player, a_Animation))
+ if (cPluginManager::Get()->CallHookPlayerAnimation(*m_Player, a_Animation))
{
// Plugin disagrees, bail out
return;
@@ -1469,12 +1476,6 @@ void cClientHandle::Tick(float a_Dt)
}
m_Protocol->DataReceived(IncomingData.data(), IncomingData.size());
- if (m_State == csAuthenticated)
- {
- StreamChunks();
- m_State = csDownloadingWorld;
- }
-
m_TimeSinceLastPacket += a_Dt;
if (m_TimeSinceLastPacket > 30000.f) // 30 seconds time-out
{
@@ -1488,13 +1489,8 @@ void cClientHandle::Tick(float a_Dt)
}
// If the chunk the player's in was just sent, spawn the player:
- if (m_HasSentPlayerChunk && (m_State != csPlaying) && !IsDestroying())
+ if (m_HasSentPlayerChunk && (m_State == csDownloadingWorld))
{
- if (!cRoot::Get()->GetPluginManager()->CallHookPlayerJoined(*m_Player))
- {
- // Broadcast that this player has joined the game! Yay~
- m_Player->GetWorld()->BroadcastChat(m_Username + " joined the game!", this);
- }
m_Protocol->SendPlayerMoveLook();
m_State = csPlaying;
}
@@ -1534,6 +1530,49 @@ void cClientHandle::Tick(float a_Dt)
+void cClientHandle::ServerTick(float a_Dt)
+{
+ // Handle clients that are waiting for final close while destroyed:
+ if (m_State == csDestroyedWaiting)
+ {
+ // Do not wait while the client is not in the world, simply cut them off.
+ m_State = csDestroyed;
+ return;
+ }
+
+ // Process received network data:
+ AString IncomingData;
+ {
+ cCSLock Lock(m_CSIncomingData);
+ std::swap(IncomingData, m_IncomingData);
+ }
+ m_Protocol->DataReceived(IncomingData.data(), IncomingData.size());
+
+ if (m_State == csAuthenticated)
+ {
+ StreamChunks();
+
+ // Remove the client handle from the server, it will be ticked from its cPlayer object from now on
+ cRoot::Get()->GetServer()->ClientMovedToWorld(this);
+
+ // Add the player to the world (start ticking from there):
+ m_State = csDownloadingWorld;
+ m_Player->GetWorld()->AddPlayer(m_Player);
+ return;
+ }
+
+ m_TimeSinceLastPacket += a_Dt;
+ if (m_TimeSinceLastPacket > 30000.f) // 30 seconds time-out
+ {
+ SendDisconnect("Nooooo!! You timed out! D: Come back!");
+ Destroy();
+ }
+}
+
+
+
+
+
void cClientHandle::SendAttachEntity(const cEntity & a_Entity, const cEntity * a_Vehicle)
{
m_Protocol->SendAttachEntity(a_Entity, a_Vehicle);
@@ -1673,6 +1712,15 @@ void cClientHandle::SendEditSign(int a_BlockX, int a_BlockY, int a_BlockZ)
+void cClientHandle::SendEntityEffect(const cEntity & a_Entity, int a_EffectID, int a_Amplifier, short a_Duration)
+{
+ m_Protocol->SendEntityEffect(a_Entity, a_EffectID, a_Amplifier, a_Duration);
+}
+
+
+
+
+
void cClientHandle::SendEntityEquipment(const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item)
{
m_Protocol->SendEntityEquipment(a_Entity, a_SlotNum, a_Item);
@@ -1746,8 +1794,6 @@ void cClientHandle::SendEntityStatus(const cEntity & a_Entity, char a_Status)
void cClientHandle::SendEntityVelocity(const cEntity & a_Entity)
{
- ASSERT(a_Entity.GetUniqueID() != m_Player->GetUniqueID()); // Must not send for self
-
m_Protocol->SendEntityVelocity(a_Entity);
}
@@ -1822,6 +1868,15 @@ void cClientHandle::SendEntityAnimation(const cEntity & a_Entity, char a_Animati
+void cClientHandle::SendPlayerAbilities()
+{
+ m_Protocol->SendPlayerAbilities();
+}
+
+
+
+
+
void cClientHandle::SendPlayerListItem(const cPlayer & a_Player, bool a_IsOnline)
{
m_Protocol->SendPlayerListItem(a_Player, a_IsOnline);
@@ -1882,6 +1937,15 @@ void cClientHandle::SendPlayerSpawn(const cPlayer & a_Player)
+void cClientHandle::SendRemoveEntityEffect(const cEntity & a_Entity, int a_EffectID)
+{
+ m_Protocol->SendRemoveEntityEffect(a_Entity, a_EffectID);
+}
+
+
+
+
+
void cClientHandle::SendRespawn(void)
{
m_Protocol->SendRespawn();
diff --git a/src/ClientHandle.h b/src/ClientHandle.h
index 2ff75b28a..b426153b9 100644
--- a/src/ClientHandle.h
+++ b/src/ClientHandle.h
@@ -29,7 +29,6 @@ class cExpOrb;
class cPickup;
class cPlayer;
class cProtocol;
-class cRedstone;
class cWindow;
class cFallingBlock;
class cItemHandler;
@@ -79,7 +78,11 @@ public:
inline bool IsLoggedIn(void) const { return (m_State >= csAuthenticating); }
+ /// Called while the client is being ticked from the world via its cPlayer object
void Tick(float a_Dt);
+
+ /// Called while the client is being ticked from the cServer object
+ void ServerTick(float a_Dt);
void Destroy(void);
@@ -100,6 +103,7 @@ public:
void SendDestroyEntity (const cEntity & a_Entity);
void SendDisconnect (const AString & a_Reason);
void SendEditSign (int a_BlockX, int a_BlockY, int a_BlockZ);
+ void SendEntityEffect (const cEntity & a_Entity, int a_EffectID, int a_Amplifier, short a_Duration);
void SendEntityEquipment (const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item);
void SendEntityHeadLook (const cEntity & a_Entity);
void SendEntityLook (const cEntity & a_Entity);
@@ -115,11 +119,13 @@ public:
void SendInventorySlot (char a_WindowID, short a_SlotNum, const cItem & a_Item);
void SendPickupSpawn (const cPickup & a_Pickup);
void SendEntityAnimation (const cEntity & a_Entity, char a_Animation);
+ void SendPlayerAbilities (void);
void SendPlayerListItem (const cPlayer & a_Player, bool a_IsOnline);
void SendPlayerMaxSpeed (void); ///< Informs the client of the maximum player speed (1.6.1+)
void SendPlayerMoveLook (void);
void SendPlayerPosition (void);
void SendPlayerSpawn (const cPlayer & a_Player);
+ void SendRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID);
void SendRespawn (void);
void SendExperience (void);
void SendExperienceOrb (const cExpOrb & a_ExpOrb);
@@ -173,6 +179,7 @@ public:
void HandleKeepAlive (int a_KeepAliveID);
void HandleLeftClick (int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, char a_Status);
void HandlePing (void);
+ void HandlePlayerAbilities (bool a_CanFly, bool a_IsFlying, float FlyingSpeed, float WalkingSpeed);
void HandlePlayerLook (float a_Rotation, float a_Pitch, bool a_IsOnGround);
void HandlePlayerMoveLook (double a_PosX, double a_PosY, double a_PosZ, double a_Stance, float a_Rotation, float a_Pitch, bool a_IsOnGround); // While m_bPositionConfirmed (normal gameplay)
void HandlePlayerPos (double a_PosX, double a_PosY, double a_PosZ, double a_Stance, bool a_IsOnGround);
diff --git a/src/Entities/Boat.cpp b/src/Entities/Boat.cpp
index 56e766dd4..184aeeeeb 100644
--- a/src/Entities/Boat.cpp
+++ b/src/Entities/Boat.cpp
@@ -39,6 +39,15 @@ void cBoat::DoTakeDamage(TakeDamageInfo & TDI)
if (GetHealth() == 0)
{
+ if (TDI.Attacker != NULL)
+ {
+ if (TDI.Attacker->IsPlayer())
+ {
+ cItems Pickups;
+ Pickups.Add(cItem(E_ITEM_BOAT));
+ m_World->SpawnItemPickups(Pickups, GetPosX(), GetPosY(), GetPosZ(), 0, 0, 0, true);
+ }
+ }
Destroy(true);
}
}
@@ -76,12 +85,32 @@ void cBoat::OnRightClicked(cPlayer & a_Player)
-void cBoat::HandlePhysics(float a_Dt, cChunk & a_Chunk)
+void cBoat::Tick(float a_Dt, cChunk & a_Chunk)
{
- super::HandlePhysics(a_Dt, a_Chunk);
+ super::Tick(a_Dt, a_Chunk);
BroadcastMovementUpdate();
+ SetSpeed(GetSpeed() * 0.97); // Slowly decrease the speed.
+ if (IsBlockWater(m_World->GetBlock((int) GetPosX(), (int) GetPosY(), (int) GetPosZ())))
+ {
+ SetSpeedY(1);
+ }
}
+
+void cBoat::HandleSpeedFromAttachee(float a_Forward, float a_Sideways)
+{
+ if (GetSpeed().Length() > 7)
+ {
+ return;
+ }
+
+ Vector3d ToAddSpeed(m_Attachee->GetLookVector() * (a_Sideways * 1.5));
+ ToAddSpeed.y = 0;
+
+ AddSpeed(ToAddSpeed);
+}
+
+ \ No newline at end of file
diff --git a/src/Entities/Boat.h b/src/Entities/Boat.h
index 8c51ab86c..c4c9afe7a 100644
--- a/src/Entities/Boat.h
+++ b/src/Entities/Boat.h
@@ -27,7 +27,8 @@ public:
virtual void SpawnOn(cClientHandle & a_ClientHandle) override;
virtual void OnRightClicked(cPlayer & a_Player) override;
virtual void DoTakeDamage(TakeDamageInfo & TDI) override;
- virtual void HandlePhysics(float a_Dt, cChunk & a_Chunk) override;
+ virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
+ virtual void HandleSpeedFromAttachee(float a_Forward, float a_Sideways) override;
cBoat(double a_X, double a_Y, double a_Z);
} ;
diff --git a/src/Entities/Effects.h b/src/Entities/Effects.h
new file mode 100644
index 000000000..e7611847d
--- /dev/null
+++ b/src/Entities/Effects.h
@@ -0,0 +1,30 @@
+#pragma once
+
+// tolua_begin
+enum ENUM_ENTITY_EFFECT
+{
+ E_EFFECT_SPEED = 1,
+ E_EFFECT_SLOWNESS = 2,
+ E_EFFECT_HASTE = 3,
+ E_EFFECT_MINING_FATIGUE = 4,
+ E_EFFECT_STENGTH = 5,
+ E_EFFECT_INSTANT_HEALTH = 6,
+ E_EFFECT_INSTANT_DAMAGE = 7,
+ E_EFFECT_JUMP_BOOST = 8,
+ E_EFFECT_NAUSEA = 9,
+ E_EFFECT_REGENERATION = 10,
+ E_EFFECT_RESISTANCE = 11,
+ E_EFFECT_FIRE_RESISTANCE = 12,
+ E_EFFECT_WATER_BREATHING = 13,
+ E_EFFECT_INVISIBILITY = 14,
+ E_EFFECT_BLINDNESS = 15,
+ E_EFFECT_NIGHT_VISION = 16,
+ E_EFFECT_HUNGER = 17,
+ E_EFFECT_WEAKNESS = 18,
+ E_EFFECT_POISON = 19,
+ E_EFFECT_WITHER = 20,
+ E_EFFECT_HEALTH_BOOST = 21,
+ E_EFFECT_ABSORPTION = 22,
+ E_EFFECT_SATURATION = 23,
+} ;
+// tolua_end \ No newline at end of file
diff --git a/src/Entities/Entity.cpp b/src/Entities/Entity.cpp
index 0a2145e81..7721d58b3 100644
--- a/src/Entities/Entity.cpp
+++ b/src/Entities/Entity.cpp
@@ -1341,6 +1341,19 @@ void cEntity::AddSpeedZ(double a_AddSpeedZ)
+void cEntity::HandleSpeedFromAttachee(float a_Forward, float a_Sideways)
+{
+ Vector3d LookVector = m_Attachee->GetLookVector();
+ double AddSpeedX = LookVector.x * a_Forward + LookVector.z * a_Sideways;
+ double AddSpeedZ = LookVector.z * a_Forward - LookVector.x * a_Sideways;
+ SetSpeed(AddSpeedX, 0, AddSpeedZ);
+ BroadcastMovementUpdate();
+}
+
+
+
+
+
void cEntity::SteerVehicle(float a_Forward, float a_Sideways)
{
if (m_AttachedTo == NULL)
@@ -1349,10 +1362,7 @@ void cEntity::SteerVehicle(float a_Forward, float a_Sideways)
}
if ((a_Forward != 0) || (a_Sideways != 0))
{
- Vector3d LookVector = GetLookVector();
- double AddSpeedX = LookVector.x * a_Forward + LookVector.z * a_Sideways;
- double AddSpeedZ = LookVector.z * a_Forward - LookVector.x * a_Sideways;
- m_AttachedTo->AddSpeed(AddSpeedX, 0, AddSpeedZ);
+ m_AttachedTo->HandleSpeedFromAttachee(a_Forward, a_Sideways);
}
}
diff --git a/src/Entities/Entity.h b/src/Entities/Entity.h
index de5f176ae..8d1692c98 100644
--- a/src/Entities/Entity.h
+++ b/src/Entities/Entity.h
@@ -197,6 +197,7 @@ public:
void AddSpeedY (double a_AddSpeedY);
void AddSpeedZ (double a_AddSpeedZ);
+ virtual void HandleSpeedFromAttachee(float a_Forward, float a_Sideways);
void SteerVehicle(float a_Forward, float a_Sideways);
inline int GetUniqueID(void) const { return m_UniqueID; }
diff --git a/src/Entities/ExpOrb.cpp b/src/Entities/ExpOrb.cpp
index 248fb7278..04ee85823 100644
--- a/src/Entities/ExpOrb.cpp
+++ b/src/Entities/ExpOrb.cpp
@@ -54,7 +54,7 @@ void cExpOrb::Tick(float a_Dt, cChunk & a_Chunk)
Destroy(true);
}
a_Distance.Normalize();
- a_Distance *= ((float) (5.5 - Distance));
+ a_Distance *= ((float) (5.5 - Distance));
SetSpeedX( a_Distance.x );
SetSpeedY( a_Distance.y );
SetSpeedZ( a_Distance.z );
diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp
index 85833f31d..7e7d77433 100644
--- a/src/Entities/Player.cpp
+++ b/src/Entities/Player.cpp
@@ -63,6 +63,8 @@ cPlayer::cPlayer(cClientHandle* a_Client, const AString & a_PlayerName)
, m_IsSprinting(false)
, m_IsSwimming(false)
, m_IsSubmerged(false)
+ , m_IsFlying(false)
+ , m_CanFly(false)
, m_EatingFinishTick(-1)
, m_IsChargingBow(false)
, m_BowCharge(0)
@@ -135,28 +137,6 @@ cPlayer::~cPlayer(void)
-bool cPlayer::Initialize(cWorld * a_World)
-{
- ASSERT(a_World != NULL);
-
- if (super::Initialize(a_World))
- {
- // Remove the client handle from the server, it will be ticked from this object from now on
- if (m_ClientHandle != NULL)
- {
- cRoot::Get()->GetServer()->ClientMovedToWorld(m_ClientHandle);
- }
-
- GetWorld()->AddPlayer(this);
- return true;
- }
- return false;
-}
-
-
-
-
-
void cPlayer::Destroyed()
{
CloseWindow(false);
@@ -557,9 +537,13 @@ void cPlayer::FoodPoison(int a_NumTicks)
m_FoodPoisonedTicksRemaining = std::max(m_FoodPoisonedTicksRemaining, a_NumTicks);
if (!HasBeenFoodPoisoned)
{
- // TODO: Send the poisoning indication to the client - how?
+ m_World->BroadcastRemoveEntityEffect(*this, E_EFFECT_HUNGER);
SendHealth();
}
+ else
+ {
+ m_World->BroadcastEntityEffect(*this, E_EFFECT_HUNGER, 0, 400); // Give the player the "Hunger" effect for 20 seconds.
+ }
}
@@ -747,6 +731,36 @@ void cPlayer::SetSprint(bool a_IsSprinting)
+void cPlayer::SetCanFly(bool a_CanFly)
+{
+ if (a_CanFly == m_CanFly)
+ {
+ return;
+ }
+
+ m_CanFly = a_CanFly;
+ m_ClientHandle->SendPlayerAbilities();
+}
+
+
+
+
+
+void cPlayer::SetFlying(bool a_IsFlying)
+{
+ if (a_IsFlying == m_IsFlying)
+ {
+ return;
+ }
+
+ m_IsFlying = a_IsFlying;
+ m_ClientHandle->SendPlayerAbilities();
+}
+
+
+
+
+
void cPlayer::DoTakeDamage(TakeDamageInfo & a_TDI)
{
if (a_TDI.DamageType != dtInVoid)
@@ -1033,6 +1047,16 @@ Vector3d cPlayer::GetThrowSpeed(double a_SpeedCoeff) const
+void cPlayer::ForceSetSpeed(Vector3d a_Direction)
+{
+ SetSpeed(a_Direction);
+ m_ClientHandle->SendEntityVelocity(*this);
+}
+
+
+
+
+
void cPlayer::MoveTo( const Vector3d & a_NewPos )
{
if ((a_NewPos.y < -990) && (GetPosY() > -100))
@@ -1471,6 +1495,7 @@ bool cPlayer::LoadFromDisk()
m_FoodExhaustionLevel = root.get("foodExhaustion", 0).asDouble();
m_LifetimeTotalXp = (short) root.get("xpTotal", 0).asInt();
m_CurrentXp = (short) root.get("xpCurrent", 0).asInt();
+ m_IsFlying = root.get("isflying", 0).asBool();
//SetExperience(root.get("experience", 0).asInt());
@@ -1521,7 +1546,8 @@ bool cPlayer::SaveToDisk()
root["foodSaturation"] = m_FoodSaturationLevel;
root["foodTickTimer"] = m_FoodTickTimer;
root["foodExhaustion"] = m_FoodExhaustionLevel;
- root["world"] = GetWorld()->GetName();
+ root["world"] = GetWorld()->GetName();
+ root["isflying"] = IsFlying();
if (m_GameMode == GetWorld()->GetGameMode())
{
@@ -1704,6 +1730,10 @@ void cPlayer::HandleFood(void)
m_FoodPoisonedTicksRemaining--;
m_FoodExhaustionLevel += 0.025; // 0.5 per second = 0.025 per tick
}
+ else
+ {
+ m_World->BroadcastRemoveEntityEffect(*this, E_EFFECT_HUNGER); // Remove the "Hunger" effect.
+ }
// Apply food exhaustion that has accumulated:
if (m_FoodExhaustionLevel >= 4)
diff --git a/src/Entities/Player.h b/src/Entities/Player.h
index 44cab7d74..59e941040 100644
--- a/src/Entities/Player.h
+++ b/src/Entities/Player.h
@@ -41,8 +41,6 @@ public:
cPlayer(cClientHandle * a_Client, const AString & a_PlayerName);
virtual ~cPlayer();
- virtual bool Initialize(cWorld * a_World) override;
-
virtual void SpawnOn(cClientHandle & a_Client) override;
virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
@@ -167,6 +165,9 @@ public:
// Sets the current gamemode, doesn't check validity, doesn't send update packets to client
void LoginSetGameMode(eGameMode a_GameMode);
+ /// Forces the player to move in the given direction.
+ void ForceSetSpeed(Vector3d a_Direction); // tolua_export
+
/// Tries to move to a new position, with attachment-related checks (y == -999)
void MoveTo(const Vector3d & a_NewPos); // tolua_export
@@ -250,6 +251,8 @@ public:
/// Returns true if the player is currently in the process of eating the currently equipped item
bool IsEating(void) const { return (m_EatingFinishTick >= 0); }
+ /// Returns true if the player is currently flying.
+ bool IsFlying(void) const { return m_IsFlying; }
// tolua_end
/// Starts eating the currently equipped item. Resets the eating timer and sends the proper animation packet
@@ -319,12 +322,20 @@ public:
/// Starts or stops sprinting, sends the max speed update to the client, if needed
void SetSprint(bool a_IsSprinting);
+ /// Flags the player as flying
+ void SetFlying(bool a_IsFlying);
+
+ /// If true the player can fly even when he's not in creative.
+ void SetCanFly(bool a_CanFly);
+
/// Returns whether the player is swimming or not
virtual bool IsSwimming(void) const{ return m_IsSwimming; }
/// Return whether the player is under water or not
virtual bool IsSubmerged(void) const{ return m_IsSubmerged; }
+ /// Returns wheter the player can fly or not.
+ virtual bool CanFly(void) const { return m_CanFly; }
// tolua_end
// cEntity overrides:
@@ -415,10 +426,12 @@ protected:
bool m_IsCrouched;
bool m_IsSprinting;
-
+ bool m_IsFlying;
bool m_IsSwimming;
bool m_IsSubmerged;
+ bool m_CanFly; // If this is true the player can fly. Even if he is not in creative.
+
/// The world tick in which eating will be finished. -1 if not eating
Int64 m_EatingFinishTick;
diff --git a/src/Globals.h b/src/Globals.h
index cb67d9fda..58badf4dd 100644
--- a/src/Globals.h
+++ b/src/Globals.h
@@ -124,9 +124,6 @@ typedef unsigned short UInt16;
#include <semaphore.h>
#include <errno.h>
#include <fcntl.h>
-#if !defined(ANDROID_NDK)
- #include <tr1/memory>
-#endif
#endif
#if defined(ANDROID_NDK)
@@ -220,6 +217,7 @@ public:
// Common headers (part 2, with macros):
#include "ChunkDef.h"
#include "BlockID.h"
+#include "Entities/Effects.h"
diff --git a/src/Items/ItemBoat.h b/src/Items/ItemBoat.h
index 6e3395f1d..79c8e9589 100644
--- a/src/Items/ItemBoat.h
+++ b/src/Items/ItemBoat.h
@@ -10,6 +10,7 @@
#pragma once
#include "../Entities/Boat.h"
+#include "../LineBlockTracer.h"
@@ -30,23 +31,47 @@ public:
virtual bool OnItemUse(cWorld * a_World, cPlayer * a_Player, const cItem & a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Dir) override
{
- if (a_Dir < 0)
+ if (a_Dir > 0)
{
return false;
}
+
+ class cCallbacks :
+ public cBlockTracer::cCallbacks
+ {
+ public:
+ Vector3d Pos;
+ virtual bool OnNextBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, char a_EntryFace) override
+ {
+ if (a_BlockType != E_BLOCK_AIR)
+ {
+ Pos = Vector3d(a_BlockX, a_BlockY, a_BlockZ);
+ return true;
+ }
+ return false;
+ }
+ } Callbacks;
- double x = (double)a_BlockX + 0.5;
- double y = (double)a_BlockY + 0.5;
- double z = (double)a_BlockZ + 0.5;
+ cLineBlockTracer Tracer(*a_World, Callbacks);
+ Vector3d Start(a_Player->GetEyePosition() + a_Player->GetLookVector());
+ Vector3d End(a_Player->GetEyePosition() + a_Player->GetLookVector() * 5);
- cBoat * Boat = NULL;
+ Tracer.Trace(Start.x, Start.y, Start.z, End.x, End.y, End.z);
+
+ double x = Callbacks.Pos.x;
+ double y = Callbacks.Pos.y;
+ double z = Callbacks.Pos.z;
+
+ if ((x == 0) && (y == 0) && (z == 0))
+ {
+ return false;
+ }
- Boat = new cBoat (x, y, z);
+ cBoat * Boat = new cBoat(x + 0.5, y + 1, z + 0.5);
Boat->Initialize(a_World);
return true;
}
-
} ;
diff --git a/src/Items/ItemBucket.h b/src/Items/ItemBucket.h
index fa3d48da1..c9a632580 100644
--- a/src/Items/ItemBucket.h
+++ b/src/Items/ItemBucket.h
@@ -5,6 +5,7 @@
#include "../World.h"
#include "../Simulator/FluidSimulator.h"
#include "../Blocks/BlockHandler.h"
+#include "../LineBlockTracer.h"
@@ -39,61 +40,54 @@ public:
bool ScoopUpFluid(cWorld * a_World, cPlayer * a_Player, const cItem & a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace)
{
- if (a_BlockFace < 0)
+ if (a_BlockFace > 0)
{
return false;
}
- AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace);
- BLOCKTYPE ClickedBlock;
- NIBBLETYPE ClickedMeta;
- a_World->GetBlockTypeMeta(a_BlockX, a_BlockY, a_BlockZ, ClickedBlock, ClickedMeta);
- LOGD("Bucket Clicked BlockType %d, meta %d", ClickedBlock, ClickedMeta);
- if (ClickedMeta != 0)
+
+ Vector3i BlockPos;
+ if (!GetBlockFromTrace(a_World, a_Player, BlockPos))
+ {
+ return false; // Nothing in range.
+ }
+
+ if (a_World->GetBlockMeta(BlockPos.x, BlockPos.y, BlockPos.z) != 0)
{
// Not a source block
return false;
}
-
- if (a_Player->GetGameMode() == gmCreative)
+
+ BLOCKTYPE Block = a_World->GetBlock(BlockPos.x, BlockPos.y, BlockPos.z);
+ ENUM_ITEM_ID NewItem;
+
+ if (IsBlockWater(Block))
{
- // In creative mode don't modify the inventory, just remove the fluid:
- a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_AIR, 0);
- return true;
+ NewItem = E_ITEM_WATER_BUCKET;
}
-
- ENUM_ITEM_ID NewItem = E_ITEM_EMPTY;
- switch (ClickedBlock)
+ else if (IsBlockLava(Block))
{
- case E_BLOCK_WATER:
- case E_BLOCK_STATIONARY_WATER:
- {
- NewItem = E_ITEM_WATER_BUCKET;
- break;
- }
- case E_BLOCK_LAVA:
- case E_BLOCK_STATIONARY_LAVA:
- {
- NewItem = E_ITEM_LAVA_BUCKET;
- break;
- }
-
- default: return false;
+ NewItem = E_ITEM_LAVA_BUCKET;
}
-
- // Remove the bucket from the inventory
- if (!a_Player->GetInventory().RemoveOneEquippedItem())
+ else
{
- LOG("Clicked with an empty bucket, but cannot remove one from the inventory? WTF?");
- ASSERT(!"Inventory bucket mismatch");
- return true;
+ return false;
}
- // Give new bucket, filled with fluid:
- cItem Item(NewItem, 1);
- a_Player->GetInventory().AddItem(Item, true, true);
+ // Give new bucket, filled with fluid when the gamemode is not creative:
+ if (!a_Player->IsGameModeCreative())
+ {
+ // Remove the bucket from the inventory
+ if (!a_Player->GetInventory().RemoveOneEquippedItem())
+ {
+ LOG("Clicked with an empty bucket, but cannot remove one from the inventory? WTF?");
+ ASSERT(!"Inventory bucket mismatch");
+ return true;
+ }
+ a_Player->GetInventory().AddItem(cItem(NewItem), true, true);
+ }
// Remove water / lava block
- a_Player->GetWorld()->SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_AIR, 0);
+ a_Player->GetWorld()->SetBlock(BlockPos.x, BlockPos.y, BlockPos.z, E_BLOCK_AIR, 0);
return true;
}
@@ -157,4 +151,52 @@ public:
return true;
}
+
+ bool GetBlockFromTrace(cWorld * a_World, cPlayer * a_Player, Vector3i & BlockPos)
+ {
+ class cCallbacks :
+ public cBlockTracer::cCallbacks
+ {
+ public:
+ Vector3i m_Pos;
+ bool m_HasHitFluid;
+
+
+ cCallbacks(void) :
+ m_HasHitFluid(false)
+ {
+ }
+
+ virtual bool OnNextBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, char a_EntryFace) override
+ {
+ if (a_BlockMeta != 0) // Even if it was a water block it would not be a source.
+ {
+ return false;
+ }
+ if (IsBlockWater(a_BlockType) || IsBlockLava(a_BlockType))
+ {
+ m_HasHitFluid = true;
+ m_Pos.Set(a_BlockX, a_BlockY, a_BlockZ);
+ return true;
+ }
+ return false;
+ }
+ } Callbacks;
+
+ cLineBlockTracer Tracer(*a_World, Callbacks);
+ Vector3d Start(a_Player->GetEyePosition() + a_Player->GetLookVector());
+ Vector3d End(a_Player->GetEyePosition() + a_Player->GetLookVector() * 5);
+
+ Tracer.Trace(Start.x, Start.y, Start.z, End.x, End.y, End.z);
+
+ if (!Callbacks.m_HasHitFluid)
+ {
+ return false;
+ }
+
+
+ BlockPos.Set(Callbacks.m_Pos.x, Callbacks.m_Pos.y, Callbacks.m_Pos.z);
+ return true;
+ }
+
};
diff --git a/src/Items/ItemHandler.cpp b/src/Items/ItemHandler.cpp
index 92ba94999..23b9a86d4 100644
--- a/src/Items/ItemHandler.cpp
+++ b/src/Items/ItemHandler.cpp
@@ -23,6 +23,7 @@
#include "ItemLeaves.h"
#include "ItemLighter.h"
#include "ItemMinecart.h"
+#include "ItemNetherWart.h"
#include "ItemPickaxe.h"
#include "ItemThrowable.h"
#include "ItemRedstoneDust.h"
@@ -101,6 +102,7 @@ cItemHandler *cItemHandler::CreateItemHandler(int a_ItemType)
case E_ITEM_FIREWORK_ROCKET: return new cItemFireworkHandler();
case E_ITEM_FLINT_AND_STEEL: return new cItemLighterHandler(a_ItemType);
case E_ITEM_FLOWER_POT: return new cItemFlowerPotHandler(a_ItemType);
+ case E_ITEM_NETHER_WART: return new cItemNetherWartHandler(a_ItemType);
case E_ITEM_REDSTONE_DUST: return new cItemRedstoneDustHandler(a_ItemType);
case E_ITEM_REDSTONE_REPEATER: return new cItemRedstoneRepeaterHandler(a_ItemType);
case E_ITEM_SHEARS: return new cItemShearsHandler(a_ItemType);
diff --git a/src/Items/ItemNetherWart.h b/src/Items/ItemNetherWart.h
new file mode 100644
index 000000000..aa4a44340
--- /dev/null
+++ b/src/Items/ItemNetherWart.h
@@ -0,0 +1,54 @@
+
+#pragma once
+
+#include "ItemHandler.h"
+#include "../World.h"
+
+
+
+
+
+class cItemNetherWartHandler :
+ public cItemHandler
+{
+public:
+ cItemNetherWartHandler(int a_ItemType) :
+ cItemHandler(a_ItemType)
+ {
+
+ }
+
+ virtual bool IsPlaceable(void) override
+ {
+ return true;
+ }
+
+ 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
+ {
+ if (a_BlockFace != BLOCK_FACE_TOP)
+ {
+ // Only allow planting nether wart from the top side of the block
+ return false;
+ }
+
+ // Only allow placement on farmland
+ int X = a_BlockX;
+ int Y = a_BlockY;
+ int Z = a_BlockZ;
+ AddFaceDirection(X, Y, Z, a_BlockFace, true);
+ if (a_World->GetBlock(X, Y, Z) != E_BLOCK_SOULSAND)
+ {
+ return false;
+ }
+
+ a_BlockMeta = 0;
+ a_BlockType = E_BLOCK_NETHER_WART;
+
+ return true;
+ }
+} ; \ No newline at end of file
diff --git a/src/Protocol/Protocol.h b/src/Protocol/Protocol.h
index ff6541aeb..d90ece2b0 100644
--- a/src/Protocol/Protocol.h
+++ b/src/Protocol/Protocol.h
@@ -62,6 +62,7 @@ public:
virtual void SendDestroyEntity (const cEntity & a_Entity) = 0;
virtual void SendDisconnect (const AString & a_Reason) = 0;
virtual void SendEditSign (int a_BlockX, int a_BlockY, int a_BlockZ) = 0; ///< Request the client to open up the sign editor for the sign (1.6+)
+ virtual void SendEntityEffect (const cEntity & a_Entity, int a_EffectID, int a_Amplifier, short a_Duration) = 0;
virtual void SendEntityEquipment (const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item) = 0;
virtual void SendEntityHeadLook (const cEntity & a_Entity) = 0;
virtual void SendEntityLook (const cEntity & a_Entity) = 0;
@@ -85,6 +86,7 @@ public:
virtual void SendPlayerMoveLook (void) = 0;
virtual void SendPlayerPosition (void) = 0;
virtual void SendPlayerSpawn (const cPlayer & a_Player) = 0;
+ virtual void SendRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID) = 0;
virtual void SendRespawn (void) = 0;
virtual void SendExperience (void) = 0;
virtual void SendExperienceOrb (const cExpOrb & a_ExpOrb) = 0;
diff --git a/src/Protocol/Protocol125.cpp b/src/Protocol/Protocol125.cpp
index 9334e6f2d..48f23801c 100644
--- a/src/Protocol/Protocol125.cpp
+++ b/src/Protocol/Protocol125.cpp
@@ -73,7 +73,9 @@ enum
PACKET_ENT_STATUS = 0x26,
PACKET_ATTACH_ENTITY = 0x27,
PACKET_METADATA = 0x28,
+ PACKET_ENTITY_EFFECT = 0x29,
PACKET_SPAWN_EXPERIENCE_ORB = 0x1A,
+ PACKET_REMOVE_ENTITY_EFFECT = 0x2a,
PACKET_EXPERIENCE = 0x2b,
PACKET_PRE_CHUNK = 0x32,
PACKET_MAP_CHUNK = 0x33,
@@ -300,6 +302,21 @@ void cProtocol125::SendEditSign(int a_BlockX, int a_BlockY, int a_BlockZ)
+void cProtocol125::SendEntityEffect(const cEntity & a_Entity, int a_EffectID, int a_Amplifier, short a_Duration)
+{
+ cCSLock Lock(m_CSPacket);
+ WriteByte (PACKET_ENTITY_EFFECT);
+ WriteInt (a_Entity.GetUniqueID());
+ WriteByte (a_EffectID);
+ WriteByte (a_Amplifier);
+ WriteShort(a_Duration);
+ Flush();
+}
+
+
+
+
+
void cProtocol125::SendEntityEquipment(const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item)
{
cCSLock Lock(m_CSPacket);
@@ -678,6 +695,19 @@ void cProtocol125::SendPlayerSpawn(const cPlayer & a_Player)
+void cProtocol125::SendRemoveEntityEffect(const cEntity & a_Entity, int a_EffectID)
+{
+ cCSLock Lock(m_CSPacket);
+ WriteByte (PACKET_REMOVE_ENTITY_EFFECT);
+ WriteInt (a_Entity.GetUniqueID());
+ WriteByte (a_EffectID);
+ Flush();
+}
+
+
+
+
+
void cProtocol125::SendRespawn(void)
{
cCSLock Lock(m_CSPacket);
diff --git a/src/Protocol/Protocol125.h b/src/Protocol/Protocol125.h
index 32efef4e8..ebbcd762a 100644
--- a/src/Protocol/Protocol125.h
+++ b/src/Protocol/Protocol125.h
@@ -38,6 +38,7 @@ public:
virtual void SendDestroyEntity (const cEntity & a_Entity) override;
virtual void SendDisconnect (const AString & a_Reason) override;
virtual void SendEditSign (int a_BlockX, int a_BlockY, int a_BlockZ) override; ///< Request the client to open up the sign editor for the sign (1.6+)
+ virtual void SendEntityEffect (const cEntity & a_Entity, int a_EffectID, int a_Amplifier, short a_Duration) override;
virtual void SendEntityEquipment (const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item) override;
virtual void SendEntityHeadLook (const cEntity & a_Entity) override;
virtual void SendEntityLook (const cEntity & a_Entity) override;
@@ -61,6 +62,7 @@ public:
virtual void SendPlayerMoveLook (void) override;
virtual void SendPlayerPosition (void) override;
virtual void SendPlayerSpawn (const cPlayer & a_Player) override;
+ virtual void SendRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID) override;
virtual void SendRespawn (void) override;
virtual void SendExperience (void) override;
virtual void SendExperienceOrb (const cExpOrb & a_ExpOrb) override;
diff --git a/src/Protocol/Protocol17x.cpp b/src/Protocol/Protocol17x.cpp
index bfb38904c..fff5311f6 100644
--- a/src/Protocol/Protocol17x.cpp
+++ b/src/Protocol/Protocol17x.cpp
@@ -236,6 +236,19 @@ void cProtocol172::SendEditSign(int a_BlockX, int a_BlockY, int a_BlockZ)
+void cProtocol172::SendEntityEffect(const cEntity & a_Entity, int a_EffectID, int a_Amplifier, short a_Duration)
+{
+ cPacketizer Pkt(*this, 0x1D); // Entity Effect packet
+ Pkt.WriteInt(a_Entity.GetUniqueID());
+ Pkt.WriteByte(a_EffectID);
+ Pkt.WriteByte(a_Amplifier);
+ Pkt.WriteShort(a_Duration);
+}
+
+
+
+
+
void cProtocol172::SendEntityEquipment(const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item)
{
cPacketizer Pkt(*this, 0x04); // Entity Equipment packet
@@ -478,7 +491,15 @@ void cProtocol172::SendPlayerAbilities(void)
{
Flags |= 0x01;
}
- // TODO: Other flags (god mode, flying, can fly
+ if (m_Client->GetPlayer()->IsFlying())
+ {
+ Flags |= 0x02;
+ }
+ if (m_Client->GetPlayer()->CanFly())
+ {
+ Flags |= 0x04;
+ }
+ // TODO: Other flags (god mode)
Pkt.WriteByte(Flags);
// TODO: Pkt.WriteFloat(m_Client->GetPlayer()->GetMaxFlyingSpeed());
Pkt.WriteFloat(0.05f);
@@ -541,7 +562,11 @@ void cProtocol172::SendPlayerMoveLook(void)
{
cPacketizer Pkt(*this, 0x08); // Player Position And Look packet
Pkt.WriteDouble(m_Client->GetPlayer()->GetPosX());
- Pkt.WriteDouble(m_Client->GetPlayer()->GetPosY());
+
+ // Protocol docs say this is PosY, but #323 says this is eye-pos
+ // Moreover, the "+ 0.001" is there because otherwise the player falls through the block they were standing on.
+ Pkt.WriteDouble(m_Client->GetPlayer()->GetStance() + 0.001);
+
Pkt.WriteDouble(m_Client->GetPlayer()->GetPosZ());
Pkt.WriteFloat((float)m_Client->GetPlayer()->GetYaw());
Pkt.WriteFloat((float)m_Client->GetPlayer()->GetPitch());
@@ -585,6 +610,17 @@ void cProtocol172::SendPlayerSpawn(const cPlayer & a_Player)
+void cProtocol172::SendRemoveEntityEffect(const cEntity & a_Entity, int a_EffectID)
+{
+ cPacketizer Pkt(*this, 0x1E);
+ Pkt.WriteInt(a_Entity.GetUniqueID());
+ Pkt.WriteByte(a_EffectID);
+}
+
+
+
+
+
void cProtocol172::SendRespawn(void)
{
cPacketizer Pkt(*this, 0x07); // Respawn packet
@@ -921,7 +957,6 @@ void cProtocol172::SendWindowProperty(const cWindow & a_Window, short a_Property
void cProtocol172::AddReceivedData(const char * a_Data, int a_Size)
{
- LOGD("Received %d bytes of data", a_Size);
if (!m_ReceivedData.Write(a_Data, a_Size))
{
// Too much data in the incoming queue, report to caller:
@@ -958,9 +993,6 @@ void cProtocol172::AddReceivedData(const char * a_Data, int a_Size)
return;
}
- // DEBUG:
- LOGD("Packet 0x%x, len %d (0x%x), start at %d", PacketType, PacketLen, PacketLen, PacketStart);
-
HandlePacket(bb, PacketType);
if (bb.GetReadableSpace() != 1)
@@ -1258,7 +1290,25 @@ void cProtocol172::HandlePacketPlayerAbilities(cByteBuffer & a_ByteBuffer)
HANDLE_READ(a_ByteBuffer, ReadByte, Byte, Flags);
HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, FlyingSpeed);
HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, WalkingSpeed);
- // TODO: m_Client->HandlePlayerAbilities();
+
+ bool IsFlying, CanFly;
+ if ((Flags & 2) != 0)
+ {
+ IsFlying = true;
+ }
+ else
+ {
+ IsFlying = false;
+ }
+ if ((Flags & 4) != 0)
+ {
+ CanFly = true;
+ }
+ else
+ {
+ CanFly = false;
+ }
+ m_Client->HandlePlayerAbilities(CanFly, IsFlying, FlyingSpeed, WalkingSpeed);
}
diff --git a/src/Protocol/Protocol17x.h b/src/Protocol/Protocol17x.h
index b8c91fbeb..4a91f0e56 100644
--- a/src/Protocol/Protocol17x.h
+++ b/src/Protocol/Protocol17x.h
@@ -47,6 +47,7 @@ public:
virtual void SendDestroyEntity (const cEntity & a_Entity) override;
virtual void SendDisconnect (const AString & a_Reason) override;
virtual void SendEditSign (int a_BlockX, int a_BlockY, int a_BlockZ) override; ///< Request the client to open up the sign editor for the sign (1.6+)
+ virtual void SendEntityEffect (const cEntity & a_Entity, int a_EffectID, int a_Amplifier, short a_Duration) override;
virtual void SendEntityEquipment (const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item) override;
virtual void SendEntityHeadLook (const cEntity & a_Entity) override;
virtual void SendEntityLook (const cEntity & a_Entity) override;
@@ -70,6 +71,7 @@ public:
virtual void SendPlayerMoveLook (void) override;
virtual void SendPlayerPosition (void) override;
virtual void SendPlayerSpawn (const cPlayer & a_Player) override;
+ virtual void SendRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID) override;
virtual void SendRespawn (void) override;
virtual void SendSoundEffect (const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch) override; // a_Src coords are Block * 8
virtual void SendExperience (void) override;
diff --git a/src/Protocol/ProtocolRecognizer.cpp b/src/Protocol/ProtocolRecognizer.cpp
index 683700d37..30b48a92f 100644
--- a/src/Protocol/ProtocolRecognizer.cpp
+++ b/src/Protocol/ProtocolRecognizer.cpp
@@ -216,6 +216,16 @@ void cProtocolRecognizer::SendEditSign(int a_BlockX, int a_BlockY, int a_BlockZ)
+void cProtocolRecognizer::SendEntityEffect(const cEntity & a_Entity, int a_EffectID, int a_Amplifier, short a_Duration)
+{
+ ASSERT(m_Protocol != NULL);
+ m_Protocol->SendEntityEffect(a_Entity, a_EffectID, a_Amplifier, a_Duration);
+}
+
+
+
+
+
void cProtocolRecognizer::SendEntityEquipment(const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item)
{
ASSERT(m_Protocol != NULL);
@@ -456,6 +466,16 @@ void cProtocolRecognizer::SendPlayerSpawn(const cPlayer & a_Player)
+void cProtocolRecognizer::SendRemoveEntityEffect(const cEntity & a_Entity, int a_EffectID)
+{
+ ASSERT(m_Protocol != NULL);
+ m_Protocol->SendRemoveEntityEffect(a_Entity, a_EffectID);
+}
+
+
+
+
+
void cProtocolRecognizer::SendRespawn(void)
{
ASSERT(m_Protocol != NULL);
diff --git a/src/Protocol/ProtocolRecognizer.h b/src/Protocol/ProtocolRecognizer.h
index 83fc23c22..0d69e9406 100644
--- a/src/Protocol/ProtocolRecognizer.h
+++ b/src/Protocol/ProtocolRecognizer.h
@@ -73,6 +73,7 @@ public:
virtual void SendDestroyEntity (const cEntity & a_Entity) override;
virtual void SendDisconnect (const AString & a_Reason) override;
virtual void SendEditSign (int a_BlockX, int a_BlockY, int a_BlockZ) override; ///< Request the client to open up the sign editor for the sign (1.6+)
+ virtual void SendEntityEffect (const cEntity & a_Entity, int a_EffectID, int a_Amplifier, short a_Duration) override;
virtual void SendEntityEquipment (const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item) override;
virtual void SendEntityHeadLook (const cEntity & a_Entity) override;
virtual void SendEntityLook (const cEntity & a_Entity) override;
@@ -96,6 +97,7 @@ public:
virtual void SendPlayerMoveLook (void) override;
virtual void SendPlayerPosition (void) override;
virtual void SendPlayerSpawn (const cPlayer & a_Player) override;
+ virtual void SendRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID) override;
virtual void SendRespawn (void) override;
virtual void SendExperience (void) override;
virtual void SendExperienceOrb (const cExpOrb & a_ExpOrb) override;
diff --git a/src/Server.cpp b/src/Server.cpp
index f90f7a474..a93be9a5b 100644
--- a/src/Server.cpp
+++ b/src/Server.cpp
@@ -402,7 +402,7 @@ void cServer::TickClients(float a_Dt)
itr = m_Clients.erase(itr);
continue;
}
- (*itr)->Tick(a_Dt);
+ (*itr)->ServerTick(a_Dt);
++itr;
} // for itr - m_Clients[]
}
diff --git a/src/Simulator/RedstoneSimulator.cpp b/src/Simulator/RedstoneSimulator.cpp
index f61e1c63b..eb26d0ca3 100644
--- a/src/Simulator/RedstoneSimulator.cpp
+++ b/src/Simulator/RedstoneSimulator.cpp
@@ -3,6 +3,7 @@
#include "RedstoneSimulator.h"
#include "../BlockEntities/DropSpenserEntity.h"
+#include "../BlockEntities/NoteEntity.h"
#include "../Entities/TNTEntity.h"
#include "../Blocks/BlockTorch.h"
#include "../Blocks/BlockDoor.h"
@@ -81,18 +82,24 @@ void cRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, c
{
int RelX = itr->a_SourcePos.x - a_ChunkX * cChunkDef::Width;
int RelZ = itr->a_SourcePos.z - a_ChunkZ * cChunkDef::Width;
+ int DestRelX = itr->a_BlockPos.x - a_ChunkX * cChunkDef::Width;
+ int DestRelZ = itr->a_BlockPos.z - a_ChunkZ * cChunkDef::Width;
BLOCKTYPE SourceBlockType;
NIBBLETYPE SourceBlockMeta;
- if (!a_Chunk->UnboundedRelGetBlock(RelX, itr->a_SourcePos.y, RelZ, SourceBlockType, SourceBlockMeta))
+ BLOCKTYPE DestBlockType;
+ if (
+ !a_Chunk->UnboundedRelGetBlock(RelX, itr->a_SourcePos.y, RelZ, SourceBlockType, SourceBlockMeta) ||
+ !a_Chunk->UnboundedRelGetBlockType(DestRelX, itr->a_BlockPos.y, DestRelZ, DestBlockType)
+ )
{
continue;
}
if (SourceBlockType != itr->a_SourceBlock)
{
- itr = m_PoweredBlocks.erase(itr);
LOGD("cRedstoneSimulator: Erased block %s from powered blocks list due to present/past block type mismatch", ItemToFullString(itr->a_SourceBlock).c_str());
+ itr = m_PoweredBlocks.erase(itr);
}
else if (
// Changeable sources
@@ -102,8 +109,14 @@ void cRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, c
(((SourceBlockType == E_BLOCK_STONE_BUTTON) || (SourceBlockType == E_BLOCK_WOODEN_BUTTON)) && (!IsButtonOn(SourceBlockMeta)))
)
{
- itr = m_PoweredBlocks.erase(itr);
LOGD("cRedstoneSimulator: Erased block %s from powered blocks list due to present/past metadata mismatch", ItemToFullString(itr->a_SourceBlock).c_str());
+ itr = m_PoweredBlocks.erase(itr);
+ }
+ else if ((SourceBlockType == E_BLOCK_REDSTONE_WIRE) && (DestBlockType == E_BLOCK_REDSTONE_WIRE))
+ {
+ // It is simply not allowed that a wire powers another wire, presuming that data here is sane and a dest and source are beside each other
+ LOGD("cRedstoneSimulator: Erased redstone wire from powered blocks list because it's source was also wire");
+ itr = m_PoweredBlocks.erase(itr);
}
else
{
@@ -132,13 +145,13 @@ void cRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, c
if (SourceBlockType != itr->a_SourceBlock)
{
- itr = m_LinkedPoweredBlocks.erase(itr);
LOGD("cRedstoneSimulator: Erased block %s from linked powered blocks list due to present/past block type mismatch", ItemToFullString(itr->a_SourceBlock).c_str());
+ itr = m_LinkedPoweredBlocks.erase(itr);
}
else if (MiddleBlockType != itr->a_MiddleBlock)
{
- itr = m_LinkedPoweredBlocks.erase(itr);
LOGD("cRedstoneSimulator: Erased block %s from linked powered blocks list due to present/past middle block mismatch", ItemToFullString(itr->a_SourceBlock).c_str());
+ itr = m_LinkedPoweredBlocks.erase(itr);
}
else if (
// Things that can send power through a block but which depends on meta
@@ -147,8 +160,8 @@ void cRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, c
(((SourceBlockType == E_BLOCK_STONE_BUTTON) || (SourceBlockType == E_BLOCK_WOODEN_BUTTON)) && (!IsButtonOn(SourceBlockMeta)))
)
{
- itr = m_LinkedPoweredBlocks.erase(itr);
LOGD("cRedstoneSimulator: Erased block %s from linked powered blocks list due to present/past metadata mismatch", ItemToFullString(itr->a_SourceBlock).c_str());
+ itr = m_LinkedPoweredBlocks.erase(itr);
}
else
{
@@ -196,6 +209,7 @@ void cRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, c
case E_BLOCK_TNT: HandleTNT(a_X, dataitr->y, a_Z); break;
case E_BLOCK_TRAPDOOR: HandleTrapdoor(a_X, dataitr->y, a_Z); break;
case E_BLOCK_REDSTONE_WIRE: HandleRedstoneWire(a_X, dataitr->y, a_Z); break;
+ case E_BLOCK_NOTE_BLOCK: HandleNoteBlock(a_X, dataitr->y, a_Z); break;
case E_BLOCK_REDSTONE_TORCH_OFF:
case E_BLOCK_REDSTONE_TORCH_ON:
@@ -392,20 +406,32 @@ void cRedstoneSimulator::HandleRedstoneWire(int a_BlockX, int a_BlockY, int a_Bl
int x, y, z;
} gCrossCoords[] =
{
- { 1, 0, 0},
+ { 1, 0, 0}, /* Wires on same level start */
{-1, 0, 0},
{ 0, 0, 1},
- { 0, 0, -1},
- { 1, 1, 0}, // From here to end, check for wire placed on sides of blocks
+ { 0, 0, -1}, /* Wires on same level stop */
+ { 1, 1, 0}, /* Wires one higher, surrounding self start */
{-1, 1, 0},
{ 0, 1, 1},
- { 0, 1, -1},
- { 1,-1, 0},
+ { 0, 1, -1}, /* Wires one higher, surrounding self stop */
+ { 1,-1, 0}, /* Wires one lower, surrounding self start */
{-1,-1, 0},
{ 0,-1, 1},
- { 0,-1, -1},
+ { 0,-1, -1}, /* Wires one lower, surrounding self stop */
} ;
+ static const struct // Define which directions the wire will check for repeater prescence
+ {
+ int x, y, z;
+ } gSideCoords[] =
+ {
+ { 1, 0, 0 },
+ {-1, 0, 0 },
+ { 0, 0, 1 },
+ { 0, 0,-1 },
+ { 0, 1, 0 },
+ };
+
// Check to see if directly beside a power source
if (AreCoordsPowered(a_BlockX, a_BlockY, a_BlockZ))
{
@@ -419,6 +445,21 @@ void cRedstoneSimulator::HandleRedstoneWire(int a_BlockX, int a_BlockY, int a_Bl
for (size_t i = 0; i < ARRAYCOUNT(gCrossCoords); i++) // Loop through all directions to transfer or receive power
{
+ if ((i >= 4) && (i <= 7)) // If we are currently checking for wire surrounding ourself one block above...
+ {
+ if (g_BlockIsSolid[m_World.GetBlock(a_BlockX, a_BlockY + 1, a_BlockZ)]) // If there is something solid above us (wire cut off)...
+ {
+ continue; // We don't receive power from that wire
+ }
+ }
+ else if ((i >= 8) && (i <= 11)) // See above, but this is for wire below us
+ {
+ if (g_BlockIsSolid[m_World.GetBlock(a_BlockX + gCrossCoords[i].x, a_BlockY + gCrossCoords[i].y + 1, a_BlockZ + gCrossCoords[i].z)])
+ {
+ continue;
+ }
+ }
+
BLOCKTYPE SurroundType;
NIBBLETYPE SurroundMeta;
m_World.GetBlockTypeMeta(a_BlockX + gCrossCoords[i].x, a_BlockY + gCrossCoords[i].y, a_BlockZ + gCrossCoords[i].z, SurroundType, SurroundMeta);
@@ -459,12 +500,20 @@ void cRedstoneSimulator::HandleRedstoneWire(int a_BlockX, int a_BlockY, int a_Bl
}
}
- // Wire still powered, power blocks beneath
- SetBlockPowered(a_BlockX, a_BlockY - 1, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_WIRE);
- SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_YM, E_BLOCK_REDSTONE_WIRE);
-
if (m_World.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ) != 0) // A powered wire
{
+ for (size_t i = 0; i < ARRAYCOUNT(gSideCoords); i++) // Look for repeaters immediately surrounding self and try to power them
+ {
+ if (m_World.GetBlock(a_BlockX + gSideCoords[i].x, a_BlockY + gSideCoords[i].y, a_BlockZ + gSideCoords[i].z) == E_BLOCK_REDSTONE_REPEATER_OFF)
+ {
+ SetBlockPowered(a_BlockX + gSideCoords[i].x, a_BlockY + gSideCoords[i].y, a_BlockZ + gSideCoords[i].z, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_WIRE);
+ }
+ }
+
+ // Wire still powered, power blocks beneath
+ SetBlockPowered(a_BlockX, a_BlockY - 1, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_WIRE);
+ SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_YM, E_BLOCK_REDSTONE_WIRE);
+
switch (GetWireDirection(a_BlockX, a_BlockY, a_BlockZ))
{
case REDSTONE_NONE:
@@ -481,37 +530,25 @@ void cRedstoneSimulator::HandleRedstoneWire(int a_BlockX, int a_BlockY, int a_Bl
}
case REDSTONE_X_POS:
{
- if (m_World.GetBlock(a_BlockX + 1, a_BlockY, a_BlockZ) != E_BLOCK_REDSTONE_WIRE)
- {
- SetBlockPowered(a_BlockX + 1, a_BlockY, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_WIRE);
- }
+ SetBlockPowered(a_BlockX + 1, a_BlockY, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_WIRE);
SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_XP, E_BLOCK_REDSTONE_WIRE);
break;
}
case REDSTONE_X_NEG:
{
- if (m_World.GetBlock(a_BlockX - 1, a_BlockY, a_BlockZ) != E_BLOCK_REDSTONE_WIRE)
- {
- SetBlockPowered(a_BlockX - 1, a_BlockY, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_WIRE);
- }
+ SetBlockPowered(a_BlockX - 1, a_BlockY, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_WIRE);
SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_XM, E_BLOCK_REDSTONE_WIRE);
break;
}
case REDSTONE_Z_POS:
{
- if (m_World.GetBlock(a_BlockX, a_BlockY, a_BlockZ + 1) != E_BLOCK_REDSTONE_WIRE)
- {
- SetBlockPowered(a_BlockX, a_BlockY, a_BlockZ + 1, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_WIRE);
- }
+ SetBlockPowered(a_BlockX, a_BlockY, a_BlockZ + 1, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_WIRE);
SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_ZP, E_BLOCK_REDSTONE_WIRE);
break;
}
case REDSTONE_Z_NEG:
{
- if (m_World.GetBlock(a_BlockX, a_BlockY, a_BlockZ - 1) != E_BLOCK_REDSTONE_WIRE)
- {
- SetBlockPowered(a_BlockX, a_BlockY, a_BlockZ - 1, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_WIRE);
- }
+ SetBlockPowered(a_BlockX, a_BlockY, a_BlockZ - 1, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_WIRE);
SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_ZM, E_BLOCK_REDSTONE_WIRE);
break;
}
@@ -525,109 +562,75 @@ void cRedstoneSimulator::HandleRedstoneWire(int a_BlockX, int a_BlockY, int a_Bl
void cRedstoneSimulator::HandleRedstoneRepeater(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_MyState)
{
+ NIBBLETYPE a_Meta = m_World.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ);
+
// We do this so that the repeater can continually update block power status (without being affected by it's own block type, which would happen if the block powering code was in an IF statement)
- bool IsOn = false;
- if (a_MyState == E_BLOCK_REDSTONE_REPEATER_ON)
+ bool IsOn = ((a_MyState == E_BLOCK_REDSTONE_REPEATER_ON) ? true : false);
+ bool IsSelfPowered = IsRepeaterPowered(a_BlockX, a_BlockY, a_BlockZ, a_Meta & 0x3);
+
+ if (IsSelfPowered && !IsOn) // Queue a power change if I am receiving power but not on
{
- IsOn = true;
+ QueueRepeaterPowerChange(a_BlockX, a_BlockY, a_BlockZ, a_Meta, 0, true);
+ }
+ else if (!IsSelfPowered && IsOn) // Queue a power change if I am not receiving power but on
+ {
+ QueueRepeaterPowerChange(a_BlockX, a_BlockY, a_BlockZ, a_Meta, 0, false);
}
- NIBBLETYPE a_Meta = m_World.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ);
-
- if (IsRepeaterPowered(a_BlockX, a_BlockY, a_BlockZ, a_Meta & 0x3))
+ for (RepeatersDelayList::iterator itr = m_RepeatersDelayList.begin(); itr != m_RepeatersDelayList.end(); itr++)
{
- if (!IsOn)
+ if (!itr->a_BlockPos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ)))
{
- bool ShouldCreate = true;
- // If repeater is not on already (and is POWERED), see if it is in repeater list, or has reached delay time
- for (RepeatersDelayList::iterator itr = m_RepeatersDelayList.begin(); itr != m_RepeatersDelayList.end(); itr++)
+ continue;
+ }
+
+ if (itr->a_ElapsedTicks >= itr->a_DelayTicks) // Has the elapsed ticks reached the target ticks?
+ {
+ if (itr->ShouldPowerOn)
{
- if (itr->a_BlockPos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ)))
+ m_World.SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_REPEATER_ON, a_Meta);
+
+ switch (a_Meta & 0x3) // We only want the direction (bottom) bits
{
- if (itr->a_DelayTicks <= itr->a_ElapsedTicks) // Shouldn't need <=; just in case something happens
+ case 0x0:
+ {
+ SetBlockPowered(a_BlockX, a_BlockY, a_BlockZ - 1, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_REPEATER_ON);
+ SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_ZM, E_BLOCK_REDSTONE_REPEATER_ON);
+ break;
+ }
+ case 0x1:
+ {
+ SetBlockPowered(a_BlockX + 1, a_BlockY, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_REPEATER_ON);
+ SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_XP, E_BLOCK_REDSTONE_REPEATER_ON);
+ break;
+ }
+ case 0x2:
{
- m_RepeatersDelayList.erase(itr);
- ShouldCreate = false;
- break; // Delay time reached, break straight out, and into the powering code
+ SetBlockPowered(a_BlockX, a_BlockY, a_BlockZ + 1, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_REPEATER_ON);
+ SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_ZP, E_BLOCK_REDSTONE_REPEATER_ON);
+ break;
}
- else
+ case 0x3:
{
- itr->a_ElapsedTicks++; // Increment elapsed ticks and quit
- return;
+ SetBlockPowered(a_BlockX - 1, a_BlockY, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_REPEATER_ON);
+ SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_XM, E_BLOCK_REDSTONE_REPEATER_ON);
+ break;
}
}
- }
- if (ShouldCreate)
- {
- // Self not in list, add self to list
- sRepeatersDelayList RC;
- RC.a_BlockPos = Vector3i(a_BlockX, a_BlockY, a_BlockZ);
- RC.a_DelayTicks = ((a_Meta & 0xC) >> 0x2) + 1; // Gets the top two bits (delay time), shifts them into the lower two bits, and adds one (meta 0 = 1 tick; 1 = 2 etc.)
- RC.a_ElapsedTicks = 0;
- m_RepeatersDelayList.push_back(RC);
+ m_RepeatersDelayList.erase(itr);
return;
}
-
- m_World.SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_REPEATER_ON, a_Meta); // Only set if not on; SetBlock otherwise server doesn't set it in time for SimulateChunk's invalidation
- }
- switch (a_Meta & 0x3) // We only want the direction (bottom) bits
- {
- case 0x0:
- {
- SetBlockPowered(a_BlockX, a_BlockY, a_BlockZ - 1, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_REPEATER_ON);
- SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_ZM, E_BLOCK_REDSTONE_REPEATER_ON);
- break;
- }
- case 0x1:
- {
- SetBlockPowered(a_BlockX + 1, a_BlockY, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_REPEATER_ON);
- SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_XP, E_BLOCK_REDSTONE_REPEATER_ON);
- break;
- }
- case 0x2:
- {
- SetBlockPowered(a_BlockX, a_BlockY, a_BlockZ + 1, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_REPEATER_ON);
- SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_ZP, E_BLOCK_REDSTONE_REPEATER_ON);
- break;
- }
- case 0x3:
+ else
{
- SetBlockPowered(a_BlockX - 1, a_BlockY, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_REPEATER_ON);
- SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_XM, E_BLOCK_REDSTONE_REPEATER_ON);
- break;
+ m_World.SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_REPEATER_OFF, a_Meta);
+ m_RepeatersDelayList.erase(itr);
+ return;
}
}
- }
- else
- {
- if (IsOn)
+ else
{
- // If repeater is not off already (and is NOT POWERED), see if it is in repeater list, or has reached delay time
- for (RepeatersDelayList::iterator itr = m_RepeatersDelayList.begin(); itr != m_RepeatersDelayList.end(); itr++)
- {
- if (itr->a_BlockPos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ)))
- {
- if (itr->a_DelayTicks <= itr->a_ElapsedTicks) // Shouldn't need <=; just in case something happens
- {
- m_RepeatersDelayList.erase(itr);
- m_World.SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_REPEATER_OFF, a_Meta);
- return;
- }
- else
- {
- itr->a_ElapsedTicks++; // Increment elapsed ticks and quit
- return;
- }
- }
- }
-
- // Self not in list, add self to list
- sRepeatersDelayList RC;
- RC.a_BlockPos = Vector3i(a_BlockX, a_BlockY, a_BlockZ);
- RC.a_DelayTicks = ((a_Meta & 0xC) >> 0x2); // Repeaters power off slower than they power on, so no +1. Why? No idea.
- RC.a_ElapsedTicks = 0;
- m_RepeatersDelayList.push_back(RC);
+ itr->a_ElapsedTicks++;
return;
}
}
@@ -821,6 +824,48 @@ void cRedstoneSimulator::HandleTrapdoor(int a_BlockX, int a_BlockY, int a_BlockZ
+void cRedstoneSimulator::HandleNoteBlock(int a_BlockX, int a_BlockY, int a_BlockZ)
+{
+ bool m_bAreCoordsPowered = AreCoordsPowered(a_BlockX, a_BlockY, a_BlockZ);
+
+ if (m_bAreCoordsPowered)
+ {
+ if (!AreCoordsSimulated(a_BlockX, a_BlockY, a_BlockZ, true))
+ {
+ class cSetPowerToNoteBlock :
+ public cNoteBlockCallback
+ {
+ bool m_IsPowered;
+ public:
+ cSetPowerToNoteBlock(bool a_IsPowered) : m_IsPowered(a_IsPowered) {}
+
+ virtual bool Item(cNoteEntity * a_NoteBlock) override
+ {
+ if (m_IsPowered)
+ {
+ a_NoteBlock->MakeSound();
+ }
+ return false;
+ }
+ } NoteBlockSP(m_bAreCoordsPowered);
+
+ m_World.DoWithNoteBlockAt(a_BlockX, a_BlockY, a_BlockZ, NoteBlockSP);
+ SetPlayerToggleableBlockAsSimulated(a_BlockX, a_BlockY, a_BlockZ, true);
+ }
+ }
+ else
+ {
+ if (!AreCoordsSimulated(a_BlockX, a_BlockY, a_BlockZ, false))
+ {
+ SetPlayerToggleableBlockAsSimulated(a_BlockX, a_BlockY, a_BlockZ, false);
+ }
+ }
+}
+
+
+
+
+
bool cRedstoneSimulator::AreCoordsDirectlyPowered(int a_BlockX, int a_BlockY, int a_BlockZ)
{
for (PoweredBlocksList::const_iterator itr = m_PoweredBlocks.begin(); itr != m_PoweredBlocks.end(); ++itr) // Check powered list
@@ -1103,11 +1148,17 @@ void cRedstoneSimulator::SetAllDirsAsPowered(int a_BlockX, int a_BlockY, int a_B
void cRedstoneSimulator::SetBlockPowered(int a_BlockX, int a_BlockY, int a_BlockZ, int a_SourceX, int a_SourceY, int a_SourceZ, BLOCKTYPE a_SourceBlock)
{
- if (m_World.GetBlock(a_BlockX, a_BlockY, a_BlockZ) == E_BLOCK_AIR)
+ BLOCKTYPE Block = m_World.GetBlock(a_BlockX, a_BlockY, a_BlockZ);
+ if (Block == E_BLOCK_AIR)
{
// Don't set air, fixes some bugs (wires powering themselves)
return;
}
+ if ((Block == E_BLOCK_REDSTONE_WIRE) && (a_SourceBlock == E_BLOCK_REDSTONE_WIRE))
+ {
+ // Wires cannot power themselves normally, instead, the wire handler will manually set meta
+ return;
+ }
for (PoweredBlocksList::const_iterator itr = m_PoweredBlocks.begin(); itr != m_PoweredBlocks.end(); ++itr) // Check powered list
{
@@ -1214,6 +1265,30 @@ void cRedstoneSimulator::SetPlayerToggleableBlockAsSimulated(int a_BlockX, int a
+void cRedstoneSimulator::QueueRepeaterPowerChange(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_Meta, short a_ElapsedTicks, bool ShouldPowerOn)
+{
+ for (RepeatersDelayList::iterator itr = m_RepeatersDelayList.begin(); itr != m_RepeatersDelayList.end(); itr++)
+ {
+ if (itr->a_BlockPos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ)))
+ {
+ return;
+ }
+ }
+
+ // Self not in list, add self to list
+ sRepeatersDelayList RC;
+ RC.a_BlockPos = Vector3i(a_BlockX, a_BlockY, a_BlockZ);
+ RC.a_DelayTicks = ((a_Meta & 0xC) >> 0x2) + 1; // Gets the top two bits (delay time), shifts them into the lower two bits, and adds one (meta 0 = 1 tick; 1 = 2 etc.)
+ RC.a_ElapsedTicks = 0;
+ RC.ShouldPowerOn = ShouldPowerOn;
+ m_RepeatersDelayList.push_back(RC);
+ return;
+}
+
+
+
+
+
cRedstoneSimulator::eRedstoneDirection cRedstoneSimulator::GetWireDirection(int a_BlockX, int a_BlockY, int a_BlockZ)
{
int Dir = REDSTONE_NONE;
diff --git a/src/Simulator/RedstoneSimulator.h b/src/Simulator/RedstoneSimulator.h
index 23ac510fc..d40d88342 100644
--- a/src/Simulator/RedstoneSimulator.h
+++ b/src/Simulator/RedstoneSimulator.h
@@ -62,6 +62,7 @@ private:
Vector3i a_BlockPos;
short a_DelayTicks;
short a_ElapsedTicks;
+ bool ShouldPowerOn;
};
typedef std::vector <sPoweredBlocks> PoweredBlocksList;
@@ -112,6 +113,8 @@ private:
void HandleRail(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_MyType);
/// <summary>Handles trapdoors</summary>
void HandleTrapdoor(int a_BlockX, int a_BlockY, int a_BlockZ);
+ /// <summary>Handles noteblocks</summary>
+ void HandleNoteBlock(int a_BlockX, int a_BlockY, int a_BlockZ);
/* ===================== */
/* ====== Helper functions ====== */
@@ -125,6 +128,8 @@ private:
void SetDirectionLinkedPowered(int a_BlockX, int a_BlockY, int a_BlockZ, char a_Direction, BLOCKTYPE a_SourceBlock);
/// <summary>Marks all blocks immediately surrounding a coordinate as powered</summary>
void SetAllDirsAsPowered(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_SourceBlock);
+ /// <summary>Queues a repeater to be powered or unpowered</summary>
+ void QueueRepeaterPowerChange(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_Meta, short a_ElapsedTicks, bool ShouldPowerOn);
/// <summary>Returns if a coordinate is powered or linked powered</summary>
bool AreCoordsPowered(int a_BlockX, int a_BlockY, int a_BlockZ) { return AreCoordsDirectlyPowered(a_BlockX, a_BlockY, a_BlockZ) || AreCoordsLinkedPowered(a_BlockX, a_BlockY, a_BlockZ); }
diff --git a/src/World.cpp b/src/World.cpp
index 564905d33..f81456334 100644
--- a/src/World.cpp
+++ b/src/World.cpp
@@ -234,7 +234,6 @@ cWorld::cWorld(const AString & a_WorldName) :
m_WorldAge(0),
m_TimeOfDay(0),
m_LastTimeUpdate(0),
- m_RSList(0),
m_Weather(eWeather_Sunny),
m_WeatherInterval(24000), // Guaranteed 1 day of sunshine at server start :)
m_TickThread(*this),
@@ -716,29 +715,6 @@ void cWorld::Tick(float a_Dt, int a_LastTickDurationMSec)
}
TickMobs(a_Dt);
-
- std::vector<int> m_RSList_copy(m_RSList);
-
- m_RSList.clear();
-
- std::vector<int>::const_iterator cii; // FIXME - Please rename this variable, WTF is cii??? Use human readable variable names or common abbreviations (i, idx, itr, iter)
- for (cii = m_RSList_copy.begin(); cii != m_RSList_copy.end();)
- {
- int tempX = *cii; cii++;
- int tempY = *cii; cii++;
- int tempZ = *cii; cii++;
- int state = *cii; cii++;
-
- if ((state == 11111) && ((int)GetBlock(tempX, tempY, tempZ) == E_BLOCK_REDSTONE_TORCH_OFF))
- {
- FastSetBlock(tempX, tempY, tempZ, E_BLOCK_REDSTONE_TORCH_ON, (int)GetBlockMeta(tempX, tempY, tempZ));
- }
- else if ((state == 00000) && ((int)GetBlock(tempX, tempY, tempZ) == E_BLOCK_REDSTONE_TORCH_ON))
- {
- FastSetBlock(tempX, tempY, tempZ, E_BLOCK_REDSTONE_TORCH_OFF, (int)GetBlockMeta(tempX, tempY, tempZ));
- }
- }
- m_RSList_copy.erase(m_RSList_copy.begin(),m_RSList_copy.end());
}
@@ -1129,6 +1105,15 @@ bool cWorld::DoWithFurnaceAt(int a_BlockX, int a_BlockY, int a_BlockZ, cFurnaceC
+bool cWorld::DoWithNoteBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cNoteBlockCallback & a_Callback)
+{
+ return m_ChunkMap->DoWithNoteBlockAt(a_BlockX, a_BlockY, a_BlockZ, a_Callback);
+}
+
+
+
+
+
bool cWorld::GetSignLines(int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4)
{
return m_ChunkMap->GetSignLines(a_BlockX, a_BlockY, a_BlockZ, a_Line1, a_Line2, a_Line3, a_Line4);
@@ -1804,6 +1789,15 @@ void cWorld::BroadcastDestroyEntity(const cEntity & a_Entity, const cClientHandl
+void cWorld::BroadcastEntityEffect(const cEntity & a_Entity, int a_EffectID, int a_Amplifier, short a_Duration, const cClientHandle * a_Exclude)
+{
+ m_ChunkMap->BroadcastEntityEffect(a_Entity, a_EffectID, a_Amplifier, a_Duration, a_Exclude);
+}
+
+
+
+
+
void cWorld::BroadcastEntityEquipment(const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item, const cClientHandle * a_Exclude)
{
m_ChunkMap->BroadcastEntityEquipment(a_Entity, a_SlotNum, a_Item, a_Exclude);
@@ -1902,6 +1896,15 @@ void cWorld::BroadcastPlayerListItem (const cPlayer & a_Player, bool a_IsOnline,
+void cWorld::BroadcastRemoveEntityEffect(const cEntity & a_Entity, int a_EffectID, const cClientHandle * a_Exclude)
+{
+ m_ChunkMap->BroadcastRemoveEntityEffect(a_Entity, a_EffectID, a_Exclude);
+}
+
+
+
+
+
void cWorld::BroadcastSoundEffect(const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch, const cClientHandle * a_Exclude)
{
m_ChunkMap->BroadcastSoundEffect(a_SoundName, a_SrcX, a_SrcY, a_SrcZ, a_Volume, a_Pitch, a_Exclude);
diff --git a/src/World.h b/src/World.h
index fc821a68a..2d9e8b551 100644
--- a/src/World.h
+++ b/src/World.h
@@ -27,7 +27,6 @@
-class cRedstone;
class cFireSimulator;
class cFluidSimulator;
class cSandSimulator;
@@ -42,6 +41,7 @@ class cChunkGenerator; // The thread responsible for generating chunks
class cChestEntity;
class cDispenserEntity;
class cFurnaceEntity;
+class cNoteEntity;
class cMobCensus;
typedef std::list< cPlayer * > cPlayerList;
@@ -51,6 +51,7 @@ typedef cItemCallback<cEntity> cEntityCallback;
typedef cItemCallback<cChestEntity> cChestCallback;
typedef cItemCallback<cDispenserEntity> cDispenserCallback;
typedef cItemCallback<cFurnaceEntity> cFurnaceCallback;
+typedef cItemCallback<cNoteEntity> cNoteBlockCallback;
@@ -151,6 +152,7 @@ public:
void BroadcastChunkData (int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer, const cClientHandle * a_Exclude = NULL);
void BroadcastCollectPickup (const cPickup & a_Pickup, const cPlayer & a_Player, const cClientHandle * a_Exclude = NULL);
void BroadcastDestroyEntity (const cEntity & a_Entity, const cClientHandle * a_Exclude = NULL);
+ void BroadcastEntityEffect (const cEntity & a_Entity, int a_EffectID, int a_Amplifier, short a_Duration, const cClientHandle * a_Exclude = NULL);
void BroadcastEntityEquipment (const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item, const cClientHandle * a_Exclude = NULL);
void BroadcastEntityHeadLook (const cEntity & a_Entity, const cClientHandle * a_Exclude = NULL);
void BroadcastEntityLook (const cEntity & a_Entity, const cClientHandle * a_Exclude = NULL);
@@ -161,6 +163,7 @@ public:
void BroadcastEntityVelocity (const cEntity & a_Entity, const cClientHandle * a_Exclude = NULL);
void BroadcastEntityAnimation (const cEntity & a_Entity, char a_Animation, const cClientHandle * a_Exclude = NULL);
void BroadcastPlayerListItem (const cPlayer & a_Player, bool a_IsOnline, const cClientHandle * a_Exclude = NULL);
+ void BroadcastRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID, const cClientHandle * a_Exclude = NULL);
void BroadcastSoundEffect (const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch, const cClientHandle * a_Exclude = NULL); // tolua_export a_Src coords are Block * 8
void BroadcastSoundParticleEffect(int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data, const cClientHandle * a_Exclude = NULL); // tolua_export
void BroadcastSpawnEntity (cEntity & a_Entity, const cClientHandle * a_Exclude = NULL);
@@ -444,6 +447,9 @@ public:
/// Calls the callback for the furnace at the specified coords; returns false if there's no furnace at those coords or callback returns true, returns true if found
bool DoWithFurnaceAt(int a_BlockX, int a_BlockY, int a_BlockZ, cFurnaceCallback & a_Callback); // Exported in ManualBindings.cpp
+
+ /// Calls the callback for the noteblock at the specified coords; returns false if there's no noteblock at those coords or callback returns true, returns true if found
+ bool DoWithNoteBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cNoteBlockCallback & a_Callback); // Exported in ManualBindings.cpp
/// Retrieves the test on the sign at the specified coords; returns false if there's no sign at those coords, true if found
bool GetSignLines (int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4); // Exported in ManualBindings.cpp
@@ -661,10 +667,6 @@ private:
bool m_bEnabledPVP;
bool m_IsDeepSnowEnabled;
bool m_ShouldLavaSpawnFire;
-
- // The cRedstone class simulates redstone and needs access to m_RSList
- // friend class cRedstone;
- std::vector<int> m_RSList;
std::vector<BlockTickQueueItem *> m_BlockTickQueue;
std::vector<BlockTickQueueItem *> m_BlockTickQueueCopy; // Second is for safely removing the objects from the queue