void connectserv(const char *servername, int serverport, const char *serverpassword) { if(connpeer) { conoutf("aborting connection attempt"); abortconnect(); } if(serverport <= 0) serverport = server::serverport(); ENetAddress address; address.port = serverport; if(servername) { if(strcmp(servername, connectname)) setsvar("connectname", servername); if(serverport != connectport) setvar("connectport", serverport); conoutf("attempting to connect to %s:%d", servername, serverport); if(!resolverwait(servername, &address)) { conoutf("\f3could not resolve server %s", servername); return; } } else { setsvar("connectname", ""); setvar("connectport", 0); conoutf("attempting to connect over LAN"); address.host = ENET_HOST_BROADCAST; } if(!clienthost) { clienthost = enet_host_create(NULL, 2, server::numchannels(), rate*1024, rate*1024); if(!clienthost) { conoutf("\f3could not connect to server"); return; } clienthost->duplicatePeers = 0; } connpeer = enet_host_connect(clienthost, &address, server::numchannels(), 0); enet_host_flush(clienthost); connmillis = totalmillis; connattempts = 0; }
//! The user picks 'upload map' in the GUI. //! First we save the map. Then we call Python, which packages the map //! and uploads it to the correct asset server, then notify the instance we //! are connected to that the map has been updated, which then gets and runs //! that new map. That process causes it to tell all clients of a new map that //! they should get, which makes them get the new version. Among those clients is //! this one, the uploader, which we do not treat differently in that respect. void do_upload() { renderprogress(0.1, "compiling scripts..."); // Make sure the script compiles ok TODO: All scripts, not just the main one REFLECT_PYTHON( get_map_script_filename ); std::string filename = boost::python::extract<std::string>( get_map_script_filename() ); if (!checkCompile(filename)) return; // Save ogz renderprogress(0.3, "generating map..."); save_world(game::getclientmap()); // load_world: ogzname, mname, cname: packages/base/spiral/map.ogz,base/spiral/map,(null) // save_world ogzname, mname, cname: packages//packages.ogz,/packages // Save entities (and backup) renderprogress(0.4, "exporting entities..."); REFLECT_PYTHON( export_entities ); export_entities("entities.json"); // Do the upload renderprogress(0.5, "uploading map..."); REFLECT_PYTHON( upload_map ); upload_map(); // Remember asset REFLECT_PYTHON( get_curr_map_asset_id ); std::string assetId = boost::python::extract<std::string>( get_curr_map_asset_id() ); setsvar("last_uploaded_map_asset", assetId.c_str()); }
void connectserv(const char *name, int port, const char *password) { abortconnect(); if(!port) port = ENG_SERVER_PORT; ENetAddress address; address.port = port; setsvar("serveraddress", ""); setvar("serverconport", 0); if(name && *name) { addserver(name, port); conoutft(CON_MESG, "\faattempting to connect to %s:[%d]", name, port); if(!resolverwait(name, &address)) { conoutft(CON_MESG, "\frcould not resolve host %s", name); connectfail(); return; } setsvar("serveraddress", name); setvar("serverconport", port); } else { conoutft(CON_MESG, "\faattempting to connect to a local server"); address.host = ENET_HOST_BROADCAST; } if(!clienthost) clienthost = enet_host_create(NULL, 2, server::numchannels(), rate, rate); if(clienthost) { connpeer = enet_host_connect(clienthost, &address, server::numchannels(), 0); enet_host_flush(clienthost); connmillis = totalmillis; connattempts = 0; client::connectattempt(name ? name : "", port, password ? password : "", address); conoutft(CON_MESG, "\fgconnecting to %s:[%d]", name != NULL ? name : "local server", port); } else { conoutft(CON_MESG, "\frfailed creating client socket"); connectfail(); } }
static PyObject *setVariable(PyObject *self, PyObject *args) { char *variableName; char *value; if(!PyArg_ParseTuple(args, "ss", &variableName, &value)) return 0; static string scmdval; scmdval[0] = 0; ident *id = idents->access(variableName); if(id) { switch(id->type) { case ID_VAR: { int ret = parseint(value); if(ret < id->minval || ret > id->maxval) { PyErr_Format(PyExc_ValueError, id->flags&IDF_HEX ? (id->minval <= 255 ? "valid range for %s is %d..0x%X" : "valid range for %s is 0x%X..0x%X") : "valid range for %s is %d..%d", variableName, id->minval, id->maxval); return 0; } setvar(variableName, ret); break; } case ID_FVAR: { float ret = parsefloat(value); if(ret < id->minvalf || ret > id->maxvalf) { PyErr_Format(PyExc_ValueError, "valid range for %s is %s..%s", variableName, floatstr(id->minvalf), floatstr(id->maxvalf)); return 0; } setfvar(variableName, ret); break; } case ID_SVAR: { setsvar(variableName, value); break; } default: { PyErr_SetString(PyExc_ValueError, "Unknown server variable type"); return 0; break; } } printf("hopefully to set: %s to %s\n", variableName, value); Py_INCREF(Py_None); return Py_None; } PyErr_SetString(PyExc_ValueError, "Invalid variable specified"); return 0; }
// Get instance data and create a GUI for it void show_instances() { REFLECT_PYTHON( get_possible_instances ); boost::python::object instances = get_possible_instances(); REFLECT_PYTHON( None ); if (instances == None) { setsvar("error_message", "Could not get the list of instances"); showgui("error"); return; } std::string command = "newgui instances [\n" " guitext \"Pick an instance to enter:\"\n" " guibar\n"; int numInstances = boost::python::extract<int>(instances.attr("__len__")()); for (int i = 0; i < numInstances; i++) { boost::python::object instance = instances[i]; std::string instance_id = boost::python::extract<std::string>(instance.attr("__getitem__")("instance_id")); std::string event_name = boost::python::extract<std::string>(instance.attr("__getitem__")("event_name")); assert( Utility::validateAlphaNumeric(instance_id) ); assert( Utility::validateAlphaNumeric(event_name, " (),.;") ); // XXX: Allow more than alphanumeric+spaces: ()s, .s, etc. command += " guibutton \"" + event_name + "\" \"connect_to_instance " + instance_id + "\"\n"; } command += "]\n"; command += "showgui instances\n"; Logging::log(Logging::DEBUG, "Instances GUI: %s\r\n", command.c_str()); execute(command.c_str()); }
// Sets up a GUI for editing an entity's state data void prepare_entity_gui() { GuiControl::EditedEntity::stateData.clear(); GuiControl::EditedEntity::sortedKeys.clear(); GuiControl::EditedEntity::currEntity = TargetingControl::targetLogicEntity; if (GuiControl::EditedEntity::currEntity->isNone()) { Logging::log(Logging::DEBUG, "No entity to show the GUI for\r\n"); return; } int uniqueId = GuiControl::EditedEntity::currEntity->getUniqueId(); ScriptValuePtr stateData = ScriptEngineManager::runScript( "getEntity(" + Utility::toString(uniqueId) + ").createStateDataDict()" ); ScriptValuePtr keys = ScriptEngineManager::getGlobal()->call("keys", stateData); num_entity_gui_fields = keys->getPropertyInt("length"); // Save the stateData, to see what changed and what didn't for (int i = 0; i < num_entity_gui_fields; i++) { std::string key = keys->getPropertyString( Utility::toString(i) ); std::string guiName = ScriptEngineManager::getGlobal()->call( "__getVariableGuiName", ScriptValueArgs().append(uniqueId).append(key) )->getString(); std::string value = stateData->getPropertyString(key); GuiControl::EditedEntity::stateData.insert( GuiControl::EditedEntity::StateDataMap::value_type( key, std::pair<std::string, std::string>( guiName, value ) ) ); // std::string a = python::extract<std::string>( keys[i] ); // std::string b = python::extract<std::string>( pythonStateData[keys[i]] ); GuiControl::EditedEntity::sortedKeys.push_back( key ); } sort( GuiControl::EditedEntity::sortedKeys.begin(), GuiControl::EditedEntity::sortedKeys.end() ); // So order is always the same for (int i = 0; i < num_entity_gui_fields; i++) { std::string key = GuiControl::EditedEntity::sortedKeys[i]; std::string guiName = GuiControl::EditedEntity::stateData[key].first; std::string value = GuiControl::EditedEntity::stateData[key].second; std::string fieldName = "entity_gui_field_" + Utility::toString(i); std::string labelName = "entity_gui_label_" + Utility::toString(i); setsvar((char*)fieldName.c_str(), (char*)value.c_str()); setsvar((char*)labelName.c_str(), (char*)guiName.c_str()); } // Title std::string title = GuiControl::EditedEntity::currEntity->scriptEntity->getPropertyString("_class"); title = Utility::toString(uniqueId) + ": " + title; setsvar((char*)"entity_gui_title", (char*)title.c_str()); // Create the gui std::string command = "newgui entity [\n" " guitext $entity_gui_title\n" " guibar\n"; for (int i = 0; i < num_entity_gui_fields; i++) { std::string sI = Utility::toString(i); std::string key = GuiControl::EditedEntity::sortedKeys[i]; std::string value = GuiControl::EditedEntity::stateData[key].second; if (value.size() > 50) { Logging::log(Logging::WARNING, "Not showing field '%s' as it is overly large for the GUI\r\n", key.c_str()); continue; // Do not even try to show overly-large items } command += " guilist [\n" " guitext (get_entity_gui_label " + sI + ")\n" " new_entity_gui_field_" + sI + " = (get_entity_gui_value " + sI + ")\n" " guifield new_entity_gui_field_" + sI + " " + Utility::toString((int)value.size()+25) + " [set_entity_gui_value " + sI + " $new_entity_gui_field_" + sI + "] 0\n" " ]\n"; if ((i+1) % 10 == 0) { command += " guitab " + Utility::toString(i) + "\n"; } } command += "]"; // printf("Command: %s\r\n", command.c_str()); execute(command.c_str()); }