📄 win32srv.c
字号:
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include "merc.h"
#include "merc-win.rh"
/*
* Global variables.
*/
DESCRIPTOR_DATA * descriptor_free; /* Free list for descriptors */
DESCRIPTOR_DATA * descriptor_list; /* All open descriptors */
DESCRIPTOR_DATA * d_next; /* Next descriptor in loop */
FILE * fpReserve; /* Reserved file handle */
bool god; /* All new chars are gods! */
bool merc_down; /* Shutdown */
bool wizlock; /* Game is wizlocked */
char str_boot_time[MAX_INPUT_LENGTH];
time_t current_time; /* Time of this pulse */
/*
* Other local functions (OS-independent).
*/
bool check_parse_name args( ( char *name ) );
bool check_reconnect args( ( DESCRIPTOR_DATA *d, char *name,
bool fConn ) );
bool check_playing args( ( DESCRIPTOR_DATA *d, char *name ) );
int main args( ( int argc, char **argv ) );
void nanny args( ( DESCRIPTOR_DATA *d, char *argument ) );
bool process_output args( ( DESCRIPTOR_DATA *d, bool fPrompt ) );
void read_from_buffer args( ( DESCRIPTOR_DATA *d ) );
void stop_idling args( ( CHAR_DATA *ch ) );
void bust_a_prompt args( ( CHAR_DATA *ch ) );
const char echo_off_str [] = { '\0' };
const char echo_on_str [] = { '\0' };
const char go_ahead_str [] = { '\0' };
bool write_to_descriptor args( ( int desc, char *txt, int length ) );
void send_to_char args( ( const char *txt, CHAR_DATA *ch ) )
{
if ( txt == NULL || ch->desc == NULL )
return;
ch->desc->showstr_head = alloc_mem( strlen( txt ) + 1 );
strcpy( ch->desc->showstr_head, txt );
ch->desc->showstr_point = ch->desc->showstr_head;
show_string( ch->desc, "" );
}
void gettimeofday( struct timeval *tp, void *tzp )
{
tp->tv_sec = time( NULL );
tp->tv_usec = 0;
}
bool read_from_descriptor( DESCRIPTOR_DATA *d )
{
int iStart;
/* Hold horses if pending command already. */
if ( d->incomm[0] != '\0' )
return TRUE;
/* Check for overflow. */
iStart = strlen(d->inbuf);
if ( iStart >= sizeof(d->inbuf) - 10 )
{
sprintf( log_buf, "%s input overflow!", d->host );
log_string( log_buf );
write_to_descriptor( d->descriptor,
"\n\r*** PUT A LID ON IT!!! ***\n\r", 0 );
return FALSE;
}
#if 0
/* Snarf input. */
for ( ; ; )
{
int c;
c = getc( stdin );
if ( c == '\0' || c == EOF )
break;
putc( c, stdout );
if ( c == '\r' )
putc( '\n', stdout );
d->inbuf[iStart++] = c;
if ( iStart > sizeof(d->inbuf) - 10 )
break;
}
#else
if (fUserReady)
{
int nLen = strlen(UserMessage);
fUserReady = FALSE;
if (iStart + nLen <= sizeof d->inbuf - 10)
{
memcpy(d->inbuf + iStart, UserMessage, nLen);
iStart += nLen;
d->inbuf[iStart++] = '\r';
}
}
#endif
d->inbuf[iStart] = '\0';
return TRUE;
}
/*
* Transfer one line from input buffer to input line.
*/
void read_from_buffer( DESCRIPTOR_DATA *d )
{
int i, j, k;
/*
* Hold horses if pending command already.
*/
if ( d->incomm[0] != '\0' )
return;
/*
* Look for at least one new line.
*/
for ( i = 0; d->inbuf[i] != '\n' && d->inbuf[i] != '\r'; i++ )
{
if ( d->inbuf[i] == '\0' )
return;
}
/*
* Canonical input processing.
*/
for ( i = 0, k = 0; d->inbuf[i] != '\n' && d->inbuf[i] != '\r'; i++ )
{
if ( k >= MAX_INPUT_LENGTH - 2 )
{
write_to_descriptor( d->descriptor, "Line too long.\n\r", 0 );
/* skip the rest of the line */
for ( ; d->inbuf[i] != '\0'; i++ )
{
if ( d->inbuf[i] == '\n' || d->inbuf[i] == '\r' )
break;
}
d->inbuf[i] = '\n';
d->inbuf[i+1] = '\0';
break;
}
if ( d->inbuf[i] == '\b' && k > 0 )
--k;
else if ( isascii(d->inbuf[i]) && isprint(d->inbuf[i]) )
d->incomm[k++] = d->inbuf[i];
}
/*
* Finish off the line.
*/
if ( k == 0 )
d->incomm[k++] = ' ';
d->incomm[k] = '\0';
/*
* Deal with bozos with #repeat 1000 ...
*/
if ( k > 1 || d->incomm[0] == '!' )
{
if ( d->incomm[0] != '!' && strcmp( d->incomm, d->inlast ) )
{
d->repeat = 0;
}
else
{
if ( ++d->repeat >= 20 )
{
sprintf( log_buf, "%s input spamming!", d->host );
log_string( log_buf );
write_to_descriptor( d->descriptor,
"\n\r*** PUT A LID ON IT!!! ***\n\r", 0 );
strcpy( d->incomm, "quit" );
}
}
}
/*
* Do '!' substitution.
*/
if ( d->incomm[0] == '!' )
strcpy( d->incomm, d->inlast );
else
strcpy( d->inlast, d->incomm );
/*
* Shift the input buffer.
*/
while ( d->inbuf[i] == '\n' || d->inbuf[i] == '\r' )
i++;
for ( j = 0; ( d->inbuf[j] = d->inbuf[i+j] ) != '\0'; j++ )
;
return;
}
void CloseMerc(void)
{
}
HINSTANCE hInst;
HWND hQryDlgBox; // handle of modeless dialog box
HWND hWndMain;
HWND hWndOutput;
char UserMessage[512];
BOOL fUserReady;
LRESULT CALLBACK _export MercWndProc(HWND hWnd, UINT message,
WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_MOVE:
// Move the dialog box on top of our main window every
// time the main window moves.
if (IsWindow(hQryDlgBox))
SendMessage(hQryDlgBox, message, wParam, lParam);
break;
case WM_SETFOCUS:
// Always set the input focus to the dialog box.
if (IsWindow(hQryDlgBox))
SendMessage(hQryDlgBox, message, wParam, lParam);
break;
case WM_CLOSE:
// Tell windows to destroy our window.
DestroyWindow(hWnd);
break;
case WM_QUERYENDSESSION:
// If we return TRUE we are saying it's ok with us to end the
// windows session.
return((long) TRUE); // we agree to end session.
case WM_ENDSESSION:
// If wParam is not zero, it meany every application said ok
// to WM_QUERYENDSESSION messages, so we are really ending.
if (wParam) // if all apps aggreed to end session.
CloseMerc(); // This is the end. We will not get a
// WM_DESTROY message on end session.
break;
case WM_DESTROY:
// This is the end if we were closed by a DestroyWindow call.
CloseMerc();
PostQuitMessage(0);
break;
default:
if (message == uMercOpen)
new_descriptor( (HWND) wParam )
else if (message == uMercClose)
MessageBox(hWnd, "Somebody went down", "MercServ", MB_OK);
// else if (message == uMercSend)
// @@@
else
return(DefWindowProc(hWnd, message, wParam, lParam));
break;
}
return(0L);
}
#if 0
BOOL CALLBACK _export MercDlgProc(HWND hDlg, UINT message,
WPARAM wParam, LPARAM lParam)
{
static RECT wrect;
int x, y, w, h, i;
long rc;
// char *cp, *cpd, tmp[30], sdrives[30];
// HANDLE hCursor;
HWND hWndInput;
switch (message)
{
case WM_INITDIALOG:
// Save the handle of this proc for use by main window proc.
hQryDlgBox = hDlg;
// Save the handle to the output window
hWndOutput = GetDlgItem(hDlg, 102);
SetFocus(GetDlgItem(hDlg, 101));
// Get position of dialog box window.
GetWindowRect(hDlg, (LPRECT) &wrect);
w = wrect.right - wrect.left;
h = wrect.bottom - wrect.top;
// Move main application window to same position.
SetWindowPos(hWndMain, hDlg,
wrect.left, wrect.top, w, h,
0);
break;
case WM_MOVE:
// Always keep this dialog box on top of main window.
GetWindowRect(hWndMain, (LPRECT) &wrect);
x = wrect.left;
y = wrect.top;
w = wrect.right - wrect.left;
h = wrect.bottom - wrect.top;
MoveWindow(hDlg, x, y, w, h, 1);
break;
case WM_SYSCOMMAND:
// Pass WM_SYSCOMMAND messages on to main window so both
// main window and dialog box get iconized, minimized etc.
// in parallel.
SendMessage(hWndMain, message, wParam, lParam);
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDOK:
hWndInput = GetDlgItem(hDlg, 101);
SendMessage(hWndInput, WM_GETTEXT, sizeof UserMessage, (LPARAM) UserMessage);
SendMessage(hWndInput, WM_SETTEXT, 0, (LPARAM) "");
SetFocus(hWndInput);
fUserReady = TRUE;
break;
case IDCANCEL: // Cancel button
// Tell main application window we want to quit.
SendMessage(hWndMain, WM_CLOSE, 0, 0L);
break;
default:
break;
}
break;
case WM_CLOSE:
// Unlock dialog resource we locked above.
// Zero handle to this dialog window.
hQryDlgBox = 0;
// Tell main window to close.
PostMessage(hWndMain, WM_CLOSE, 0, 0L);
// Destroy ourseleves.
DestroyWindow(hDlg);
break;
default:
return FALSE;
}
return(TRUE);
}
#endif
void InitMerc22(HINSTANCE hInstance, int cmdShow)
{
WNDCLASS wcMercClass;
// Define the window class for this application.
wcMercClass.lpszClassName = "Merc22";
wcMercClass.hInstance = hInstance;
wcMercClass.lpfnWndProc = MercWndProc;
wcMercClass.hCursor = LoadCursor(NULL, IDC_ARROW);
// wcMercClass.hIcon = LoadIcon(hInstance, SetUpData.szAppName);
wcMercClass.hIcon = 0;
wcMercClass.lpszMenuName = (LPSTR) NULL;
wcMercClass.hbrBackground = GetStockObject(WHITE_BRUSH);
wcMercClass.style = CS_HREDRAW | CS_VREDRAW;
wcMercClass.cbClsExtra = 0;
wcMercClass.cbWndExtra = 0;
// Register the class
if (RegisterClass(&wcMercClass) == 0)
{
MessageBox(0, "Could not create Window", "@@@", MB_ICONHAND|MB_OK);
exit(1);
}
hInst = hInstance; // save for use by window procs
// Create applications main window.
hWndMain = CreateWindow(
"Merc22",
"Welcome to Merc22/Win32",
WS_BORDER |
WS_CAPTION |
WS_SYSMENU |
WS_MINIMIZEBOX,
10,
19,
256,
123,
NULL,
NULL,
hInstance,
NULL
);
CreateDialog(hInst, MAKEINTRESOURCE(1), hWndMain, (DLGPROC) MercDlgProc);
ShowWindow(hWndMain, cmdShow);
UpdateWindow(hWndMain);
}
void new_descriptor( HWND hWnd )
{
static DESCRIPTOR_DATA d_zero;
char buf[MAX_STRING_LENGTH];
DESCRIPTOR_DATA *dnew;
BAN_DATA *pban;
struct sockaddr_in sock;
struct hostent *from;
// int desc;
int size;
/*
* Cons a new descriptor.
*/
if ( descriptor_free == NULL )
{
dnew = alloc_perm( sizeof(*dnew) );
}
else
{
dnew = descriptor_free;
descriptor_free = descriptor_free->next;
}
*dnew = d_zero;
dnew->descriptor = (sh_int) hWnd;
dnew->connected = CON_GET_NAME;
dnew->showstr_head = NULL;
dnew->showstr_point = NULL;
dnew->outsize = 2000;
dnew->outbuf = alloc_mem( dnew->outsize );
sprintf(buf, "HWND: 0x%x", hWnd);
dnew->host = str_dup( buf );
/*
* Init descriptor data.
*/
dnew->next = descriptor_list;
descriptor_list = dnew;
/*
* Send the greeting.
*/
{
extern char * help_greeting;
if ( help_greeting[0] == '.' )
write_to_buffer( dnew, help_greeting+1, 0 );
else
write_to_buffer( dnew, help_greeting , 0 );
}
return;
}
WPARAM game_loop_win32(HINSTANCE hInstance, HINSTANCE hPrevInstance, int nCmdShow)
{
struct timeval last_time;
struct timeval now_time;
static DESCRIPTOR_DATA dcon;
DESCRIPTOR_DATA *d;
MSG msg;
// DWORD dwTick = -1;
BOOL fBackground;
gettimeofday( &last_time, NULL );
current_time = (time_t) last_time.tv_sec;
#if 0
/*
* New_descriptor analogue.
*/
dcon.descriptor = 0;
dcon.connected = CON_GET_NAME;
dcon.host = str_dup( "localhost" );
dcon.outsize = 2000;
dcon.outbuf = alloc_mem( dcon.outsize );
dcon.next = descriptor_list;
descriptor_list = &dcon;
/*
* Send the greeting.
*/
{
extern char * help_greeting;
if ( help_greeting[0] == '.' )
write_to_buffer( &dcon, help_greeting+1, 0 );
else
write_to_buffer( &dcon, help_greeting , 0 );
}
#endif
/* Main loop */
#if 1
// Go init this application.
InitMerc22(hInstance, nCmdShow);
// Get and dispatch messages for this applicaton.
fBackground = FALSE;
for ( ;; )
{
if (PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE))
{
if (msg.message == WM_QUIT)
break;
if (!IsDialogMessage(hQryDlgBox, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
else if (/*GetTickCount() > dwTick + 1000 &&*/ !fBackground)
{
fBackground++;
// dwTick = GetTickCount();
/*
* Process input.
*/
for ( d = descriptor_list; d != NULL; d = d_next )
{
if (PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE))
{
if (msg.message == WM_QUIT)
goto merc_done;
if (!IsDialogMessage(hQryDlgBox, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
d_next = d->next;
d->fcommand = FALSE;
if ( d->character != NULL )
d->character->timer = 0;
// Did the user break connection?
if ( !read_from_descriptor( d ) )
{
if ( d->character != NULL )
save_char_obj( d->character );
d->outtop = 0;
close_socket( d );
continue;
}
if ( d->character != NULL && d->character->wait > 0 )
{
--d->character->wait;
continue;
}
read_from_buffer( d );
if ( d->incomm[0] != '\0' )
{
d->fcommand = TRUE;
stop_idling( d->character );
if ( d->connected == CON_PLAYING )
if ( d->showstr_point )
show_string( d, d->incomm );
else
interpret( d->character, d->incomm );
else
nanny( d, d->incomm );
d->incomm[0] = '\0';
}
}
/*
* Autonomous game motion.
*/
update_handler( );
/*
* Output.
*/
for ( d = descriptor_list; d != NULL; d = d_next )
{
d_next = d->next;
if ( ( d->fcommand || d->outtop > 0 ) )
{
if ( !process_output( d, TRUE ) )
{
if ( d->character != NULL )
save_char_obj( d->character );
d->outtop = 0;
close_socket( d );
}
}
}
/*
* Synchronize to a clock.
* Busy wait (blargh).
*/
now_time = last_time;
for ( ; ; )
{
int delta;
{
if ( dcon.character != NULL )
dcon.character->timer = 0;
if ( !read_from_descriptor( &dcon ) )
{
if ( dcon.character != NULL )
save_char_obj( d->character );
dcon.outtop = 0;
close_socket( &dcon );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -