__CD__BEGIN Vector3D my_tri_tri_intersect(const Triangle& t1, const Triangle& t2) { Plane p1(t1.v1,t1.v2,t1.v3); int other_side=0; { float f1=p1.Classify(t2.v1); float f2=p1.Classify(t2.v2); float f3=p1.Classify(t2.v3); float f12=f1*f2; float f23=f2*f3; if (f12>0.0f && f23>0.0f) return Vector3D::Zero; other_side=(f12<0.0f?(f23<0.0f?1:0):2); } Plane p2(t2.v1,t2.v2,t2.v3); Vector3D n12(p1.normal+p2.normal); TriangleDesc td2(t2,p2); const Vector3D& a2=td2[other_side+1]; const Vector3D& b2=td2[other_side]; const Vector3D& c2=td2[other_side+2]; float t21=-(p1.d+p2.d+a2*n12)/((b2-a2)*n12); TriangleDesc td1(t1,p1); Vector3D P21(a2+t21*(b2-a2)); if (td1.pointInTri(P21)) return P21; float t22=-(p1.d+p2.d+c2*n12)/((b2-c2)*n12); Vector3D P22(c2+t22*(b2-c2)); if (td1.pointInTri(P22)) return P22; { float f1=p2.Classify(t1.v1); float f2=p2.Classify(t1.v2); float f3=p2.Classify(t1.v3); float f12=f1*f2; float f23=f2*f3; if (f12>0.0f && f23>0.0f) return Vector3D::Zero; other_side=(f12<0.0f?(f23<0.0f?1:0):2); } const Vector3D& a1=td1[other_side+1]; const Vector3D& b1=td1[other_side]; const Vector3D& c1=td1[other_side+2]; float t11=-(p1.d+p2.d+a1*n12)/((b1-a1)*n12); Vector3D P11(a1+t11*(b1-a1)); if (td2.pointInTri(P11)) return P11; float t12=-(p1.d+p2.d+c1*n12)/((b1-c1)*n12); Vector3D P12(c1+t12*(b1-c1)); if (td2.pointInTri(P12)) return P12; return Vector3D::Zero; }
//! Convert a utc time to local time static time_type utc_to_local(const time_type& t) { date_type time_t_start_day(1970,1,1); time_type time_t_start_time(time_t_start_day,time_duration_type(0,0,0)); if (t < time_t_start_time) { throw std::out_of_range("Cannot convert dates prior to Jan 1, 1970"); } date_duration_type dd = t.date() - time_t_start_day; time_duration_type td = t.time_of_day(); std::time_t t2 = dd.days()*86400 + td.hours()*3600 + td.minutes()*60 + td.seconds(); std::tm tms, *tms_ptr; tms_ptr = c_time::localtime(&t2, &tms); //tms_ptr = std::localtime(&t2); date_type d(static_cast<unsigned short>(tms_ptr->tm_year + 1900), static_cast<unsigned short>(tms_ptr->tm_mon + 1), static_cast<unsigned short>(tms_ptr->tm_mday)); time_duration_type td2(tms_ptr->tm_hour, tms_ptr->tm_min, tms_ptr->tm_sec, t.time_of_day().fractional_seconds()); return time_type(d,td2); }
/// Main function int Master::Run() { /// worldd PID file creation std::string pidfile = sConfig.GetStringDefault("PidFile", ""); if(!pidfile.empty()) { uint32 pid = CreatePIDFile(pidfile); if( !pid ) { sLog.outError( "Cannot create PID file %s.\n", pidfile.c_str() ); return 1; } sLog.outString( "Daemon PID: %u\n", pid ); } ///- Start the databases if (!_StartDB()) return 1; ///- Initialize the World sWorld.SetInitialWorldSettings(); ///- Catch termination signals _HookSignals(); ///- Launch WorldRunnable thread ACE_Based::Thread t(*new WorldRunnable); t.setPriority(ACE_Based::Highest); // set server online loginDatabase.PExecute("UPDATE realmlist SET color = 0, population = 0 WHERE id = '%d'",realmID); #ifdef WIN32 if (sConfig.GetBoolDefault("Console.Enable", true) && (m_ServiceStatus == -1)/* need disable console in service mode*/) #else if (sConfig.GetBoolDefault("Console.Enable", true)) #endif { ///- Launch CliRunnable thread ACE_Based::Thread td1(*new CliRunnable); } ACE_Based::Thread td2(*new RARunnable); ///- Handle affinity for multiple processors and process priority on Windows #ifdef WIN32 { HANDLE hProcess = GetCurrentProcess(); uint32 Aff = sConfig.GetIntDefault("UseProcessors", 0); if(Aff > 0) { ULONG_PTR appAff; ULONG_PTR sysAff; if(GetProcessAffinityMask(hProcess,&appAff,&sysAff)) { ULONG_PTR curAff = Aff & appAff; // remove non accessible processors if(!curAff ) { sLog.outError("Processors marked in UseProcessors bitmask (hex) %x not accessible for mangosd. Accessible processors bitmask (hex): %x",Aff,appAff); } else { if(SetProcessAffinityMask(hProcess,curAff)) sLog.outString("Using processors (bitmask, hex): %x", curAff); else sLog.outError("Can't set used processors (hex): %x",curAff); } } sLog.outString(); } bool Prio = sConfig.GetBoolDefault("ProcessPriority", false); // if(Prio && (m_ServiceStatus == -1)/* need set to default process priority class in service mode*/) if(Prio) { if(SetPriorityClass(hProcess,HIGH_PRIORITY_CLASS)) sLog.outString("mangosd process priority class set to HIGH"); else sLog.outError("ERROR: Can't set mangosd process priority class."); sLog.outString(); } } #endif uint32 realCurrTime, realPrevTime; realCurrTime = realPrevTime = getMSTime(); uint32 socketSelecttime = sWorld.getConfig(CONFIG_SOCKET_SELECTTIME); // maximum counter for next ping uint32 numLoops = (sConfig.GetIntDefault( "MaxPingTime", 30 ) * (MINUTE * 1000000 / socketSelecttime)); uint32 loopCounter = 0; ///- Start up freeze catcher thread uint32 freeze_delay = sConfig.GetIntDefault("MaxCoreStuckTime", 0); if(freeze_delay) { FreezeDetectorRunnable *fdr = new FreezeDetectorRunnable(); fdr->SetDelayTime(freeze_delay*1000); ACE_Based::Thread t(*fdr); t.setPriority(ACE_Based::Highest); } ///- Launch the world listener socket port_t wsport = sWorld.getConfig (CONFIG_PORT_WORLD); std::string bind_ip = sConfig.GetStringDefault ("BindIP", "0.0.0.0"); if (sWorldSocketMgr->StartNetwork (wsport, bind_ip.c_str ()) == -1) { sLog.outError ("Failed to start network"); World::StopNow(ERROR_EXIT_CODE); // go down and shutdown the server } sWorldSocketMgr->Wait (); // set server offline loginDatabase.PExecute("UPDATE realmlist SET color = 2 WHERE id = '%d'",realmID); ///- Remove signal handling before leaving _UnhookSignals(); // when the main thread closes the singletons get unloaded // since worldrunnable uses them, it will crash if unloaded after master t.wait(); td2.wait (); ///- Clean database before leaving clearOnlineAccounts(); ///- Wait for delay threads to end CharacterDatabase.HaltDelayThread(); WorldDatabase.HaltDelayThread(); loginDatabase.HaltDelayThread(); sLog.outString( "Halting process..." ); #ifdef WIN32 if (sConfig.GetBoolDefault("Console.Enable", true)) { // this only way to terminate CLI thread exist at Win32 (alt. way exist only in Windows Vista API) //_exit(1); // send keyboard input to safely unblock the CLI thread INPUT_RECORD b[5]; HANDLE hStdIn = GetStdHandle(STD_INPUT_HANDLE); b[0].EventType = KEY_EVENT; b[0].Event.KeyEvent.bKeyDown = TRUE; b[0].Event.KeyEvent.uChar.AsciiChar = 'X'; b[0].Event.KeyEvent.wVirtualKeyCode = 'X'; b[0].Event.KeyEvent.wRepeatCount = 1; b[1].EventType = KEY_EVENT; b[1].Event.KeyEvent.bKeyDown = FALSE; b[1].Event.KeyEvent.uChar.AsciiChar = 'X'; b[1].Event.KeyEvent.wVirtualKeyCode = 'X'; b[1].Event.KeyEvent.wRepeatCount = 1; b[2].EventType = KEY_EVENT; b[2].Event.KeyEvent.bKeyDown = TRUE; b[2].Event.KeyEvent.dwControlKeyState = 0; b[2].Event.KeyEvent.uChar.AsciiChar = '\r'; b[2].Event.KeyEvent.wVirtualKeyCode = VK_RETURN; b[2].Event.KeyEvent.wRepeatCount = 1; b[2].Event.KeyEvent.wVirtualScanCode = 0x1c; b[3].EventType = KEY_EVENT; b[3].Event.KeyEvent.bKeyDown = FALSE; b[3].Event.KeyEvent.dwControlKeyState = 0; b[3].Event.KeyEvent.uChar.AsciiChar = '\r'; b[3].Event.KeyEvent.wVirtualKeyCode = VK_RETURN; b[3].Event.KeyEvent.wVirtualScanCode = 0x1c; b[3].Event.KeyEvent.wRepeatCount = 1; DWORD numb; BOOL ret = WriteConsoleInput(hStdIn, b, 4, &numb); } #endif // for some unknown reason, unloading scripts here and not in worldrunnable // fixes a memory leak related to detaching threads from the module UnloadScriptingModule(); // Exit the process with specified return value return World::GetExitCode(); }