/* * /bezier - * * Draws a beizer curvee using between user-specified control points. * The curve will pass through the first and last points, but not necessarily * through the rest. * * Permissions: * - command.draw.bezier * Needed to execute the command. */ void c_bezier::execute (player *pl, command_reader& reader) { if (!pl->perm ("command.draw.bezier")) return; if (!reader.parse (this, pl)) return; if (reader.no_args () || reader.arg_count () > 2) { this->show_summary (pl); return; } std::string str = reader.next ().as_str (); if (!sutils::is_block (str)) { pl->message ("§c * §7Invalid block§f: §c" + str); return; } blocki bl = sutils::to_block (str); if (bl.id == BT_UNKNOWN) { pl->message ("§c * §7Unknown block§f: §c" + str); return; } int order = 2; if (reader.has_next ()) { command_reader::argument arg = reader.next (); if (!arg.is_int ()) { pl->message ("§c * §7Usage§f: §e/bezier §cblock §8[§corder§8]"); return; } order = arg.as_int (); if (order <= 0 || order > 20) { pl->message ("§c * §7Invalid bezier curve order §f(§7Must be between §b1-20§f)"); return; } } bezier_data *data = new bezier_data (pl->get_world (), bl, order); pl->create_data ("bezier", data, [] (void *ptr) { delete static_cast<bezier_data *> (ptr); }); pl->get_nth_marking_callback (1) += on_blocks_marked; std::ostringstream ss; ss << "§5Draw§f: §3bezier curve §f[§7order§f: §8" << order << "§f, §7block§f: §8" << block_info::from_id (bl.id)->name; if (bl.meta != 0) ss << ':' << (int)bl.meta; ss << "§f]:"; pl->message (ss.str ()); ss.str (std::string ()); ss.clear (); ss << "§7 | §ePlease mark §b" << (order + 1) << " §eblocks§f."; pl->message (ss.str ()); }
/* * /help - * * When executed without any arguments, the command displays general tips, * tricks and hints about what the player can do in the server. Otherwise, * it displays detailed information about the supplied command. * * Permissions: * - command.info.help * To execute the command. */ void c_help::execute (player *pl, command_reader& reader) { if (!pl->perm ("command.info.help")) return; // we handle --help and --summary ourselves, instead of passing the work // to the command reader. reader.add_option ("help", "h", true); reader.add_option ("summary", "s"); if (!reader.parse (this, pl, false)) return; if (reader.opt ("summary")->found () && reader.no_args ()) { this->show_summary (pl); return; } else if (reader.opt ("help")->found ()) { auto& opt = *reader.opt ("help"); if (opt.got_args ()) { auto& arg = opt.arg (0); if (!arg.is_int ()) { pl->message ("§c * §7Invalid page number§: §c" + arg.as_str ()); return; } int page = arg.as_int (); this->show_help (pl, page, 12); } else this->show_help (pl, 1, 12); return; } if (reader.arg_count () > 2) { this->show_summary (pl); return; } else if (reader.arg_count () > 0) { command *cmd = pl->get_server ().get_commands ().find (reader.arg (0).c_str ()); if (!cmd || !pl->has (cmd->get_exec_permission ())) { pl->message ("§c * §7Unable to find help for§f: §c" + reader.arg (0)); return; } if (reader.opt ("summary")->found ()) cmd->show_summary (pl); int page = 1; if (reader.arg_count () == 2) { if (!sutils::is_int (reader.arg (1))) { pl->message ("§c * §7Invalid page number§: §c" + reader.arg (1)); return; } page = sutils::to_int (reader.arg (1)); } cmd->show_help (pl, page, 12); return; } for (const std::string& str : pl->get_server ().msgs.help) pl->message (messages::compile (str, messages::environment (pl))); }
/* * /ping - * * Displays to the player how much time it takes for the server to both * send and retreive a single keep alive (ping: 0x00) packet (in ms). * * Permissions: * - command.misc.ping * Needed to execute the command. */ void c_ping::execute (player *pl, command_reader& reader) { if (!pl->perm ("command.misc.ping")) return; if (!reader.parse (this, pl)) return; if (reader.arg_count () > 1) { this->show_summary (pl); return; } if (reader.has_args ()) { player *target = pl->get_server ().get_players ().find (reader.arg (0).c_str ()); if (!target) { pl->message ("§c * §7No such player §f: §c" + reader.arg (0) + "§f."); return; } std::ostringstream ss; ss << "§a" << target->get_username () << "§e's ping§f: §c" << target->get_ping () << " §emilliseconds§f."; pl->message (ss.str ()); return; } std::ostringstream ss; ss << "§ePing§f: §c" << pl->get_ping () << " §emilliseconds§f."; pl->message (ss.str ()); }
/* * /whodid * * Displays modification records for blocks selected by the user. * * Permissions: * - command.info.whodid * Needed to execute the command. */ void c_whodid::execute (player *pl, command_reader& reader) { if (!pl->perm (this->get_exec_permission ())) return; reader.add_option ("page", "p", 1, 1); if (!reader.parse (this, pl)) return; int page = -1; auto opt_page = reader.opt ("page"); if (opt_page->found ()) { auto& arg = opt_page->arg (0); if (!arg.is_int () || (page = arg.as_int ()) <= 0) { pl->message ("§c * §7Option to §4--§cpage §7must be an integer > 0"); return; } } whodid_data *data = new whodid_data {page - 1}; pl->create_data ("whodid", data, [] (void *ptr) { delete static_cast<whodid_data *> (ptr); }); pl->get_nth_marking_callback (1) += on_blocks_marked; pl->message ("§ePlease mark §bone §eblock."); }
/* * /zone * * Zone management. * * Permissions: * - command.world.zone * Needed to execute the command. */ void c_zone::execute (player *pl, command_reader& reader) { if (!pl->perm (this->get_exec_permission ())) return; if (!reader.parse (this, pl)) return; if (reader.no_args ()) { this->show_summary (pl); return; } std::string arg = reader.next (); static const std::unordered_map<cistring, void (*)(player *, command_reader&)> _map { { "create", _handle_create }, { "delete", _handle_delete }, { "build-perms", _handle_build_perms }, { "enter-perms", _handle_enter_perms }, { "leave-perms", _handle_leave_perms }, { "enter-msg", _handle_enter_msg }, { "leave-msg", _handle_leave_msg }, { "select", _handle_select }, { "reset", _handle_reset }, { "check", _handle_check }, }; auto itr = _map.find (arg.c_str ()); if (itr == _map.end ()) { pl->message ("§c * §7Invalid sub-command§f: §c" + arg); return; } itr->second (pl, reader); }
/* * /physics - * * Changes the current state of physics of the player's world. * * Permissions: * - command.world.physics * Needed to execute the command. */ void c_physics::execute (player *pl, command_reader& reader) { if (!pl->perm ("command.world.physics")) return; if (!reader.parse (this, pl)) return; if (reader.no_args () || reader.no_args ()) { this->show_summary (pl); return; } std::string& opt = reader.next (); static std::unordered_map<cistring, void (*)(player *, command_reader &)> funs { { "on", handle_on }, { "off", handle_off }, { "pause", handle_pause }, { "threads", handle_threads }, }; auto itr = funs.find (opt.c_str ()); if (itr == funs.end ()) { pl->message ("§c * §7Invalid option§f: §c" + opt); return; } itr->second (pl, reader); }
/* * /unban * * Revokes a permanent ban from a specified player. * * Permissions: * - command.admin.unban * Needed to execute the command. * - command.admin.unban.ip * Required to lift IP bans. */ void c_unban::execute (player *pl, command_reader& reader) { if (!pl->perm (this->get_exec_permission ())) return; reader.add_option ("ip", "i"); if (!reader.parse (this, pl)) return; if (reader.no_args ()) { this->show_summary (pl); return; } std::string target_name = reader.next ().as_str (); std::string reason = reader.has_next () ? reader.all_after (0) : "No reason specified"; if (reader.opt ("ip")->found ()) { if (!pl->has ("command.admin.unban.ip")) { pl->message ("§c * §7You are not allowed to do that§c."); return; } _unban_ip (pl, target_name); } else _unban_player (pl, target_name, reason, false); }
/* * /world - * * Lets the user modify or view world related information. * * Permissions: * - command.world.world * Needed to execute the command. * - command.world.world.change-members * Needed to add\remove world members. * - command.world.world.change-owners * Needed to add\remove world owners. * - command.world.world.owner.change-members * If a world owner is allowed to add\remove members. * - command.world.world.owner.change-owners * If a world owner is allowed to add\remove owners. * - command.world.world.set-perms * Required to set build-perms or join-perms * - command.world.world.get-perms * Required to view build-perms or join-perms * - commands.world.world.def-gm * Needed to change the world's default gamemode. * - commands.world.world.resize * Required to resize the world. * - commands.world.world.regenerate * Required to regenerate the world. * - commands.world.world.save * Required to save the world. * - commands.world.world.time * Required to change the time of the world. * - commands.world.world.pvp * Required to turn PvP on or off. */ void c_world::execute (player *pl, command_reader& reader) { if (!pl->perm ("command.world.world")) return; reader.add_option ("world", "w", 1, 1); if (!reader.parse (this, pl)) return; world *w = pl->get_world (); auto opt_w = reader.opt ("world"); if (opt_w->found ()) { const std::string w_name = opt_w->arg (0).as_str (); w = pl->get_server ().get_worlds ().find (w_name.c_str ()); if (!w) { pl->message ("§c * §7Unknown world§f: §c" + w_name); return; } } if (!reader.has_next ()) _handle_no_args (pl, w); else { std::string arg1 = reader.next ().as_str (); static const std::unordered_map<cistring, void (*)(player *, world *, command_reader &)> _map { { "owners", _handle_owners }, { "members", _handle_members }, { "build-perms", _handle_build_perms }, { "join-perms", _handle_join_perms }, { "def-gm", _handle_def_gm }, { "def-inv", _handle_def_inv }, { "resize", _handle_resize }, { "regenerate", _handle_regenerate }, { "backup", _handle_backup }, { "restore", _handle_restore }, { "save", _handle_save }, { "time", _handle_time }, { "pvp", _handle_pvp }, }; auto itr = _map.find (arg1.c_str ()); if (itr == _map.end ()) { pl->message ("§c * §7Unknown sub-command§f: §c" + arg1); return; } itr->second (pl, w, reader); } }
/* * /wunload - * * Saves and removes a requested world from the server's online world world * list, optionally removing it from the autoload list as well. * * Permissions: * - command.world.wunload * Needed to execute the command. */ void c_wunload::execute (player *pl, command_reader& reader) { if (!pl->perm ("command.world.wunload")) return; reader.add_option ("autoload", "a"); if (!reader.parse (this, pl)) return; if (reader.no_args () || reader.arg_count () > 1) { this->show_summary (pl); return; } std::string world_name = reader.arg (0); world *wr = pl->get_server ().find_world (world_name.c_str ()); if (!wr) { if (reader.opt ("autoload")->found ()) { if (remove_from_autoload (pl->get_server (), world_name)) pl->message ("§eWorld §b" + world_name + " §ehas been removed from the autoload list§f."); else pl->message ("§cWorld §7" + world_name + " §cis not in the autoload list§7."); } else pl->message ("§c * §7World §b" + world_name + " §7is not loaded§f."); return; } else if (wr == pl->get_server ().get_main_world ()) { pl->message ("§c * §7You can not unload the main world§f!"); return; } world_name.assign (wr->get_name ()); // transfer all players to the server's main world. std::vector<player *> to_transfer; wr->get_players ().populate (to_transfer); for (player *pl : to_transfer) pl->join_world (pl->get_server ().get_main_world ()); pl->get_server ().remove_world (wr); if (reader.opt ("autoload")->found ()) { if (remove_from_autoload (pl->get_server (), world_name)) pl->message ("§eWorld §b" + world_name + " §ehas been removed from the autoload list§f."); else pl->message ("§cWorld §7" + world_name + " §cis not in the autoload list§7."); } pl->get_server ().get_players ().message ( "§cWorld §4" + world_name + " §chas been unloaded§c!"); }
/* * /players * * Displays a list of online players. * * Permissions: * - command.info.players * Needed to execute the command. */ void c_players::execute (player *pl, command_reader& reader) { if (!pl->perm (this->get_exec_permission ())) return; if (!reader.parse (this, pl)) return; auto& players = pl->get_server ().get_players (); std::ostringstream ss; ss << "§eThere " << ((players.count () == 1) ? "is" : "are") << " currently §b" << players.count () << " §eplayer" << ((players.count () == 1) ? "" : "s") << " online§f:"; pl->message (ss.str ()); server &srv = pl->get_server (); group_manager &gman = srv.get_groups (); // create a sorted list of groups (in descending values of power) std::vector<group *> group_list; for (auto itr = gman.begin (); itr != gman.end (); ++itr) group_list.push_back (itr->second); std::sort (group_list.begin (), group_list.end (), [] (const group *a, const group *b) -> bool { return (*a) > (*b); }); for (group *grp : group_list) { std::vector<player *> vec; players.all ( [&vec, grp] (player *pl) { if (pl->get_rank ().main () == grp) vec.push_back (pl); }); if (!vec.empty ()) { ss.str (std::string ()); ss << "§" << grp->color << " " << grp->name << _suffix (grp->name) << " §e(§7" << vec.size () << "§e): §7"; for (player *pl : vec) ss << pl->get_username () << " "; pl->message_spaced (ss.str ()); } } }
/* * /portal - * * Turns blocks in the user's selected area to portals. * * Permissions: * - command.world.portal * Needed to execute the command. * - command.world.portal.interworld * Needed to place portals between different worlds. */ void c_portal::execute (player *pl, command_reader& reader) { if (!pl->perm (this->get_exec_permission ())) return; if (!reader.parse (this, pl)) return; if (reader.no_args ()) { pl->message ("§c * §7Usage§f: §e/portal §ctarget-block §8[§creplace-block§8]"); return; } std::string& target_block_str = reader.next ().as_str (); if (sutils::iequals (target_block_str, "exit")) { _finish_portal (pl); return; } else if (sutils::iequals (target_block_str, "cancel")) { _cancel_portal (pl); return; } else { portal_data *data = static_cast<portal_data *> (pl->get_data ("portal")); if (data) { pl->message ("§c * §7Type §c/portal cancel §7to cancel your previous portal§c."); return; } } if (pl->selections.empty ()) { pl->message ("§c * §7You§f'§7re not selecting anything§f."); return; } world_selection *sel = pl->curr_sel; world *w = pl->get_world (); blocki target_block; if (!(target_block = sutils::to_block (target_block_str)).valid ()) { pl->message ("§c * §7Invalid block§f: §c" + target_block_str); return; } blocki replace_block = target_block; if (reader.has_next ()) { std::string& replace_block_str = reader.next ().as_str (); if (!(replace_block = sutils::to_block (replace_block_str)).valid ()) { pl->message ("§c * §7Invalid block§f: §c" + replace_block_str); return; } } if (!pl->get_world ()->security ().can_build (pl)) { pl->message ("§4 * §cYou are not allowed to build here§4."); return; } int blocks = 0; sparse_edit_stage *es = new sparse_edit_stage (pl->get_world ()); portal *ptl = new portal (); block_pos smin = sel->min (), smax = sel->max (); if (smin.y < 0) smin.y = 0; if (smin.y > 255) smin.y = 255; if (smax.y < 0) smax.y = 0; if (smax.y > 255) smax.y = 255; for (int x = smin.x; x <= smax.x; ++x) for (int y = smin.y; y <= smax.y; ++y) for (int z = smin.z; z <= smax.z; ++z) { if (!w->in_bounds (x, y, z)) continue; if (sel->contains (x, y, z)) { block_data bd = w->get_block (x, y, z); if (bd.id == target_block.id && bd.meta == target_block.meta) { es->set (x, y, z, replace_block.id, replace_block.meta, BE_PORTAL); ptl->affected.emplace_back (x, y, z); ++ blocks; } } } ptl->calc_bounds (); portal_data *data = new portal_data {w, es, ptl}; pl->create_data ("portal", data, [] (void *ptr) { delete static_cast<portal_data *> (ptr); }); { std::ostringstream ss; ss << "§7 | §b" << blocks << " §eentrance blocks have been marked."; pl->message (ss.str ()); pl->message ("§7 | §eType §c/portal exit §eto complete the portal."); pl->message ("§7 | §eIf you wish to cancel the portal, type §c/portal cancel"); } }
/* * /gm - * * Changes the gamemode of the executor or of a specified player. * * Permissions: * - command.admin.gm * Needed to execute the command. */ void c_gm::execute (player *pl, command_reader& reader) { if (!pl->perm ("command.admin.gm")) return; if (!reader.parse (this, pl)) return; if (reader.no_args () || reader.arg_count () > 2) { this->show_summary (pl); return; } player *target = pl; if (reader.arg_count () == 2) { std::string& plname = reader.next ().as_str (); target = pl->get_server ().get_players ().find (plname.c_str ()); if (!target) { pl->message ("§c * §7No such player§f: §c" + plname); return; } } std::string& gmstr = reader.next ().as_str (); gamemode_type gm = GT_SURVIVAL; if (gmstr.size () == 1) { switch (gmstr[0]) { case 's': break; case 'c': gm = GT_CREATIVE; break; //case 'a': gm = GT_ADVENTURE; break; default: pl->message ("§c * §7Invalid gamemode type§f: §c" + gmstr); return; } } else { if (sutils::iequals (gmstr, "survival")) ; else if (sutils::iequals (gmstr, "creative")) gm = GT_CREATIVE; //else if (sutils::iequals (gmstr, "adventure")) // gm = GT_ADVENTURE; else { pl->message ("§c * §7Invalid gamemode type§f: §c" + gmstr); return; } } if (gm == target->gamemode ()) { if (pl == target) target->message ("§c * §7You already have that gamemode set§f."); else { std::ostringstream ss; ss << "§c * §7" << target->get_colored_username () << " §7already has that gamemode set§f."; target->message (ss.str ()); } return; } const char *gm_name = (gm == GT_SURVIVAL) ? "survival" : ((gm == GT_CREATIVE) ? "creative" : "adventure"); if (pl != target) { std::ostringstream ss; ss << target->get_colored_username () << " §egamemode has been set to§f: §4" << gm_name; pl->message (ss.str ()); } target->change_gamemode (gm); /* // Commented out due to Minecraft's ugly "Your gamemode has been updated." // message. std::ostringstream ss; ss << "§6Your gamemode has been set to§f: §c" << gm_name; target->message (ss.str ()); */ }
/* /kick * * Kicks a player from the server. * * Permissions: * - command.admin.kick * Needed to execute the command. */ void c_kick::execute (player *pl, command_reader& reader) { if (!pl->perm (this->get_exec_permission ())) return; reader.add_option ("message", "m", 1, 1); if (!reader.parse (this, pl)) return; if (reader.no_args ()) { this->show_summary (pl); return; } std::string& target_name = reader.next ().as_str (); std::string reason = reader.has_next () ? reader.all_after (0) : "No reason specified"; std::string kick_msg = "§c"; { auto opt = reader.opt ("message"); if (opt->found ()) kick_msg.append (opt->arg (0).as_str ()); else kick_msg.append ("You have been kicked from the server"); } player *target = pl->get_server ().get_players ().find (target_name.c_str ()); if (!target) { pl->message ("§c * §7No such player§f: §c" + target_name); return; } else if (target->bad ()) return; server& srv = pl->get_server (); // record kick { auto& conn = pl->get_server ().sql ().pop (); try { sqlops::record_kick (conn, target->get_username (), pl->get_username (), reason.c_str ()); } catch (const std::exception& ex) { pl->message ("§4 * §cAn error has occurred while recording kick message"); } pl->get_server ().sql ().push (conn); std::ostringstream ss; ss << "§7 | §eRecorded kick message§7: §c\"" << reason << "§c\""; pl->message (ss.str ()); } { std::ostringstream ss; ss << "§4 > " << target->get_colored_nickname () << " §chas been kicked by " << pl->get_colored_nickname () << "§c!"; srv.get_players ().message (ss.str ()); } target->kick (kick_msg.c_str (), reason.c_str ()); }
/* * /sphere - * * Draws a three-dimensional sphere centered at a point. * * Permissions: * - command.draw.sphere * Needed to execute the command. */ void c_sphere::execute (player *pl, command_reader& reader) { if (!pl->perm (this->get_exec_permission ())) return; reader.add_option ("fill", "f"); if (!reader.parse (this, pl)) return; if (reader.no_args () || reader.arg_count () > 3) { this->show_summary (pl); return; } bool do_fill = reader.opt ("fill")->found (); std::string& str = reader.next ().as_str (); if (!sutils::is_block (str)) { pl->message ("§c * §7Invalid block§f: §c" + str); return; } blocki bl = sutils::to_block (str); if (bl.id == BT_UNKNOWN) { pl->message ("§c * §7Unknown block§f: §c" + str); return; } int radius = -1; if (reader.has_next ()) { command_reader::argument arg = reader.next (); if (!arg.is_int ()) { pl->message ("§c * §7Usage§f: §e/sphere §cblock §8[§cradius§8]"); return; } radius = arg.as_int (); if (radius <= 0) { pl->message ("§c * §7Radius must be greater than zero.§f"); return; } } sphere_data *data = new sphere_data {bl, radius, do_fill}; pl->create_data ("sphere", data, [] (void *ptr) { delete static_cast<sphere_data *> (ptr); }); pl->get_nth_marking_callback ((radius == -1) ? 2 : 1) += on_blocks_marked; std::ostringstream ss; ss << "§8Sphere §7("; if (radius != -1) ss << "§8Radius§7: §b" << radius << "§7, "; ss << "§8Block§7: §b" << str << "§7):"; pl->message (ss.str ()); ss.str (std::string ()); ss.clear (); ss << "§8 * §7Please mark §b" << ((radius == -1) ? 2 : 1) << " §7block" << ((radius == -1) ? "s" : "") << "§7."; pl->message (ss.str ()); }
/* /rank * * Changes the rank of a specified player. * * Permissions: * - command.admin.rank * Needed to execute the command. */ void c_rank::execute (player *pl, command_reader& reader) { if (!pl->perm (this->get_exec_permission ())) return; reader.add_option ("quiet", "q"); if (!reader.parse (this, pl)) return; if (reader.arg_count () != 2) { this->show_summary (pl); return; } bool quiet = reader.opt ("quiet")->found (); enum { ACT_RANK, ACT_PROMOTE, ACT_DEMOTE, } action = ACT_RANK; std::string target_name; rank new_rank; std::string arg1 = reader.next (); if (sutils::iequals (arg1, "promote")) { action = ACT_PROMOTE; target_name = reader.next ().as_str (); } else if (sutils::iequals (arg1, "demote")) { action = ACT_DEMOTE; target_name = reader.next ().as_str (); } else { target_name = arg1; std::string rank_str = reader.next (); if (sutils::iequals (rank_str, "up")) action = ACT_PROMOTE; else if (sutils::iequals (rank_str, "down")) action = ACT_DEMOTE; else { try { new_rank.set (rank_str.c_str (), pl->get_server ().get_groups ()); } catch (const std::exception& str) { pl->message ("§c * §7Invalid rank§f: §c" + rank_str); return; } } } player *target = nullptr; sqlops::player_info pinf; { soci::session sql (pl->get_server ().sql_pool ()); if (!sqlops::player_data (sql, target_name.c_str (), pl->get_server (), pinf)) { pl->message ("§c * §7Unknown player§f: §c" + target_name); return; } target_name.assign (pinf.name); target = pl->get_server ().get_players ().find (target_name.c_str ()); if (action == ACT_PROMOTE || action == ACT_DEMOTE) { if (!get_next_rank (pl, pinf.rnk, new_rank, action == ACT_PROMOTE)) return; } if (!pl->is_op ()) { if (target_name == pl->get_username ()) { pl->message ("§c * §7You cannot change your own rank§c."); return; } else if (pinf.rnk >= pl->get_rank ()) { pl->message ("§c * §7You cannot change the rank of someone higher than you§c."); return; } else if (new_rank >= pl->get_rank ()) { pl->message ("§c * §7You cannot give a player a rank that is higher than yours§c."); return; } } try { std::string rank_str; new_rank.get_string (rank_str); sqlops::modify_player_rank (sql, target_name.c_str (), rank_str.c_str ()); } catch (const std::exception& ex) { pl->message ("§c * §4Failed to update database§c."); } // update the player's in-game status. if (target) { target->set_rank (new_rank); if (!quiet) { group *main = new_rank.main (); std::ostringstream ss; ss << "§9 > §" << pinf.rnk.main ()->color << pinf.nick << "§7's rank has been set to" //<< (is_vowel (main->name[0]) ? "n" : "") << " §" << main->color << main->name << "§7!"; pl->get_server ().get_players ().message (ss.str ()); } } { std::ostringstream ss; ss << "§7 | The database has been updated."; pl->message (ss.str ()); } } }
/* * /wcreate - * * Creates a new world, and if requested, loads it into the current world * list. * * Permissions: * - command.world.wcreate * Needed to execute the command. */ void c_wcreate::execute (player *pl, command_reader& reader) { if (!pl->perm ("command.world.wcreate")) return; reader.add_option ("load", "l"); reader.add_option ("width", "w", true, true); reader.add_option ("depth", "d", true, true); reader.add_option ("provider", "p", true, true); reader.add_option ("generator", "g", true, true); reader.add_option ("seed", "s", true, true); if (!reader.parse (this, pl)) return; if (reader.no_args () || reader.arg_count () > 1) { this->show_summary (pl); return; } //---- /* * Parse arguments: */ // world name std::string& world_name = reader.arg (0); if (!world::is_valid_name (world_name.c_str ())) { pl->message ("§c * §eWorld names must be under §a32 §echaracters long and " "may only contain alpha§f-§enumeric characters§f, §edots§f, " "§ehyphens and underscores§f."); return; } // world width int world_width = 0; auto opt_width = reader.opt ("width"); if (opt_width->found ()) { auto& arg = opt_width->arg (0); if (!arg.is_int ()) { pl->message ("§c * §eArgument to flag §c--width §emust be an integer§f."); return; } world_width = arg.as_int (); if (world_width < 0) world_width = 0; } // world depth int world_depth = 0; auto opt_depth = reader.opt ("depth"); if (opt_depth->found ()) { auto& arg = opt_depth->arg (0); if (!arg.is_int ()) { pl->message ("§c * §eArgument to flag §c--depth §emust be an integer§f."); return; } world_depth = arg.as_int (); if (world_depth < 0) world_depth = 0; } // world provider std::string provider_name ("hw"); auto opt_prov = reader.opt ("provider"); if (opt_prov->found ()) { auto& arg = opt_prov->arg (0); provider_name.assign (arg.as_str ()); } // world generator std::string gen_name ("flatgrass"); auto opt_gen = reader.opt ("generator"); if (opt_gen->found ()) { auto& arg = opt_gen->arg (0); gen_name.assign (arg.as_str ()); } // generator seed int gen_seed = std::chrono::duration_cast<std::chrono::milliseconds> ( std::chrono::high_resolution_clock::now ().time_since_epoch ()).count () & 0x7FFFFFFF; auto opt_seed = reader.opt ("seed"); if (opt_seed->found ()) { auto& arg = opt_seed->arg (0); if (arg.is_int ()) gen_seed = arg.as_int (); else gen_seed = std::hash<std::string> () (arg.as_str ()) & 0x7FFFFFFF; } // load world bool load_world = reader.opt ("load")->found (); //---- if (load_world && (pl->get_server ().find_world (world_name.c_str ()) != nullptr)) { pl->message ("§c * §eA world with the same name is already loaded§f."); return; } world_generator *gen = world_generator::create (gen_name.c_str (), gen_seed); if (!gen) { pl->message ("§c * §eInvalid world generator§f: §c" + gen_name); return; } world_provider *prov = world_provider::create (provider_name.c_str (), "data/worlds", world_name.c_str ()); if (!prov) { pl->message ("§c * §eInvalid world provider§f: §c" + provider_name); delete gen; return; } { std::ostringstream ss; pl->message ("§eCreating a new world with the name of §a" + world_name + "§f:"); ss << "§eWorld dimensions§f: §c"; if (world_width == 0) ss << "§binf"; else ss << "§a" << world_width; ss << " §ex §a256 §ex "; if (world_depth == 0) ss << "§binf"; else ss << "§a" << world_depth; pl->message (ss.str ()); ss.clear (); ss.str (std::string ()); if ((world_width == 0) || (world_depth == 0)) ss << "§eEstimated size §f(§ewhen full§f): §cinfinite"; else { double est_kb = ((world_width * world_depth) / 256) * 7.2375 + 49.7; ss.clear (); ss.str (std::string ()); ss << "§eEstimated size §f(§ewhen full§f): §c~"; if (est_kb >= 1024.0) ss << (est_kb / 1024.0) << "MB"; else ss << est_kb << "KB"; } pl->message (ss.str ()); ss.clear (); ss.str (std::string ()); ss << "§eGenerator§f: §b" << gen_name << "§f, §eProvider§f: §b" << provider_name; pl->message (ss.str ()); ss.clear (); ss.str (std::string ()); ss << "§eWorld seed§f: §a" << gen_seed; pl->message (ss.str ()); } world *wr = new world (pl->get_server (), world_name.c_str (), pl->get_logger (), gen, prov); wr->set_width (world_width); wr->set_depth (world_depth); wr->prepare_spawn (10, true); wr->save_all (); if (load_world) { if (!pl->get_server ().add_world (wr)) { delete wr; pl->message ("§cFailed to load world§7."); } wr->start (); pl->get_server ().get_players ().message ( "§3World §b" + world_name + " §3has been loaded§b!"); } else { delete wr; } }
/* * /money - * * Displays the amount of money a player has. * * Permissions: * - command.info.money * Needed to execute the command. * - command.info.money.others * Required to display the amount of money _other_ players have. * - command.info.money.pay * Whether the player is allowed to send money out of their own account. * - command.info.money.give * Whether the player is allowed to give money to players _wihout_ * taking it out of their own account. * - command.info.money.set * Required to modify a player's balance directly. */ void c_money::execute (player *pl, command_reader& reader) { if (!pl->perm (this->get_exec_permission ())) return; if (!reader.parse (this, pl)) return; bool someone_else = false; std::string target_name; if (!reader.has_next ()) { target_name.assign (pl->get_username ()); } else { std::string& a = reader.next (); if (sutils::iequals (a, "pay")) { do_pay (pl, reader); return; } else if (sutils::iequals (a, "give")) { do_give (pl, reader); return; } else if (sutils::iequals (a, "take")) { do_take (pl, reader); return; } else if (sutils::iequals (a, "set")) { do_set (pl, reader); return; } else { target_name = a; someone_else = true; } } // // /money [player] // std::ostringstream ss; if (someone_else) { if (!pl->has ("command.info.money.others")) { pl->message ("§c * §7You are not allowed to do that§c."); return; } if (sutils::iequals (target_name, pl->get_username ())) ss << "§2Balance§8: §a$§f" << utils::format_number (pl->bal, 2); else { player *target = pl->get_server ().get_players ().find (target_name.c_str ()); if (target) ss << target->get_colored_username () << "§e's balance§f: §a$§f" << utils::format_number (target->bal, 2); else { soci::session sql (pl->get_server ().sql_pool ()); try { if (!sqlops::player_exists (sql, target_name.c_str ())) { pl->message ("§c * §7No such player§f: §c" + target_name); return; } ss << sqlops::player_colored_name (sql, target_name.c_str (), pl->get_server ()) << "§2's balance§f: §a$§f" << utils::format_number (sqlops::get_money (sql, target_name.c_str ()), 2); } catch (const std::exception& ex) { pl->message ("§4 * §cAn error has occurred§4."); return; } } } } else ss << "§2Balance§f: §a$§f" << utils::format_number (pl->bal, 2); pl->message (ss.str ()); }
/* /unban * * Revokes a permanent ban from a specified player. * * Permissions: * - command.admin.unban * Needed to execute the command. */ void c_unban::execute (player *pl, command_reader& reader) { if (!pl->perm (this->get_exec_permission ())) return; if (!reader.parse (this, pl)) return; if (reader.no_args ()) { this->show_summary (pl); return; } std::string target_name = reader.next ().as_str (); std::string reason = reader.has_next () ? reader.all_after (0) : "No reason specified"; player *target = pl->get_server ().get_players ().find (target_name.c_str ()); if (target) { if (target == pl) { pl->message ("§c * §7You are not banned§c."); return; } pl->message ("§c * §7That player is online§c..."); return; } std::string target_colored_nick; server& srv = pl->get_server (); // record unban { auto& conn = pl->get_server ().sql ().pop (); try { if (!sqlops::player_exists (conn, target_name.c_str ())) { pl->message ("§c * §7No such player§f: §c" + target_name); pl->get_server ().sql ().push (conn); return; } if (!sqlops::is_banned (conn, target_name.c_str ())) { pl->message ("§c * §7Player is not banned§c."); pl->get_server ().sql ().push (conn); return; } target_name = sqlops::player_name (conn, target_name.c_str ()); target_colored_nick = sqlops::player_colored_nick (conn, target_name.c_str (), pl->get_server ()); sqlops::modify_ban_status (conn, target_name.c_str (), false); sqlops::record_unban (conn, target_name.c_str (), pl->get_username (), reason.c_str ()); } catch (const std::exception& ex) { pl->message ("§4 * §cAn error has occurred while recording unban message"); } pl->get_server ().sql ().push (conn); std::ostringstream ss; ss << "§7 | §eRecorded unban message§7: §c\"" << reason << "§c\""; pl->message (ss.str ()); } { std::ostringstream ss; ss << "§8 > " << target_colored_nick << " §8has been unbanned by " << pl->get_colored_nickname () << "§8!"; srv.get_players ().message (ss.str ()); } }
/* * /ellipse - * * Draws a two-dimensional ellipse centered at a point. * * Permissions: * - command.draw.ellipse * Needed to execute the command. */ void c_ellipse::execute (player *pl, command_reader& reader) { if (!pl->perm (this->get_exec_permission ())) return; reader.add_option ("fill", "f"); if (!reader.parse (this, pl)) return; if (reader.no_args () || reader.arg_count () > 4) { this->show_summary (pl); return; } bool do_fill = reader.opt ("fill")->found (); std::string& str = reader.next ().as_str (); if (!sutils::is_block (str)) { pl->message ("§c * §7Invalid block§f: §c" + str); return; } blocki bl = sutils::to_block (str); if (bl.id == BT_UNKNOWN) { pl->message ("§c * §7Unknown block§f: §c" + str); return; } draw_ops::plane pn = draw_ops::XZ_PLANE; if (reader.has_next ()) { std::string& str = reader.next ().as_str (); if (sutils::iequals (str, "XZ") || sutils::iequals (str, "ZX")) ; else if (sutils::iequals (str, "YX") || sutils::iequals (str, "XY")) pn = draw_ops::YX_PLANE; else if (sutils::iequals (str, "YZ") || sutils::iequals (str, "ZY")) pn = draw_ops::YZ_PLANE; else { pl->message ("§c * §7The plane must be one of§f: §cXZ, YX, YZ§f."); return; } } int a = -1, b = -1; if (reader.has_next ()) { command_reader::argument a_arg = reader.next (); if (!a_arg.is_int ()) { pl->message ("§c * §7Usage§c: §e/ellipe §cblock §8[§cplane§8] §8[§cradx radz§8]."); return; } a = a_arg.as_int (); if (!reader.has_next ()) b = a; else { command_reader::argument b_arg = reader.next (); if (!b_arg.is_int ()) { pl->message ("§c * §7Usage§c: §e/ellipe §cblock §8[§cplane§8] §8[§cradx radz§8]."); return; } b = b_arg.as_int (); } if (a < 1 || a > 2000 || b < 1 || b > 2000) { pl->message ("§c * §7Radii must be in the range of 1-2000."); return; } } ellipse_data *data = new ellipse_data {bl, pn, do_fill, a, b}; pl->create_data ("ellipse", data, [] (void *ptr) { delete static_cast<ellipse_data *> (ptr); }); pl->get_nth_marking_callback ((a == -1) ? 3 : 1) += on_blocks_marked; std::ostringstream ss; ss << "§8Ellipse §7(§8Plane§7: §b"; switch (pn) { case draw_ops::XZ_PLANE: ss << "XZ§7, "; break; case draw_ops::YX_PLANE: ss << "YX§7, "; break; case draw_ops::YZ_PLANE: ss << "YZ§7, "; break; } if (a != -1) ss << "§8A§7: §b" << a << "§7, "; if (b != -1) ss << "§8B§7: §b" << b << "§7, "; ss << "§8Block§7: §b" << str << "§7):"; pl->message (ss.str ()); ss.str (std::string ()); ss.clear (); ss << "§8 * §7Please mark §b" << ((a == -1) ? 3 : 1) << " §7blocks§7."; pl->message (ss.str ()); }
/* * /wload - * * Loads a world from disk onto the server's world list. Doing this enables * players to go to that world using /w. * * Permissions: * - command.world.wload * Needed to execute the command. */ void c_wload::execute (player *pl, command_reader& reader) { if (!pl->perm ("command.world.wload")) return; reader.add_option ("autoload", "a"); if (!reader.parse (this, pl)) return; if (reader.no_args () || reader.arg_count () > 1) { this->show_summary (pl); return; } std::string& world_name = reader.arg (0); world *twr = pl->get_server ().find_world (world_name.c_str ()); if (twr) { if (reader.opt ("autoload")->found ()) { if (add_to_autoload (pl->get_server (), world_name)) pl->message ("§eWorld §b" + world_name + " §ehas been added to the autoload list§f."); else pl->message ("§cWorld §7" + world_name + " §cis already autoloaded§7."); } else pl->message ("§c * §7World §b" + world_name + " §7is already loaded§f."); return; } std::string prov_name = world_provider::determine ("data/worlds", world_name.c_str ()); if (prov_name.empty ()) { pl->message ("§c * §7World §b" + world_name + " §7does not exist§f."); return; } world_provider *prov = world_provider::create (prov_name.c_str (), "data/worlds", world_name.c_str ()); if (!prov) { pl->message ("§c * ERROR§f: §eInvalid provider§f."); return; } const world_information& winf = prov->info (); world_generator *gen = world_generator::create (winf.generator.c_str (), winf.seed); if (!gen) { pl->message ("§c * ERROR§f: §eInvalid generator§f."); return; } pl->get_logger () () << "Loading world \"" << world_name << "\"" << std::endl; world *wr = new world (pl->get_server (), world_name.c_str (), pl->get_logger (), gen, prov); wr->set_size (winf.width, winf.depth); wr->set_spawn (winf.spawn_pos); wr->prepare_spawn (10, false); wr->start (); if (!pl->get_server ().add_world (wr)) { pl->get_logger () (LT_ERROR) << "Failed to load world \"" << world_name << "\": Already loaded." << std::endl; pl->message ("§c * ERROR§f: §eFailed to load world§f."); delete wr; return; } // add to autoload list if (reader.opt ("autoload")->found ()) { if (add_to_autoload (pl->get_server (), world_name)) pl->message ("§eWorld §b" + world_name + " §ehas been added to the autoload list§f."); else pl->message ("§cWorld §7" + world_name + " §cis already autoloaded§7."); } wr->start (); pl->get_server ().get_players ().message ( "§3World §b" + world_name + " §3has been loaded§b!"); }