int main(int argc, const char * argv[]) { pthread_mutex_init(&::treeLock, NULL); qInstallMessageHandler(sharedMessageHandler); NodeList* nodeList = NodeList::createInstance(NODE_TYPE_VOXEL_SERVER, VOXEL_LISTEN_PORT); setvbuf(stdout, NULL, _IOLBF, 0); // Handle Local Domain testing with the --local command line const char* local = "--local"; ::wantLocalDomain = cmdOptionExists(argc, argv,local); if (::wantLocalDomain) { printf("Local Domain MODE!\n"); nodeList->setDomainIPToLocalhost(); } nodeList->linkedDataCreateCallback = &attachVoxelNodeDataToNode; nodeList->startSilentNodeRemovalThread(); srand((unsigned)time(0)); const char* DISPLAY_VOXEL_STATS = "--displayVoxelStats"; ::displayVoxelStats = cmdOptionExists(argc, argv, DISPLAY_VOXEL_STATS); printf("displayVoxelStats=%s\n", debug::valueOf(::displayVoxelStats)); const char* DEBUG_VOXEL_SENDING = "--debugVoxelSending"; ::debugVoxelSending = cmdOptionExists(argc, argv, DEBUG_VOXEL_SENDING); printf("debugVoxelSending=%s\n", debug::valueOf(::debugVoxelSending)); const char* DEBUG_VOXEL_RECEIVING = "--debugVoxelReceiving"; ::debugVoxelReceiving = cmdOptionExists(argc, argv, DEBUG_VOXEL_RECEIVING); printf("debugVoxelReceiving=%s\n", debug::valueOf(::debugVoxelReceiving)); const char* WANT_ANIMATION_DEBUG = "--shouldShowAnimationDebug"; ::shouldShowAnimationDebug = cmdOptionExists(argc, argv, WANT_ANIMATION_DEBUG); printf("shouldShowAnimationDebug=%s\n", debug::valueOf(::shouldShowAnimationDebug)); const char* WANT_COLOR_RANDOMIZER = "--wantColorRandomizer"; ::wantColorRandomizer = cmdOptionExists(argc, argv, WANT_COLOR_RANDOMIZER); printf("wantColorRandomizer=%s\n", debug::valueOf(::wantColorRandomizer)); // By default we will voxel persist, if you want to disable this, then pass in this parameter const char* NO_VOXEL_PERSIST = "--NoVoxelPersist"; if (cmdOptionExists(argc, argv, NO_VOXEL_PERSIST)) { ::wantVoxelPersist = false; } printf("wantVoxelPersist=%s\n", debug::valueOf(::wantVoxelPersist)); // if we want Voxel Persistance, load the local file now... bool persistantFileRead = false; if (::wantVoxelPersist) { printf("loading voxels from file...\n"); persistantFileRead = ::serverTree.readFromSVOFile(::wantLocalDomain ? LOCAL_VOXELS_PERSIST_FILE : VOXELS_PERSIST_FILE); if (persistantFileRead) { PerformanceWarning warn(::shouldShowAnimationDebug, "persistVoxelsWhenDirty() - reaverageVoxelColors()", ::shouldShowAnimationDebug); // after done inserting all these voxels, then reaverage colors serverTree.reaverageVoxelColors(serverTree.rootNode); printf("Voxels reAveraged\n"); } ::serverTree.clearDirtyBit(); // the tree is clean since we just loaded it printf("DONE loading voxels from file... fileRead=%s\n", debug::valueOf(persistantFileRead)); unsigned long nodeCount = ::serverTree.rootNode->getSubTreeNodeCount(); unsigned long internalNodeCount = ::serverTree.rootNode->getSubTreeInternalNodeCount(); unsigned long leafNodeCount = ::serverTree.rootNode->getSubTreeLeafNodeCount(); printf("Nodes after loading scene %lu nodes %lu internal %lu leaves\n", nodeCount, internalNodeCount, leafNodeCount); } // Check to see if the user passed in a command line option for loading an old style local // Voxel File. If so, load it now. This is not the same as a voxel persist file const char* INPUT_FILE = "-i"; const char* voxelsFilename = getCmdOption(argc, argv, INPUT_FILE); if (voxelsFilename) { serverTree.readFromSVOFile(voxelsFilename); } // Check to see if the user passed in a command line option for setting packet send rate const char* PACKETS_PER_SECOND = "--packetsPerSecond"; const char* packetsPerSecond = getCmdOption(argc, argv, PACKETS_PER_SECOND); if (packetsPerSecond) { PACKETS_PER_CLIENT_PER_INTERVAL = atoi(packetsPerSecond)/10; if (PACKETS_PER_CLIENT_PER_INTERVAL < 1) { PACKETS_PER_CLIENT_PER_INTERVAL = 1; } printf("packetsPerSecond=%s PACKETS_PER_CLIENT_PER_INTERVAL=%d\n", packetsPerSecond, PACKETS_PER_CLIENT_PER_INTERVAL); } const char* ADD_RANDOM_VOXELS = "--AddRandomVoxels"; if (cmdOptionExists(argc, argv, ADD_RANDOM_VOXELS)) { // create an octal code buffer and load it with 0 so that the recursive tree fill can give // octal codes to the tree nodes that it is creating randomlyFillVoxelTree(MAX_VOXEL_TREE_DEPTH_LEVELS, serverTree.rootNode); } const char* ADD_SCENE = "--AddScene"; bool addScene = cmdOptionExists(argc, argv, ADD_SCENE); const char* NO_ADD_SCENE = "--NoAddScene"; bool noAddScene = cmdOptionExists(argc, argv, NO_ADD_SCENE); if (addScene && noAddScene) { printf("WARNING! --AddScene and --NoAddScene are mutually exclusive. We will honor --NoAddScene\n"); } // We will add a scene if... // 1) we attempted to load a persistant file and it wasn't there // 2) you asked us to add a scene // HOWEVER -- we will NEVER add a scene if you explicitly tell us not to! // // TEMPORARILY DISABLED!!! bool actuallyAddScene = false; // !noAddScene && (addScene || (::wantVoxelPersist && !persistantFileRead)); if (actuallyAddScene) { addSphereScene(&serverTree); } // for now, initialize the environments with fixed values environmentData[1].setID(1); environmentData[1].setGravity(1.0f); environmentData[1].setAtmosphereCenter(glm::vec3(0.5, 0.5, (0.25 - 0.06125)) * (float)TREE_SCALE); environmentData[1].setAtmosphereInnerRadius(0.030625f * TREE_SCALE); environmentData[1].setAtmosphereOuterRadius(0.030625f * TREE_SCALE * 1.05f); environmentData[2].setID(2); environmentData[2].setGravity(1.0f); environmentData[2].setAtmosphereCenter(glm::vec3(0.5f, 0.5f, 0.5f) * (float)TREE_SCALE); environmentData[2].setAtmosphereInnerRadius(0.1875f * TREE_SCALE); environmentData[2].setAtmosphereOuterRadius(0.1875f * TREE_SCALE * 1.05f); environmentData[2].setScatteringWavelengths(glm::vec3(0.475f, 0.570f, 0.650f)); // swaps red and blue pthread_t sendVoxelThread; pthread_create(&sendVoxelThread, NULL, distributeVoxelsToListeners, NULL); sockaddr nodePublicAddress; unsigned char *packetData = new unsigned char[MAX_PACKET_SIZE]; ssize_t receivedBytes; timeval lastDomainServerCheckIn = {}; // loop to send to nodes requesting data while (true) { // send a check in packet to the domain server if DOMAIN_SERVER_CHECK_IN_USECS has elapsed if (usecTimestampNow() - usecTimestamp(&lastDomainServerCheckIn) >= DOMAIN_SERVER_CHECK_IN_USECS) { gettimeofday(&lastDomainServerCheckIn, NULL); NodeList::getInstance()->sendDomainServerCheckIn(); } // check to see if we need to persist our voxel state persistVoxelsWhenDirty(); if (nodeList->getNodeSocket()->receive(&nodePublicAddress, packetData, &receivedBytes) && packetVersionMatch(packetData)) { int numBytesPacketHeader = numBytesForPacketHeader(packetData); if (packetData[0] == PACKET_TYPE_SET_VOXEL || packetData[0] == PACKET_TYPE_SET_VOXEL_DESTRUCTIVE) { bool destructive = (packetData[0] == PACKET_TYPE_SET_VOXEL_DESTRUCTIVE); PerformanceWarning warn(::shouldShowAnimationDebug, destructive ? "PACKET_TYPE_SET_VOXEL_DESTRUCTIVE" : "PACKET_TYPE_SET_VOXEL", ::shouldShowAnimationDebug); ::receivedPacketCount++; unsigned short int itemNumber = (*((unsigned short int*)(packetData + numBytesPacketHeader))); if (::shouldShowAnimationDebug) { printf("got %s - command from client receivedBytes=%ld itemNumber=%d\n", destructive ? "PACKET_TYPE_SET_VOXEL_DESTRUCTIVE" : "PACKET_TYPE_SET_VOXEL", receivedBytes,itemNumber); } if (::debugVoxelReceiving) { printf("got %s - %d command from client receivedBytes=%ld itemNumber=%d\n", destructive ? "PACKET_TYPE_SET_VOXEL_DESTRUCTIVE" : "PACKET_TYPE_SET_VOXEL", ::receivedPacketCount, receivedBytes,itemNumber); } int atByte = numBytesPacketHeader + sizeof(itemNumber); unsigned char* voxelData = (unsigned char*)&packetData[atByte]; while (atByte < receivedBytes) { unsigned char octets = (unsigned char)*voxelData; const int COLOR_SIZE_IN_BYTES = 3; int voxelDataSize = bytesRequiredForCodeLength(octets) + COLOR_SIZE_IN_BYTES; int voxelCodeSize = bytesRequiredForCodeLength(octets); // color randomization on insert int colorRandomizer = ::wantColorRandomizer ? randIntInRange (-50, 50) : 0; int red = voxelData[voxelCodeSize + 0]; int green = voxelData[voxelCodeSize + 1]; int blue = voxelData[voxelCodeSize + 2]; if (::shouldShowAnimationDebug) { printf("insert voxels - wantColorRandomizer=%s old r=%d,g=%d,b=%d \n", (::wantColorRandomizer?"yes":"no"),red,green,blue); } red = std::max(0, std::min(255, red + colorRandomizer)); green = std::max(0, std::min(255, green + colorRandomizer)); blue = std::max(0, std::min(255, blue + colorRandomizer)); if (::shouldShowAnimationDebug) { printf("insert voxels - wantColorRandomizer=%s NEW r=%d,g=%d,b=%d \n", (::wantColorRandomizer?"yes":"no"),red,green,blue); } voxelData[voxelCodeSize + 0] = red; voxelData[voxelCodeSize + 1] = green; voxelData[voxelCodeSize + 2] = blue; if (::shouldShowAnimationDebug) { float* vertices = firstVertexForCode(voxelData); printf("inserting voxel at: %f,%f,%f\n", vertices[0], vertices[1], vertices[2]); delete []vertices; } serverTree.readCodeColorBufferToTree(voxelData, destructive); // skip to next voxelData += voxelDataSize; atByte += voxelDataSize; } } else if (packetData[0] == PACKET_TYPE_ERASE_VOXEL) { // Send these bits off to the VoxelTree class to process them pthread_mutex_lock(&::treeLock); serverTree.processRemoveVoxelBitstream((unsigned char*)packetData, receivedBytes); pthread_mutex_unlock(&::treeLock); } else if (packetData[0] == PACKET_TYPE_Z_COMMAND) { // the Z command is a special command that allows the sender to send the voxel server high level semantic // requests, like erase all, or add sphere scene char* command = (char*) &packetData[numBytesPacketHeader]; // start of the command int commandLength = strlen(command); // commands are null terminated strings int totalLength = numBytesPacketHeader + commandLength + 1; // 1 for null termination printf("got Z message len(%ld)= %s\n", receivedBytes, command); bool rebroadcast = true; // by default rebroadcast while (totalLength <= receivedBytes) { if (strcmp(command, ERASE_ALL_COMMAND) == 0) { printf("got Z message == erase all\n"); eraseVoxelTreeAndCleanupNodeVisitData(); rebroadcast = false; } if (strcmp(command, ADD_SCENE_COMMAND) == 0) { printf("got Z message == add scene\n"); addSphereScene(&serverTree); rebroadcast = false; } if (strcmp(command, TEST_COMMAND) == 0) { printf("got Z message == a message, nothing to do, just report\n"); } totalLength += commandLength + 1; // 1 for null termination } if (rebroadcast) { // Now send this to the connected nodes so they can also process these messages printf("rebroadcasting Z message to connected nodes... nodeList.broadcastToNodes()\n"); nodeList->broadcastToNodes(packetData, receivedBytes, &NODE_TYPE_AGENT, 1); } } else if (packetData[0] == PACKET_TYPE_HEAD_DATA) { // If we got a PACKET_TYPE_HEAD_DATA, then we're talking to an NODE_TYPE_AVATAR, and we // need to make sure we have it in our nodeList. uint16_t nodeID = 0; unpackNodeId(packetData + numBytesPacketHeader, &nodeID); Node* node = nodeList->addOrUpdateNode(&nodePublicAddress, &nodePublicAddress, NODE_TYPE_AGENT, nodeID); nodeList->updateNodeWithData(node, packetData, receivedBytes); } else if (packetData[0] == PACKET_TYPE_PING) { // If the packet is a ping, let processNodeData handle it. nodeList->processNodeData(&nodePublicAddress, packetData, receivedBytes); } } } pthread_join(sendVoxelThread, NULL); pthread_mutex_destroy(&::treeLock); return 0; }
void processSplitSVOFile(const char* splitSVOFile,const char* splitJurisdictionRoot,const char* splitJurisdictionEndNodes) { char outputFileName[512]; printf("splitSVOFile: %s Jurisdictions Root: %s EndNodes: %s\n", splitSVOFile, splitJurisdictionRoot, splitJurisdictionEndNodes); VoxelTree rootSVO; rootSVO.readFromSVOFile(splitSVOFile); JurisdictionMap jurisdiction(splitJurisdictionRoot, splitJurisdictionEndNodes); printf("Jurisdiction Root Octcode: "); printOctalCode(jurisdiction.getRootOctalCode()); printf("Jurisdiction End Nodes: %d \n", jurisdiction.getEndNodeCount()); for (int i = 0; i < jurisdiction.getEndNodeCount(); i++) { unsigned char* endNodeCode = jurisdiction.getEndNodeOctalCode(i); printf("End Node: %d ", i); printOctalCode(endNodeCode); // get the endNode details VoxelPositionSize endNodeDetails; voxelDetailsForCode(endNodeCode, endNodeDetails); // Now, create a split SVO for the EndNode. // copy the EndNode into a temporary tree VoxelTree endNodeTree; // create a small voxels at corners of the endNode Tree, this will is a hack // to work around a bug in voxel server that will send Voxel not exists // for regions that don't contain anything even if they're not in the // jurisdiction of the server // This hack assumes the end nodes for demo dinner since it only guarantees // nodes in the 8 child voxels of the main root voxel const float verySmall = 0.015625; endNodeTree.createVoxel(0.0, 0.0, 0.0, verySmall, 1, 1, 1, true); endNodeTree.createVoxel(1.0, 0.0, 0.0, verySmall, 1, 1, 1, true); endNodeTree.createVoxel(0.0, 1.0, 0.0, verySmall, 1, 1, 1, true); endNodeTree.createVoxel(0.0, 0.0, 1.0, verySmall, 1, 1, 1, true); endNodeTree.createVoxel(1.0, 1.0, 1.0, verySmall, 1, 1, 1, true); endNodeTree.createVoxel(1.0, 1.0, 0.0, verySmall, 1, 1, 1, true); endNodeTree.createVoxel(0.0, 1.0, 1.0, verySmall, 1, 1, 1, true); endNodeTree.createVoxel(1.0, 0.0, 1.0, verySmall, 1, 1, 1, true); // Delete the voxel for the EndNode from the temporary tree, so we can // import our endNode content into it... endNodeTree.deleteOctalCodeFromTree(endNodeCode, COLLAPSE_EMPTY_TREE); VoxelTreeElement* endNode = rootSVO.getVoxelAt(endNodeDetails.x, endNodeDetails.y, endNodeDetails.z, endNodeDetails.s); rootSVO.copySubTreeIntoNewTree(endNode, &endNodeTree, false); sprintf(outputFileName, "splitENDNODE%d%s", i, splitSVOFile); printf("outputFile: %s\n", outputFileName); endNodeTree.writeToSVOFile(outputFileName); // Delete the voxel for the EndNode from the root tree... rootSVO.deleteOctalCodeFromTree(endNodeCode, COLLAPSE_EMPTY_TREE); // create a small voxel in center of each EndNode, this will is a hack // to work around a bug in voxel server that will send Voxel not exists // for regions that don't contain anything even if they're not in the // jurisdiction of the server float x = endNodeDetails.x + endNodeDetails.s * 0.5; float y = endNodeDetails.y + endNodeDetails.s * 0.5; float z = endNodeDetails.z + endNodeDetails.s * 0.5; float s = endNodeDetails.s * verySmall; rootSVO.createVoxel(x, y, z, s, 1, 1, 1, true); } sprintf(outputFileName, "splitROOT%s", splitSVOFile); printf("outputFile: %s\n", outputFileName); rootSVO.writeToSVOFile(outputFileName); printf("exiting now\n"); }
int main(int argc, const char * argv[]) { pthread_mutex_init(&::treeLock, NULL); qInstallMessageHandler(sharedMessageHandler); int listenPort = VOXEL_LISTEN_PORT; // Check to see if the user passed in a command line option for setting listen port const char* PORT_PARAMETER = "--port"; const char* portParameter = getCmdOption(argc, argv, PORT_PARAMETER); if (portParameter) { listenPort = atoi(portParameter); if (listenPort < 1) { listenPort = VOXEL_LISTEN_PORT; } printf("portParameter=%s listenPort=%d\n", portParameter, listenPort); } const char* JURISDICTION_FILE = "--jurisdictionFile"; const char* jurisdictionFile = getCmdOption(argc, argv, JURISDICTION_FILE); if (jurisdictionFile) { printf("jurisdictionFile=%s\n", jurisdictionFile); printf("about to readFromFile().... jurisdictionFile=%s\n", jurisdictionFile); jurisdiction = new JurisdictionMap(jurisdictionFile); printf("after readFromFile().... jurisdictionFile=%s\n", jurisdictionFile); } else { const char* JURISDICTION_ROOT = "--jurisdictionRoot"; const char* jurisdictionRoot = getCmdOption(argc, argv, JURISDICTION_ROOT); if (jurisdictionRoot) { printf("jurisdictionRoot=%s\n", jurisdictionRoot); } const char* JURISDICTION_ENDNODES = "--jurisdictionEndNodes"; const char* jurisdictionEndNodes = getCmdOption(argc, argv, JURISDICTION_ENDNODES); if (jurisdictionEndNodes) { printf("jurisdictionEndNodes=%s\n", jurisdictionEndNodes); } if (jurisdictionRoot || jurisdictionEndNodes) { ::jurisdiction = new JurisdictionMap(jurisdictionRoot, jurisdictionEndNodes); } } // should we send environments? Default is yes, but this command line suppresses sending const char* DUMP_VOXELS_ON_MOVE = "--dumpVoxelsOnMove"; ::dumpVoxelsOnMove = cmdOptionExists(argc, argv, DUMP_VOXELS_ON_MOVE); printf("dumpVoxelsOnMove=%s\n", debug::valueOf(::dumpVoxelsOnMove)); // should we send environments? Default is yes, but this command line suppresses sending const char* DONT_SEND_ENVIRONMENTS = "--dontSendEnvironments"; bool dontSendEnvironments = cmdOptionExists(argc, argv, DONT_SEND_ENVIRONMENTS); if (dontSendEnvironments) { printf("Sending environments suppressed...\n"); ::sendEnvironments = false; } else { // should we send environments? Default is yes, but this command line suppresses sending const char* MINIMAL_ENVIRONMENT = "--MinimalEnvironment"; ::sendMinimalEnvironment = cmdOptionExists(argc, argv, MINIMAL_ENVIRONMENT); printf("Using Minimal Environment=%s\n", debug::valueOf(::sendMinimalEnvironment)); } printf("Sending environments=%s\n", debug::valueOf(::sendEnvironments)); NodeList* nodeList = NodeList::createInstance(NODE_TYPE_VOXEL_SERVER, listenPort); setvbuf(stdout, NULL, _IOLBF, 0); // tell our NodeList about our desire to get notifications nodeList->addHook(&nodeWatcher); // Handle Local Domain testing with the --local command line const char* local = "--local"; ::wantLocalDomain = cmdOptionExists(argc, argv,local); if (::wantLocalDomain) { printf("Local Domain MODE!\n"); nodeList->setDomainIPToLocalhost(); } else { const char* domainIP = getCmdOption(argc, argv, "--domain"); if (domainIP) { NodeList::getInstance()->setDomainHostname(domainIP); } } nodeList->linkedDataCreateCallback = &attachVoxelNodeDataToNode; nodeList->startSilentNodeRemovalThread(); srand((unsigned)time(0)); const char* DISPLAY_VOXEL_STATS = "--displayVoxelStats"; ::displayVoxelStats = cmdOptionExists(argc, argv, DISPLAY_VOXEL_STATS); printf("displayVoxelStats=%s\n", debug::valueOf(::displayVoxelStats)); const char* DEBUG_VOXEL_SENDING = "--debugVoxelSending"; ::debugVoxelSending = cmdOptionExists(argc, argv, DEBUG_VOXEL_SENDING); printf("debugVoxelSending=%s\n", debug::valueOf(::debugVoxelSending)); const char* DEBUG_VOXEL_RECEIVING = "--debugVoxelReceiving"; ::debugVoxelReceiving = cmdOptionExists(argc, argv, DEBUG_VOXEL_RECEIVING); printf("debugVoxelReceiving=%s\n", debug::valueOf(::debugVoxelReceiving)); const char* WANT_ANIMATION_DEBUG = "--shouldShowAnimationDebug"; ::shouldShowAnimationDebug = cmdOptionExists(argc, argv, WANT_ANIMATION_DEBUG); printf("shouldShowAnimationDebug=%s\n", debug::valueOf(::shouldShowAnimationDebug)); // By default we will voxel persist, if you want to disable this, then pass in this parameter const char* NO_VOXEL_PERSIST = "--NoVoxelPersist"; if (cmdOptionExists(argc, argv, NO_VOXEL_PERSIST)) { ::wantVoxelPersist = false; } printf("wantVoxelPersist=%s\n", debug::valueOf(::wantVoxelPersist)); // if we want Voxel Persistence, load the local file now... bool persistantFileRead = false; if (::wantVoxelPersist) { // Check to see if the user passed in a command line option for setting packet send rate const char* VOXELS_PERSIST_FILENAME = "--voxelsPersistFilename"; const char* voxelsPersistFilenameParameter = getCmdOption(argc, argv, VOXELS_PERSIST_FILENAME); if (voxelsPersistFilenameParameter) { strcpy(voxelPersistFilename, voxelsPersistFilenameParameter); } else { strcpy(voxelPersistFilename, ::wantLocalDomain ? LOCAL_VOXELS_PERSIST_FILE : VOXELS_PERSIST_FILE); } printf("loading voxels from file: %s...\n", voxelPersistFilename); persistantFileRead = ::serverTree.readFromSVOFile(::voxelPersistFilename); if (persistantFileRead) { PerformanceWarning warn(::shouldShowAnimationDebug, "persistVoxelsWhenDirty() - reaverageVoxelColors()", ::shouldShowAnimationDebug); // after done inserting all these voxels, then reaverage colors serverTree.reaverageVoxelColors(serverTree.rootNode); printf("Voxels reAveraged\n"); } ::serverTree.clearDirtyBit(); // the tree is clean since we just loaded it printf("DONE loading voxels from file... fileRead=%s\n", debug::valueOf(persistantFileRead)); unsigned long nodeCount = ::serverTree.rootNode->getSubTreeNodeCount(); unsigned long internalNodeCount = ::serverTree.rootNode->getSubTreeInternalNodeCount(); unsigned long leafNodeCount = ::serverTree.rootNode->getSubTreeLeafNodeCount(); printf("Nodes after loading scene %lu nodes %lu internal %lu leaves\n", nodeCount, internalNodeCount, leafNodeCount); // now set up VoxelPersistThread ::voxelPersistThread = new VoxelPersistThread(&::serverTree, ::voxelPersistFilename); if (::voxelPersistThread) { ::voxelPersistThread->initialize(true); } } // Check to see if the user passed in a command line option for loading an old style local // Voxel File. If so, load it now. This is not the same as a voxel persist file const char* INPUT_FILE = "-i"; const char* voxelsFilename = getCmdOption(argc, argv, INPUT_FILE); if (voxelsFilename) { serverTree.readFromSVOFile(voxelsFilename); } // Check to see if the user passed in a command line option for setting packet send rate const char* PACKETS_PER_SECOND = "--packetsPerSecond"; const char* packetsPerSecond = getCmdOption(argc, argv, PACKETS_PER_SECOND); if (packetsPerSecond) { PACKETS_PER_CLIENT_PER_INTERVAL = atoi(packetsPerSecond)/INTERVALS_PER_SECOND; if (PACKETS_PER_CLIENT_PER_INTERVAL < 1) { PACKETS_PER_CLIENT_PER_INTERVAL = 1; } printf("packetsPerSecond=%s PACKETS_PER_CLIENT_PER_INTERVAL=%d\n", packetsPerSecond, PACKETS_PER_CLIENT_PER_INTERVAL); } // for now, initialize the environments with fixed values environmentData[1].setID(1); environmentData[1].setGravity(1.0f); environmentData[1].setAtmosphereCenter(glm::vec3(0.5, 0.5, (0.25 - 0.06125)) * (float)TREE_SCALE); environmentData[1].setAtmosphereInnerRadius(0.030625f * TREE_SCALE); environmentData[1].setAtmosphereOuterRadius(0.030625f * TREE_SCALE * 1.05f); environmentData[2].setID(2); environmentData[2].setGravity(1.0f); environmentData[2].setAtmosphereCenter(glm::vec3(0.5f, 0.5f, 0.5f) * (float)TREE_SCALE); environmentData[2].setAtmosphereInnerRadius(0.1875f * TREE_SCALE); environmentData[2].setAtmosphereOuterRadius(0.1875f * TREE_SCALE * 1.05f); environmentData[2].setScatteringWavelengths(glm::vec3(0.475f, 0.570f, 0.650f)); // swaps red and blue sockaddr senderAddress; unsigned char *packetData = new unsigned char[MAX_PACKET_SIZE]; ssize_t packetLength; timeval lastDomainServerCheckIn = {}; // set up our jurisdiction broadcaster... ::jurisdictionSender = new JurisdictionSender(::jurisdiction); if (::jurisdictionSender) { ::jurisdictionSender->initialize(true); } // set up our VoxelServerPacketProcessor ::voxelServerPacketProcessor = new VoxelServerPacketProcessor(); if (::voxelServerPacketProcessor) { ::voxelServerPacketProcessor->initialize(true); } // loop to send to nodes requesting data while (true) { // send a check in packet to the domain server if DOMAIN_SERVER_CHECK_IN_USECS has elapsed if (usecTimestampNow() - usecTimestamp(&lastDomainServerCheckIn) >= DOMAIN_SERVER_CHECK_IN_USECS) { gettimeofday(&lastDomainServerCheckIn, NULL); NodeList::getInstance()->sendDomainServerCheckIn(); } if (nodeList->getNodeSocket()->receive(&senderAddress, packetData, &packetLength) && packetVersionMatch(packetData)) { int numBytesPacketHeader = numBytesForPacketHeader(packetData); if (packetData[0] == PACKET_TYPE_HEAD_DATA) { // If we got a PACKET_TYPE_HEAD_DATA, then we're talking to an NODE_TYPE_AVATAR, and we // need to make sure we have it in our nodeList. uint16_t nodeID = 0; unpackNodeId(packetData + numBytesPacketHeader, &nodeID); Node* node = NodeList::getInstance()->addOrUpdateNode(&senderAddress, &senderAddress, NODE_TYPE_AGENT, nodeID); NodeList::getInstance()->updateNodeWithData(node, packetData, packetLength); } else if (packetData[0] == PACKET_TYPE_PING) { // If the packet is a ping, let processNodeData handle it. NodeList::getInstance()->processNodeData(&senderAddress, packetData, packetLength); } else if (packetData[0] == PACKET_TYPE_DOMAIN) { NodeList::getInstance()->processNodeData(&senderAddress, packetData, packetLength); } else if (packetData[0] == PACKET_TYPE_VOXEL_JURISDICTION_REQUEST) { if (::jurisdictionSender) { ::jurisdictionSender->queueReceivedPacket(senderAddress, packetData, packetLength); } } else if (::voxelServerPacketProcessor) { ::voxelServerPacketProcessor->queueReceivedPacket(senderAddress, packetData, packetLength); } else { printf("unknown packet ignored... packetData[0]=%c\n", packetData[0]); } } } if (::jurisdiction) { delete ::jurisdiction; } if (::jurisdictionSender) { ::jurisdictionSender->terminate(); delete ::jurisdictionSender; } if (::voxelServerPacketProcessor) { ::voxelServerPacketProcessor->terminate(); delete ::voxelServerPacketProcessor; } if (::voxelPersistThread) { ::voxelPersistThread->terminate(); delete ::voxelPersistThread; } // tell our NodeList we're done with notifications nodeList->removeHook(&nodeWatcher); pthread_mutex_destroy(&::treeLock); return 0; }