mirror of
https://github.com/p2r3/bareiron.git
synced 2025-10-01 23:25:09 +02:00
add more mob types
This commit is contained in:
@@ -28,8 +28,8 @@
|
|||||||
#define GAMEMODE 0
|
#define GAMEMODE 0
|
||||||
// Max render distance, determines how many chunks to send
|
// Max render distance, determines how many chunks to send
|
||||||
#define VIEW_DISTANCE 2
|
#define VIEW_DISTANCE 2
|
||||||
// Time between server ticks in microseconds (default = 2s)
|
// Time between server ticks in microseconds (default = 1s)
|
||||||
#define TIME_BETWEEN_TICKS 2000000
|
#define TIME_BETWEEN_TICKS 1000000
|
||||||
// How many visited chunks to "remember"
|
// How many visited chunks to "remember"
|
||||||
// The server will not re-send chunks that the player has recently been in
|
// The server will not re-send chunks that the player has recently been in
|
||||||
#define VISITED_HISTORY 4
|
#define VISITED_HISTORY 4
|
||||||
@@ -51,7 +51,7 @@ extern uint8_t recv_buffer[256];
|
|||||||
extern uint32_t world_seed;
|
extern uint32_t world_seed;
|
||||||
extern uint32_t rng_seed;
|
extern uint32_t rng_seed;
|
||||||
|
|
||||||
extern uint64_t world_time;
|
extern uint16_t world_time;
|
||||||
|
|
||||||
extern uint16_t client_count;
|
extern uint16_t client_count;
|
||||||
|
|
||||||
|
@@ -29,7 +29,7 @@ uint8_t recv_buffer[256] = {0};
|
|||||||
uint32_t world_seed = 0xA103DE6C;
|
uint32_t world_seed = 0xA103DE6C;
|
||||||
uint32_t rng_seed = 0xE2B9419;
|
uint32_t rng_seed = 0xE2B9419;
|
||||||
|
|
||||||
uint64_t world_time = 0;
|
uint16_t world_time = 0;
|
||||||
|
|
||||||
uint16_t client_count;
|
uint16_t client_count;
|
||||||
|
|
||||||
|
20
src/main.c
20
src/main.c
@@ -282,12 +282,28 @@ void handlePacket (int client_fd, int length, int packet_id) {
|
|||||||
start = clock();
|
start = clock();
|
||||||
|
|
||||||
uint32_t r = fast_rand();
|
uint32_t r = fast_rand();
|
||||||
|
// One in every 4 new chunks spawns a mob
|
||||||
if ((r & 3) == 0) {
|
if ((r & 3) == 0) {
|
||||||
|
// The mob is placed in the middle of the new chunk row,
|
||||||
|
// at a random position within the chunk
|
||||||
short mob_x = (_x + dx * VIEW_DISTANCE) * 16 + ((r >> 4) & 15);
|
short mob_x = (_x + dx * VIEW_DISTANCE) * 16 + ((r >> 4) & 15);
|
||||||
short mob_z = (_z + dz * VIEW_DISTANCE) * 16 + ((r >> 8) & 15);
|
short mob_z = (_z + dz * VIEW_DISTANCE) * 16 + ((r >> 8) & 15);
|
||||||
uint8_t mob_y = getHeightAt(mob_x, mob_z) + 1;
|
uint8_t mob_y = getHeightAt(mob_x, mob_z) + 1;
|
||||||
if (getBlockAt(mob_x, mob_y, mob_z) == B_air) {
|
// Ensure that there's space to spawn the mob
|
||||||
spawnMob(95, mob_x, mob_y, mob_z);
|
if (
|
||||||
|
getBlockAt(mob_x, mob_y, mob_z) == B_air &&
|
||||||
|
getBlockAt(mob_x, mob_y + 1, mob_z) == B_air
|
||||||
|
) {
|
||||||
|
// Spawn passive mobs during the day, hostiles during the night
|
||||||
|
if (world_time < 12000) {
|
||||||
|
uint32_t mob_choice = (r >> 12) & 3;
|
||||||
|
if (mob_choice == 0) spawnMob(25, mob_x, mob_y, mob_z); // Chicken
|
||||||
|
else if (mob_choice == 1) spawnMob(28, mob_x, mob_y, mob_z); // Cow
|
||||||
|
else if (mob_choice == 2) spawnMob(95, mob_x, mob_y, mob_z); // Pig
|
||||||
|
else if (mob_choice == 3) spawnMob(106, mob_x, mob_y, mob_z); // Sheep
|
||||||
|
} else {
|
||||||
|
spawnMob(145, mob_x, mob_y, mob_z); // Zombie
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -259,7 +259,7 @@ int sc_updateTime (int client_fd, uint64_t ticks) {
|
|||||||
writeVarInt(client_fd, sizeVarInt(0x6A) + 17);
|
writeVarInt(client_fd, sizeVarInt(0x6A) + 17);
|
||||||
writeVarInt(client_fd, 0x6A);
|
writeVarInt(client_fd, 0x6A);
|
||||||
|
|
||||||
writeUint64(client_fd, ticks);
|
writeUint64(client_fd, get_program_time() / 50000);
|
||||||
writeUint64(client_fd, ticks);
|
writeUint64(client_fd, ticks);
|
||||||
writeByte(client_fd, true);
|
writeByte(client_fd, true);
|
||||||
|
|
||||||
|
@@ -504,7 +504,7 @@ void spawnMob (uint8_t type, short x, uint8_t y, short z) {
|
|||||||
player_data[j].client_fd,
|
player_data[j].client_fd,
|
||||||
65536 + i, // Try to avoid conflict with client file descriptors
|
65536 + i, // Try to avoid conflict with client file descriptors
|
||||||
recv_buffer, // The UUID doesn't matter, feed it garbage
|
recv_buffer, // The UUID doesn't matter, feed it garbage
|
||||||
type, x, y, z,
|
type, (double)x + 0.5f, y, (double)z + 0.5f,
|
||||||
// Face opposite of the player, as if looking at them when spawning
|
// Face opposite of the player, as if looking at them when spawning
|
||||||
(player_data[j].yaw + 127) & 255, 0
|
(player_data[j].yaw + 127) & 255, 0
|
||||||
);
|
);
|
||||||
@@ -520,7 +520,7 @@ void spawnMob (uint8_t type, short x, uint8_t y, short z) {
|
|||||||
void handleServerTick (int64_t time_since_last_tick) {
|
void handleServerTick (int64_t time_since_last_tick) {
|
||||||
|
|
||||||
// Send Keep Alive and Update Time packets to all in-game clients
|
// Send Keep Alive and Update Time packets to all in-game clients
|
||||||
world_time += 20 * time_since_last_tick / 1000000;
|
world_time = (world_time + 20 * time_since_last_tick / 1000000) % 24000;
|
||||||
for (int i = 0; i < MAX_PLAYERS; i ++) {
|
for (int i = 0; i < MAX_PLAYERS; i ++) {
|
||||||
if (player_data[i].client_fd == -1) continue;
|
if (player_data[i].client_fd == -1) continue;
|
||||||
sc_keepAlive(player_data[i].client_fd);
|
sc_keepAlive(player_data[i].client_fd);
|
||||||
@@ -540,33 +540,46 @@ void handleServerTick (int64_t time_since_last_tick) {
|
|||||||
for (int i = 0; i < MAX_MOBS; i ++) {
|
for (int i = 0; i < MAX_MOBS; i ++) {
|
||||||
if (mob_data[i].type == 0) continue;
|
if (mob_data[i].type == 0) continue;
|
||||||
|
|
||||||
|
uint8_t passive = (
|
||||||
|
mob_data[i].type == 25 || // Chicken
|
||||||
|
mob_data[i].type == 28 || // Cow
|
||||||
|
mob_data[i].type == 95 || // Pig
|
||||||
|
mob_data[i].type == 106 // Sheep
|
||||||
|
);
|
||||||
|
|
||||||
uint32_t r = fast_rand();
|
uint32_t r = fast_rand();
|
||||||
|
|
||||||
// Skip 50% of ticks randomly
|
// Skip 25% of passive mob ticks randomly
|
||||||
if (r & 1) continue;
|
if (passive && (r & 3)) continue;
|
||||||
|
|
||||||
// Find the player closest to this mob
|
// Find the player closest to this mob
|
||||||
uint16_t closest_x = 65535, closest_z = 65535;
|
PlayerData* closest_player;
|
||||||
|
uint32_t closest_dist = 65535;
|
||||||
for (int j = 0; j < MAX_PLAYERS; j ++) {
|
for (int j = 0; j < MAX_PLAYERS; j ++) {
|
||||||
if (player_data[j].client_fd == -1) continue;
|
if (player_data[j].client_fd == -1) continue;
|
||||||
uint16_t dist_x = abs(mob_data[i].x - player_data[j].x);
|
uint16_t curr_dist = (
|
||||||
uint16_t dist_z = abs(mob_data[i].z - player_data[j].z);
|
abs(mob_data[i].x - player_data[j].x) +
|
||||||
if (dist_x + dist_z < closest_x + closest_z) {
|
abs(mob_data[i].z - player_data[j].z)
|
||||||
closest_x = dist_x;
|
);
|
||||||
closest_z = dist_z;
|
if (curr_dist < closest_dist) {
|
||||||
|
closest_dist = curr_dist;
|
||||||
|
closest_player = &player_data[j];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Despawn mobs past a certain distance from nearest player
|
// Despawn mobs past a certain distance from nearest player
|
||||||
if (closest_x + closest_z > MOB_DESPAWN_DISTANCE) {
|
if (closest_dist > MOB_DESPAWN_DISTANCE) {
|
||||||
mob_data[i].type = 0;
|
mob_data[i].type = 0;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move by one block on the X or Z axis
|
|
||||||
// Yaw is set to face in the direction of motion
|
|
||||||
short new_x = mob_data[i].x, new_z = mob_data[i].z;
|
short new_x = mob_data[i].x, new_z = mob_data[i].z;
|
||||||
uint8_t yaw;
|
uint8_t new_y = mob_data[i].y, yaw = 0;
|
||||||
|
|
||||||
|
if (passive) { // Passive mob movement handling
|
||||||
|
|
||||||
|
// Move by one block on the X or Z axis
|
||||||
|
// Yaw is set to face in the direction of motion
|
||||||
if ((r >> 2) & 1) {
|
if ((r >> 2) & 1) {
|
||||||
if ((r >> 1) & 1) { new_x += 1; yaw = 192; }
|
if ((r >> 1) & 1) { new_x += 1; yaw = 192; }
|
||||||
else { new_x -= 1; yaw = 64; }
|
else { new_x -= 1; yaw = 64; }
|
||||||
@@ -575,14 +588,42 @@ void handleServerTick (int64_t time_since_last_tick) {
|
|||||||
else { new_z -= 1; yaw = 128; }
|
else { new_z -= 1; yaw = 128; }
|
||||||
}
|
}
|
||||||
// Vary the yaw angle to look just a little less robotic
|
// Vary the yaw angle to look just a little less robotic
|
||||||
yaw += ((r >> 6) & 15) - 8;
|
yaw += ((r >> 7) & 31) - 16;
|
||||||
|
|
||||||
|
} else { // Hostile mob movement handling
|
||||||
|
|
||||||
|
// If we're already next to the player, hurt them and skip movement
|
||||||
|
if (closest_dist < 3) {
|
||||||
|
if (closest_player->health < 6) closest_player->health = 0;
|
||||||
|
else closest_player->health -= 6;
|
||||||
|
sc_damageEvent(closest_player->client_fd, closest_player->client_fd, D_generic);
|
||||||
|
sc_setHealth(closest_player->client_fd, closest_player->health, closest_player->hunger);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move towards the closest player on 8 axis
|
||||||
|
// The condition nesting ensures a correct yaw at 45 degree turns
|
||||||
|
if (closest_player->x < mob_data[i].x) {
|
||||||
|
new_x -= 1; yaw = 64;
|
||||||
|
if (closest_player->z < mob_data[i].z) { new_z -= 1; yaw += 32; }
|
||||||
|
else if (closest_player->z > mob_data[i].z) { new_z += 1; yaw -= 32; }
|
||||||
|
}
|
||||||
|
else if (closest_player->x > mob_data[i].x) {
|
||||||
|
new_x += 1; yaw = 192;
|
||||||
|
if (closest_player->z < mob_data[i].z) { new_z -= 1; yaw -= 32; }
|
||||||
|
else if (closest_player->z > mob_data[i].z) { new_z += 1; yaw += 32; }
|
||||||
|
} else {
|
||||||
|
if (closest_player->z < mob_data[i].z) { new_z -= 1; yaw = 128; }
|
||||||
|
else if (closest_player->z > mob_data[i].z) { new_z += 1; yaw = 0; }
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// Check if the block we're moving into is passable:
|
// Check if the block we're moving into is passable:
|
||||||
// if yes, and the block below is solid, keep the same Y level;
|
// if yes, and the block below is solid, keep the same Y level;
|
||||||
// if yes, but the block below isn't solid, drop down one block;
|
// if yes, but the block below isn't solid, drop down one block;
|
||||||
// if not, go up by up to one block;
|
// if not, go up by up to one block;
|
||||||
// if going up isn't possible, skip this iteration.
|
// if going up isn't possible, skip this iteration.
|
||||||
uint8_t new_y = mob_data[i].y;
|
|
||||||
uint8_t block = getBlockAt(new_x, new_y, new_z);
|
uint8_t block = getBlockAt(new_x, new_y, new_z);
|
||||||
if (block != B_air) {
|
if (block != B_air) {
|
||||||
if (getBlockAt(new_x, new_y + 1, new_z) == B_air) new_y += 1;
|
if (getBlockAt(new_x, new_y + 1, new_z) == B_air) new_y += 1;
|
||||||
|
Reference in New Issue
Block a user