Search in sources :

Example 1 with EntityBridge

use of org.spongepowered.common.bridge.world.entity.EntityBridge in project SpongeCommon by SpongePowered.

the class ServerLevelMixin method impl$constructPostEventForEntityAdd.

@Inject(method = "addEntity", at = @At("HEAD"))
private void impl$constructPostEventForEntityAdd(final Entity entity, final CallbackInfoReturnable<Boolean> cir) {
    if (!(entity instanceof EntityBridge)) {
        return;
    }
    if (!((EntityBridge) entity).bridge$isConstructing()) {
        return;
    }
    ((EntityBridge) entity).bridge$fireConstructors();
    final Vec3 position = entity.position();
    final ServerLocation location = ServerLocation.of((ServerWorld) this, position.x(), position.y(), position.z());
    final Vec2 rotationVector = entity.getRotationVector();
    final Vector3d rotation = new Vector3d(rotationVector.x, rotationVector.y, 0);
    try (final CauseStackManager.StackFrame frame = PhaseTracker.SERVER.pushCauseFrame()) {
        frame.pushCause(entity);
        final Event construct = SpongeEventFactory.createConstructEntityEventPost(frame.currentCause(), (org.spongepowered.api.entity.Entity) entity, location, rotation, ((EntityType<?>) entity.getType()));
        SpongeCommon.post(construct);
    }
}
Also used : EntityType(org.spongepowered.api.entity.EntityType) ServerLocation(org.spongepowered.api.world.server.ServerLocation) Vector3d(org.spongepowered.math.vector.Vector3d) Vec2(net.minecraft.world.phys.Vec2) CauseStackManager(org.spongepowered.api.event.CauseStackManager) Vec3(net.minecraft.world.phys.Vec3) ExplosionEvent(org.spongepowered.api.event.world.ExplosionEvent) PlaySoundEvent(org.spongepowered.api.event.sound.PlaySoundEvent) ChangeWeatherEvent(org.spongepowered.api.event.world.ChangeWeatherEvent) LightningEvent(org.spongepowered.api.event.action.LightningEvent) Event(org.spongepowered.api.event.Event) EntityBridge(org.spongepowered.common.bridge.world.entity.EntityBridge) Inject(org.spongepowered.asm.mixin.injection.Inject)

Example 2 with EntityBridge

use of org.spongepowered.common.bridge.world.entity.EntityBridge in project SpongeCommon by SpongePowered.

the class SpongeCommonEventFactory method handleCollideBlockEvent.

public static boolean handleCollideBlockEvent(final Block block, final Level world, final BlockPos pos, final net.minecraft.world.level.block.state.BlockState state, final net.minecraft.world.entity.Entity entity, final Direction direction, final CollisionType type) {
    if (world.isClientSide() || pos.getY() <= 0) {
        return false;
    }
    try (final CauseStackManager.StackFrame frame = PhaseTracker.getCauseStackManager().pushCauseFrame()) {
        frame.pushCause(entity);
        if (entity instanceof CreatorTrackedBridge) {
            final CreatorTrackedBridge spongeEntity = (CreatorTrackedBridge) entity;
            spongeEntity.tracker$getCreatorUUID().ifPresent(user -> frame.addContext(EventContextKeys.CREATOR, user));
        }
        // TODO: Add target side support
        final ServerLocation loc = ServerLocation.of((ServerWorld) world, VecHelper.toVector3d(pos));
        final CollideBlockEvent event;
        switch(type) {
            case MOVE:
                event = SpongeEventFactory.createCollideBlockEventMove(frame.currentCause(), (BlockState) state, loc, direction);
                break;
            case FALL:
                event = SpongeEventFactory.createCollideBlockEventFall(frame.currentCause(), (BlockState) state, loc, direction);
                break;
            case STEP_ON:
                event = SpongeEventFactory.createCollideBlockEventStepOn(frame.currentCause(), (BlockState) state, loc, direction);
                break;
            case INSIDE:
                event = SpongeEventFactory.createCollideBlockEventInside(frame.currentCause(), (BlockState) state, loc, direction);
                break;
            default:
                throw new IllegalArgumentException("Unknown type " + type);
        }
        final boolean cancelled = SpongeCommon.post(event);
        if (!cancelled) {
            final EntityBridge spongeEntity = (EntityBridge) entity;
            if (!pos.equals(spongeEntity.bridge$getLastCollidedBlockPos())) {
                final PhaseContext<?> context = PhaseTracker.getInstance().getPhaseContext();
                context.applyNotifierIfAvailable(notifier -> {
                    LevelChunkBridge spongeChunk = ((ActiveChunkReferantBridge) entity).bridge$getActiveChunk();
                    if (spongeChunk == null) {
                        spongeChunk = (LevelChunkBridge) world.getChunkAt(pos);
                    }
                    spongeChunk.bridge$addTrackedBlockPosition(block, pos, notifier, PlayerTracker.Type.NOTIFIER);
                });
            }
        }
        return cancelled;
    }
}
Also used : CreatorTrackedBridge(org.spongepowered.common.bridge.CreatorTrackedBridge) BlockState(org.spongepowered.api.block.BlockState) ServerLocation(org.spongepowered.api.world.server.ServerLocation) CauseStackManager(org.spongepowered.api.event.CauseStackManager) LevelChunkBridge(org.spongepowered.common.bridge.world.level.chunk.LevelChunkBridge) CollideBlockEvent(org.spongepowered.api.event.block.CollideBlockEvent) EntityBridge(org.spongepowered.common.bridge.world.entity.EntityBridge) PlatformEntityBridge(org.spongepowered.common.bridge.world.entity.PlatformEntityBridge) ActiveChunkReferantBridge(org.spongepowered.common.bridge.world.level.chunk.ActiveChunkReferantBridge)

