From 549e5dbc2a58427fb878403d7ee005976a97bcec Mon Sep 17 00:00:00 2001 From: JavaProphet Date: Thu, 5 Jan 2017 00:13:32 -0800 Subject: [PATCH] Water/Lava physics, plugins system --- basin/.cproject | 14 +- basin/Debug/objects.mk | 2 +- basin/Debug/src/subdir.mk | 3 + basin/src/block.c | 341 ++++++++++++++++++++++++++++++++------ basin/src/block.h | 3 + basin/src/item.c | 44 +++++ basin/src/json.c | 10 +- basin/src/main.c | 3 + basin/src/world.c | 23 ++- basin/src/world.h | 10 +- 10 files changed, 377 insertions(+), 76 deletions(-) diff --git a/basin/.cproject b/basin/.cproject index c48766e..89923d4 100644 --- a/basin/.cproject +++ b/basin/.cproject @@ -14,24 +14,24 @@ - + - - - + + + - + - + - + diff --git a/basin/Debug/objects.mk b/basin/Debug/objects.mk index f8feef8..b21271d 100644 --- a/basin/Debug/objects.mk +++ b/basin/Debug/objects.mk @@ -4,5 +4,5 @@ USER_OBJS := -LIBS := -lpthread -lcrypto -lssl -lm -lz +LIBS := -lpthread -lcrypto -lssl -lm -lz -ldl diff --git a/basin/Debug/src/subdir.mk b/basin/Debug/src/subdir.mk index e165450..ebdb722 100644 --- a/basin/Debug/src/subdir.mk +++ b/basin/Debug/src/subdir.mk @@ -29,6 +29,7 @@ C_SRCS += \ ../src/hashmap.c \ ../src/profile.c \ ../src/anticheat.c \ +../src/plugin.c \ ../src/xstring.c OBJS += \ @@ -61,6 +62,7 @@ OBJS += \ ./src/hashmap.o \ ./src/profile.o \ ./src/anticheat.o \ +./src/plugin.o \ ./src/xstring.o C_DEPS += \ @@ -93,6 +95,7 @@ C_DEPS += \ ./src/hashmap.d \ ./src/profile.d \ ./src/anticheat.d \ +./src/plugin.d \ ./src/xstring.d diff --git a/basin/src/block.c b/basin/src/block.c index a4453e5..672d6ea 100644 --- a/basin/src/block.c +++ b/basin/src/block.c @@ -610,62 +610,188 @@ void tree_addHangingVine(struct world* world, struct chunk* chunk, block b, int3 } } +int tree_checkAndPlaceLeaf(struct world* world, struct chunk* chunk, block b, int32_t x, int32_t y, int32_t z) { + struct block_info* bi = getBlockInfo(getBlockWorld_guess(world, chunk, x, y, z)); + if (bi == NULL || streq_nocase(bi->material->name, "air") || streq_nocase(bi->material->name, "leaves")) { + setBlockWorld_guess(world, chunk, b, x, y, z); + return 1; + } + return 0; +} + void randomTick_sapling(struct world* world, struct chunk* chunk, block blk, int32_t x, int32_t y, int32_t z) { uint8_t lwu = getLightWorld(world, x, y + 1, z, 1); if (lwu >= 9 && rand() % 7 == 0) { if ((blk & 0x8) == 0x8) { uint8_t type = blk & 0x7; - if (type == 0 || type == 2 || type == 3) { //oak - block log = BLK_LOG_OAK; - block leaf = BLK_LEAVES_OAK_2; - if (type == 2) { - log = BLK_LOG_BIRCH; - leaf = BLK_LEAVES_BIRCH_2; - } else if (type == 3) { - log = BLK_LOG_JUNGLE; - leaf = BLK_LEAVES_JUNGLE_2; + block log = BLK_LOG_OAK; + block leaf = BLK_LEAVES_OAK_2; + if (type == 1) { + log = BLK_LOG_SPRUCE; + leaf = BLK_LEAVES_SPRUCE_2; + } else if (type == 2) { + log = BLK_LOG_BIRCH; + leaf = BLK_LEAVES_BIRCH_2; + } else if (type == 3) { + log = BLK_LOG_JUNGLE; + leaf = BLK_LEAVES_JUNGLE_2; + } else if (type == 4) { + log = BLK_LOG_ACACIA_1; + leaf = BLK_LEAVES_ACACIA_2; + } else if (type == 5) { + log = BLK_LOG_BIG_OAK_1; + leaf = BLK_LEAVES_BIG_OAK_2; + } + uint8_t biome = getBiome(world, x, z); + uint8_t vines = type == 0 && (biome == BIOME_SWAMPLAND || biome == BIOME_SWAMPLANDM); + uint8_t cocoa = type == 3; + int big = type == 0 && rand() % 10 == 0; + if (!big) { + uint8_t height = 0; + if (type == 0) height = rand() % 3 + 4; + else if (type == 1) height = 6 + rand() % 4; + else if (type == 2) height = rand() % 3 + 5; + else if (type == 3) height = 3 + rand() % 10; + else if (type == 4) height = 5 + rand() % 6; + if (y < 1 || y + height + 1 > 256) return; + for (int ty = y; ty <= y + height + 1; ty++) { + if (ty < 0 || ty >= 256) return; + int width = 1; + if (ty == y) width = 0; + if (ty >= y + 1 + height - 2) width = 2; + for (int tx = x - width; tx <= x + width; tx++) { + for (int tz = z - width; tz <= z + width; tz++) { + if (!tree_canGrowInto(getBlockWorld_guess(world, chunk, tx, ty, tz))) return; + } + } } - uint8_t biome = getBiome(world, x, z); - uint8_t vines = type == 0 && (biome == BIOME_SWAMPLAND || biome == BIOME_SWAMPLANDM); - uint8_t cocoa = type == 3; - int big = type == 0 && rand() % 10 == 0; - if (!big) { - uint8_t height = rand() % 3; - if (type == 0) height += 4; - else if (type == 2) height += 5; - else if (type == 3) height += 3 + rand() % 7; - if (y < 1 || y + height + 1 > 256) return; - for (int ty = y; ty <= y + height + 1; ty++) { - if (ty < 0 || ty >= 256) return; - int width = 1; - if (ty == y) width = 0; - if (ty >= y + 1 + height - 2) width = 2; - for (int tx = x - width; tx <= x + width; tx++) { - for (int tz = z - width; tz <= z + width; tz++) { - if (!tree_canGrowInto(getBlockWorld_guess(world, chunk, tx, ty, tz))) return; + block down = getBlockWorld_guess(world, chunk, x, y - 1, z); + if ((down != BLK_GRASS && down != BLK_DIRT && down != BLK_FARMLAND) || y >= 256 - height - 1) return; + if (down == BLK_FARMLAND && type == 4) return; + setBlockWorld_guess(world, chunk, BLK_DIRT, x, y - 1, z); + if (type == 4) { + int k2 = height - rand() % 4 - 1; + int l2 = 3 - rand() % 3; + int i3 = x; + int j1 = z; + int k1 = 0; + int rx = rand() % 4; + int ox = 0; + int oz = 0; + if (rx == 0) ox++; + else if (rx == 1) ox--; + else if (rx == 2) oz++; + else if (rx == 3) oz--; + for (int l1 = 0; l1 < height; l1++) { + int i2 = y + l1; + if (l1 >= k2 && l2 > 0) { + i3 += ox; + j1 += oz; + l2--; + } + struct block_info* bi = getBlockInfo(getBlockWorld_guess(world, chunk, i3, i2, j1)); + if (bi != NULL && (streq_nocase(bi->material->name, "air") || streq_nocase(bi->material->name, "leaves") || streq_nocase(bi->material->name, "vine") || streq_nocase(bi->material->name, "plants"))) { + setBlockWorld_guess(world, chunk, log, i3, i2, j1); + k1 = i2; + } + } + for (int j3 = -3; j3 <= 3; j3++) { + for (int i4 = -3; i4 <= +3; i4++) { + if (abs(j3) != 3 || abs(i4) != 3) { + tree_checkAndPlaceLeaf(world, chunk, leaf, i3 + j3, k1, j1 + i4); + } + if (abs(j3) <= 1 || abs(i4) <= 1) { + tree_checkAndPlaceLeaf(world, chunk, leaf, i3 + j3, k1 + 1, j1 + i4); } } } - block down = getBlockWorld_guess(world, chunk, x, y - 1, z); - if ((down != BLK_GRASS && down != BLK_DIRT && down != BLK_FARMLAND) || y >= 256 - height - 1) return; - setBlockWorld_guess(world, chunk, BLK_DIRT, x, y - 1, z); - for (int ty = y - 3 + height; ty <= y + height; ty++) { - int dist_from_top = ty - y - height; - int width = 1 - dist_from_top / 2; - for (int tx = x - width; tx <= x + width; tx++) { - int tx2 = tx - x; - for (int tz = z - width; tz <= z + width; tz++) { - int tz2 = tz - z; - if (abs(tx2) != width || abs(tz2) != width || (rand() % 2 == 0 && dist_from_top != 0)) { - struct block_info* bi = getBlockInfo(getBlockWorld_guess(world, chunk, tx, ty, tz)); - if (bi != NULL && (streq_nocase(bi->material->name, "air") || streq_nocase(bi->material->name, "leaves") || streq_nocase(bi->material->name, "vine"))) { - setBlockWorld_guess(world, chunk, leaf, tx, ty, tz); + tree_checkAndPlaceLeaf(world, chunk, leaf, i3 - 2, k1 + 1, j1); + tree_checkAndPlaceLeaf(world, chunk, leaf, i3 + 2, k1 + 1, j1); + tree_checkAndPlaceLeaf(world, chunk, leaf, i3, k1 + 1, j1 - 2); + tree_checkAndPlaceLeaf(world, chunk, leaf, i3, k1 + 1, j1 + 1); + i3 = x; + j1 = z; + int nrx = rand() % 4; + if (rx == nrx) return; + rx = nrx; + ox = 0; + oz = 0; + if (rx == 0) ox++; + else if (rx == 1) ox--; + else if (rx == 2) oz++; + else if (rx == 3) oz--; + int l3 = k2 - rand() % 2 - 1; + int k4 = 1 + rand() % 3; + k1 = 0; + for (int l4 = l3; l4 < height && k4 > 0; k4--) { + if (l4 >= 1) { + int j2 = y + l4; + i3 += ox; + j1 += oz; + if (tree_checkAndPlaceLeaf(world, chunk, log, i3, j2, j1)) { + k1 = j2; + } + } + l4++; + } + if (k1 > 0) { + for (int i5 = -2; i5 <= 2; i5++) { + for (int k5 = -2; k5 <= 2; k5++) { + if (abs(i5) != 2 || abs(k5) != 2) tree_checkAndPlaceLeaf(world, chunk, leaf, i3 + i5, k1, j1 + k5); + if (abs(i5) <= 1 && abs(k5) <= 1) tree_checkAndPlaceLeaf(world, chunk, leaf, i3 + i5, k1 + 1, j1 + k5); + } + } + } + } else if (type == 1) { + int32_t j = 1 + rand() % 2; + int k = height - j; + int l = 2 + rand() % 2; + int i3 = rand() % 2; + int j3 = 1; + int k3 = 0; + for (int l3 = 0; l3 <= k; l3++) { + int yoff = y + height - l3; + for (int i2 = x - i3; i2 <= x + i3; i2++) { + int xoff = i2 - x; + for (int k2 = z - i3; k2 <= z + i3; k2++) { + int zoff = k2 - z; + if (abs(xoff) != i3 || abs(zoff) != i3 || i3 <= 0) { + struct block_info* bi = getBlockInfo(getBlockWorld_guess(world, chunk, i2, yoff, k2)); + if (bi == NULL || !bi->fullCube) { + setBlockWorld_guess(world, chunk, leaf, i2, yoff, k2); } } } } + if (i3 >= j3) { + i3 = j3; + k3 = 1; + j3++; + if (j3 > l) { + j3 = l; + } + } else { + i3++; + } } - for (int th = 0; th < height; th++) { + } else for (int ty = y - 3 + height; ty <= y + height; ty++) { + int dist_from_top = ty - y - height; + int width = 1 - dist_from_top / 2; + for (int tx = x - width; tx <= x + width; tx++) { + int tx2 = tx - x; + for (int tz = z - width; tz <= z + width; tz++) { + int tz2 = tz - z; + if (abs(tx2) != width || abs(tz2) != width || (rand() % 2 == 0 && dist_from_top != 0)) { + struct block_info* bi = getBlockInfo(getBlockWorld_guess(world, chunk, tx, ty, tz)); + if (bi != NULL && (streq_nocase(bi->material->name, "air") || streq_nocase(bi->material->name, "leaves") || streq_nocase(bi->material->name, "vine"))) { + setBlockWorld_guess(world, chunk, leaf, tx, ty, tz); + } + } + } + } + } + if (type != 4) { + for (int th = 0; th < height - (type == 1 ? (rand() % 3) : 0); th++) { struct block_info* bi = getBlockInfo(getBlockWorld_guess(world, chunk, x, y + th, z)); if (bi != NULL && (streq_nocase(bi->material->name, "air") || streq_nocase(bi->material->name, "leaves") || streq_nocase(bi->material->name, "vine") || streq_nocase(bi->material->name, "plants"))) { setBlockWorld_guess(world, chunk, log, x, y + th, z); @@ -701,18 +827,8 @@ void randomTick_sapling(struct world* world, struct chunk* chunk, block blk, int } } } - } else { - } - } else if (type == 1) { // spruce - - } else if (type == 2) { // birch - - } else if (type == 3) { // jungle - - } else if (type == 4) { // acacia - - } else if (type == 5) { // darkoak + } else { } } else { @@ -732,10 +848,123 @@ block onBlockPlaced_log(struct player* player, struct world* world, block blk, i } void onBlockInteract_fencegate(struct world* world, block blk, int32_t x, int32_t y, int32_t z, struct player* player, uint8_t face, float curPosX, float curPosY, float curPosZ) { - blk ^= (block)0b0100; // toggle opened bit + blk ^= (block) 0b0100; // toggle opened bit setBlockWorld_guess(world, NULL, blk, x, y, z); } +int fluid_getDepth(int water, block b) { + uint16_t ba = b >> 4; + if (water && (ba != BLK_WATER >> 4 && ba != BLK_WATER_1 >> 4)) return -1; + else if (!water && (ba != BLK_LAVA >> 4 && ba != BLK_LAVA_1 >> 4)) return -1; + return b & 0x0f; +} + +int fluid_checkAdjacentBlock(int water, struct world* world, struct chunk* ch, int32_t x, uint8_t y, int32_t z, int cmin, int* adj) { + block b = getBlockWorld_guess(world, ch, x, y, z); + int m = fluid_getDepth(water, b); + if (m < 0) return cmin; + else { + if (m == 0) (*adj)++; + if (m >= 8) m = 0; + return cmin >= 0 && m >= cmin ? cmin : m; + } +} + +int fluid_isUnblocked(int water, block b, struct block_info* bi) { + uint16_t ba = b >> 4; + if (ba == BLK_DOOROAK >> 4 || ba == BLK_DOORIRON >> 4 || ba == BLK_SIGN >> 4 || ba == BLK_LADDER >> 4 || ba == BLK_REEDS >> 4) return 0; + if (bi == NULL) return 0; + if (!streq_nocase(bi->material->name, "portal") && !streq_nocase(bi->material->name, "structure_void") ? bi->material->blocksMovement : 1) return 0; + return 1; +} + +int fluid_canFlowInto(int water, block b) { + struct block_info* bi = getBlockInfo(b); + if (bi == NULL) return 1; + if (!((water ? !streq_nocase(bi->material->name, "water") : 1) && !streq_nocase(bi->material->name, "lava"))) return 0; + return fluid_isUnblocked(water, b, bi); +} + +void fluid_doFlowInto(int water, struct world* world, struct chunk* ch, int32_t x, uint8_t y, int32_t z, int level, block b) { + // potentially triggerMixEffects + struct block_info* bi = getBlockInfo(b); + if (bi != NULL && !streq_nocase(bi->material->name, "air") && !streq_nocase(bi->material->name, "lava")) { + dropBlockDrops(world, b, NULL, x, y, z); + } + setBlockWorld_guess(world, ch, (water ? BLK_WATER : BLK_LAVA) | level, x, y, z); +} + +void onBlockUpdate_fluid(struct world* world, block blk, int32_t x, int32_t y, int32_t z) { + struct chunk* ch = getChunk(world, x >> 4, z >> 4); + if (ch == NULL) return; + int level = blk & 0x0f; + int resistance = 1; + if (((blk >> 4) == (BLK_LAVA >> 4) || (blk >> 4) == (BLK_LAVA_1 >> 4)) && world->dimension != -1) resistance++; + int adjSource = 0; + int water = (blk >> 4) == (BLK_WATER >> 4) || (blk >> 4) == (BLK_WATER_1 >> 4); + int tickRate = water ? 5 : (world->dimension == -1 ? 10 : 30); + if (level > 0) { + int l = -100; + l = fluid_checkAdjacentBlock(water, world, ch, x + 1, y, z, l, &adjSource); + l = fluid_checkAdjacentBlock(water, world, ch, x - 1, y, z, l, &adjSource); + l = fluid_checkAdjacentBlock(water, world, ch, x, y, z + 1, l, &adjSource); + l = fluid_checkAdjacentBlock(water, world, ch, x, y, z - 1, l, &adjSource); + int i1 = l + resistance; + if (i1 >= 8 || l < 0) i1 = -1; + int ha = fluid_getDepth(water, getBlockWorld_guess(world, ch, x, y + 1, z)); + if (ha >= 0) { + if (ha >= 8) i1 = ha; + else i1 = ha + 8; + } + if (adjSource >= 2 && water) { + block below = getBlockWorld_guess(world, ch, x, y - 1, z); + if ((below >> 4) == (BLK_WATER >> 4) || (below >> 4) == (BLK_WATER_1 >> 4)) { + i1 = 0; + } else { + struct block_info* bi = getBlockInfo(below); + if (bi != NULL && bi->material->solid) i1 = 0; + } + } + if (!water && level < 8 && i1 < 8 && i1 > level && rand() % 4 > 0) { + tickRate *= 4; + } + if (i1 == level) { + // set static + } else { + level = i1; + if (i1 < 0) setBlockWorld_guess(world, ch, 0, x, y, z); + else { + setBlockWorld_guess(world, ch, (blk & ~0x0f) | i1, x, y, z); + } + } + } else { + //set static + } + block down = getBlockWorld_guess(world, ch, x, y - 1, z); + if (fluid_canFlowInto(water, down)) { + if (!water && ((down >> 4) == (BLK_WATER >> 4) || (down >> 4) == (BLK_WATER_1 >> 4))) { + setBlockWorld_guess(world, ch, BLK_STONE, x, y - 1, z); + //trigger mix effects + return; + } + fluid_doFlowInto(water, world, ch, x, y - 1, z, level >= 8 ? level : (level + 8), down); + } else if (level >= 0) { + if (level == 0 || !fluid_isUnblocked(water, down, getBlockInfo(down))) { + int k1 = level + resistance; + if (level >= 8) k1 = 1; + if (k1 >= 8) return; + block b = getBlockWorld_guess(world, ch, x + 1, y, z); + if (fluid_canFlowInto(water, b)) fluid_doFlowInto(water, world, ch, x + 1, y, z, k1, b); + b = getBlockWorld_guess(world, ch, x - 1, y, z); + if (fluid_canFlowInto(water, b)) fluid_doFlowInto(water, world, ch, x - 1, y, z, k1, b); + b = getBlockWorld_guess(world, ch, x, y, z + 1); + if (fluid_canFlowInto(water, b)) fluid_doFlowInto(water, world, ch, x, y, z + 1, k1, b); + b = getBlockWorld_guess(world, ch, x, y, z - 1); + if (fluid_canFlowInto(water, b)) fluid_doFlowInto(water, world, ch, x, y, z - 1, k1, b); + } + } +} + // struct block_info* getBlockInfo(block b) { @@ -1067,4 +1296,8 @@ void init_blocks() { tmp->onBlockUpdate = &onBlockUpdate_checkPlace; for (block b = BLK_FENCEGATE; b < BLK_FENCEGATE + 16; b++) getBlockInfo(b)->onBlockInteract = &onBlockInteract_fencegate; + getBlockInfo(BLK_WATER)->onBlockUpdate = &onBlockUpdate_fluid; + getBlockInfo(BLK_WATER_1)->onBlockUpdate = &onBlockUpdate_fluid; + getBlockInfo(BLK_LAVA)->onBlockUpdate = &onBlockUpdate_fluid; + getBlockInfo(BLK_LAVA_1)->onBlockUpdate = &onBlockUpdate_fluid; } diff --git a/basin/src/block.h b/basin/src/block.h index a6f7782..50277ed 100644 --- a/basin/src/block.h +++ b/basin/src/block.h @@ -402,8 +402,11 @@ #define BLK_THINSTAINEDGLASS_BLACK 2575 #define BLK_LEAVES_ACACIA 2576 #define BLK_LEAVES_BIG_OAK 2577 +#define BLK_LEAVES_ACACIA_1 2580 #define BLK_LEAVES_BIG_OAK_1 2581 +#define BLK_LEAVES_ACACIA_2 2584 #define BLK_LEAVES_BIG_OAK_2 2585 +#define BLK_LEAVES_ACACIA_3 2588 #define BLK_LEAVES_BIG_OAK_3 2589 #define BLK_LOG_ACACIA_1 2592 #define BLK_LOG_BIG_OAK_1 2593 diff --git a/basin/src/item.c b/basin/src/item.c index 3126abb..66dfd2a 100644 --- a/basin/src/item.c +++ b/basin/src/item.c @@ -75,6 +75,46 @@ int onItemInteract_reeds(struct world* world, struct player* player, uint8_t slo return 0; } +int onItemInteract_bucket(struct world* world, struct player* player, uint8_t slot_index, struct slot* slot, int32_t x, uint8_t y, int32_t z, uint8_t face) { + if (slot == NULL) return 0; + offsetCoordByFace(&x, &y, &z, face); + block b = getBlockWorld(world, x, y, z); + struct block_info* bi = getBlockInfo(b); + if (bi == NULL) return 0; + uint16_t ba = b >> 4; + if (slot->item == ITM_BUCKETWATER) { + if (b != 0 && !bi->material->replacable && ba != BLK_WATER >> 4 && ba != BLK_WATER_1 >> 4) return 0; + setBlockWorld(world, BLK_WATER, x, y, z); + if (player->gamemode != 1) { + slot->item = ITM_BUCKET; + setSlot(player, player->inventory, slot_index, slot, 1, 1); + } + } else if (slot->item == ITM_BUCKETLAVA) { + if (b != 0 && !bi->material->replacable && ba != BLK_LAVA >> 4 && ba != BLK_LAVA_1 >> 4) return 0; + setBlockWorld(world, BLK_LAVA, x, y, z); + if (player->gamemode != 1) { + slot->item = ITM_BUCKET; + setSlot(player, player->inventory, slot_index, slot, 1, 1); + } + } else if (slot->item == ITM_BUCKET) { + if ((b & 0x0f) != 0) return 0; + if (ba == BLK_WATER >> 4 || ba == BLK_WATER_1 >> 4) { + setBlockWorld(world, 0, x, y, z); + if (player->gamemode != 1) { + slot->item = ITM_BUCKETWATER; + setSlot(player, player->inventory, slot_index, slot, 1, 1); + } + } else if (ba == BLK_LAVA >> 4 || ba == BLK_LAVA_1 >> 4) { + setBlockWorld(world, 0, x, y, z); + if (player->gamemode != 1) { + slot->item = ITM_BUCKETLAVA; + setSlot(player, player->inventory, slot_index, slot, 1, 1); + } + } + } + return 0; +} + int onItemInteract_bonemeal(struct world* world, struct player* player, uint8_t slot_index, struct slot* slot, int32_t x, uint8_t y, int32_t z, uint8_t face) { if (slot == NULL) return 0; block b = getBlockWorld(world, x, y, z); @@ -327,6 +367,10 @@ void init_items() { getItemInfo(ITM_SHOVELIRON)->onItemInteract = &onItemInteract_shovel; getItemInfo(ITM_SHOVELDIAMOND)->onItemInteract = &onItemInteract_shovel; getItemInfo(ITM_REEDS)->onItemInteract = &onItemInteract_reeds; + getItemInfo(ITM_BUCKET)->onItemInteract = &onItemInteract_bucket; + getItemInfo(ITM_BUCKETWATER)->onItemInteract = &onItemInteract_bucket; + getItemInfo(ITM_BUCKETLAVA)->onItemInteract = &onItemInteract_bucket; + } void add_item(item id, struct item_info* info) { diff --git a/basin/src/json.c b/basin/src/json.c index ae2f3bc..ad4fce4 100644 --- a/basin/src/json.c +++ b/basin/src/json.c @@ -135,11 +135,12 @@ int __recurJSON(struct json_object* cur, size_t* i, char* json) { size_t sl = strlen(json); int cs = 0; struct json_object* nchild = NULL; + char ck = cur->type == JSON_OBJECT ? '}' : ']'; for (; *i < sl; (*i)++) { if (cs == 0) { if (json[*i] == '{') cs = 1; } else if (cs == 1) { - if (json[*i] == '}') break; + if (json[*i] == ck) break; else if (json[*i] == '\"') { nchild = xmalloc(sizeof(struct json_object)); memset(nchild, 0, sizeof(struct json_object)); @@ -170,7 +171,7 @@ int __recurJSON(struct json_object* cur, size_t* i, char* json) { cs = 4; } else if (cs == 4) { if (json[*i] == ',') cs = 1; - else if (json[*i] == '}') break; + else if (json[*i] == ck) break; } } if (nchild != NULL) { @@ -181,12 +182,13 @@ int __recurJSON(struct json_object* cur, size_t* i, char* json) { } ssize_t parseJSON(struct json_object* root, char* json) { - if (strlen(json) < 2 || json[0] != '{') { + if (strlen(json) < 2 || (json[0] != '{' && json[0] != '[')) { + memset(root, 0, sizeof(struct json_object)); errno = EINVAL; return -1; } root->name = NULL; - root->type = JSON_OBJECT; + root->type = json[0] == '{' ? JSON_OBJECT : JSON_ARRAY; root->children = NULL; root->child_count = 0; root->data.string = NULL; diff --git a/basin/src/main.c b/basin/src/main.c index eddc6ee..86158fc 100644 --- a/basin/src/main.c +++ b/basin/src/main.c @@ -41,6 +41,7 @@ #include "command.h" #include "queue.h" #include "profile.h" +#include "plugin.h" void main_tick() { pthread_cond_broadcast (&glob_tick_cond); @@ -201,6 +202,8 @@ int main(int argc, char* argv[]) { printf("Smelting Initialized\n"); init_base_commands(); printf("Commands Initialized\n"); + init_plugins(); + printf("Plugins Initialized\n"); for (int i = 0; i < servsl; i++) { struct cnode* serv = servs[i]; const char* bind_mode = getConfigValue(serv, "bind-mode"); diff --git a/basin/src/world.c b/basin/src/world.c index 54d2649..d6fdad8 100644 --- a/basin/src/world.c +++ b/basin/src/world.c @@ -462,11 +462,13 @@ uint8_t getLightChunk(struct chunk* chunk, uint8_t x, uint8_t y, uint8_t z, uint } uint8_t getLightWorld_guess(struct world* world, struct chunk* ch, int32_t x, int32_t y, int32_t z) { + if (y < 0 || y > 255) return 0; if ((x >> 4) == ch->x && ((z >> 4) == ch->z)) return getLightChunk(ch, x & 0x0f, y, z & 0x0f, world->skylightSubtracted); else return getLightWorld(world, x, y, z, 0); } uint8_t getLightWorld(struct world* world, int32_t x, int32_t y, int32_t z, uint8_t checkNeighbors) { + if (y < 0 || y > 255) return 0; struct chunk* chunk = getChunk(world, x >> 4, z >> 4); if (chunk == NULL) return 15; if (checkNeighbors) { @@ -486,18 +488,20 @@ uint8_t getLightWorld(struct world* world, int32_t x, int32_t y, int32_t z, uint } } -block getBlockWorld(struct world* world, int32_t x, uint8_t y, int32_t z) { +block getBlockWorld(struct world* world, int32_t x, int32_t y, int32_t z) { + if (y < 0 || y > 255) return 0; struct chunk* chunk = getChunk(world, x >> 4, z >> 4); if (chunk == NULL) return 0; return getBlockChunk(chunk, x & 0x0f, y, z & 0x0f); } -block getBlockWorld_guess(struct world* world, struct chunk* ch, int32_t x, uint8_t y, int32_t z) { +block getBlockWorld_guess(struct world* world, struct chunk* ch, int32_t x, int32_t y, int32_t z) { + if (y < 0 || y > 255) return 0; if ((x >> 4) == ch->x && ((z >> 4) == ch->z)) return getBlockChunk(ch, x & 0x0f, y, z & 0x0f); else return getBlockWorld(world, x, y, z); } -struct tile_entity* getTileEntityChunk(struct chunk* chunk, int32_t x, uint8_t y, int32_t z) { // TODO: optimize +struct tile_entity* getTileEntityChunk(struct chunk* chunk, int32_t x, int32_t y, int32_t z) { // TODO: optimize if (y > 255 || y < 0) return NULL; for (size_t i = 0; i < chunk->tileEntities->size; i++) { struct tile_entity* te = (struct tile_entity*) chunk->tileEntities->data[i]; @@ -545,13 +549,15 @@ void disableTileEntityTickable(struct world* world, struct tile_entity* te) { rem_collection(chunk->tileEntitiesTickable, te); } -struct tile_entity* getTileEntityWorld(struct world* world, int32_t x, uint8_t y, int32_t z) { +struct tile_entity* getTileEntityWorld(struct world* world, int32_t x, int32_t y, int32_t z) { + if (y < 0 || y > 255) return NULL; struct chunk* chunk = getChunk(world, x >> 4, z >> 4); if (chunk == NULL) return NULL; return getTileEntityChunk(chunk, x, y, z); } -void setTileEntityWorld(struct world* world, int32_t x, uint8_t y, int32_t z, struct tile_entity* te) { +void setTileEntityWorld(struct world* world, int32_t x, int32_t y, int32_t z, struct tile_entity* te) { + if (y < 0 || y > 255) return; struct chunk* chunk = getChunk(world, x >> 4, z >> 4); if (chunk == NULL) return; setTileEntityChunk(chunk, te); @@ -680,18 +686,21 @@ void setBlockChunk(struct chunk* chunk, block blk, uint8_t x, uint8_t y, uint8_t } void setBlockWorld(struct world* world, block blk, int32_t x, int32_t y, int32_t z) { + if (y < 0 || y > 255) return; struct chunk* ch = getChunk(world, x >> 4, z >> 4); if (ch == NULL) return; setBlockWorld_guess(world, ch, blk, x, y, z); } void setBlockWorld_noupdate(struct world* world, block blk, int32_t x, int32_t y, int32_t z) { + if (y < 0 || y > 255) return; struct chunk* ch = getChunk(world, x >> 4, z >> 4); if (ch == NULL) return; setBlockWorld_guess_noupdate(world, ch, blk, x, y, z); } void setBlockWorld_guess(struct world* world, struct chunk* chunk, block blk, int32_t x, int32_t y, int32_t z) { + if (y < 0 || y > 255) return; if (chunk == NULL || (x >> 4) != chunk->x || ((z >> 4) != chunk->z)) { chunk = getChunk(world, x >> 4, z >> 4); } @@ -719,6 +728,7 @@ void setBlockWorld_guess(struct world* world, struct chunk* chunk, block blk, in } void setBlockWorld_guess_noupdate(struct world* world, struct chunk* chunk, block blk, int32_t x, int32_t y, int32_t z) { + if (y < 0 || y > 255) return; if (chunk == NULL || (x >> 4) != chunk->x || ((z >> 4) != chunk->z)) { chunk = getChunk(world, x >> 4, z >> 4); } @@ -962,6 +972,7 @@ void spawnPlayer(struct world* world, struct player* player) { struct subworld* sw = xmalloc(sizeof(struct subworld)); sw->world = world; sw->players = new_hashmap(1, 1); + sw->defunct = 0; player->subworld = sw; put_hashmap(world->subworlds, (uint64_t) sw, sw); pthread_t swt; @@ -1017,12 +1028,14 @@ struct entity* getEntity(struct world* world, int32_t id) { } void updateBlockWorld_guess(struct world* world, struct chunk* ch, int32_t x, int32_t y, int32_t z) { + if (y < 0 || y > 255) return; block b = getBlockWorld_guess(world, ch, x, y, z); struct block_info* bi = getBlockInfo(b); if (bi != NULL && bi->onBlockUpdate != NULL) bi->onBlockUpdate(world, b, x, y, z); } void updateBlockWorld(struct world* world, int32_t x, int32_t y, int32_t z) { + if (y < 0 || y > 255) return; block b = getBlockWorld(world, x, y, z); struct block_info* bi = getBlockInfo(b); if (bi != NULL && bi->onBlockUpdate != NULL) bi->onBlockUpdate(world, b, x, y, z); diff --git a/basin/src/world.h b/basin/src/world.h index f315d79..27dbb43 100644 --- a/basin/src/world.h +++ b/basin/src/world.h @@ -197,9 +197,9 @@ int getBiome(struct world* world, int32_t x, int32_t z); block getBlockChunk(struct chunk* chunk, uint8_t x, uint8_t y, uint8_t z); -block getBlockWorld(struct world* world, int32_t x, uint8_t y, int32_t z); +block getBlockWorld(struct world* world, int32_t x, int32_t y, int32_t z); -block getBlockWorld_guess(struct world* world, struct chunk* ch, int32_t x, uint8_t y, int32_t z); +block getBlockWorld_guess(struct world* world, struct chunk* ch, int32_t x, int32_t y, int32_t z); struct chunk* newChunk(int16_t x, int16_t z); @@ -215,13 +215,13 @@ void setBlockWorld(struct world* world, block blk, int32_t x, int32_t y, int32_t void setBlockWorld_guess(struct world* world, struct chunk* chunk, block blk, int32_t x, int32_t y, int32_t z); -struct tile_entity* getTileEntityChunk(struct chunk* chunk, int32_t x, uint8_t y, int32_t z); +struct tile_entity* getTileEntityChunk(struct chunk* chunk, int32_t x, int32_t y, int32_t z); void setTileEntityChunk(struct chunk* chunk, struct tile_entity* te); -struct tile_entity* getTileEntityWorld(struct world* world, int32_t x, uint8_t y, int32_t z); +struct tile_entity* getTileEntityWorld(struct world* world, int32_t x, int32_t y, int32_t z); -void setTileEntityWorld(struct world* world, int32_t x, uint8_t y, int32_t z, struct tile_entity* te); +void setTileEntityWorld(struct world* world, int32_t x, int32_t y, int32_t z, struct tile_entity* te); void enableTileEntityTickable(struct world* world, struct tile_entity* te);