@@ -341,23 +341,30 @@ static void run_server(int p){
341341
342342 logf (INF, " Server is ready on port %d" , p);
343343
344- // sender thread
345- sender_thread = std::thread ([&](){
346- auto last_send = std::chrono::steady_clock::now () - std::chrono::hours (1 );
347- while (server_active) {
344+ sender_thread = std::thread ([&]() {
345+ while (true ) {
348346 std::unique_lock<std::mutex> lk (g_queue_mtx);
349- g_queue_cv.wait (lk, [&]{ return !g_cmd_queue.empty () || !server_active; });
350- if (!server_active && g_cmd_queue.empty ()) break ;
351- std::string cmd = g_cmd_queue.front (); g_cmd_queue.pop (); lk.unlock ();
352- int delay_ms = g_delay_ms.load ();
347+ g_queue_cv.wait (lk, [&] {
348+ return !g_cmd_queue.empty () || !server_active;
349+ });
350+
351+ if (!server_active && g_cmd_queue.empty ())
352+ break ;
353+
354+ std::string cmd = std::move (g_cmd_queue.front ());
355+ g_cmd_queue.pop ();
356+ lk.unlock ();
357+
358+ const int delay_ms = g_delay_ms.load ();
353359 if (delay_ms > 0 ) {
354- auto now = std::chrono::steady_clock::now ();
355- auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(now - last_send).count ();
356- if (elapsed < delay_ms) std::this_thread::sleep_for (std::chrono::milliseconds (delay_ms - elapsed));
360+ std::this_thread::sleep_for (
361+ std::chrono::milliseconds (delay_ms));
357362 }
358- std::string json = makeCommandJSON (cmd);
359- broadcast (json);
360- last_send = std::chrono::steady_clock::now ();
363+
364+ if (!server_active)
365+ break ;
366+
367+ broadcast (makeCommandJSON (cmd));
361368 logf (INF, " [SENT] %s" , cmd.c_str ());
362369 }
363370 });
@@ -426,8 +433,18 @@ static void interactive(){
426433 logf (INF," Interactive mode. Commands: setting start stop exit quit help" );
427434 interactive_mode.store (true );
428435 std::string line;
429- while (std::cout << " list2hosting> " , std::getline (std::cin, line)) {
430- if (line.empty ()) continue ;
436+ while (true ) {
437+ std::cout << " list2hosting> " << std::flush;
438+ if (!std::getline (std::cin, line))
439+ break ;
440+
441+ if (line.empty ())
442+ continue ;
443+
444+ // ユーザー入力の処理中は、logfによる自動再プロンプトを停止する
445+ // これにより、コマンド実行中に出るログ([ENQUEUE]など)がプロンプトを重複させないようにする
446+ interactive_mode.store (false );
447+
431448 std::istringstream ss (line); std::string cmd; ss>>cmd;
432449 std::string lcmd = tolower_s (cmd);
433450 if (lcmd==" exit" ||lcmd==" quit" ){
@@ -451,68 +468,103 @@ static void interactive(){
451468 }
452469 break ;
453470 }
454- if (lcmd==" help" ){ std::cout<<" setting <key> <value>\n start [port]\n stop\n queue\n exit\n <any other line> -> send as Minecraft command\n " ; continue ; }
471+ if (lcmd==" help" ){
472+ std::cout<<" setting <key> <value>\n start [port]\n stop\n queue\n exit\n <any other line> -> send as Minecraft command\n " ;
473+ interactive_mode.store (true ); // 次のループのために戻す
474+ continue ;
475+ }
455476
456477 if (lcmd==" setting" ){
457- std::string key, val; ss>>key>>val; if (key.empty ()||val.empty ()){ logf (WARN," usage: setting <port|delay> <value>" ); continue ; }
458- if (key==" port" ){ try { setting_port = std::stoi (val); logf (INF," port=%d" ,setting_port);}catch (...){ logf (WARN," bad port" ); } }
459- else if (key==" delay" ){ try { setting_delay = std::stoi (val); logf (INF," delay=%d" ,setting_delay);}catch (...){ logf (WARN," bad delay" ); } }
478+ std::string key, val; ss>>key>>val; if (key.empty ()||val.empty ()){ logf (WARN," usage: setting <port|delay> <value>" ); }
479+ else if (key==" port" ){ try { setting_port = std::stoi (val); logf (INF," port=%d" ,setting_port);}catch (...){ logf (WARN," bad port" ); } }
480+ // Bug fix: Update g_delay_ms immediately
481+ else if (key==" delay" ){
482+ try {
483+ setting_delay = std::stoi (val);
484+ g_delay_ms = setting_delay;
485+ logf (INF," delay=%d" ,setting_delay);
486+ }catch (...){ logf (WARN," bad delay" ); }
487+ }
460488 else { logf (WARN," unknown setting" ); }
489+ interactive_mode.store (true );
461490 continue ;
462491 }
463492
464493 if (lcmd==" start" ){
465494 int p = setting_port; if (ss>>p) { /* if provided */ }
466- if (server_active){ logf (WARN," server already running" ); continue ; }
467- g_delay_ms = setting_delay;
468- // initialize WinSock on Windows
495+ if (server_active){ logf (WARN," server already running" ); }
496+ else {
497+ g_delay_ms = setting_delay;
498+ // initialize WinSock on Windows
469499#ifdef _WIN32
470- {
471- WSADATA wsa;
472- if (WSAStartup (MAKEWORD (2 ,2 ), &wsa) != 0 ) { logf (ERR, " WSAStartup failed" ); continue ; }
473- }
500+ {
501+ WSADATA wsa;
502+ if (WSAStartup (MAKEWORD (2 ,2 ), &wsa) != 0 ) { logf (ERR, " WSAStartup failed" ); }
503+ else {
504+ // start server in background
505+ std::lock_guard<std::mutex> lk (server_mtx);
506+ server_active = true ;
507+ server_thread = std::thread (run_server, p);
508+ }
509+ }
510+ #else
511+ {
512+ std::lock_guard<std::mutex> lk (server_mtx);
513+ server_active = true ;
514+ server_thread = std::thread (run_server, p);
515+ }
474516#endif
475- // start server in background
476- {
477- std::lock_guard<std::mutex> lk (server_mtx);
478- server_active = true ;
479- server_thread = std::thread (run_server, p);
480517 }
518+ interactive_mode.store (true );
481519 continue ;
482520 }
483521
484522 if (lcmd==" stop" ){
485- if (!server_active){ logf (WARN," server not running" ); continue ; }
486- // stop server
487- server_active = false ;
488- // close listening socket to break accept/poll
489- std::lock_guard<std::mutex> lk (server_mtx);
490- if (server_sock!=INVALID_SOCKET){
523+ if (!server_active){ logf (WARN," server not running" ); }
524+ else {
525+ // stop server
526+ server_active = false ;
527+ // close listening socket to break accept/poll
528+ {
529+ std::lock_guard<std::mutex> lk (server_mtx);
530+ if (server_sock!=INVALID_SOCKET){
491531#ifdef _WIN32
492- closesocket (server_sock);
532+ closesocket (server_sock);
493533#else
494- close (server_sock);
534+ close (server_sock);
495535#endif
496- server_sock = INVALID_SOCKET;
497- }
498- // wake sender
499- g_queue_cv.notify_one ();
500- if (server_thread.joinable ()) server_thread.join ();
501- if (sender_thread.joinable ()) sender_thread.join ();
536+ server_sock = INVALID_SOCKET;
537+ }
538+ }
539+ // wake sender
540+ g_queue_cv.notify_one ();
541+ if (server_thread.joinable ()) server_thread.join ();
542+ if (sender_thread.joinable ()) sender_thread.join ();
502543#ifdef _WIN32
503- WSACleanup ();
544+ WSACleanup ();
504545#endif
505- logf (INF," server stopped" );
546+ logf (INF," server stopped" );
547+ }
548+ interactive_mode.store (true );
506549 continue ;
507550 }
508551
509- if (lcmd==" queue" ){ enqueue_command (" /say queue" ); continue ; }
552+ if (lcmd==" queue" ){
553+ enqueue_command (" /say queue" );
554+ interactive_mode.store (true );
555+ continue ;
556+ }
510557 // any other line is treated as a raw command to send
511558 {
512559 std::string raw = line;
513- if (!raw.empty ()) { enqueue_command (raw); continue ; }
560+ if (!raw.empty ()) {
561+ enqueue_command (raw);
562+ interactive_mode.store (true );
563+ continue ;
564+ }
514565 }
515566 logf (WARN," unknown cmd" );
567+ interactive_mode.store (true );
516568 }
517569 interactive_mode.store (false );
518570}
@@ -548,4 +600,4 @@ int main(int argc, char** argv) {
548600 WSACleanup ();
549601#endif
550602 return 0 ;
551- }
603+ }
0 commit comments