Example 3 with EntityBridge

use of org.spongepowered.common.bridge.world.entity.EntityBridge in project SpongeCommon by SpongePowered.

the class EntityData method register.

// @formatter:off
public static void register(final DataProviderRegistrator registrator) {
    registrator.asMutable(Entity.class).create(Keys.AGE).get(h -> h.tickCount).setAnd((h, v) -> {
        if (v < 0) {
            return false;
        }
        h.tickCount = v;
        return true;
    }).create(Keys.BASE_SIZE).get(h -> (double) h.getBbWidth()).create(Keys.BASE_VEHICLE).get(h -> {
        final Entity rootVehicle = h.getRootVehicle();
        if (rootVehicle == h) {
            return null;
        }
        return (org.spongepowered.api.entity.Entity) rootVehicle;
    }).create(Keys.CUSTOM_NAME).get(h -> h.hasCustomName() ? SpongeAdventure.asAdventure(h.getCustomName()) : null).set((h, v) -> h.setCustomName(SpongeAdventure.asVanilla(v))).delete(h -> {
        h.setCustomName(null);
        h.setCustomNameVisible(false);
    }).create(Keys.DISPLAY_NAME).get(h -> SpongeAdventure.asAdventure(h.getDisplayName())).create(Keys.EYE_HEIGHT).get(h -> (double) h.getEyeHeight()).create(Keys.EYE_POSITION).get(h -> VecHelper.toVector3d(h.getEyePosition(1f))).create(Keys.FALL_DISTANCE).get(h -> (double) h.fallDistance).setAnd((h, v) -> {
        if (v < 0) {
            return false;
        }
        h.fallDistance = v.floatValue();
        return true;
    }).create(Keys.FIRE_DAMAGE_DELAY).get(h -> new SpongeTicks(((EntityAccessor) h).invoker$getFireImmuneTicks())).setAnd((h, v) -> {
        final int ticks = (int) v.ticks();
        if (ticks < 1 || ticks > Short.MAX_VALUE) {
            return false;
        }
        ((EntityBridge) h).bridge$setFireImmuneTicks(ticks);
        return ((EntityAccessor) h).invoker$getFireImmuneTicks() == ticks;
    }).create(Keys.FIRE_TICKS).get(h -> ((EntityAccessor) h).accessor$remainingFireTicks() > 0 ? Ticks.of(((EntityAccessor) h).accessor$remainingFireTicks()) : null).set((h, v) -> {
        final int ticks = (int) v.ticks();
        ((EntityAccessor) h).accessor$remainingFireTicks(Math.max(ticks, Constants.Entity.MINIMUM_FIRE_TICKS));
    }).deleteAndGet(h -> {
        final EntityAccessor accessor = (EntityAccessor) h;
        final int ticks = accessor.accessor$remainingFireTicks();
        if (ticks < Constants.Entity.MINIMUM_FIRE_TICKS) {
            return DataTransactionResult.failNoData();
        }
        final DataTransactionResult.Builder dtrBuilder = DataTransactionResult.builder();
        dtrBuilder.replace(Value.immutableOf(Keys.FIRE_TICKS, new SpongeTicks(ticks)));
        dtrBuilder.replace(Value.immutableOf(Keys.FIRE_DAMAGE_DELAY, new SpongeTicks(((EntityAccessor) h).invoker$getFireImmuneTicks())));
        h.clearFire();
        return dtrBuilder.result(DataTransactionResult.Type.SUCCESS).build();
    }).create(Keys.HEIGHT).get(h -> (double) h.getBbHeight()).create(Keys.INVULNERABILITY_TICKS).get(h -> new SpongeTicks(h.invulnerableTime)).setAnd((h, v) -> {
        final int ticks = (int) v.ticks();
        if (ticks < 0) {
            return false;
        }
        h.invulnerableTime = ticks;
        if (h instanceof LivingEntity) {
            ((LivingEntity) h).hurtTime = ticks;
        }
        return true;
    }).create(Keys.IS_CUSTOM_NAME_VISIBLE).get(Entity::isCustomNameVisible).set(Entity::setCustomNameVisible).create(Keys.IS_FLYING).get(h -> h.hasImpulse).set((h, v) -> h.hasImpulse = v).supports(h -> !(h instanceof Player)).create(Keys.IS_GLOWING).get(Entity::isGlowing).set(Entity::setGlowing).create(Keys.IS_GRAVITY_AFFECTED).get(h -> !h.isNoGravity()).set((h, v) -> h.setNoGravity(!v)).create(Keys.IS_SNEAKING).get(Entity::isShiftKeyDown).set(Entity::setShiftKeyDown).create(Keys.IS_SPRINTING).get(Entity::isSprinting).set(Entity::setSprinting).create(Keys.IS_SILENT).get(Entity::isSilent).set(Entity::setSilent).create(Keys.IS_WET).get(Entity::isInWaterOrRain).create(Keys.ON_GROUND).get(Entity::isOnGround).create(Keys.PASSENGERS).get(h -> h.getPassengers().stream().map(org.spongepowered.api.entity.Entity.class::cast).collect(Collectors.toList())).set((h, v) -> {
        h.ejectPassengers();
        v.forEach(v1 -> ((Entity) v1).startRiding(h, true));
    }).create(Keys.REMAINING_AIR).get(h -> Math.max(0, h.getAirSupply())).setAnd((h, v) -> {
        if (v < 0 || v > h.getMaxAirSupply()) {
            return false;
        }
        if (v == 0 && h.getAirSupply() < 0) {
            return false;
        }
        h.setAirSupply(v);
        return true;
    }).create(Keys.SCALE).get(h -> 1d).create(Keys.SCOREBOARD_TAGS).get(Entity::getTags).set((h, v) -> {
        h.getTags().clear();
        h.getTags().addAll(v);
    }).create(Keys.TRANSIENT).get(h -> ((EntityAccessor) h).invoker$getEncodeId() == null).set((h, v) -> ((EntityBridge) h).bridge$setTransient(v)).create(Keys.VEHICLE).get(h -> (org.spongepowered.api.entity.Entity) h.getVehicle()).set((h, v) -> h.startRiding((Entity) v, true)).create(Keys.VELOCITY).get(h -> VecHelper.toVector3d(h.getDeltaMovement())).set((h, v) -> h.setDeltaMovement(VecHelper.toVanillaVector3d(v))).create(Keys.SWIFTNESS).get(m -> m.getDeltaMovement().length()).set((m, v) -> m.setDeltaMovement(m.getDeltaMovement().normalize().scale(v))).supports(m -> m.getDeltaMovement().lengthSqr() > 0).asMutable(EntityMaxAirBridge.class).create(Keys.MAX_AIR).get(EntityMaxAirBridge::bridge$getMaxAir).set(EntityMaxAirBridge::bridge$setMaxAir);
    registrator.spongeDataStore(ResourceKey.sponge("max_air"), EntityMaxAirBridge.class, Keys.MAX_AIR);
    registrator.newDataStore(SpongeEntitySnapshot.class, SpongeEntityArchetype.class).dataStore(Keys.CUSTOM_NAME, (dv, v) -> dv.set(Constants.Entity.CUSTOM_NAME, GsonComponentSerializer.gson().serialize(v)), dv -> dv.getString(Constants.Entity.CUSTOM_NAME).map(GsonComponentSerializer.gson()::deserialize));
// @formatter:on
}
Also used : GsonComponentSerializer(net.kyori.adventure.text.serializer.gson.GsonComponentSerializer) Ticks(org.spongepowered.api.util.Ticks) LivingEntity(net.minecraft.world.entity.LivingEntity) EntityMaxAirBridge(org.spongepowered.common.bridge.world.entity.EntityMaxAirBridge) Constants(org.spongepowered.common.util.Constants) SpongeEntityArchetype(org.spongepowered.common.entity.SpongeEntityArchetype) SpongeAdventure(org.spongepowered.common.adventure.SpongeAdventure) DataTransactionResult(org.spongepowered.api.data.DataTransactionResult) Collectors(java.util.stream.Collectors) Value(org.spongepowered.api.data.value.Value) SpongeEntitySnapshot(org.spongepowered.common.entity.SpongeEntitySnapshot) Player(net.minecraft.world.entity.player.Player) EntityBridge(org.spongepowered.common.bridge.world.entity.EntityBridge) Keys(org.spongepowered.api.data.Keys) Entity(net.minecraft.world.entity.Entity) DataProviderRegistrator(org.spongepowered.common.data.provider.DataProviderRegistrator) EntityAccessor(org.spongepowered.common.accessor.world.entity.EntityAccessor) VecHelper(org.spongepowered.common.util.VecHelper) ResourceKey(org.spongepowered.api.ResourceKey) SpongeTicks(org.spongepowered.common.util.SpongeTicks) EntityAccessor(org.spongepowered.common.accessor.world.entity.EntityAccessor) LivingEntity(net.minecraft.world.entity.LivingEntity) Entity(net.minecraft.world.entity.Entity) Player(net.minecraft.world.entity.player.Player) EntityMaxAirBridge(org.spongepowered.common.bridge.world.entity.EntityMaxAirBridge) SpongeEntityArchetype(org.spongepowered.common.entity.SpongeEntityArchetype) LivingEntity(net.minecraft.world.entity.LivingEntity) SpongeEntitySnapshot(org.spongepowered.common.entity.SpongeEntitySnapshot) SpongeTicks(org.spongepowered.common.util.SpongeTicks)

