static bool InputHandler_CheckIsFree(BlockID block) { struct Entity* p = &LocalPlayer_Instance.Base; struct HacksComp* hacks = &LocalPlayer_Instance.Hacks; Vector3 pos, nextPos; struct AABB blockBB, playerBB; struct LocationUpdate update; /* Non solid blocks (e.g. water/flowers) can always be placed on players */ if (Blocks.Collide[block] != COLLIDE_SOLID) return true; Vector3I_ToVector3(&pos, &Game_SelectedPos.TranslatedPos); if (InputHandler_IntersectsOthers(pos, block)) return false; nextPos = LocalPlayer_Instance.Interp.Next.Pos; Vector3_Add(&blockBB.Min, &pos, &Blocks.MinBB[block]); Vector3_Add(&blockBB.Max, &pos, &Blocks.MaxBB[block]); /* NOTE: Need to also test against next position here, otherwise player can fall through the block at feet as collision is performed against nextPos */ Entity_GetBounds(p, &playerBB); playerBB.Min.Y = min(nextPos.Y, playerBB.Min.Y); if (hacks->Noclip || !AABB_Intersects(&playerBB, &blockBB)) return true; if (hacks->CanPushbackBlocks && hacks->PushbackPlacing && hacks->Enabled) { return InputHandler_PushbackPlace(&blockBB); } playerBB.Min.Y += 0.25f + ENTITY_ADJUSTMENT; if (AABB_Intersects(&playerBB, &blockBB)) return false; /* Push player upwards when they are jumping and trying to place a block underneath them */ nextPos.Y = pos.Y + Blocks.MaxBB[block].Y + ENTITY_ADJUSTMENT; LocationUpdate_MakePos(&update, nextPos, false); p->VTABLE->SetLocation(p, &update, false); return true; }
void Particles_BreakBlockEffect(Vector3I coords, BlockID oldBlock, BlockID block) { if (block != BLOCK_AIR || Block_Draw[oldBlock] == DRAW_GAS) return; block = oldBlock; Vector3 worldPos; Vector3I_ToVector3(&worldPos, &coords); TextureLoc texLoc = Block_GetTexLoc(block, FACE_XMIN); Int32 texIndex; TextureRec baseRec = Atlas1D_TexRec(texLoc, 1, &texIndex); Real32 uScale = (1.0f / 16.0f), vScale = (1.0f / 16.0f) * Atlas1D_InvTileSize; Vector3 minBB = Block_MinBB[block]; Vector3 maxBB = Block_MaxBB[block]; Int32 minX = (Int32)(minBB.X * 16), minZ = (Int32)(minBB.Z * 16); Int32 maxX = (Int32)(maxBB.X * 16), maxZ = (Int32)(maxBB.Z * 16); Int32 minU = min(minX, minZ), maxU = min(maxX, maxZ); Int32 minV = (Int32)(16 - maxBB.Y * 16), maxV = (Int32)(16 - minBB.Y * 16); Int32 maxUsedU = maxU, maxUsedV = maxV; /* This way we can avoid creating particles which outside the bounds and need to be clamped */ if (minU < 12 && maxU > 12) maxUsedU = 12; if (minV < 12 && maxV > 12) maxUsedV = 12; #define GRID_SIZE 4 /* gridOffset gives the centre of the cell on a grid */ #define CELL_CENTRE ((1.0f / GRID_SIZE) * 0.5f) Int32 x, y, z; Real32 maxU2 = baseRec.U1 + maxU * uScale; Real32 maxV2 = baseRec.V1 + maxV * vScale; for (x = 0; x < GRID_SIZE; x++) { for (y = 0; y < GRID_SIZE; y++) { for (z = 0; z < GRID_SIZE; z++) { Real32 cellX = (Real32)x / GRID_SIZE, cellY = (Real32)y / GRID_SIZE, cellZ = (Real32)z / GRID_SIZE; Vector3 cell = Vector3_Create3(CELL_CENTRE + cellX, CELL_CENTRE / 2 + cellY, CELL_CENTRE + cellZ); if (cell.X < minBB.X || cell.X > maxBB.X || cell.Y < minBB.Y || cell.Y > maxBB.Y || cell.Z < minBB.Z || cell.Z > maxBB.Z) continue; Vector3 velocity; /* centre random offset around [-0.2, 0.2] */ velocity.X = CELL_CENTRE + (cellX - 0.5f) + (Random_Float(&rnd) * 0.4f - 0.2f); velocity.Y = CELL_CENTRE + (cellY - 0.0f) + (Random_Float(&rnd) * 0.4f - 0.2f); velocity.Z = CELL_CENTRE + (cellZ - 0.5f) + (Random_Float(&rnd) * 0.4f - 0.2f); TextureRec rec = baseRec; rec.U1 = baseRec.U1 + Random_Range(&rnd, minU, maxUsedU) * uScale; rec.V1 = baseRec.V1 + Random_Range(&rnd, minV, maxUsedV) * vScale; rec.U2 = rec.U1 + 4 * uScale; rec.V2 = rec.V1 + 4 * vScale; rec.U2 = min(rec.U2, maxU2) - 0.01f * uScale; rec.V2 = min(rec.V2, maxV2) - 0.01f * vScale; if (Terrain_Count == PARTICLES_MAX) Terrain_RemoveAt(0); TerrainParticle* p = &Terrain_Particles[Terrain_Count++]; Real32 life = 0.3f + Random_Float(&rnd) * 1.2f; Vector3 pos; Vector3_Add(&pos, &worldPos, &cell); Particle_Reset(&p->Base, pos, velocity, life); p->Rec = rec; p->TexLoc = (TextureLoc)texLoc; p->Block = block; Int32 type = Random_Range(&rnd, 0, 30); p->Base.Size = (UInt8)(type >= 28 ? 12 : (type >= 25 ? 10 : 8)); } } } }