m_script = new GameScripting(this);
- std::string scriptpath = getBuiltinLuaPath() + DIR_DELIM "init.lua";
+ std::string script_path = getBuiltinLuaPath() + DIR_DELIM "init.lua";
- if (!m_script->loadScript(scriptpath))
- throw ModError("Failed to load and run " + scriptpath);
+ if (!m_script->loadMod(script_path, BUILTIN_MOD_NAME)) {
+ throw ModError("Failed to load and run " + script_path);
+ }
- // Print 'em
- infostream<<"Server: Loading mods: ";
+ // Print mods
+ infostream << "Server: Loading mods: ";
for(std::vector<ModSpec>::iterator i = m_mods.begin();
i != m_mods.end(); i++){
const ModSpec &mod = *i;
- infostream<<mod.name<<" ";
+ infostream << mod.name << " ";
}
- infostream<<std::endl;
+ infostream << std::endl;
// Load and run "mod" scripts
- for(std::vector<ModSpec>::iterator i = m_mods.begin();
- i != m_mods.end(); i++){
+ for (std::vector<ModSpec>::iterator i = m_mods.begin();
+ i != m_mods.end(); i++) {
const ModSpec &mod = *i;
- std::string scriptpath = mod.path + DIR_DELIM + "init.lua";
- infostream<<" ["<<padStringRight(mod.name, 12)<<"] [\""
- <<scriptpath<<"\"]"<<std::endl;
- bool success = m_script->loadMod(scriptpath, mod.name);
- if(!success){
- errorstream<<"Server: Failed to load and run "
- <<scriptpath<<std::endl;
- throw ModError("Failed to load and run "+scriptpath);
+ if (!string_allowed(mod.name, MODNAME_ALLOWED_CHARS)) {
+ errorstream << "Error loading mod \"" << mod.name
+ << "\": mod_name does not follow naming conventions: "
+ << "Only chararacters [a-z0-9_] are allowed." << std::endl;
+ throw ModError("Mod \"" + mod.name + "\" does not follow naming conventions.");
+ }
+ std::string script_path = mod.path + DIR_DELIM "init.lua";
+ infostream << " [" << padStringRight(mod.name, 12) << "] [\""
+ << script_path << "\"]" << std::endl;
+ if (!m_script->loadMod(script_path, mod.name)) {
+ errorstream << "Server: Failed to load and run "
+ << script_path << std::endl;
+ throw ModError("Failed to load and run " + script_path);
}
}
// Apply item aliases in the node definition manager
m_nodedef->updateAliases(m_itemdef);
+ // Apply texture overrides from texturepack/override.txt
+ std::string texture_path = g_settings->get("texture_path");
+ if (texture_path != "" && fs::IsDir(texture_path))
+ m_nodedef->applyTextureOverrides(texture_path + DIR_DELIM + "override.txt");
+
m_nodedef->setNodeRegistrationStatus(true);
// Perform pending node name resolutions
- m_nodedef->runNodeResolverCallbacks();
+ m_nodedef->runNodeResolveCallbacks();
+
+ // init the recipe hashes to speed up crafting
+ m_craftdef->initHashes(this);
// Initialize Environment
m_env = new ServerEnvironment(servermap, m_script, this, m_path_world);
static_cast<RemotePlayer*>(m_env->getPlayer(playername.c_str()));
// If failed, cancel
- if((playersao == NULL) || (player == NULL)) {
- if(player && player->peer_id != 0) {
- errorstream<<"Server: "<<playername<<": Failed to emerge player"
- <<" (player allocated to an another client)"<<std::endl;
+ if ((playersao == NULL) || (player == NULL)) {
+ if (player && player->peer_id != 0) {
+ actionstream << "Server: Failed to emerge player \"" << playername
+ << "\" (player allocated to an another client)" << std::endl;
DenyAccess_Legacy(peer_id, L"Another client is connected with this "
L"name. If your client closed unexpectedly, try again in "
L"a minute.");
} else {
- errorstream<<"Server: "<<playername<<": Failed to emerge player"
- <<std::endl;
+ errorstream << "Server: " << playername << ": Failed to emerge player"
+ << std::endl;
DenyAccess_Legacy(peer_id, L"Could not allocate player.");
}
return NULL;
}
handleCommand(pkt);
- }
- catch(SendFailedException &e) {
+ } catch (SendFailedException &e) {
errorstream << "Server::ProcessData(): SendFailedException: "
<< "what=" << e.what()
<< std::endl;
+ } catch (PacketError &e) {
+ actionstream << "Server::ProcessData(): PacketError: "
+ << "what=" << e.what()
+ << std::endl;
}
}
Send(&pkt);
}
-void Server::SendAccessDenied(u16 peer_id, AccessDeniedCode reason, const std::wstring &custom_reason)
+void Server::SendAccessDenied(u16 peer_id, AccessDeniedCode reason, const std::string &custom_reason)
{
DSTACK(__FUNCTION_NAME);
{
DSTACK(__FUNCTION_NAME);
PlayerSAO *playersao = getPlayerSAO(peer_id);
- assert(playersao);
+ // In some rare case, if the player is disconnected
+ // while Lua call l_punch, for example, this can be NULL
+ if (!playersao)
+ return;
+
SendHP(peer_id, playersao->getHP());
m_script->player_event(playersao,"health_changed");
u32 Server::SendActiveObjectRemoveAdd(u16 peer_id, const std::string &datas)
{
- NetworkPacket pkt(TOCLIENT_ACTIVE_OBJECT_REMOVE_ADD, 0, peer_id);
+ NetworkPacket pkt(TOCLIENT_ACTIVE_OBJECT_REMOVE_ADD, datas.size(), peer_id);
pkt.putRawString(datas.c_str(), datas.size());
Send(&pkt);
return pkt.getSize();
void Server::SendActiveObjectMessages(u16 peer_id, const std::string &datas, bool reliable)
{
NetworkPacket pkt(TOCLIENT_ACTIVE_OBJECT_MESSAGES,
- 0, peer_id);
+ datas.size(), peer_id);
pkt.putRawString(datas.c_str(), datas.size());
m_clients.send(pkt.getPeerId(),
- clientCommandFactoryTable[pkt.getCommand()].channel,
+ reliable ? clientCommandFactoryTable[pkt.getCommand()].channel : 1,
&pkt, reliable);
}
bool repositioned = m_script->on_respawnplayer(playersao);
if(!repositioned){
- v3f pos = findSpawnPos(m_env->getServerMap());
+ v3f pos = findSpawnPos();
// setPos will send the new position to client
playersao->setPos(pos);
}
}
+void Server::DenySudoAccess(u16 peer_id)
+{
+ DSTACK(__FUNCTION_NAME);
-void Server::DenyAccess(u16 peer_id, AccessDeniedCode reason, const std::wstring &custom_reason)
+ NetworkPacket pkt(TOCLIENT_DENY_SUDO_MODE, 0, peer_id);
+ Send(&pkt);
+}
+
+void Server::DenyAccess(u16 peer_id, AccessDeniedCode reason, const std::string &custom_reason)
{
DSTACK(__FUNCTION_NAME);
m_con.DisconnectPeer(peer_id);
}
+void Server::acceptAuth(u16 peer_id, bool forSudoMode)
+{
+ DSTACK(__FUNCTION_NAME);
+
+ if (!forSudoMode) {
+ RemoteClient* client = getClient(peer_id, CS_Invalid);
+
+ NetworkPacket resp_pkt(TOCLIENT_AUTH_ACCEPT, 1 + 6 + 8 + 4, peer_id);
+
+ // Right now, the auth mechs don't change between login and sudo mode.
+ u32 sudo_auth_mechs = client->allowed_auth_mechs;
+ client->allowed_sudo_mechs = sudo_auth_mechs;
+
+ resp_pkt << v3f(0,0,0) << (u64) m_env->getServerMap().getSeed()
+ << g_settings->getFloat("dedicated_server_step")
+ << sudo_auth_mechs;
+
+ Send(&resp_pkt);
+ m_clients.event(peer_id, CSE_AuthAccept);
+ } else {
+ NetworkPacket resp_pkt(TOCLIENT_ACCEPT_SUDO_MODE, 1 + 6 + 8 + 4, peer_id);
+
+ // We only support SRP right now
+ u32 sudo_auth_mechs = AUTH_MECHANISM_FIRST_SRP;
+
+ resp_pkt << sudo_auth_mechs;
+ Send(&resp_pkt);
+ m_clients.event(peer_id, CSE_SudoSuccess);
+ }
+}
+
void Server::DeleteClient(u16 peer_id, ClientDeletionReason reason)
{
DSTACK(__FUNCTION_NAME);
if (hotbar_itemcount <= 0 || hotbar_itemcount > HUD_HOTBAR_ITEMCOUNT_MAX)
return false;
+ player->setHotbarItemcount(hotbar_itemcount);
std::ostringstream os(std::ios::binary);
writeS32(os, hotbar_itemcount);
SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_ITEMCOUNT, os.str());
return true;
}
+s32 Server::hudGetHotbarItemcount(Player *player) {
+ if (!player)
+ return 0;
+ return player->getHotbarItemcount();
+}
+
void Server::hudSetHotbarImage(Player *player, std::string name) {
if (!player)
return;
+ player->setHotbarImage(name);
SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_IMAGE, name);
}
+std::string Server::hudGetHotbarImage(Player *player) {
+ if (!player)
+ return "";
+ return player->getHotbarImage();
+}
+
void Server::hudSetHotbarSelectedImage(Player *player, std::string name) {
if (!player)
return;
+ player->setHotbarSelectedImage(name);
SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_SELECTED_IMAGE, name);
}
+std::string Server::hudGetHotbarSelectedImage(Player *player) {
+ if (!player)
+ return "";
+
+ return player->getHotbarSelectedImage();
+}
+
bool Server::setLocalPlayerAnimations(Player *player, v2s32 animation_frames[4], f32 frame_speed)
{
if (!player)
return false;
+ player->setLocalAnimations(animation_frames, frame_speed);
SendLocalPlayerAnimations(player->peer_id, animation_frames, frame_speed);
return true;
}
if (!player)
return false;
+ player->eye_offset_first = first;
+ player->eye_offset_third = third;
SendEyeOffset(player->peer_id, first, third);
return true;
}
if (!player)
return false;
+ player->setSky(bgcolor, type, params);
SendSetSky(player->peer_id, bgcolor, type, params);
return true;
}
if (!player)
return false;
+ player->overrideDayNightRatio(do_override, ratio);
SendOverrideDayNightRatio(player->peer_id, do_override, ratio);
return true;
}
return m_craftdef;
}
-const ModSpec* Server::getModSpec(const std::string &modname)
+const ModSpec* Server::getModSpec(const std::string &modname) const
{
- for(std::vector<ModSpec>::iterator i = m_mods.begin();
+ for(std::vector<ModSpec>::const_iterator i = m_mods.begin();
i != m_mods.end(); i++){
const ModSpec &mod = *i;
if(mod.name == modname)
return porting::path_share + DIR_DELIM + "builtin";
}
-v3f findSpawnPos(ServerMap &map)
+v3f Server::findSpawnPos()
{
- //return v3f(50,50,50)*BS;
+ ServerMap &map = m_env->getServerMap();
+ v3f nodeposf;
+ if (g_settings->getV3FNoEx("static_spawnpoint", nodeposf)) {
+ return nodeposf * BS;
+ }
- v3s16 nodepos;
+ // Default position is static_spawnpoint
+ // We will return it if we don't found a good place
+ v3s16 nodepos(nodeposf.X, nodeposf.Y, nodeposf.Z);
-#if 0
- nodepos = v2s16(0,0);
- groundheight = 20;
-#endif
-
-#if 1
s16 water_level = map.getWaterLevel();
+ bool is_good = false;
+
// Try to find a good place a few times
- for(s32 i=0; i<1000; i++)
- {
+ for(s32 i = 0; i < 1000 && !is_good; i++) {
s32 range = 1 + i;
// We're going to try to throw the player to this position
v2s16 nodepos2d = v2s16(
continue;
nodepos = v3s16(nodepos2d.X, groundheight, nodepos2d.Y);
- bool is_good = false;
+
s32 air_count = 0;
for (s32 i = 0; i < 10; i++) {
v3s16 blockpos = getNodeBlockPos(nodepos);
}
nodepos.Y++;
}
- if(is_good){
- // Found a good place
- //infostream<<"Searched through "<<i<<" places."<<std::endl;
- break;
- }
}
-#endif
return intToFloat(nodepos, BS);
}
// Set player position
infostream<<"Server: Finding spawn place for player \""
<<name<<"\""<<std::endl;
- v3f pos = findSpawnPos(m_env->getServerMap());
+ v3f pos = findSpawnPos();
player->setPosition(pos);
// Make sure the player is saved
}
}
}
-
-