Example 4 with EntityBridge

use of org.spongepowered.common.bridge.world.entity.EntityBridge in project SpongeCommon by SpongePowered.

the class SynchedEntityDataMixin method set.

/**
 * @author gabizou December 27th, 2017
 * @reason Inject ChangeValueEvent for entities by utilizing keys. Keys are registered
 *     based on the entity of which they belong to. This is to make the events more streamlined
 *     with regards to "when" they are being changed.
 * @param key The parameter key
 * @param value The value
 * @param <T> The type of value
 */
@SuppressWarnings({ "unchecked", "rawtypes" })
@Overwrite
public <T> void set(final EntityDataAccessor<T> key, T value) {
    final SynchedEntityData.DataItem<T> dataentry = this.<T>getItem(key);
    // Sponge Start - set up the current value, so we don't have to retrieve it multiple times
    final T currentValue = dataentry.getValue();
    final T incomingValue = value;
    if (ObjectUtils.notEqual(value, currentValue)) {
        // I don't know, ask Grum....
        if (this.entity != null && this.entity.level != null && !this.entity.level.isClientSide && !((EntityBridge) this.entity).bridge$isConstructing()) {
            // We only want to spam the server world ;)
            final Optional<DataParameterConverter<T>> converter = ((EntityDataAccessorBridge) key).bridge$getDataConverter();
            // At this point it is changing
            if (converter.isPresent()) {
                // Ok, we have a key ready to use the converter
                final Optional<DataTransactionResult> optional = converter.get().createTransaction(this.entity, currentValue, value);
                if (optional.isPresent()) {
                    // Only need to make a transaction if there are actual changes necessary.
                    final DataTransactionResult transaction = optional.get();
                    final ChangeDataHolderEvent.ValueChange event = SpongeEventFactory.createChangeDataHolderEventValueChange(PhaseTracker.getCauseStackManager().currentCause(), transaction, (DataHolder.Mutable) this.entity);
                    Sponge.eventManager().post(event);
                    if (event.isCancelled()) {
                        // If the event is cancelled, well, don't change the underlying value.
                        return;
                    }
                    try {
                        value = converter.get().getValueFromEvent(currentValue, event.endResult());
                    } catch (final Exception e) {
                        // Worst case scenario, we don't want to cause an issue, so we just set the value
                        value = incomingValue;
                    }
                }
            }
        }
        // Sponge End
        dataentry.setValue(value);
        this.entity.onSyncedDataUpdated(key);
        dataentry.setDirty(true);
        this.isDirty = true;
    }
}
Also used : SynchedEntityData(net.minecraft.network.syncher.SynchedEntityData) EntityDataAccessorBridge(org.spongepowered.common.bridge.network.syncher.EntityDataAccessorBridge) DataParameterConverter(org.spongepowered.common.data.datasync.DataParameterConverter) DataHolder(org.spongepowered.api.data.DataHolder) DataTransactionResult(org.spongepowered.api.data.DataTransactionResult) EntityBridge(org.spongepowered.common.bridge.world.entity.EntityBridge) ChangeDataHolderEvent(org.spongepowered.api.event.data.ChangeDataHolderEvent) Overwrite(org.spongepowered.asm.mixin.Overwrite)

