Exemplo n.º 1
0
void network_multiplexer_deleteclient(t_player *player)
{
  int max;

  if (player && player->client)
    {
      FD_CLR(player->client->sock[TCP], &g_core.network->fdset);
      FD_CLR(player->client->sock[TCP], &g_core.network->wfdset);
      player->client->disconnect(player->client);
      g_core.network->list_client->
	erase(g_core.network->list_client, player, NULL);
      if (player->client->sock[TCP] == (g_core.network->max_fd - 1))
	{
	  max = g_core.network->serv->sock[TCP];
	  g_core.network->list_client->foreach2(g_core.network->list_client,
						network_mutiplexer_maxfd, &max);
	  g_core.network->max_fd = max + 1;
	}
      network_multiplexer_deleteclient_treatement(player);
      network_multiplexer_deleteclient_stack(player);
      if (player->type == GRAPHIC)
	g_core.graphic->erase(g_core.graphic, player, NULL);
      delete_player(player);
    }
}
Exemplo n.º 2
0
void		dtor_egg(void *data)
{
  if (data)
    {
      if (((t_egg)data)->status && ((t_egg)data)->fetus)
	delete_player(((t_egg)data)->fetus);
      free(data);
    }
}
Exemplo n.º 3
0
/** Reset all of a player's player list entries (names/aliases).
 * This is called when a player changes name or alias.
 * We remove all their old entries, and add back their new ones.
 * \param player dbref of player
 * \param oldname player's former name (NULL if not changing)
 * \param oldalias player's former aliases (NULL if not changing)
 * \param name player's new name
 * \param alias player's new aliases
 */
