Beispiel #1
0
cBlockEntity * cBlockEntity::CreateByBlockType(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World)
{
    switch (a_BlockType)
    {
    case E_BLOCK_BEACON:
        return new cBeaconEntity      (a_BlockX, a_BlockY, a_BlockZ, a_World);
    case E_BLOCK_CHEST:
        return new cChestEntity       (a_BlockX, a_BlockY, a_BlockZ, a_World, a_BlockType);
    case E_BLOCK_COMMAND_BLOCK:
        return new cCommandBlockEntity(a_BlockX, a_BlockY, a_BlockZ, a_World);
    case E_BLOCK_DISPENSER:
        return new cDispenserEntity   (a_BlockX, a_BlockY, a_BlockZ, a_World);
    case E_BLOCK_DROPPER:
        return new cDropperEntity     (a_BlockX, a_BlockY, a_BlockZ, a_World);
    case E_BLOCK_ENDER_CHEST:
        return new cEnderChestEntity  (a_BlockX, a_BlockY, a_BlockZ, a_World);
    case E_BLOCK_FLOWER_POT:
        return new cFlowerPotEntity   (a_BlockX, a_BlockY, a_BlockZ, a_World);
    case E_BLOCK_FURNACE:
        return new cFurnaceEntity     (a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta, a_World);
    case E_BLOCK_HEAD:
        return new cMobHeadEntity     (a_BlockX, a_BlockY, a_BlockZ, a_World);
    case E_BLOCK_HOPPER:
        return new cHopperEntity      (a_BlockX, a_BlockY, a_BlockZ, a_World);
    case E_BLOCK_JUKEBOX:
        return new cJukeboxEntity     (a_BlockX, a_BlockY, a_BlockZ, a_World);
    case E_BLOCK_LIT_FURNACE:
        return new cFurnaceEntity     (a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta, a_World);
    case E_BLOCK_SIGN_POST:
        return new cSignEntity        (a_BlockType, a_BlockX, a_BlockY, a_BlockZ, a_World);
    case E_BLOCK_TRAPPED_CHEST:
        return new cChestEntity       (a_BlockX, a_BlockY, a_BlockZ, a_World, a_BlockType);
    case E_BLOCK_WALLSIGN:
        return new cSignEntity        (a_BlockType, a_BlockX, a_BlockY, a_BlockZ, a_World);
    case E_BLOCK_NOTE_BLOCK:
        return new cNoteEntity        (a_BlockX, a_BlockY, a_BlockZ, a_World);
    }
    LOGD("%s: Requesting creation of an unknown block entity - block type %d (%s)",
         __FUNCTION__, a_BlockType, ItemTypeToString(a_BlockType).c_str()
        );
    ASSERT(!"Requesting creation of an unknown block entity");
    return NULL;
}
Beispiel #2
0
cBlockEntity * cBlockEntity::CreateByBlockType(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World)
{
	switch (a_BlockType)
	{
		case E_BLOCK_CHEST:       return new cChestEntity    (a_BlockX, a_BlockY, a_BlockZ, a_World);
		case E_BLOCK_DISPENSER:   return new cDispenserEntity(a_BlockX, a_BlockY, a_BlockZ, a_World);
		case E_BLOCK_DROPPER:     return new cDropperEntity  (a_BlockX, a_BlockY, a_BlockZ, a_World);
		case E_BLOCK_LIT_FURNACE: return new cFurnaceEntity  (a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta, a_World);
		case E_BLOCK_FURNACE:     return new cFurnaceEntity  (a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta, a_World);
		case E_BLOCK_HOPPER:      return new cHopperEntity   (a_BlockX, a_BlockY, a_BlockZ, a_World);
		case E_BLOCK_SIGN_POST:   return new cSignEntity     (a_BlockType, a_BlockX, a_BlockY, a_BlockZ, a_World);
		case E_BLOCK_WALLSIGN:    return new cSignEntity     (a_BlockType, a_BlockX, a_BlockY, a_BlockZ, a_World);
		case E_BLOCK_NOTE_BLOCK:  return new cNoteEntity     (a_BlockX, a_BlockY, a_BlockZ, a_World);
		case E_BLOCK_JUKEBOX:     return new cJukeboxEntity  (a_BlockX, a_BlockY, a_BlockZ, a_World);
	}
	LOGD("%s: Requesting creation of an unknown block entity - block type %d (%s)",
		__FUNCTION__, a_BlockType, ItemTypeToString(a_BlockType).c_str()
	);
	return NULL;
}
Beispiel #3
0
void cDispenserEntity::DropSpenseFromSlot(cChunk & a_Chunk, int a_SlotNum)
{
	int DispX = m_RelX;
	int DispY = m_PosY;
	int DispZ = m_RelZ;
	NIBBLETYPE Meta = a_Chunk.GetMeta(m_RelX, m_PosY, m_RelZ);
	AddDropSpenserDir(DispX, DispY, DispZ, Meta);
	cChunk * DispChunk = a_Chunk.GetRelNeighborChunkAdjustCoords(DispX, DispZ);
	if (DispChunk == NULL)
	{
		// Would dispense into / interact with a non-loaded chunk, ignore the tick
		return;
	}

	BLOCKTYPE DispBlock = DispChunk->GetBlock(DispX, DispY, DispZ);
	int BlockX = (DispX + DispChunk->GetPosX() * cChunkDef::Width);
	int BlockZ = (DispZ + DispChunk->GetPosZ() * cChunkDef::Width);

	// Dispense the item:
	switch (m_Contents.GetSlot(a_SlotNum).m_ItemType)
	{
		case E_ITEM_BUCKET:
		{
			LOGD("Dispensing empty bucket in slot %d; DispBlock is \"%s\" (%d).", a_SlotNum, ItemTypeToString(DispBlock).c_str(), DispBlock);
			switch (DispBlock)
			{
				case E_BLOCK_STATIONARY_WATER:
				case E_BLOCK_WATER:
				{
					if (ScoopUpLiquid(a_SlotNum, E_ITEM_WATER_BUCKET))
					{
						DispChunk->SetBlock(DispX, DispY, DispZ, E_BLOCK_AIR, 0);
					}
					break;
				}
				case E_BLOCK_STATIONARY_LAVA:
				case E_BLOCK_LAVA:
				{
					if (ScoopUpLiquid(a_SlotNum, E_ITEM_LAVA_BUCKET))
					{
						DispChunk->SetBlock(DispX, DispY, DispZ, E_BLOCK_AIR, 0);
					}
					break;
				}
				default:
				{
					DropFromSlot(a_Chunk, a_SlotNum);
					break;
				}
			}
			break;
		}  // E_ITEM_BUCKET

		case E_ITEM_WATER_BUCKET:
		{
			LOGD("Dispensing water bucket in slot %d; DispBlock is \"%s\" (%d).", a_SlotNum, ItemTypeToString(DispBlock).c_str(), DispBlock);
			if (EmptyLiquidBucket(DispBlock, a_SlotNum))
			{
				DispChunk->SetBlock(DispX, DispY, DispZ, E_BLOCK_WATER, 0);
			}
			else
			{
				DropFromSlot(a_Chunk, a_SlotNum);
			}
			break;
		}

		case E_ITEM_LAVA_BUCKET:
		{
			LOGD("Dispensing lava bucket in slot %d; DispBlock is \"%s\" (%d).", a_SlotNum, ItemTypeToString(DispBlock).c_str(), DispBlock);
			if (EmptyLiquidBucket(DispBlock, a_SlotNum))
			{
				DispChunk->SetBlock(DispX, DispY, DispZ, E_BLOCK_LAVA, 0);
			}
			else
			{
				DropFromSlot(a_Chunk, a_SlotNum);
			}
			break;
		}

		case E_ITEM_SPAWN_EGG:
		{
			double MobX = 0.5 + (DispX + DispChunk->GetPosX() * cChunkDef::Width);
			double MobZ = 0.5 + (DispZ + DispChunk->GetPosZ() * cChunkDef::Width);
			if (m_World->SpawnMob(MobX, DispY, MobZ, (cMonster::eType)m_Contents.GetSlot(a_SlotNum).m_ItemDamage) >= 0)
			{
				m_Contents.ChangeSlotCount(a_SlotNum, -1);
			}
			break;
		}

		case E_BLOCK_TNT:
		{
			// Spawn a primed TNT entity, if space allows:
			if (DispChunk->GetBlock(DispX, DispY, DispZ) == E_BLOCK_AIR)
			{
				double TNTX = 0.5 + (DispX + DispChunk->GetPosX() * cChunkDef::Width);
				double TNTZ = 0.5 + (DispZ + DispChunk->GetPosZ() * cChunkDef::Width);
				m_World->SpawnPrimedTNT(TNTX, DispY + 0.5, TNTZ, 80, 0);  // 80 ticks fuse, no initial velocity
				m_Contents.ChangeSlotCount(a_SlotNum, -1);
			}
			break;
		}

		case E_ITEM_FLINT_AND_STEEL:
		{
			// Spawn fire if the block in front is air.
			if (DispChunk->GetBlock(DispX, DispY, DispZ) == E_BLOCK_AIR)
			{
				DispChunk->SetBlock(DispX, DispY, DispZ, E_BLOCK_FIRE, 0);

				bool ItemBroke = m_Contents.DamageItem(a_SlotNum, 1);

				if (ItemBroke)
				{
					m_Contents.ChangeSlotCount(a_SlotNum, -1);
				}
			}
			break;
		}

		case E_ITEM_FIRE_CHARGE:
		{
			SpawnProjectileFromDispenser(BlockX, DispY, BlockZ, cProjectileEntity::pkFireCharge, GetShootVector(Meta) * 20);
			m_Contents.ChangeSlotCount(a_SlotNum, -1);
			break;
		}

		case E_ITEM_ARROW:
		{
			SpawnProjectileFromDispenser(BlockX, DispY, BlockZ, cProjectileEntity::pkArrow, GetShootVector(Meta) * 20 + Vector3d(0, 1, 0));
			m_Contents.ChangeSlotCount(a_SlotNum, -1);
			break;
		}

		case E_ITEM_SNOWBALL:
		{
			SpawnProjectileFromDispenser(BlockX, DispY, BlockZ, cProjectileEntity::pkSnowball, GetShootVector(Meta) * 20 + Vector3d(0, 1, 0));
			m_Contents.ChangeSlotCount(a_SlotNum, -1);
			break;
		}

		case E_ITEM_EGG:
		{
			SpawnProjectileFromDispenser(BlockX, DispY, BlockZ, cProjectileEntity::pkEgg, GetShootVector(Meta) * 20 + Vector3d(0, 1, 0));
			m_Contents.ChangeSlotCount(a_SlotNum, -1);
			break;
		}

		case E_ITEM_FIREWORK_ROCKET:
		{
			// TODO: Add the fireworks entity
			break;
		}

		default:
		{
			DropFromSlot(a_Chunk, a_SlotNum);
			break;
		}
	}  // switch (ItemType)
}
void cFloodyFluidSimulator::SpreadToNeighbor(cChunk * a_NearChunk, int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_NewMeta)
{
	ASSERT(a_NewMeta <= 8);  // Invalid meta values
	ASSERT(a_NewMeta > 0);  // Source blocks aren't spread

	a_NearChunk = a_NearChunk->GetRelNeighborChunkAdjustCoords(a_RelX, a_RelZ);
	if ((a_NearChunk == NULL) || (!a_NearChunk->IsValid()))
	{
		// Chunk not available
		return;
	}

	const int BlockX = a_NearChunk->GetPosX() * cChunkDef::Width + a_RelX;
	const int BlockZ = a_NearChunk->GetPosZ() * cChunkDef::Width + a_RelZ;
	
	BLOCKTYPE BlockType;
	NIBBLETYPE BlockMeta;
	a_NearChunk->GetBlockTypeMeta(a_RelX, a_RelY, a_RelZ, BlockType, BlockMeta);
	
	if (IsAllowedBlock(BlockType))
	{
		if ((BlockMeta == a_NewMeta) || IsHigherMeta(BlockMeta, a_NewMeta))
		{
			// Don't spread there, there's already a higher or same level there
			return;
		}
	}

	// Check water - lava interaction:
	if (m_FluidBlock == E_BLOCK_LAVA)
	{
		if (IsBlockWater(BlockType))
		{
			// Lava flowing into water, change to stone / cobblestone based on direction:
			BLOCKTYPE NewBlock = (a_NewMeta == 8) ? E_BLOCK_STONE : E_BLOCK_COBBLESTONE;
			FLOG("  Lava flowing into water, turning water at rel {%d, %d, %d} into stone", 
				a_RelX, a_RelY, a_RelZ,
				ItemTypeToString(NewBlock).c_str()
			);
			a_NearChunk->SetBlock(a_RelX, a_RelY, a_RelZ, NewBlock, 0);

			a_NearChunk->BroadcastSoundEffect("random.fizz", BlockX * 8, a_RelY * 8, BlockZ * 8, 0.5f, 1.5f);
			return;
		}
	}
	else if (m_FluidBlock == E_BLOCK_WATER)
	{
		if (IsBlockLava(BlockType))
		{
			// Water flowing into lava, change to cobblestone / obsidian based on dest block:
			BLOCKTYPE NewBlock = (BlockMeta == 0) ? E_BLOCK_OBSIDIAN : E_BLOCK_COBBLESTONE;
			FLOG("  Water flowing into lava, turning lava at rel {%d, %d, %d} into %s", 
				a_RelX, a_RelY, a_RelZ, ItemTypeToString(NewBlock).c_str()
			);
			a_NearChunk->SetBlock(a_RelX, a_RelY, a_RelZ, NewBlock, 0);

			a_NearChunk->BroadcastSoundEffect("random.fizz", BlockX * 8, a_RelY * 8, BlockZ * 8, 0.5f, 1.5f);
			return;
		}
	}
	else
	{
		ASSERT(!"Unknown fluid!");
	}
	
	if (!IsPassableForFluid(BlockType))
	{
		// Can't spread there
		return;
	}
	
	// Wash away the block there, if possible:
	if (CanWashAway(BlockType))
	{
		cBlockHandler * Handler = BlockHandler(BlockType);
		if (Handler->DoesDropOnUnsuitable())
		{
			cChunkInterface ChunkInterface(m_World.GetChunkMap());
			cBlockInServerPluginInterface PluginInterface(m_World);
			Handler->DropBlock(
				ChunkInterface,
				m_World,
				PluginInterface,
				NULL, 
				BlockX, 
				a_RelY,
				BlockZ
			);
		}
	}  // if (CanWashAway)

	// Spread:
	FLOG("  Spreading to {%d, %d, %d} with meta %d", BlockX, a_RelY, BlockZ, a_NewMeta);
	a_NearChunk->SetBlock(a_RelX, a_RelY, a_RelZ, m_FluidBlock, a_NewMeta);
	m_World.GetSimulatorManager()->WakeUp(BlockX, a_RelY, BlockZ, a_NearChunk);

	HardenBlock(a_NearChunk, a_RelX, a_RelY, a_RelZ, m_FluidBlock, a_NewMeta);
}
Beispiel #5
0
void cDispenserEntity::DropSpenseFromSlot(cChunk & a_Chunk, int a_SlotNum)
{
	int DispX = m_RelX;
	int DispY = m_PosY;
	int DispZ = m_RelZ;
	NIBBLETYPE Meta = a_Chunk.GetMeta(m_RelX, m_PosY, m_RelZ);
	AddDropSpenserDir(DispX, DispY, DispZ, Meta);
	cChunk * DispChunk = a_Chunk.GetRelNeighborChunkAdjustCoords(DispX, DispZ);
	if (DispChunk == NULL)
	{
		// Would dispense into / interact with a non-loaded chunk, ignore the tick
		return;
	}
	BLOCKTYPE DispBlock = DispChunk->GetBlock(DispX, DispY, DispZ);

	// Dispense the item:
	switch (m_Contents.GetSlot(a_SlotNum).m_ItemType)
	{
		case E_ITEM_BUCKET:
		{
			LOGD("Dispensing empty bucket in slot %d; DispBlock is \"%s\" (%d).", a_SlotNum, ItemTypeToString(DispBlock).c_str(), DispBlock);
			switch (DispBlock)
			{
				case E_BLOCK_STATIONARY_WATER:
				case E_BLOCK_WATER:
				{
					if (ScoopUpLiquid(a_SlotNum, E_ITEM_WATER_BUCKET))
					{
						DispChunk->SetBlock(DispX, DispY, DispZ, E_BLOCK_AIR, 0);
					}
					break;
				}
				case E_BLOCK_STATIONARY_LAVA:
				case E_BLOCK_LAVA:
				{
					if (ScoopUpLiquid(a_SlotNum, E_ITEM_LAVA_BUCKET))
					{
						DispChunk->SetBlock(DispX, DispY, DispZ, E_BLOCK_AIR, 0);
					}
					break;
				}
				default:
				{
					DropFromSlot(a_Chunk, a_SlotNum);
					break;
				}
			}
			break;
		}  // E_ITEM_BUCKET
		
		case E_ITEM_WATER_BUCKET:
		{
			LOGD("Dispensing water bucket in slot %d; DispBlock is \"%s\" (%d).", a_SlotNum, ItemTypeToString(DispBlock).c_str(), DispBlock);
			if (EmptyLiquidBucket(DispBlock, a_SlotNum))
			{
				DispChunk->SetBlock(DispX, DispY, DispZ, E_BLOCK_WATER, 0);
			}
			else
			{
				DropFromSlot(a_Chunk, a_SlotNum);
			}
			break;
		}
		
		case E_ITEM_LAVA_BUCKET:
		{
			LOGD("Dispensing lava bucket in slot %d; DispBlock is \"%s\" (%d).", a_SlotNum, ItemTypeToString(DispBlock).c_str(), DispBlock);
			if (EmptyLiquidBucket(DispBlock, a_SlotNum))
			{
				DispChunk->SetBlock(DispX, DispY, DispZ, E_BLOCK_LAVA, 0);
			}
			else
			{
				DropFromSlot(a_Chunk, a_SlotNum);
			}
			break;
		}
		
		case E_ITEM_SPAWN_EGG:
		{
			double MobX = 0.5 + (DispX + DispChunk->GetPosX() * cChunkDef::Width);
			double MobZ = 0.5 + (DispZ + DispChunk->GetPosZ() * cChunkDef::Width);
			if (m_World->SpawnMob(MobX, DispY, MobZ, m_Contents.GetSlot(a_SlotNum).m_ItemDamage) >= 0)
			{
				m_Contents.ChangeSlotCount(a_SlotNum, -1);
			}
			break;
		}
		
		case E_BLOCK_TNT:
		{
			// Spawn a primed TNT entity, if space allows:
			if (DispChunk->GetBlock(DispX, DispY, DispZ) == E_BLOCK_AIR)
			{
				double TNTX = 0.5 + (DispX + DispChunk->GetPosX() * cChunkDef::Width);
				double TNTZ = 0.5 + (DispZ + DispChunk->GetPosZ() * cChunkDef::Width);
				m_World->SpawnPrimedTNT(TNTX, DispY + 0.5, TNTZ, 4, 0);  // 4 seconds fuse, no initial velocity
				m_Contents.ChangeSlotCount(a_SlotNum, -1);
			}
			break;
		}

		case E_ITEM_FLINT_AND_STEEL:
		{
			// Spawn fire if the block in front is air.
			if (DispChunk->GetBlock(DispX, DispY, DispZ) == E_BLOCK_AIR)
			{
				DispChunk->SetBlock(DispX, DispY, DispZ, E_BLOCK_FIRE, 0);
				m_Contents.SetSlot(a_SlotNum, m_Contents.GetSlot(a_SlotNum).m_ItemType, m_Contents.GetSlot(a_SlotNum).m_ItemCount, m_Contents.GetSlot(a_SlotNum).m_ItemDamage + 1);
				// If the durability has run out destroy the item.
				if (m_Contents.GetSlot(a_SlotNum).m_ItemDamage > 64)
				{				
					m_Contents.ChangeSlotCount(a_SlotNum, -1);
				}
			}
			break;
		}
		
		default:
		{
			DropFromSlot(a_Chunk, a_SlotNum);
			break;
		}
	}  // switch (ItemType)
}