Example 5 with EntityBridge

use of org.spongepowered.common.bridge.world.entity.EntityBridge in project SpongeCommon by SpongePowered.

the class RunAroundLikeCrazyGoalMixin method tick.

// @formatter:on
/**
 * @author rexbut - December 16th, 2016
 * @author i509VCB - February 18th, 2020 - 1.14.4
 *
 * @reason - adjusted to support {@link DismountTypes}
 */
@Overwrite
public void tick() {
    if (!this.horse.isTamed() && this.horse.getRandom().nextInt(50) == 0) {
        Entity entity = this.horse.getPassengers().get(0);
        if (entity == null) {
            return;
        }
        if (entity instanceof Player) {
            int i = this.horse.getTemper();
            int j = this.horse.getMaxTemper();
            if (j > 0 && this.horse.getRandom().nextInt(j) < i) {
                // Sponge start - Fire Tame Entity event
                try (CauseStackManager.StackFrame frame = PhaseTracker.getCauseStackManager().pushCauseFrame()) {
                    frame.pushCause(entity);
                    if (SpongeCommon.post(SpongeEventFactory.createTameEntityEvent(frame.currentCause(), (HorseLike) this.horse))) {
                        return;
                    }
                }
                // Sponge end
                this.horse.tameWithName((Player) entity);
                return;
            }
            this.horse.modifyTemper(5);
        }
        // this.horseHost.ejectPassengers(); // Vanilla
        if (((EntityBridge) this.horse).bridge$removePassengers(DismountTypes.DERAIL.get())) {
            // Sponge end
            this.horse.makeMad();
            this.horse.level.broadcastEntityEvent(this.horse, (byte) 6);
        }
    }
}
Also used : Entity(net.minecraft.world.entity.Entity) Player(net.minecraft.world.entity.player.Player) CauseStackManager(org.spongepowered.api.event.CauseStackManager) HorseLike(org.spongepowered.api.entity.living.animal.horse.HorseLike) EntityBridge(org.spongepowered.common.bridge.world.entity.EntityBridge) Overwrite(org.spongepowered.asm.mixin.Overwrite)