void
reset_player_list(dbref player, const char *oldname, const char *oldalias,
                  const char *name, const char *alias)
{
  char tbuf1[BUFFER_LEN];
  char tbuf2[BUFFER_LEN];
  if (!oldname)
    name = Name(player);
  if (oldalias) {
    mush_strncpy(tbuf1, oldalias, BUFFER_LEN);
    if (alias) {
      strncpy(tbuf2, alias, BUFFER_LEN - 1);
      tbuf2[BUFFER_LEN - 1] = '\0';
    } else {
      tbuf2[0] = '\0';
    }
  } else {
    /* We are not changing aliases, just name, but we need to get the
     * aliases anyway, since we may change name to something that's
     * in the alias, and thus must not be deleted.
     */
    ATTR *a = atr_get_noparent(player, "ALIAS");
    if (a) {
      mush_strncpy(tbuf1, atr_value(a), BUFFER_LEN);
    } else {
      tbuf1[0] = '\0';
    }
    strcpy(tbuf2, tbuf1);
  }
  /* Delete all the old stuff */
  delete_player(player, tbuf1);
  delete_player(player, NULL);
  /* Add in the new stuff */
  add_player_alias(player, name);
  add_player_alias(player, tbuf2);
}
Exemplo n.º 4
0
static int run(void)
{
    player_t* pl[2];
    int res = 0;


    pl[0]= new_player(ch_stream1, ch_stream1_info, 0);
    pl[1]= new_player(ch_stream2, ch_stream2_info, 1);
    hd_channel_invalidate(ch_stream1, 1);
    hd_channel_invalidate(ch_stream2, 1);
    new_osd(ch_osd);
    start_thread();
    signal(SIGINT, signalhandler);
    signal(SIGQUIT, signalhandler);
    signal(SIGTERM, signalhandler);
    signal(SIGSEGV, signalhandlerCrash);
    signal(SIGBUS, signalhandlerCrash);

    hda->hdp_running=1;
    hda->active_player[0] = HD_PLAYER_MODE_LIVE; // Save mode
    hda->active_player[1] = HD_PLAYER_MODE_LIVE; // Save mode
    hda->osd_dont_touch&=~2; // Clear xine draw bit (prevent no fb osd if hdplayer crashes)
    /* TB: avoid busy-waiting */
    while ((res = run_player(pl[0])|run_player(pl[1]))) {
	    if(res==1) 
		    usleep(5*1000);
            if (hda->hdp_terminate==1)
		    break;
    };
    delete_player(pl[1]);
    delete_player(pl[0]);
    hda->hdp_terminate=0;
    printf("hdplayer clean exit %i\n",hda->hdp_terminate);

    return 0;
}
Exemplo n.º 5
0
// process all kick details (disconnecting players who have been kicked but haven't closed their socket)
void multi_kick_process()
{
	int idx;

	// if i'm not the server, don't do anything
	if(!(Net_player->flags & NETINFO_FLAG_AM_MASTER)){
		return;
	}

	// disconnect any kicked players who have timed out on leaving
	for(idx=0;idx<MAX_PLAYERS;idx++){
		if(MULTI_CONNECTED(Net_players[idx]) && (Net_players[idx].s_info.kick_timestamp != -1) && timestamp_elapsed(Net_players[idx].s_info.kick_timestamp) ){
			delete_player(idx, Net_players[idx].s_info.kick_reason);
		}
	}
}
Exemplo n.º 6
0
int main(int argc, char **argv) {
    srand(time(NULL));
    rand();
    if (argc == 2 || argc == 3) {
        char *hostname = argv[1];
        int port = DEFAULT_PORT;
        if (argc == 3) {
            port = atoi(argv[2]);
        }
        db_disable();
        client_enable();
        client_connect(hostname, port);
        client_start();
    }
    if (!glfwInit()) {
        return -1;
    }
    create_window();
    if (!window) {
        glfwTerminate();
        return -1;
    }
    glfwMakeContextCurrent(window);
    glfwSwapInterval(VSYNC);
    glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
    glfwSetKeyCallback(window, on_key);
    glfwSetMouseButtonCallback(window, on_mouse_button);
    glfwSetScrollCallback(window, on_scroll);

    #ifndef __APPLE__
        if (glewInit() != GLEW_OK) {
            return -1;
        }
    #endif

    if (db_init()) {
        return -1;
    }

    glEnable(GL_CULL_FACE);
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_LINE_SMOOTH);
    glLogicOp(GL_INVERT);
    glClearColor(0.53, 0.81, 0.92, 1.00);

    GLuint texture;
    glGenTextures(1, &texture);
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, texture);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    load_png_texture("texture.png");

    GLuint block_program = load_program(
        "shaders/block_vertex.glsl", "shaders/block_fragment.glsl");
    GLuint matrix_loc = glGetUniformLocation(block_program, "matrix");
    GLuint camera_loc = glGetUniformLocation(block_program, "camera");
    GLuint sampler_loc = glGetUniformLocation(block_program, "sampler");
    GLuint timer_loc = glGetUniformLocation(block_program, "timer");
    GLuint position_loc = glGetAttribLocation(block_program, "position");
    GLuint normal_loc = glGetAttribLocation(block_program, "normal");
    GLuint uv_loc = glGetAttribLocation(block_program, "uv");

    GLuint line_program = load_program(
        "shaders/line_vertex.glsl", "shaders/line_fragment.glsl");
    GLuint line_matrix_loc = glGetUniformLocation(line_program, "matrix");
    GLuint line_position_loc = glGetAttribLocation(line_program, "position");

    GLuint item_position_buffer = 0;
    GLuint item_normal_buffer = 0;
    GLuint item_uv_buffer = 0;
    int previous_block_type = 0;

    Chunk chunks[MAX_CHUNKS];
    int chunk_count = 0;

    Player players[MAX_PLAYERS];
    int player_count = 0;

    FPS fps = {0, 0};
    float matrix[16];
    float x = (rand_double() - 0.5) * 10000;
    float z = (rand_double() - 0.5) * 10000;
    float y = 0;
    float dy = 0;
    float rx = 0;
    float ry = 0;
    double px = 0;
    double py = 0;

    int loaded = db_load_state(&x, &y, &z, &rx, &ry);
    ensure_chunks(chunks, &chunk_count,
        floorf(roundf(x) / CHUNK_SIZE),
        floorf(roundf(z) / CHUNK_SIZE), 1);
    if (!loaded) {
        y = highest_block(chunks, chunk_count, x, z) + 2;
    }

    glfwGetCursorPos(window, &px, &py);
    double previous = glfwGetTime();
    while (!glfwWindowShouldClose(window)) {
        update_fps(&fps, SHOW_FPS);
        double now = glfwGetTime();
        double dt = MIN(now - previous, 0.2);
        previous = now;

        if (exclusive && (px || py)) {
            double mx, my;
            glfwGetCursorPos(window, &mx, &my);
            float m = 0.0025;
            rx += (mx - px) * m;
            ry -= (my - py) * m;
            if (rx < 0) {
                rx += RADIANS(360);
            }
            if (rx >= RADIANS(360)){
                rx -= RADIANS(360);
            }
            ry = MAX(ry, -RADIANS(90));
            ry = MIN(ry, RADIANS(90));
            px = mx;
            py = my;
        }
        else {
            glfwGetCursorPos(window, &px, &py);
        }

        int sz = 0;
        int sx = 0;
        ortho = glfwGetKey(window, 'F');
        fov = glfwGetKey(window, GLFW_KEY_LEFT_SHIFT) ? 15.0 : 65.0;
        if (glfwGetKey(window, 'Q')) break;
        if (glfwGetKey(window, 'W')) sz--;
        if (glfwGetKey(window, 'S')) sz++;
        if (glfwGetKey(window, 'A')) sx--;
        if (glfwGetKey(window, 'D')) sx++;
        float m = dt * 1.0;
        if (glfwGetKey(window, GLFW_KEY_LEFT)) rx -= m;
        if (glfwGetKey(window, GLFW_KEY_RIGHT)) rx += m;
        if (glfwGetKey(window, GLFW_KEY_UP)) ry += m;
        if (glfwGetKey(window, GLFW_KEY_DOWN)) ry -= m;
        float vx, vy, vz;
        get_motion_vector(flying, sz, sx, rx, ry, &vx, &vy, &vz);
        if (glfwGetKey(window, GLFW_KEY_SPACE)) {
            if (flying) {
                vy = 1;
            }
            else if (dy == 0) {
                dy = 8;
            }
        }
        if (glfwGetKey(window, 'Z')) {
            vx = -1; vy = 0; vz = 0;
        }
        if (glfwGetKey(window, 'X')) {
            vx = 1; vy = 0; vz = 0;
        }
        if (glfwGetKey(window, 'C')) {
            vx = 0; vy = -1; vz = 0;
        }
        if (glfwGetKey(window, 'V')) {
            vx = 0; vy = 1; vz = 0;
        }
        if (glfwGetKey(window, 'B')) {
            vx = 0; vy = 0; vz = -1;
        }
        if (glfwGetKey(window, 'N')) {
            vx = 0; vy = 0; vz = 1;
        }
        float speed = flying ? 20 : 5;
        int step = 8;
        float ut = dt / step;
        vx = vx * ut * speed;
        vy = vy * ut * speed;
        vz = vz * ut * speed;
        for (int i = 0; i < step; i++) {
            if (flying) {
                dy = 0;
            }
            else {
                dy -= ut * 25;
                dy = MAX(dy, -250);
            }
            x += vx;
            y += vy + dy * ut;
            z += vz;
            if (collide(chunks, chunk_count, 2, &x, &y, &z)) {
                dy = 0;
            }
        }
        if (y < 0) {
            y = highest_block(chunks, chunk_count, x, z) + 2;
        }

        for (int i = 0; i < chunk_count; i++) {
            Chunk *chunk = chunks + i;
            chunk->dirty = 0;
        }

        if (left_click) {
            left_click = 0;
            int hx, hy, hz;
            int hw = hit_test(chunks, chunk_count, 0, x, y, z, rx, ry,
                &hx, &hy, &hz);
            if (hy > 0 && is_destructable(hw)) {
                set_block(chunks, chunk_count, hx, hy, hz, 0, 1);
            }
        }

        if (right_click) {
            right_click = 0;
            int hx, hy, hz;
            int hw = hit_test(chunks, chunk_count, 1, x, y, z, rx, ry,
                &hx, &hy, &hz);
            if (is_obstacle(hw)) {
                if (!player_intersects_block(2, x, y, z, hx, hy, hz)) {
                    set_block(chunks, chunk_count, hx, hy, hz, block_type, 1);
                }
            }
        }

        if (middle_click) {
            middle_click = 0;
            int hx, hy, hz;
            int hw = hit_test(chunks, chunk_count, 0, x, y, z, rx, ry,
                &hx, &hy, &hz);
            if (is_selectable(hw)) {
                block_type = hw;
            }
        }

        if (teleport) {
            teleport = 0;
            if (player_count) {
                int index = rand_int(player_count);
                Player *player = players + index;
                x = player->x;
                y = player->y;
                z = player->z;
                rx = player->rx;
                ry = player->ry;
                ensure_chunks(chunks, &chunk_count,
                    floorf(roundf(x) / CHUNK_SIZE),
                    floorf(roundf(z) / CHUNK_SIZE), 1);
            }
        }

        client_position(x, y, z, rx, ry);
        char buffer[RECV_BUFFER_SIZE];
        while (client_recv(buffer, RECV_BUFFER_SIZE)) {
            float ux, uy, uz, urx, ury;
            if (sscanf(buffer, "U,%*d,%f,%f,%f,%f,%f",
                &ux, &uy, &uz, &urx, &ury) == 5)
            {
                x = ux; y = uy; z = uz; rx = urx; ry = ury;
                ensure_chunks(chunks, &chunk_count,
                    floorf(roundf(x) / CHUNK_SIZE),
                    floorf(roundf(z) / CHUNK_SIZE), 1);
                y = highest_block(chunks, chunk_count, x, z) + 2;
            }
            int bx, by, bz, bw;
            if (sscanf(buffer, "B,%*d,%*d,%d,%d,%d,%d",
                &bx, &by, &bz, &bw) == 4)
            {
                set_block(chunks, chunk_count, bx, by, bz, bw, 0);
                if ((int)roundf(x) == bx && (int)roundf(z) == bz) {
                    y = highest_block(chunks, chunk_count, x, z) + 2;
                }
            }
            int pid;
            float px, py, pz, prx, pry;
            if (sscanf(buffer, "P,%d,%f,%f,%f,%f,%f",
                &pid, &px, &py, &pz, &prx, &pry) == 6)
            {
                Player *player = find_player(players, player_count, pid);
                if (!player && player_count < MAX_PLAYERS) {
                    player = players + player_count;
                    player_count++;
                    player->id = pid;
                    player->position_buffer = 0;
                    player->normal_buffer = 0;
                    player->uv_buffer = 0;
                    printf("%d other players are online\n", player_count);
                }
                if (player) {
                    update_player(player, px, py, pz, prx, pry);
                }
            }
            if (sscanf(buffer, "D,%d", &pid) == 1) {
                delete_player(players, &player_count, pid);
                printf("%d other players are online\n", player_count);
            }
        }

        for (int i = 0; i < chunk_count; i++) {
            Chunk *chunk = chunks + i;
            if (chunk->dirty) {
                update_chunk(chunk);
            }
        }

        int p = floorf(roundf(x) / CHUNK_SIZE);
        int q = floorf(roundf(z) / CHUNK_SIZE);
        ensure_chunks(chunks, &chunk_count, p, q, 0);

        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        update_matrix_3d(matrix, x, y, z, rx, ry);

        // render chunks
        glUseProgram(block_program);
        glUniformMatrix4fv(matrix_loc, 1, GL_FALSE, matrix);
        glUniform3f(camera_loc, x, y, z);
        glUniform1i(sampler_loc, 0);
        glUniform1f(timer_loc, glfwGetTime());
        for (int i = 0; i < chunk_count; i++) {
            Chunk *chunk = chunks + i;
            if (chunk_distance(chunk, p, q) > RENDER_CHUNK_RADIUS) {
                continue;
            }
            if (!chunk_visible(chunk, matrix)) {
                continue;
            }
            draw_chunk(chunk, position_loc, normal_loc, uv_loc);
        }

        // render players
        for (int i = 0; i < player_count; i++) {
            Player *player = players + i;
            draw_player(player, position_loc, normal_loc, uv_loc);
        }

        // render focused block wireframe
        int hx, hy, hz;
        int hw = hit_test(
            chunks, chunk_count, 0, x, y, z, rx, ry, &hx, &hy, &hz);
        if (is_obstacle(hw)) {
            glUseProgram(line_program);
            glLineWidth(1);
            glEnable(GL_COLOR_LOGIC_OP);
            glUniformMatrix4fv(line_matrix_loc, 1, GL_FALSE, matrix);
            GLuint cube_buffer = make_cube_buffer(hx, hy, hz, 0.51);
            draw_lines(cube_buffer, line_position_loc, 3, 48);
            glDeleteBuffers(1, &cube_buffer);
            glDisable(GL_COLOR_LOGIC_OP);
        }

        update_matrix_2d(matrix);

        // render crosshairs
        glUseProgram(line_program);
        glLineWidth(4);
        glEnable(GL_COLOR_LOGIC_OP);
        glUniformMatrix4fv(line_matrix_loc, 1, GL_FALSE, matrix);
        GLuint line_buffer = make_line_buffer();
        draw_lines(line_buffer, line_position_loc, 2, 4);
        glDeleteBuffers(1, &line_buffer);
        glDisable(GL_COLOR_LOGIC_OP);

        // render selected item
        update_matrix_item(matrix);
        if (block_type != previous_block_type) {
            previous_block_type = block_type;
            make_single_cube(
                &item_position_buffer, &item_normal_buffer, &item_uv_buffer,
                0, 0, 0, 0.5, block_type);
        }
        glUseProgram(block_program);
        glUniformMatrix4fv(matrix_loc, 1, GL_FALSE, matrix);
        glUniform3f(camera_loc, 0, 0, 5);
        glUniform1i(sampler_loc, 0);
        glUniform1f(timer_loc, glfwGetTime());
        glDisable(GL_DEPTH_TEST);
        draw_single_cube(
            item_position_buffer, item_normal_buffer, item_uv_buffer,
            position_loc, normal_loc, uv_loc);
        glEnable(GL_DEPTH_TEST);

        glfwSwapBuffers(window);
        glfwPollEvents();
    }
    client_stop();
    db_save_state(x, y, z, rx, ry);
    db_close();
    glfwTerminate();
    return 0;
}
// called when a given netgame is about to end completely
void multi_endgame_cleanup()
{
	int idx;

	hud_config_as_player();

	send_leave_game_packet();			

	// flush all outgoing io, force all packets through
	multi_io_send_buffered_packets();
		
	// mark myself as disconnected
	if(!(Game_mode & GM_STANDALONE_SERVER)){
		Net_player->flags &= ~(NETINFO_FLAG_CONNECTED|NETINFO_FLAG_DO_NETWORKING);
	}
	
	/*this is a semi-hack so that if we're the master and we're quitting, we don't get an assert

    Karajorma - From the looks of things this code actually CAUSES an Int3 and doesn't cause an assert anymore
	besides if the game is over why are we setting flags on a Player_obj anyway? 

	if((Net_player->flags & NETINFO_FLAG_AM_MASTER) && (Player_obj != NULL)){
		Player_obj->flags &= ~(OF_PLAYER_SHIP);
		obj_set_flags( Player_obj, Player_obj->flags | OF_COULD_BE_PLAYER );
	}
	*/
	
	// shut my socket down (will also let the server know i've received any notifications/error from him)
	// psnet_rel_close_socket( &(Net_player->reliable_socket) );

	// 11/18/98 - DB, changed the above to kill all sockets. Its the safest thing to do
	for(idx=0; idx<MAX_PLAYERS; idx++){
		psnet_rel_close_socket(&Net_players[idx].reliable_socket);
		Net_players[idx].reliable_socket = INVALID_SOCKET;
	}

	// set the game quitting flag in our local netgame info - this will _insure_ that even if we miss a packet or
	// there is some sequencing error, the next time through the multi_do_frame() loop, the game will be ended
	// Netgame.flags |= (NG_FLAG_QUITTING | NG_FLAG_ENDED);

	// close all open SPX/TCP reliable sockets
	if(Net_player->flags & NETINFO_FLAG_AM_MASTER){
		// do it for all players, since we're leaving anyway.
		for(idx=0;idx<MAX_PLAYERS;idx++){
			// 6/25/98 -- MWA delete all players from the game

			if ( &Net_players[idx] != Net_player ) {
				delete_player( idx );
			}			
		}
	}	

	// if we're currently in the pause state, pop back into gameplay first
	if(gameseq_get_state() == GS_STATE_MULTI_PAUSED){
		gameseq_pop_state();
	}

	// handle game disconnect from FS2NetD (NOTE: must be done *before* standalone is reset!!)
	if ( MULTI_IS_TRACKER_GAME && (Net_player->flags & NETINFO_FLAG_AM_MASTER) ) {
		fs2netd_gameserver_disconnect();
	}

	if (Game_mode & GM_STANDALONE_SERVER) {
		// multi_standalone_quit_game();		
		multi_standalone_reset_all();
	} else {		
		Player->flags |= PLAYER_FLAGS_IS_MULTI;		

		// if we're in Parallax Online mode, log back in there	
		gameseq_post_event(GS_EVENT_MULTI_JOIN_GAME);		

		// if we have an error code, bring up the discon popup						
		if ( ((Multi_endgame_notify_code != -1) || (Multi_endgame_error_code != -1)) && !(Game_mode & GM_STANDALONE_SERVER) ) {
			multi_endgame_popup(Multi_endgame_notify_code,Multi_endgame_error_code,Multi_endgame_wsa_error);			
		}		
	}

	/*
	extern CFILE *obj_stream;
	if(obj_stream != NULL){
		cfclose(obj_stream);
		obj_stream = NULL;
	}
	*/	

	// unload the multiplayer common interface palette
	multi_common_unload_palette();
	
	// reinitialize endgame stuff
	// multi_endgame_init();
}
Exemplo n.º 8
0
Arquivo: wiz.c Projeto: hyena/fuzzball
void
do_toad(int descr, dbref player, const char *name, const char *recip)
{
	dbref victim;
	dbref recipient;
	dbref stuff;
	char buf[BUFFER_LEN];

	if (!Wizard(player) || Typeof(player) != TYPE_PLAYER) {
		notify(player, "Only a Wizard player can turn a person into a toad.");
		return;
	}
	if ((victim = lookup_player(name)) == NOTHING) {
		notify(player, "That player does not exist.");
		return;
	}
#ifdef GOD_PRIV
	if (God(victim)) {
		notify(player, "You cannot @toad God.");
		if(!God(player)) {
			log_status("TOAD ATTEMPT: %s(#%d) tried to toad God.",NAME(player),player);
		}
		return;
	}
#endif
	if(player == victim) {
		/* If GOD_PRIV isn't defined, this could happen: we don't want the
		 * last wizard to be toaded, in any case, so only someone else can
		 * do it. */
		notify(player, "You cannot toad yourself.  Get someone else to do it for you.");
		return;
	}

	if (victim == tp_toad_default_recipient) {
		notify(player, "That player is part of the @toad process, and cannot be deleted.");
		return;
	}

	if (!*recip) {
		recipient = tp_toad_default_recipient;
	} else {
		if ((recipient = lookup_player(recip)) == NOTHING || recipient == victim) {
			notify(player, "That recipient does not exist.");
			return;
		}
	}

	if (Typeof(victim) != TYPE_PLAYER) {
		notify(player, "You can only turn players into toads!");
#ifdef GOD_PRIV
	} else if (!(God(player)) && (TrueWizard(victim))) {
#else
	} else if (TrueWizard(victim)) {
#endif
		notify(player, "You can't turn a Wizard into a toad.");
	} else {
		/* we're ok */
		/* do it */
		send_contents(descr, victim, HOME);
		dequeue_prog(victim, 0);  /* Dequeue the programs that the player's running */
		for (stuff = 0; stuff < db_top; stuff++) {
			if (OWNER(stuff) == victim) {
				switch (Typeof(stuff)) {
				case TYPE_PROGRAM:
					dequeue_prog(stuff, 0);	/* dequeue player's progs */
					if (TrueWizard(recipient)) {
						FLAGS(stuff) &= ~(ABODE | WIZARD);
						SetMLevel(stuff, 1);
					}
				case TYPE_ROOM:
				case TYPE_THING:
				case TYPE_EXIT:
					OWNER(stuff) = recipient;
					DBDIRTY(stuff);
					break;
				}
			}
			if (Typeof(stuff) == TYPE_THING && THING_HOME(stuff) == victim) {
				THING_SET_HOME(stuff, tp_lost_and_found);
			}
		}

		chown_macros(victim, recipient);

		if (PLAYER_PASSWORD(victim)) {
			free((void *) PLAYER_PASSWORD(victim));
			PLAYER_SET_PASSWORD(victim, 0);
		}

		/* notify people */
		notify(victim, "You have been turned into a toad.");
		snprintf(buf, sizeof(buf), "You turned %s into a toad!", NAME(victim));
		notify(player, buf);
		log_status("TOADED: %s(%d) by %s(%d)", NAME(victim), victim, NAME(player), player);
		/* reset name */
		delete_player(victim);
		snprintf(buf, sizeof(buf), "A slimy toad named %s", NAME(victim));
		free((void *) NAME(victim));
		NAME(victim) = alloc_string(buf);
		DBDIRTY(victim);

		boot_player_off(victim); /* Disconnect the toad */

		if (PLAYER_DESCRS(victim)) {
			free(PLAYER_DESCRS(victim));
			PLAYER_SET_DESCRS(victim, NULL);
			PLAYER_SET_DESCRCOUNT(victim, 0);
		}

		ignore_remove_from_all_players(victim);
		ignore_flush_cache(victim);

		FREE_PLAYER_SP(victim);
		ALLOC_THING_SP(victim);
		THING_SET_HOME(victim, PLAYER_HOME(player));

		FLAGS(victim) = TYPE_THING;
		OWNER(victim) = player;	/* you get it */
		SETVALUE(victim, 1);	/* don't let him keep his immense wealth */
	}
}
Exemplo n.º 9
0
int main(int argc, char **argv) {
    srand(time(NULL));
    rand();
    if (argc == 2 || argc == 3) {
        char *hostname = argv[1];
        int port = DEFAULT_PORT;
        if (argc == 3) {
            port = atoi(argv[2]);
        }
        db_disable();
        client_enable();
        client_connect(hostname, port);
        client_start();
    }
    if (!glfwInit()) {
        return -1;
    }
    create_window();
    if (!window) {
        glfwTerminate();
        return -1;
    }
    glfwMakeContextCurrent(window);
    glfwSwapInterval(VSYNC);
    glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
    glfwSetKeyCallback(window, on_key);
    glfwSetCharCallback(window, on_char);
    glfwSetMouseButtonCallback(window, on_mouse_button);
    glfwSetScrollCallback(window, on_scroll);

    #ifndef __APPLE__
        if (glewInit() != GLEW_OK) {
            return -1;
        }
    #endif

    if (db_init()) {
        return -1;
    }

    glEnable(GL_CULL_FACE);
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_LINE_SMOOTH);
    glLogicOp(GL_INVERT);
    glClearColor(0.53, 0.81, 0.92, 1.00);

    GLuint texture;
    glGenTextures(1, &texture);
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, texture);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    load_png_texture("texture.png");

    GLuint font;
    glGenTextures(1, &font);
    glActiveTexture(GL_TEXTURE1);
    glBindTexture(GL_TEXTURE_2D, font);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    load_png_texture("font.png");

    GLuint block_program = load_program(
        "shaders/block_vertex.glsl", "shaders/block_fragment.glsl");
    GLuint matrix_loc = glGetUniformLocation(block_program, "matrix");
    GLuint camera_loc = glGetUniformLocation(block_program, "camera");
    GLuint sampler_loc = glGetUniformLocation(block_program, "sampler");
    GLuint timer_loc = glGetUniformLocation(block_program, "timer");
    GLuint position_loc = glGetAttribLocation(block_program, "position");
    GLuint normal_loc = glGetAttribLocation(block_program, "normal");
    GLuint uv_loc = glGetAttribLocation(block_program, "uv");

    GLuint line_program = load_program(
        "shaders/line_vertex.glsl", "shaders/line_fragment.glsl");
    GLuint line_matrix_loc = glGetUniformLocation(line_program, "matrix");
    GLuint line_position_loc = glGetAttribLocation(line_program, "position");

    GLuint text_program = load_program(
        "shaders/text_vertex.glsl", "shaders/text_fragment.glsl");
    GLuint text_matrix_loc = glGetUniformLocation(text_program, "matrix");
    GLuint text_sampler_loc = glGetUniformLocation(text_program, "sampler");
    GLuint text_position_loc = glGetAttribLocation(text_program, "position");
    GLuint text_uv_loc = glGetAttribLocation(text_program, "uv");

    GLuint item_position_buffer = 0;
    GLuint item_normal_buffer = 0;
    GLuint item_uv_buffer = 0;
    int previous_block_type = 0;
    char messages[MAX_MESSAGES][TEXT_BUFFER_SIZE] = {0};
    int message_index = 0;

    Chunk chunks[MAX_CHUNKS];
    int chunk_count = 0;

    Player players[MAX_PLAYERS];
    int player_count = 0;

    FPS fps = {0, 0};
    float matrix[16];
    float x = (rand_double() - 0.5) * 10000;
    float z = (rand_double() - 0.5) * 10000;
    float y = 0;
    float dy = 0;
    float rx = 0;
    float ry = 0;
    double px = 0;
    double py = 0;

    int loaded = db_load_state(&x, &y, &z, &rx, &ry);
    ensure_chunks(chunks, &chunk_count, x, y, z, 1);
    if (!loaded) {
        y = highest_block(chunks, chunk_count, x, z) + 2;
    }

    glfwGetCursorPos(window, &px, &py);
    double previous = glfwGetTime();
    while (!glfwWindowShouldClose(window)) {
        int width, height;
        glfwGetFramebufferSize(window, &width, &height);
        glViewport(0, 0, width, height);

        update_fps(&fps, SHOW_FPS);
        double now = glfwGetTime();
        double dt = MIN(now - previous, 0.2);
        previous = now;

        if (exclusive && (px || py)) {
            double mx, my;
            glfwGetCursorPos(window, &mx, &my);
            float m = 0.0025;
            rx += (mx - px) * m;
            ry -= (my - py) * m;
            if (rx < 0) {
                rx += RADIANS(360);
            }
            if (rx >= RADIANS(360)){
                rx -= RADIANS(360);
            }
            ry = MAX(ry, -RADIANS(90));
            ry = MIN(ry, RADIANS(90));
            px = mx;
            py = my;
        }
        else {
            glfwGetCursorPos(window, &px, &py);
        }

        int sz = 0;
        int sx = 0;
        if (!typing) {
            float m = dt * 1.0;
            ortho = glfwGetKey(window, CRAFT_KEY_ORTHO);
            fov = glfwGetKey(window, CRAFT_KEY_ZOOM) ? 15.0 : 65.0;
            if (glfwGetKey(window, CRAFT_KEY_QUIT)) break;
            if (glfwGetKey(window, CRAFT_KEY_FORWARD)) sz--;
            if (glfwGetKey(window, CRAFT_KEY_BACKWARD)) sz++;
            if (glfwGetKey(window, CRAFT_KEY_LEFT)) sx--;
            if (glfwGetKey(window, CRAFT_KEY_RIGHT)) sx++;
            if (glfwGetKey(window, GLFW_KEY_LEFT)) rx -= m;
            if (glfwGetKey(window, GLFW_KEY_RIGHT)) rx += m;
            if (glfwGetKey(window, GLFW_KEY_UP)) ry += m;
            if (glfwGetKey(window, GLFW_KEY_DOWN)) ry -= m;
        }
        float vx, vy, vz;
        get_motion_vector(flying, sz, sx, rx, ry, &vx, &vy, &vz);
        if (!typing) {
            if (glfwGetKey(window, CRAFT_KEY_JUMP)) {
                if (flying) {
                    vy = 1;
                }
                else if (dy == 0) {
                    dy = 8;
                }
            }
            if (glfwGetKey(window, CRAFT_KEY_XM)) {
                vx = -1; vy = 0; vz = 0;
            }
            if (glfwGetKey(window, CRAFT_KEY_XP)) {
                vx = 1; vy = 0; vz = 0;
            }
            if (glfwGetKey(window, CRAFT_KEY_YM)) {
                vx = 0; vy = -1; vz = 0;
            }
            if (glfwGetKey(window, CRAFT_KEY_YP)) {
                vx = 0; vy = 1; vz = 0;
            }
            if (glfwGetKey(window, CRAFT_KEY_ZM)) {
                vx = 0; vy = 0; vz = -1;
            }
            if (glfwGetKey(window, CRAFT_KEY_ZP)) {
                vx = 0; vy = 0; vz = 1;
            }
        }
        float speed = flying ? 20 : 5;
        int step = 8;
        float ut = dt / step;
        vx = vx * ut * speed;
        vy = vy * ut * speed;
        vz = vz * ut * speed;
        for (int i = 0; i < step; i++) {
            if (flying) {
                dy = 0;
            }
            else {
                dy -= ut * 25;
                dy = MAX(dy, -250);
            }
            x += vx;
            y += vy + dy * ut;
            z += vz;
            if (collide(chunks, chunk_count, 2, &x, &y, &z)) {
                dy = 0;
            }
        }
        if (y < 0) {
            y = highest_block(chunks, chunk_count, x, z) + 2;
        }

        if (left_click) {
            left_click = 0;
            int hx, hy, hz;
            int hw = hit_test(chunks, chunk_count, 0, x, y, z, rx, ry,
                &hx, &hy, &hz);
            if (hy > 0 && is_destructable(hw)) {
                set_block(chunks, chunk_count, hx, hy, hz, 0);
                int above = get_block(chunks, chunk_count, hx, hy + 1, hz);
                if (is_plant(above)) {
                    set_block(chunks, chunk_count, hx, hy + 1, hz, 0);
                }
            }
        }

        if (right_click) {
            right_click = 0;
            int hx, hy, hz;
            int hw = hit_test(chunks, chunk_count, 1, x, y, z, rx, ry,
                &hx, &hy, &hz);
            if (is_obstacle(hw)) {
                if (!player_intersects_block(2, x, y, z, hx, hy, hz)) {
                    set_block(chunks, chunk_count, hx, hy, hz, block_type);
                }
            }
        }

        if (middle_click) {
            middle_click = 0;
            int hx, hy, hz;
            int hw = hit_test(chunks, chunk_count, 0, x, y, z, rx, ry,
                &hx, &hy, &hz);
            if (is_selectable(hw)) {
                block_type = hw;
            }
        }

        if (teleport) {
            teleport = 0;
            if (player_count) {
                int index = rand_int(player_count);
                Player *player = players + index;
                x = player->x; y = player->y; z = player->z;
                rx = player->rx; ry = player->ry;
                ensure_chunks(chunks, &chunk_count, x, y, z, 1);
            }
        }

        client_position(x, y, z, rx, ry);
        char buffer[RECV_BUFFER_SIZE];
        while (client_recv(buffer, RECV_BUFFER_SIZE)) {
            float ux, uy, uz, urx, ury;
            if (sscanf(buffer, "U,%*d,%f,%f,%f,%f,%f",
                &ux, &uy, &uz, &urx, &ury) == 5)
            {
                x = ux; y = uy; z = uz; rx = urx; ry = ury;
                ensure_chunks(chunks, &chunk_count, x, y, z, 1);
                y = highest_block(chunks, chunk_count, x, z) + 2;
            }
            int bp, bq, bx, by, bz, bw;
            if (sscanf(buffer, "B,%d,%d,%d,%d,%d,%d",
                &bp, &bq, &bx, &by, &bz, &bw) == 6)
            {
                _set_block(chunks, chunk_count, bp, bq, bx, by, bz, bw);
                if (player_intersects_block(2, x, y, z, bx, by, bz)) {
                    y = highest_block(chunks, chunk_count, x, z) + 2;
                }
            }
            int pid;
            float px, py, pz, prx, pry;
            if (sscanf(buffer, "P,%d,%f,%f,%f,%f,%f",
                &pid, &px, &py, &pz, &prx, &pry) == 6)
            {
                Player *player = find_player(players, player_count, pid);
                if (!player && player_count < MAX_PLAYERS) {
                    player = players + player_count;
                    player_count++;
                    player->id = pid;
                    player->position_buffer = 0;
                    player->normal_buffer = 0;
                    player->uv_buffer = 0;
                }
                if (player) {
                    update_player(player, px, py, pz, prx, pry);
                }
            }
            if (sscanf(buffer, "D,%d", &pid) == 1) {
                delete_player(players, &player_count, pid);
            }
            if (buffer[0] == 'T' && buffer[1] == ',') {
                char *text = buffer + 2;
                printf("%s\n", text);
                snprintf(
                    messages[message_index], TEXT_BUFFER_SIZE, "%s", text);
                message_index = (message_index + 1) % MAX_MESSAGES;
            }
        }

        int p = chunked(x);
        int q = chunked(z);
        ensure_chunks(chunks, &chunk_count, x, y, z, 0);

        // RENDER 3-D SCENE //

        glClear(GL_COLOR_BUFFER_BIT);
        glClear(GL_DEPTH_BUFFER_BIT);
        set_matrix_3d(matrix, width, height, x, y, z, rx, ry, fov, ortho);

        // render chunks
        glUseProgram(block_program);
        glUniformMatrix4fv(matrix_loc, 1, GL_FALSE, matrix);
        glUniform3f(camera_loc, x, y, z);
        glUniform1i(sampler_loc, 0);
        glUniform1f(timer_loc, glfwGetTime());
        for (int i = 0; i < chunk_count; i++) {
            Chunk *chunk = chunks + i;
            if (chunk_distance(chunk, p, q) > RENDER_CHUNK_RADIUS) {
                continue;
            }
            if (y < 100 && !chunk_visible(chunk, matrix)) {
                continue;
            }
            draw_chunk(chunk, position_loc, normal_loc, uv_loc);
        }

        // render players
        for (int i = 0; i < player_count; i++) {
            Player *player = players + i;
            draw_player(player, position_loc, normal_loc, uv_loc);
        }

        // render focused block wireframe
        int hx, hy, hz;
        int hw = hit_test(
            chunks, chunk_count, 0, x, y, z, rx, ry, &hx, &hy, &hz);
        if (is_obstacle(hw)) {
            glUseProgram(line_program);
            glLineWidth(1);
            glEnable(GL_COLOR_LOGIC_OP);
            glUniformMatrix4fv(line_matrix_loc, 1, GL_FALSE, matrix);
            GLuint wireframe_buffer = gen_wireframe_buffer(hx, hy, hz, 0.51);
            draw_lines(wireframe_buffer, line_position_loc, 3, 48);
            glDeleteBuffers(1, &wireframe_buffer);
            glDisable(GL_COLOR_LOGIC_OP);
        }

        // RENDER 2-D HUD PARTS //

        glClear(GL_DEPTH_BUFFER_BIT);
        set_matrix_2d(matrix, width, height);

        // render crosshairs
        glUseProgram(line_program);
        glLineWidth(4);
        glEnable(GL_COLOR_LOGIC_OP);
        glUniformMatrix4fv(line_matrix_loc, 1, GL_FALSE, matrix);
        GLuint crosshair_buffer = gen_crosshair_buffer(width, height);
        draw_lines(crosshair_buffer, line_position_loc, 2, 4);
        glDeleteBuffers(1, &crosshair_buffer);
        glDisable(GL_COLOR_LOGIC_OP);

        // render text
        glUseProgram(text_program);
        glUniformMatrix4fv(text_matrix_loc, 1, GL_FALSE, matrix);
        glUniform1i(text_sampler_loc, 1);
        char text_buffer[1024];
        float ts = 12;
        float tx = ts / 2;
        float ty = height - ts;
        snprintf(
            text_buffer, 1024, "%d, %d, %.2f, %.2f, %.2f [%d, %d]",
            p, q, x, y, z, player_count, chunk_count);
        print(
            text_position_loc, text_uv_loc,
            tx, ty, ts, text_buffer);
        for (int i = 0; i < MAX_MESSAGES; i++) {
            int index = (message_index + i) % MAX_MESSAGES;
            if (strlen(messages[index])) {
                ty -= ts * 2;
                print(
                    text_position_loc, text_uv_loc,
                    tx, ty, ts, messages[index]);
            }
        }
        if (typing) {
            ty -= ts * 2;
            snprintf(text_buffer, 1024, "> %s", typing_buffer);
            print(
                text_position_loc, text_uv_loc,
                tx, ty, ts, text_buffer);
        }

        // RENDER 3-D HUD PARTS //

        set_matrix_item(matrix, width, height);

        // render selected item
        if (block_type != previous_block_type) {
            previous_block_type = block_type;
            if (is_plant(block_type)) {
                gen_plant_buffers(
                    &item_position_buffer, &item_normal_buffer, &item_uv_buffer,
                    0, 0, 0, 0.5, block_type);
            }
            else {
                gen_cube_buffers(
                    &item_position_buffer, &item_normal_buffer, &item_uv_buffer,
                    0, 0, 0, 0.5, block_type);
            }
        }
        glUseProgram(block_program);
        glUniformMatrix4fv(matrix_loc, 1, GL_FALSE, matrix);
        glUniform3f(camera_loc, 0, 0, 5);
        glUniform1i(sampler_loc, 0);
        glUniform1f(timer_loc, glfwGetTime());
        if (is_plant(block_type)) {
            draw_plant(
                item_position_buffer, item_normal_buffer, item_uv_buffer,
                position_loc, normal_loc, uv_loc);
        }
        else {
            draw_cube(
                item_position_buffer, item_normal_buffer, item_uv_buffer,
                position_loc, normal_loc, uv_loc);
        }

        // swap buffers
        glfwSwapBuffers(window);
        glfwPollEvents();
    }
    client_stop();
    db_save_state(x, y, z, rx, ry);
    db_close();
    glfwTerminate();
    return 0;
}
int NEAR PASCAL CommandHandler(WORD wParam, LONG lParam)
{
/*  if (HIWORD(lParam) == EN_CHANGE)
  {
    if (focus(GetDlgCtrlID(LOWORD(lParam))) && players.player_numb > -1)
      bNeedSaveP = TRUE;
    else if (courses.course_numb > -1)
      bNeedSaveC = TRUE;
  }
*/
  switch (wParam)
  {
    case IDOK:
      SendMessage(hWnd, WM_COMMAND, IDD_RLIST, MAKELONG(0, LBN_DBLCLK));
      return NULL;

    case IDM_CONTENTS:
    case IDM_SEARCHON:
    case IDM_USE:
      MessageBox(hWnd, "Help to come soon!", szAppName, MB_OK | MB_ICONEXCLAMATION);
      return NULL;

    case IDM_ABOUT:  /* display about dialog box */
      lpfnGenericDlgProc = MakeProcInstance((FARPROC)AboutDlgProc, hInst);
      DialogBox(hInst, "ABOUT", hWnd, lpfnGenericDlgProc);
      FreeProcInstance(lpfnGenericDlgProc); /* Release memory */
      return NULL;

    case IDM_HANDICAP:
      lpfnGenericDlgProc = MakeProcInstance((FARPROC)HandicapDlgProc, hInst);
      DialogBox(hInst, "HANDICAP", hWnd, lpfnGenericDlgProc);
      FreeProcInstance(lpfnGenericDlgProc); /* Release memory */
      return NULL;

    case IDM_P_SEARCH:
      if (!get_player(hWnd, &players, p_index, r_index))
	return NULL;
      /* fall through */

    case IDM_C_SEARCH:
      if (!get_course(hWnd, &courses, c_index))
	return NULL;
	wWhich = wParam;
	lpfnGenericDlgProc = MakeProcInstance((FARPROC)SearchDlgProc, hInst);
	DialogBox(hInst, "SEARCH", hWnd, lpfnGenericDlgProc);
	FreeProcInstance(lpfnGenericDlgProc); /* Release memory */
	return NULL;

    case IDM_GRAPH:
      if (!get_player(hWnd, &players, p_index, r_index))
	return NULL;
      if (!get_course(hWnd, &courses, c_index))
	return NULL;
      if (IDYES == MessageBox(hWnd, "You must have Microsoft Excel\nto use this option.  Continue?",
			      szAppName, MB_YESNO | MB_ICONQUESTION))
	GraphData(&(players).player[p_index].p_scores, &courses);
      return NULL;

    case IDM_NEW_P: /* save current file and clear viewport */
      if (bNeedSaveP && IDCANCEL == AskAboutSave(hWnd, szFileTitleP, PLAYER_MARKER))
	return FALSE;
      szFileTitleP[NULL] = '\0';
      bNeedSaveP = FALSE;
      p_index = r_index = r_last = 0;
      players.player_numb = -1;
      clear_player(hWnd, hWndRList);
      DoCaption(hWnd, szFileTitleP, szFileTitleC);
      return NULL;

    case IDM_NEW_C:
      if (bNeedSaveC && IDCANCEL == AskAboutSave(hWnd, szFileTitleC, COURSE_MARKER))
	return FALSE;
      szFileTitleC[NULL] = '\0';
      bNeedSaveC = FALSE;
      c_index = 0;
      courses.course_numb = -1;
      clear_course(hWnd);
      DoCaption(hWnd, szFileTitleP, szFileTitleC);
      return NULL;

    case IDM_OPEN_P:  /* open an existing file */
      of_player.lpstrTitle = "Open Player";
      of_player.Flags      = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY;

      if (!GetOpenFileName(&of_player))
	return FALSE;

      if (ReadFile(hWnd, szFileP, szFileTitleP, szFileTitleC, bNeedSaveP,
		   &players, &courses, PLAYER_MARKER))
      {
	bNeedSaveP = FALSE;
	p_index = 0;
	show_player(hWnd, hWndRList, &players, &p_index, &r_index, &r_last);
	DoCaption(hWnd, szFileTitleP, szFileTitleC);
      } /* if */
      return NULL;

    case IDM_OPEN_C:  /* open an existing file */
      of_course.lpstrTitle = "Open Course";
      of_course.Flags      = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY;

      if (!GetOpenFileName(&of_course))
	return FALSE;

      if (ReadFile(hWnd, szFileC, szFileTitleP, szFileTitleC, bNeedSaveC,
		   &players, &courses, COURSE_MARKER))
      {
	bNeedSaveC = FALSE;
	c_index = 0;
	show_course(hWnd, &courses, &c_index);
	DoCaption(hWnd, szFileTitleP, szFileTitleC);
      } /* if */
      return NULL;

    case IDM_SAVE_P:  /* write current file */
      if (szFileTitleP[NULL])
      {
	if (!get_player(hWnd, &players, p_index, r_index))
	  return NULL;

	if (WriteFile(hWnd, szFileP, &players, &courses, PLAYER_MARKER,
		      p_index, r_index, c_index))
	{
	  bNeedSaveP = FALSE;
	  return 1;
	} /* if */
	return NULL;
      } /* if fall through */

    case IDM_SAVEAS_P:  /* change file name */
      if (!get_player(hWnd, &players, p_index, r_index))
	return NULL;

      of_player.lpstrTitle = "Save Player";
      of_player.Flags      = OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;

      if (!GetSaveFileName(&of_player))
	return FALSE;

      if (WriteFile(hWnd, szFileP, &players, &courses, PLAYER_MARKER,
		    p_index, r_index, c_index))
      {
	bNeedSaveP = FALSE;
	DoCaption(hWnd, szFileTitleP, szFileTitleC);
      }
      return NULL;

    case IDM_SAVE_C:  /* write current file */
      if (szFileTitleC[NULL])
      {
	if (!get_course(hWnd, &courses, c_index))
	  return NULL;

	if (WriteFile(hWnd, szFileC, &players, &courses, COURSE_MARKER,
		      p_index, r_index, c_index))
	{
	  bNeedSaveC = FALSE;
	  return 1;
	} /* if */
	return NULL;
      } /* if fall through */

    case IDM_SAVEAS_C:  /* change file name */
      if (!get_course(hWnd, &courses, c_index))
	return NULL;

      of_course.lpstrTitle = "Save Course";
      of_course.Flags      = OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;

      if (!GetSaveFileName(&of_course))
	return FALSE;

      if (WriteFile(hWnd, szFileC, &players, &courses, COURSE_MARKER,
		    p_index, r_index, c_index))
      {
	bNeedSaveC = FALSE;
	DoCaption(hWnd, szFileTitleP, szFileTitleC);
      }
      return NULL;

    case IDM_PRINT_P:  /* Print current file */
      if (!get_player(hWnd, &players, p_index, r_index))
	return NULL;
      PrintFile(hInst, hWnd, szFileTitleP[NULL] ? szFileTitleP : szUntitled);
      return NULL;

    case IDM_PRINT_C:  /* Print current file */
      if (!get_course(hWnd, &courses, c_index))
	return NULL;
      PrintFile(hInst, hWnd, szFileTitleC[NULL] ? szFileTitleC : szUntitled);
      return NULL;

    case IDM_EXIT:  /* Send a close message, and exit the program */
      SendMessage(hWnd, WM_CLOSE, NULL, 0L);
      return NULL;

    case IDM_UNDO:  /* Check for undo status */
      SendMessage(GetFocus(), WM_UNDO, 0, 0L);
      return 0;

    case IDM_CUT:  /* Send cut message */
      SendMessage(GetFocus(), WM_CUT, 0, 0L);
      return 0;

    case IDM_COPY: /* Send copy message */
      SendMessage(GetFocus(), WM_COPY, 0, 0L);
      return 0;

    case IDM_PASTE:  /* Send paste message */
      SendMessage(GetFocus(), WM_PASTE, 0, 0L);
      return 0;

    case IDM_CLEAR:  /* Send clear message */
      SendMessage(GetFocus(), WM_CLEAR, 0, 0L);
      return 0;

    case IDM_P_ADD:
      if (AddPlayer(hWnd, &players, &p_index, &r_index))
	bNeedSaveP = TRUE;
      return NULL;

    case IDM_R_ADD:
      if (AddRound(hWnd, &players, &p_index, &r_index, &r_last))
	bNeedSaveP = TRUE;
      return NULL;

    case IDM_C_ADD:
      if (AddCourse(hWnd, &courses, &c_index))
	bNeedSaveC = TRUE;
      return NULL;

    case IDM_P_SORT:
      if (!get_player(hWnd, &players, p_index, r_index))
	return NULL;
      qsort(players.player, players.player_numb+1, sizeof(players.player[0]),
	    compare_player);
      bNeedSaveP = TRUE;
      p_index = r_index = 0;
      show_player(hWnd, hWndRList, &players, &p_index, &r_index, &r_last);
      return NULL;

    case IDM_R_SORT:
      if (!get_player(hWnd, &players, p_index, r_index))
	return NULL;
      qsort(players.player[p_index].p_scores.history,
	    players.player[p_index].p_scores.round_numb+1,
	    sizeof(players.player[p_index].p_scores.history[0]),
	    compare_round);
      bNeedSaveP = TRUE;
      r_index = 0;
      show_player(hWnd, hWndRList, &players, &p_index, &r_index, &r_last);
      return NULL;

    case IDM_C_SORT:
      if (!get_course(hWnd, &courses, c_index))
	return NULL;
      qsort(courses.course, courses.course_numb, sizeof(courses.course[0]),
	    compare_course);
      bNeedSaveC = TRUE;
      c_index = 0;
      show_course(hWnd, &courses, &c_index);
      return NULL;

    case IDM_P_DELETE:
      if (players.player_numb > -1)
      {
	GetDlgItemText(hWnd, IDD_PLAST, (players).player[p_index].p_last, LAST_NAME_LENGTH+1);
	GetDlgItemText(hWnd, IDD_PFIRST, (players).player[p_index].p_first, FIRST_NAME_LENGTH+1);
	lstrcpy(szDelete, "Delete : ");
	lstrcat(szDelete, (LPSTR)players.player[p_index].p_first);
	lstrcat(szDelete, " ");
	lstrcat(szDelete, (LPSTR)players.player[p_index].p_last);
	if (IDYES == MessageBox(hWnd, szDelete, "Delete Player", MB_YESNO | MB_ICONQUESTION))
	{
	  bNeedSaveP = TRUE;
	  delete_player(hWnd, hWndRList, &players, &p_index, &r_index, &r_last);
	}
      } /* if */
      return NULL;

    case IDM_R_DELETE:
      if (players.player[p_index].p_scores.round_numb > -1)
      {
	convert_date(&players.player[p_index].p_scores.history[r_index].date,
		     szDate);
	lstrcpy(szDelete, (LPSTR)"Delete : ");
	lstrcat(szDelete, (LPSTR)players.player[p_index].p_scores.history[r_index].course_name);
	lstrcat(szDelete, "  ");
	lstrcat(szDelete, szDate);
	if (IDYES == MessageBox(hWnd, szDelete, "Delete Round", MB_YESNO | MB_ICONQUESTION))
	{
	  delete_round(hWnd, hWndRList, &players, &p_index, &r_index, &r_last);
	  bNeedSaveP = TRUE;
	} /* if */
      } /* if */
      return NULL;

    case IDM_C_DELETE:
      if (courses.course_numb > -1)
      {
	GetDlgItemText(hWnd, IDD_CNAME, (courses).course[c_index].c_name, COURSE_NAME_LENGTH+1);
	lstrcpy(szc_name, (courses).course[c_index].c_name);
	lpfnGenericDlgProc = MakeProcInstance((FARPROC)DeleteCourseDlgProc, hInst);
	DialogBox(hInst, "DELETEC", hWnd, lpfnGenericDlgProc);
	FreeProcInstance(DeleteCourseDlgProc); /* Release memory */
	if (bYesNo == IDYES)
	{
	  bNeedSaveC = TRUE;
	  delete_course(&courses, &c_index);
	  if (bDeleteRounds &&  delete_rounds(&players, szc_name))
	  {
	    bNeedSaveP = TRUE;
	    show_rounds(hWnd, hWndRList, &(players).player[p_index].p_scores, &r_index, &r_last, TRUE);
	  } /* if */
	  show_course(hWnd, &courses, &c_index);
	} /* if */
      } /* if */
      return NULL;

    case IDD_RLIST:
      switch(HIWORD(lParam))
      {
	case LBN_DBLCLK:
	  if ((players.player_numb == -1) ||
	      (players.player[p_index].p_scores.round_numb == -1))
	    return NULL;
	  lstrcpy(szNDTitle, "Change Course / Name Date");
	  convert_date(&players.player[p_index].p_scores.history[r_index].date, szDate);
	  get_date_elements(szDate, szmm, szdd, szyy);
	  lstrcpy(szc_name, (LPSTR)players.player[p_index].p_scores.history[r_index].course_name);
	  lpfnGenericDlgProc = MakeProcInstance((FARPROC)NameDateDlgProc, hInst);
	  DialogBox(hInst, "NAMEDATE", hWnd, lpfnGenericDlgProc);
	  FreeProcInstance(NameDateDlgProc); /* Release memory */
	  if (bNameDate == IDOK)
	  {
	    bNeedSaveP = TRUE;
	    players.player[p_index].p_scores.history[r_index].date =
	      string_to_date(szmm, szdd, szyy);
	    lstrcpy((LPSTR)players.player[p_index].p_scores.history[r_index].course_name,
		    szc_name);
	    show_rounds(hWnd, hWndRList, &(players).player[p_index].p_scores, &r_index, &r_last, FALSE);
	  } /* if */
	  return NULL;

	case LBN_SELCHANGE:
	  if ((int)SendMessage(hWndRList, LB_GETCURSEL, 0, 0L) == r_index)
	    break;
	  if (!get_round(hWnd, &players, p_index, r_index))
	  {
	    SendMessage(hWndRList, LB_SETCURSEL, r_index, 0L);
	    return NULL;
	  }
	  r_index = (int)SendMessage(hWndRList, LB_GETCURSEL, 0, 0L);
	  if (r_index != LB_ERR && r_index != r_last)
	  {
	    show_round(hWnd, players.player[p_index].p_scores.history[r_index].score);
	    r_last = r_index;
	  } /* if */
	  return NULL;
      }  /* switch (HIWORD(lParam)) */
      return NULL;

    default:
      return FALSE;
  }  /* switch (wParam) */
} /* CommandHandler */