aboutsummaryrefslogtreecommitdiff
path: root/src/environment.h
Commit message (Collapse)AuthorAge
* Time: use locks againest312015-11-04
| | | | | | | | | | | | | | | The Atomic implementation was only partially correct, and was very complex. Use locks for sake of simplicity, following KISS principle. Only remaining atomic operation use is time of day speed, because that really is only read + written. Also fixes a bug with m_time_conversion_skew only being decremented, never incremented (Regresion from previous commit). atomic.h changes: * Add GenericAtomic<T> class for non-integral types like floats. * Remove some last remainders from atomic.h of the volatile use.
* Time: Remove serverside getter, and use atomic operationsest312015-11-03
| | | | | | | | It isn't possible to use atomic operations for floats, so don't use them there. Having a lock is good out of other reasons too, because this way the float time and the integer time both match, and can't get different values in a race, e.g. when two setTimeofDay() get executed simultaneously.
* Add DISABLE_CLASS_COPY macro (and use it)kwolekr2015-10-27
| | | | | | | | | Use this macro to disallow copying of an object using the assignment operator or copy constructor. This catches otherwise silent-but-deadly mistakes such as "ServerMap map = env->getMap();" at compile time. If so desired, it is still possible to copy a class, but it now requires an explicit call to memcpy or std::copy.
* Environment: Time of day fixes and add serverside getterest312015-10-27
| | | | | | | | -> Put access to time variables under the time lock. -> Merge both time locks, there is no point to have two locks. -> Fix the lock being released too early in Environment::setTimeOfDay -> Add serverside getter so that you don't have to get the environment if you only have the server
* ABMs: Make catch-up behaviour optionalparamat2015-10-18
| | | | | Default is true for backwards compatibility Update lua_api.txt
* Save and remove player by pointerLoic Blot2015-09-23
| | | | | | Why doing things simple ? Use pointer instead of strings to save players and remove them. Saving players by name does a lookup to find pointer we already have ! Idem with removePlayer Also remove unused removePlayer(peer_id), it's never called
* Little optimization on getAdded/Removed activeobjects per player loop.Loic Blot2015-09-19
| | | | | Use std::queue instead of std::set, we don't need such a heavy container. Don't convert position to int to convert it back to float in the next function.
* Change m_client_event_queue's type to std::queueLoic Blot2015-09-08
| | | | | As indicated in its name, m_client_event_queue should be a queue. Change std::list to std::queue to improve the queue's performance.
* Clean up threadingShadowNinja2015-08-23
| | | | | | | | | | | | | | | | | | | | * Rename everything. * Strip J prefix. * Change UpperCamelCase functions to lowerCamelCase. * Remove global (!) semaphore count mutex on OSX. * Remove semaphore count getter (unused, unsafe, depended on internal API functions on Windows, and used a hack on OSX). * Add `Atomic<type>`. * Make `Thread` handle thread names. * Add support for C++11 multi-threading. * Combine pthread and win32 sources. * Remove `ThreadStarted` (unused, unneeded). * Move some includes from the headers to the sources. * Move all of `Event` into its header (allows inlining with no new includes). * Make `Event` use `Semaphore` (except on Windows). * Move some porting functions into `Thread`. * Integrate logging with `Thread`. * Add threading test.
* SEnv: Remove static_exists from ActiveObjects in deleted blockskwolekr2015-08-16
|
* Optional reconnect functionalityest312015-07-23
| | | | | | Enable the server to request the client to reconnect. This can be done with the now extended minetest.request_shutdown([reason], [reconnect]) setting.
* Kick players when shutting down server and there is a crash due to a Lua ↵nerzhul2015-07-16
| | | | stack exception
* Generic CAO cleanups and renames for clarificationest312015-06-20
| | | | | | | | * Use enum for GENERIC_CMD_* * Rename m_attachements to attachement_parent_ids (public member and clearer name) * Rename GENERIC_CMD_SET_ATTACHMENT to GENERIC_CMD_ATTACH_TO * USHRT_MAX + 1 buffer sizes to prevent overflows as @kahrl suggested * Remove unneccessary m_id from GenericCAO (shadowing protected superclass member for no reason) as @kahrl suggested
* Make attached objects visible in 3rd person viewest312015-06-20
|
* Re-apply 972d17baea81ffe6d508b291ef97207a4822e1da...nerzhul2015-04-22
| | | | but not rename the container. Approved-By est31
* Revert "m_active_object_messages is used like a queue. Use std::queue ↵kwolekr2015-04-21
| | | | | | | | instead of std::list. Also rename to m_active_object_messages_queue" This reverts commit 972d17baea81ffe6d508b291ef97207a4822e1da. The commit being reverted was unauthorized. There had been no discussion, review, or sign-off prior to submittal to upstream.
* m_active_object_messages is used like a queue. Use std::queue instead of ↵Loic Blot2015-04-21
| | | | std::list. Also rename to m_active_object_messages_queue
* Use std::vector instead of std::set for Environment::getObjectsInsideRadiusLoic Blot2015-04-16
| | | | | We are only iterating sequentially, we don't need a set here Also use a vector reference instead of a copy
* Performance improvement: Use std::list instead of std::vector for ↵Loic Blot2015-03-05
| | | | | | request_media, Server::getModNames, Environment::m_simple_objects. * Also remove unused Server::m_modspaths
* ABMHandler and player_collisions use sequential read/write. Switch from ↵Loic Blot2015-03-04
| | | | | | std::list to std::vector * Also remove dead code Map::unloadUnusedData which is dead since a long time
* ASyncRunStep doesn't need to lock when do setTimeOfDaySpeed.Loic Blot2015-03-04
| | | | | * setTimeOfDaySpeed already lock a mutex when modify the value, we don't need to lock all environment. * add a fine grain lock for getTimeOfDay and setTimeOfDay to solve environment multithread modifications on this value
* Change many useless std::list into Environment class (m_players), ABMHandler ↵Loic Blot2015-02-17
| | | | | | and ActiveBlockList::update This improve looping performances.
* Fix all warnings and remove -Wno-unused-but-set cflagkwolekr2015-01-18
|
* Performance of main client loop up to 2x faster In places, up to 3 times fasterCraig Robbins2014-12-07
| | | | | NOTE 1: This does not mean a 2x increase in framerate. Increase in fps may be up to 1-2fps NOTE 2: This local 'caching' of settings is not optimal and an alternative solution will be worked on after 0.4.11 is released
* Replace setting unlimited_player_transfer_distance with player_transfer_distanceSmallJoker2014-11-08
|
* Only keep players loaded while they're connectedShadowNinja2014-06-23
|
* Fix race condition on accessing m_time_of_day_speed causing day night race ↵sapier2014-06-23
| | | | on some architectures
* Speedup attachement handling by replacing vector search by direct array ↵sapier2014-06-23
| | | | access and secondary child lookup vector
* Remove liquid_finite and weatherproller2014-04-18
|
* Fix all warnings reported by clangSfan52014-04-15
|
* Update ABM object counts when triggers add objectsCiaran Gultnieks2014-03-09
| | | | | Also fixes long-standing accuracy issue due to unknown wider object count not being incremented.
* Fix rendering glitches when far from the center of the mapNovatux2014-03-04
|
* ServerEnvironment: Remove direct dependency on EmergeManagerkwolekr2014-02-09
|
* Add player:override_day_night_ratio() for arbitrarily controlling sunlight ↵Perttu Ahola2014-02-01
| | | | brightness
* Add forceloadingNovatux2014-01-11
|
* Make line_of_sight return blocking node positionstujones112013-12-12
|
* Add minetest.swap_nodeNovatux2013-11-30
|
* Weather: Clean up getHeat/getHumidity somewhatkwolekr2013-09-16
|
* Omnicleanup: header cleanup, add ModApiUtil shared between game and mainmenuKahrl2013-08-14
|
* Fix anticheatPerttu Ahola2013-08-03
|
* Weather supportproller2013-07-27
|
* Add set_breath and get_breath to lua API.RealBadAngel2013-07-20
|
* Add drowningPilzAdam2013-06-19
|
* Move scriptapi to separate folder (by sapier)sapier2013-05-25
| | | | | | | | | | | On the lua side, notably minetest.env:<function>(<args>) should now be replaced by minetest.<function>(<args>). The old way is and will stay supported for a long time. Also: Update and clean up lua_api.txt (by celeron55) Move EnvRef to lua and remove add_rat and add_firefly (by kahrl) Add separate src/util/CMakeLists.txt, other minor fixes (by kahrl)
* Add Dijkstra A* and A* without prefetching pathfind algorithmssapier2013-04-06
|
* Fix nick completionPilzAdam2013-04-05
|
* Migrate to STL containers/algorithms.Ilya Zhuravlev2013-03-11
|
* Add emerge.cpp, initial EmergeThread changeskwolekr2013-02-25
| | | | | | | - Neatly placed all emerge related code into a new file, emerge.cpp - Greatly cleaned up the code in EmergeThread::Thread() - Reworked Emerge queue. Now an actual std::queue of v3s16 block positions - Removed the completely unnecessary map of peer ids requesting blocks
* Update Copyright YearsSfan52013-02-24
|
* Change Minetest-c55 to MinetestPilzAdam2013-02-24
|
.ai_protocol = 0; hints.ai_flags = 0; if(g_settings->getBool("enable_ipv6")) { // AF_UNSPEC allows both IPv6 and IPv4 addresses to be returned hints.ai_family = AF_UNSPEC; } else { hints.ai_family = AF_INET; } // Do getaddrinfo() int e = getaddrinfo(name, NULL, &hints, &resolved); if(e != 0) throw ResolveError(gai_strerror(e)); // Copy data if(resolved->ai_family == AF_INET) { struct sockaddr_in *t = (struct sockaddr_in *) resolved->ai_addr; m_addr_family = AF_INET; m_address.ipv4 = *t; } else if(resolved->ai_family == AF_INET6) { struct sockaddr_in6 *t = (struct sockaddr_in6 *) resolved->ai_addr; m_addr_family = AF_INET6; m_address.ipv6 = *t; } else { freeaddrinfo(resolved); throw ResolveError(""); } freeaddrinfo(resolved); } // IP address -> textual representation std::string Address::serializeString() const { // windows XP doesnt have inet_ntop, maybe use better func #ifdef _WIN32 if(m_addr_family == AF_INET) { u8 a, b, c, d; u32 addr; addr = ntohl(m_address.ipv4.sin_addr.s_addr); a = (addr & 0xFF000000) >> 24; b = (addr & 0x00FF0000) >> 16; c = (addr & 0x0000FF00) >> 8; d = (addr & 0x000000FF); return itos(a) + "." + itos(b) + "." + itos(c) + "." + itos(d); } else if(m_addr_family == AF_INET6) { std::ostringstream os; for(int i = 0; i < 16; i += 2) { u16 section = (m_address.ipv6.sin6_addr.s6_addr[i] << 8) | (m_address.ipv6.sin6_addr.s6_addr[i + 1]); os << std::hex << section; if(i < 14) os << ":"; } return os.str(); } else return std::string(""); #else char str[INET6_ADDRSTRLEN]; if (inet_ntop(m_addr_family, (m_addr_family == AF_INET) ? (void*)&(m_address.ipv4.sin_addr) : (void*)&(m_address.ipv6.sin6_addr), str, INET6_ADDRSTRLEN) == NULL) { return std::string(""); } return std::string(str); #endif } struct sockaddr_in Address::getAddress() const { return m_address.ipv4; // NOTE: NO PORT INCLUDED, use getPort() } struct sockaddr_in6 Address::getAddress6() const { return m_address.ipv6; // NOTE: NO PORT INCLUDED, use getPort() } u16 Address::getPort() const { return m_port; } int Address::getFamily() const { return m_addr_family; } bool Address::isIPv6() const { return m_addr_family == AF_INET6; } bool Address::isZero() const { if (m_addr_family == AF_INET) { return m_address.ipv4.sin_addr.s_addr == 0; } else if (m_addr_family == AF_INET6) { static const char zero[16] = {0}; return memcmp(m_address.ipv6.sin6_addr.s6_addr, zero, 16) == 0; } return false; } void Address::setAddress(u32 address) { m_addr_family = AF_INET; m_address.ipv4.sin_family = AF_INET; m_address.ipv4.sin_addr.s_addr = htonl(address); } void Address::setAddress(u8 a, u8 b, u8 c, u8 d) { m_addr_family = AF_INET; m_address.ipv4.sin_family = AF_INET; u32 addr = htonl((a << 24) | (b << 16) | (c << 8) | d); m_address.ipv4.sin_addr.s_addr = addr; } void Address::setAddress(const IPv6AddressBytes *ipv6_bytes) { m_addr_family = AF_INET6; m_address.ipv6.sin6_family = AF_INET6; if (ipv6_bytes) memcpy(m_address.ipv6.sin6_addr.s6_addr, ipv6_bytes->bytes, 16); else memset(m_address.ipv6.sin6_addr.s6_addr, 0, 16); } void Address::setPort(u16 port) { m_port = port; } void Address::print(std::ostream *s) const { if(m_addr_family == AF_INET6) *s << "[" << serializeString() << "]:" << m_port; else *s << serializeString() << ":" << m_port; } /* UDPSocket */ UDPSocket::UDPSocket(bool ipv6) { init(ipv6, false); } bool UDPSocket::init(bool ipv6, bool noExceptions) { if (g_sockets_initialized == false) { dstream << "Sockets not initialized" << std::endl; return false; } // Use IPv6 if specified m_addr_family = ipv6 ? AF_INET6 : AF_INET; m_handle = socket(m_addr_family, SOCK_DGRAM, IPPROTO_UDP); if (socket_enable_debug_output) { dstream << "UDPSocket(" << (int) m_handle << ")::UDPSocket(): ipv6 = " << (ipv6 ? "true" : "false") << std::endl; } if (m_handle <= 0) { if (noExceptions) { return false; } else { throw SocketException("Failed to create socket"); } } setTimeoutMs(0); return true; } UDPSocket::~UDPSocket() { if (socket_enable_debug_output) { dstream << "UDPSocket( " << (int) m_handle << ")::~UDPSocket()" << std::endl; } #ifdef _WIN32 closesocket(m_handle); #else close(m_handle); #endif } void UDPSocket::Bind(Address addr) { if(socket_enable_debug_output) { dstream << "UDPSocket(" << (int) m_handle << ")::Bind(): " << addr.serializeString() << ":" << addr.getPort() << std::endl; } if (addr.getFamily() != m_addr_family) { static const char *errmsg = "Socket and bind address families do not match"; errorstream << "Bind failed: " << errmsg << std::endl; throw SocketException(errmsg); } if(m_addr_family == AF_INET6) { struct sockaddr_in6 address; memset(&address, 0, sizeof(address)); address = addr.getAddress6(); address.sin6_family = AF_INET6; address.sin6_port = htons(addr.getPort()); if(bind(m_handle, (const struct sockaddr *) &address, sizeof(struct sockaddr_in6)) < 0) { dstream << (int) m_handle << ": Bind failed: " << strerror(errno) << std::endl; throw SocketException("Failed to bind socket"); } } else { struct sockaddr_in address; memset(&address, 0, sizeof(address)); address = addr.getAddress(); address.sin_family = AF_INET; address.sin_port = htons(addr.getPort()); if (bind(m_handle, (const struct sockaddr *) &address, sizeof(struct sockaddr_in)) < 0) { dstream << (int)m_handle << ": Bind failed: " << strerror(errno) << std::endl; throw SocketException("Failed to bind socket"); } } } void UDPSocket::Send(const Address & destination, const void * data, int size) { bool dumping_packet = false; // for INTERNET_SIMULATOR if(INTERNET_SIMULATOR) dumping_packet = myrand() % INTERNET_SIMULATOR_PACKET_LOSS == 0; if(socket_enable_debug_output) { // Print packet destination and size dstream << (int)m_handle << " -> "; destination.print(&dstream); dstream << ", size=" << size; // Print packet contents dstream << ", data="; for(int i = 0; i < size && i < 20; i++) { if(i % 2 == 0) dstream << " "; unsigned int a = ((const unsigned char *)data)[i]; dstream << std::hex << std::setw(2) << std::setfill('0') << a; } if(size > 20) dstream << "..."; if(dumping_packet) dstream << " (DUMPED BY INTERNET_SIMULATOR)"; dstream << std::endl; } if(dumping_packet) { // Lol let's forget it dstream << "UDPSocket::Send(): INTERNET_SIMULATOR: dumping packet." << std::endl; return; } if(destination.getFamily() != m_addr_family) throw SendFailedException("Address family mismatch"); int sent; if(m_addr_family == AF_INET6) { struct sockaddr_in6 address = destination.getAddress6(); address.sin6_port = htons(destination.getPort()); sent = sendto(m_handle, (const char *)data, size, 0, (struct sockaddr *)&address, sizeof(struct sockaddr_in6)); } else { struct sockaddr_in address = destination.getAddress(); address.sin_port = htons(destination.getPort()); sent = sendto(m_handle, (const char *)data, size, 0, (struct sockaddr *)&address, sizeof(struct sockaddr_in)); } if(sent != size) throw SendFailedException("Failed to send packet"); } int UDPSocket::Receive(Address & sender, void *data, int size) { // Return on timeout if(WaitData(m_timeout_ms) == false) return -1; int received; if (m_addr_family == AF_INET6) { struct sockaddr_in6 address; memset(&address, 0, sizeof(address)); socklen_t address_len = sizeof(address); received = recvfrom(m_handle, (char *) data, size, 0, (struct sockaddr *) &address, &address_len); if(received < 0) return -1; u16 address_port = ntohs(address.sin6_port); IPv6AddressBytes bytes; memcpy(bytes.bytes, address.sin6_addr.s6_addr, 16); sender = Address(&bytes, address_port); } else { struct sockaddr_in address; memset(&address, 0, sizeof(address)); socklen_t address_len = sizeof(address); received = recvfrom(m_handle, (char *)data, size, 0, (struct sockaddr *)&address, &address_len); if(received < 0) return -1; u32 address_ip = ntohl(address.sin_addr.s_addr); u16 address_port = ntohs(address.sin_port); sender = Address(address_ip, address_port); } if (socket_enable_debug_output) { // Print packet sender and size dstream << (int) m_handle << " <- "; sender.print(&dstream); dstream << ", size=" << received; // Print packet contents dstream << ", data="; for(int i = 0; i < received && i < 20; i++) { if(i % 2 == 0) dstream << " "; unsigned int a = ((const unsigned char *) data)[i]; dstream << std::hex << std::setw(2) << std::setfill('0') << a; } if(received > 20) dstream << "..."; dstream << std::endl; } return received; } int UDPSocket::GetHandle() { return m_handle; } void UDPSocket::setTimeoutMs(int timeout_ms) { m_timeout_ms = timeout_ms; } bool UDPSocket::WaitData(int timeout_ms) { fd_set readset; int result; // Initialize the set FD_ZERO(&readset); FD_SET(m_handle, &readset); // Initialize time out struct struct timeval tv; tv.tv_sec = 0; tv.tv_usec = timeout_ms * 1000; // select() result = select(m_handle+1, &readset, NULL, NULL, &tv); if (result == 0) return false; else if (result < 0 && (errno == EINTR || errno == EBADF)) { // N.B. select() fails when sockets are destroyed on Connection's dtor // with EBADF. Instead of doing tricky synchronization, allow this // thread to exit but don't throw an exception. return false; } else if (result < 0) { dstream << (int) m_handle << ": Select failed: " << strerror(errno) << std::endl; #ifdef _WIN32 int e = WSAGetLastError(); dstream << (int) m_handle << ": WSAGetLastError()=" << e << std::endl; if(e == 10004 /* = WSAEINTR */ || e == 10009 /*WSAEBADF*/) { dstream << "WARNING: Ignoring WSAEINTR/WSAEBADF." << std::endl; return false; } #endif throw SocketException("Select failed"); } else if(FD_ISSET(m_handle, &readset) == false) { // No data return false; } // There is data return true; }