Aggregations

EntityBridge (org.spongepowered.common.bridge.world.entity.EntityBridge)5 CauseStackManager (org.spongepowered.api.event.CauseStackManager)3 Entity (net.minecraft.world.entity.Entity)2 Player (net.minecraft.world.entity.player.Player)2 DataTransactionResult (org.spongepowered.api.data.DataTransactionResult)2 ServerLocation (org.spongepowered.api.world.server.ServerLocation)2 Overwrite (org.spongepowered.asm.mixin.Overwrite)2 Collectors (java.util.stream.Collectors)1 GsonComponentSerializer (net.kyori.adventure.text.serializer.gson.GsonComponentSerializer)1 SynchedEntityData (net.minecraft.network.syncher.SynchedEntityData)1 LivingEntity (net.minecraft.world.entity.LivingEntity)1 Vec2 (net.minecraft.world.phys.Vec2)1 Vec3 (net.minecraft.world.phys.Vec3)1 ResourceKey (org.spongepowered.api.ResourceKey)1 BlockState (org.spongepowered.api.block.BlockState)1 DataHolder (org.spongepowered.api.data.DataHolder)1 Keys (org.spongepowered.api.data.Keys)1 Value (org.spongepowered.api.data.value.Value)1 EntityType (org.spongepowered.api.entity.EntityType)1 HorseLike (org.spongepowered.api.entity.living.animal.horse.HorseLike)1