use of org.spongepowered.api.block.BlockState in project LanternServer by LanternPowered.
the class ProcessorPlayOutParticleEffect method preProcess.
private ICachedMessage preProcess(ParticleEffect effect0) {
final LanternParticleEffect effect = (LanternParticleEffect) effect0;
final LanternParticleType type = effect.getType();
final OptionalInt internalType = type.getInternalType();
// Special cases
if (!internalType.isPresent()) {
if (type == ParticleTypes.FIREWORKS) {
// Create the fireworks data item
final LanternItemStack itemStack = new LanternItemStack(ItemTypes.FIREWORKS);
itemStack.tryOffer(Keys.FIREWORK_EFFECTS, effect.getOptionOrDefault(ParticleOptions.FIREWORK_EFFECTS).get());
// Write the item to a parameter list
final ByteBufParameterList parameterList = new ByteBufParameterList(ByteBufferAllocator.unpooled());
parameterList.add(EntityParameters.Fireworks.ITEM, itemStack);
return new CachedFireworksMessage(new MessagePlayOutEntityMetadata(CachedFireworksMessage.ENTITY_ID, parameterList));
} else if (type == ParticleTypes.FERTILIZER) {
final int quantity = effect.getOptionOrDefault(ParticleOptions.QUANTITY).get();
return new CachedEffectMessage(2005, quantity, false);
} else if (type == ParticleTypes.SPLASH_POTION) {
final int potionId = this.potionEffectTypeToId.getInt(effect.getOptionOrDefault(ParticleOptions.POTION_EFFECT_TYPE).get());
return new CachedEffectMessage(2002, potionId, false);
} else if (type == ParticleTypes.BREAK_BLOCK) {
final int state = getBlockState(effect, type.getDefaultOption(ParticleOptions.BLOCK_STATE));
if (state == 0) {
return EmptyCachedMessage.INSTANCE;
}
return new CachedEffectMessage(2001, state, false);
} else if (type == ParticleTypes.MOBSPAWNER_FLAMES) {
return new CachedEffectMessage(2004, 0, false);
} else if (type == ParticleTypes.ENDER_TELEPORT) {
return new CachedEffectMessage(2003, 0, false);
} else if (type == ParticleTypes.DRAGON_BREATH_ATTACK) {
return new CachedEffectMessage(2006, 0, false);
} else if (type == ParticleTypes.FIRE_SMOKE) {
final Direction direction = effect.getOptionOrDefault(ParticleOptions.DIRECTION).get();
return new CachedEffectMessage(2000, getDirectionData(direction), false);
}
return EmptyCachedMessage.INSTANCE;
}
final int internalId = internalType.getAsInt();
final Vector3f offset = effect.getOption(ParticleOptions.OFFSET).map(Vector3d::toFloat).orElse(Vector3f.ZERO);
final int quantity = effect.getOption(ParticleOptions.QUANTITY).orElse(1);
int[] extra = null;
// The extra values, normal behavior offsetX, offsetY, offsetZ
double f0 = 0f;
double f1 = 0f;
double f2 = 0f;
// Depends on behavior
// Note: If the count > 0 -> speed = 0f else if count = 0 -> speed = 1f
final Optional<BlockState> defaultBlockState;
if (type != ParticleTypes.ITEM_CRACK && (defaultBlockState = type.getDefaultOption(ParticleOptions.BLOCK_STATE)).isPresent()) {
final int state = getBlockState(effect, defaultBlockState);
if (state == 0) {
return EmptyCachedMessage.INSTANCE;
}
extra = new int[] { state };
}
final Optional<ItemStackSnapshot> defaultItemStackSnapshot;
if (extra == null && (defaultItemStackSnapshot = type.getDefaultOption(ParticleOptions.ITEM_STACK_SNAPSHOT)).isPresent()) {
final Optional<ItemStackSnapshot> optItemStackSnapshot = effect.getOption(ParticleOptions.ITEM_STACK_SNAPSHOT);
if (optItemStackSnapshot.isPresent()) {
extra = toExtraItemData(optItemStackSnapshot.get().createStack());
} else {
final Optional<BlockState> optBlockState = effect.getOption(ParticleOptions.BLOCK_STATE);
if (optBlockState.isPresent()) {
final BlockState blockState = optBlockState.get();
final Optional<ItemType> optItemType = blockState.getType().getItem();
if (optItemType.isPresent()) {
// TODO: Item damage value
extra = new int[] { ItemRegistryModule.get().getInternalId(optItemType.get()), 0 };
} else {
return EmptyCachedMessage.INSTANCE;
}
} else {
extra = toExtraItemData(defaultItemStackSnapshot.get().createStack());
}
}
}
if (extra == null) {
extra = new int[0];
}
final Optional<Double> defaultScale = type.getDefaultOption(ParticleOptions.SCALE);
final Optional<Color> defaultColor;
final Optional<NotePitch> defaultNote;
final Optional<Vector3d> defaultVelocity;
if (defaultScale.isPresent()) {
double scale = effect.getOption(ParticleOptions.SCALE).orElse(defaultScale.get());
// Server formula: sizeServer = (-sizeClient * 2) + 2
if (type == ParticleTypes.LARGE_EXPLOSION || type == ParticleTypes.SWEEP_ATTACK) {
scale = (-scale * 2f) + 2f;
}
if (scale == 0f) {
return new CachedParticleMessage(internalId, offset, quantity, extra);
}
f0 = scale;
} else if ((defaultColor = type.getDefaultOption(ParticleOptions.COLOR)).isPresent()) {
final boolean isSpell = type == ParticleTypes.MOB_SPELL || type == ParticleTypes.AMBIENT_MOB_SPELL;
Color color = effect.getOption(ParticleOptions.COLOR).orElse(null);
if (!isSpell && (color == null || color.equals(defaultColor.get()))) {
return new CachedParticleMessage(internalId, offset, quantity, extra);
} else if (isSpell && color == null) {
color = defaultColor.get();
}
f0 = color.getRed() / 255f;
f1 = color.getGreen() / 255f;
f2 = color.getBlue() / 255f;
// but we already chose for the color, can't have both
if (isSpell) {
f0 = Math.max(f0, 0.001f);
f2 = Math.max(f0, 0.001f);
}
// If the f0 value 0 is, the redstone will set it automatically to red 255
if (f0 == 0f && type == ParticleTypes.REDSTONE_DUST) {
f0 = 0.00001f;
}
} else if ((defaultNote = type.getDefaultOption(ParticleOptions.NOTE)).isPresent()) {
final NotePitch notePitch = effect.getOption(ParticleOptions.NOTE).orElse(defaultNote.get());
final float note = ((LanternNotePitch) notePitch).getInternalId();
if (note == 0f) {
return new CachedParticleMessage(internalId, offset, quantity, extra);
}
f0 = note / 24f;
} else if ((defaultVelocity = type.getDefaultOption(ParticleOptions.VELOCITY)).isPresent()) {
final Vector3d velocity = effect.getOption(ParticleOptions.VELOCITY).orElse(defaultVelocity.get());
f0 = velocity.getX();
f1 = velocity.getY();
f2 = velocity.getZ();
final Optional<Boolean> slowHorizontalVelocity = type.getDefaultOption(ParticleOptions.SLOW_HORIZONTAL_VELOCITY);
if (slowHorizontalVelocity.isPresent() && effect.getOption(ParticleOptions.SLOW_HORIZONTAL_VELOCITY).orElse(slowHorizontalVelocity.get())) {
f0 = 0f;
f2 = 0f;
}
// The y value won't work for this effect, if the value isn't 0 the velocity won't work
if (type == ParticleTypes.WATER_SPLASH) {
f1 = 0f;
}
if (f0 == 0f && f1 == 0f && f2 == 0f) {
return new CachedParticleMessage(internalId, offset, quantity, extra);
}
}
// Is this check necessary?
if (f0 == 0f && f1 == 0f && f2 == 0f) {
return new CachedParticleMessage(internalId, offset, quantity, extra);
}
return new CachedOffsetParticleMessage(internalId, new Vector3f(f0, f1, f2), offset, quantity, extra);
}
use of org.spongepowered.api.block.BlockState in project LanternServer by LanternPowered.
the class LanternChunk method createSnapshot.
@Override
public BlockSnapshot createSnapshot(int x, int y, int z) {
final BlockState state = getBlock(x, y, z);
final Location<World> loc = new Location<>(this.world, x, y, z);
// TODO: Tile entity data
return new LanternBlockSnapshot(loc, state, ((LanternBlockType) state.getType()).getExtendedBlockStateProvider().get(state, loc, null), getCreator(x, y, z), getNotifier(x, y, z), ImmutableMap.of());
}
use of org.spongepowered.api.block.BlockState in project LanternServer by LanternPowered.
the class LanternChunk method get.
@Override
public <E> Optional<E> get(int x, int y, int z, Key<? extends BaseValue<E>> key) {
if (!this.loaded) {
return Optional.empty();
}
final BlockState blockState = getBlock(x, y, z);
Optional<E> value = blockState.get(key);
if (!value.isPresent()) {
final Optional<TileEntity> tileEntity = getTileEntity(x, y, z);
if (tileEntity.isPresent()) {
value = tileEntity.get().get(key);
}
}
return value;
}
use of org.spongepowered.api.block.BlockState in project LanternServer by LanternPowered.
the class LanternChunk method getBlockSelectionBox.
@Override
public Optional<AABB> getBlockSelectionBox(int x, int y, int z) {
final BlockState block = getBlock(x, y, z);
if (block.getType() == BlockTypes.AIR) {
return Optional.empty();
}
final ObjectProvider<AABB> aabbObjectProvider = ((LanternBlockType) block.getType()).getBoundingBoxProvider();
if (aabbObjectProvider == null) {
return Optional.empty();
}
final AABB aabb;
if (aabbObjectProvider instanceof ConstantObjectProvider || aabbObjectProvider instanceof CachedSimpleObjectProvider || aabbObjectProvider instanceof SimpleObjectProvider) {
aabb = aabbObjectProvider.get(block, null, null);
} else {
aabb = aabbObjectProvider.get(block, new Location<>(this.world, x, y, z), null);
}
return aabb == null ? Optional.empty() : Optional.of(aabb.offset(x, y, z));
}
use of org.spongepowered.api.block.BlockState in project LanternServer by LanternPowered.
the class LanternChunk method setBlock.
@Override
public boolean setBlock(int x, int y, int z, BlockState block, BlockChangeFlag flag) {
checkNotNull(block, "block");
checkNotNull(flag, "flag");
checkVolumeBounds(x, y, z);
if (!this.loaded) {
return false;
}
final short type = BlockRegistryModule.get().getStateInternalIdAndData(block);
final short type1;
// Air doesn't have metadata values
if (type >> 4 == 0 && type != 0) {
type1 = 0;
} else {
type1 = type;
}
final BlockState[] changeData = new BlockState[1];
final int rx = x & 0xf;
final int rz = z & 0xf;
this.chunkSections.work(y >> 4, section -> {
if (section == null) {
// so we can fail fast
if (type1 == 0) {
return section;
}
// Create a new section
section = new ChunkSection();
}
final int index = ChunkSection.index(rx, y & 0xf, rz);
final short oldType = section.types[index];
if (oldType == type1) {
return section;
}
if (oldType != 0) {
short count = section.typesCountMap.get(oldType);
if (count > 0) {
if (--count <= 0) {
section.typesCountMap.remove(oldType);
} else {
section.typesCountMap.put(oldType, count);
}
}
}
if (type1 != 0) {
section.typesCountMap.put(type1, (short) (section.typesCountMap.get(type1) + 1));
if (oldType == 0) {
section.nonAirCount++;
}
} else {
section.nonAirCount--;
}
final BlockState oldState = BlockRegistryModule.get().getStateByInternalIdAndData(oldType).get();
changeData[0] = oldState;
// The section is empty, destroy it
if (section.nonAirCount <= 0) {
return null;
}
final LanternTileEntity tileEntity = section.tileEntities.get((short) index);
boolean remove = false;
boolean refresh = false;
final Optional<TileEntityProvider> tileEntityProvider = ((LanternBlockType) block.getType()).getTileEntityProvider();
if (tileEntity != null) {
if (oldType == 0 || type1 == 0) {
remove = true;
} else if (tileEntity instanceof ITileEntityRefreshBehavior) {
if (((ITileEntityRefreshBehavior) tileEntity).shouldRefresh(oldState, block)) {
remove = true;
refresh = true;
}
} else if (oldType >> 4 != type1 >> 4) {
// The default behavior will only refresh if the
// block type is changed and not the block state
remove = true;
refresh = true;
}
if (refresh && !tileEntityProvider.isPresent()) {
refresh = false;
}
} else if (tileEntityProvider.isPresent()) {
refresh = true;
}
if (remove) {
tileEntity.setValid(false);
}
if (refresh) {
final Location<World> location = tileEntity != null ? tileEntity.getLocation() : new Location<>(this.world, x, y, z);
final LanternTileEntity newTileEntity = (LanternTileEntity) tileEntityProvider.get().get(block, location, null);
section.tileEntities.put((short) index, newTileEntity);
newTileEntity.setLocation(location);
newTileEntity.setValid(true);
} else if (remove) {
section.tileEntities.remove((short) index);
}
section.types[index] = type1;
return section;
});
final int index = rz << 4 | rx;
long stamp = this.heightMapLock.writeLock();
try {
// TODO: Check first and then use the write lock?
if (type != 0 && (this.heightMap[index] & 0xff) < y) {
this.heightMap[index] = (byte) y;
this.heightMapUpdateFlags.clear(index);
} else if (type == 0 && (this.heightMap[index] & 0xff) == y) {
this.heightMapUpdateFlags.set(index);
}
} finally {
this.heightMapLock.unlock(stamp);
}
if (changeData[0] != null) {
this.world.getEventListener().onBlockChange(x, y, z, changeData[0], block);
}
return true;
}
Aggregations