use of org.spongepowered.api.event.CauseStackManager in project SpongeCommon by SpongePowered.
the class DamageEventUtil method createEnchantmentModifiers.
public static Optional<List<DamageFunction>> createEnchantmentModifiers(final LivingEntity living, final DamageSource damageSource) {
if (damageSource.isBypassMagic()) {
return Optional.empty();
}
final Iterable<net.minecraft.world.item.ItemStack> inventory = living.getArmorSlots();
final int damageProtection = EnchantmentHelper.getDamageProtection(inventory, damageSource);
if (damageProtection <= 0) {
return Optional.empty();
}
final List<DamageFunction> modifiers = new ArrayList<>();
final DoubleUnaryOperator enchantmentFunction = incomingDamage -> -(incomingDamage - CombatRules.getDamageAfterMagicAbsorb((float) incomingDamage, damageProtection));
try (final CauseStackManager.StackFrame frame = ((Server) living.getServer()).causeStackManager().pushCauseFrame()) {
frame.pushCause(living);
final DamageModifier enchantmentModifier = DamageModifier.builder().cause(frame.currentCause()).type(DamageModifierTypes.ARMOR_ENCHANTMENT).build();
modifiers.add(new DamageFunction(enchantmentModifier, enchantmentFunction));
}
return Optional.of(modifiers);
}
use of org.spongepowered.api.event.CauseStackManager in project SpongeCommon by SpongePowered.
the class RconClientMixin method run.
/**
* @author Cybermaxke
* @reason Fix RCON, is completely broken
*/
@SuppressWarnings("ConstantConditions")
@Override
@Overwrite
public void run() {
// / Sponge: START
// Initialize the source
this.impl$source = new RconConsoleSource(SpongeCommon.server());
((RconConsoleSourceBridge) this.impl$source).bridge$setClient((RconClient) (Object) this);
// Call the connection event
final RconConnectionEvent.Connect connectEvent;
try {
connectEvent = SpongeCommon.serverScheduler().execute(() -> {
final CauseStackManager causeStackManager = PhaseTracker.getCauseStackManager();
causeStackManager.pushCause(this);
causeStackManager.pushCause(this.impl$source);
final RconConnectionEvent.Connect event = SpongeEventFactory.createRconConnectionEventConnect(causeStackManager.currentCause(), (RconConnection) this.impl$source);
SpongeCommon.post(event);
causeStackManager.popCauses(2);
return event;
}).get();
} catch (final InterruptedException | ExecutionException ignored) {
this.closeSocket();
return;
}
if (connectEvent.isCancelled()) {
this.closeSocket();
return;
}
// / 'closeSocket' is moved out of the loop
while (true) {
try {
if (!this.running) {
break;
}
final BufferedInputStream bufferedinputstream = new BufferedInputStream(this.client.getInputStream());
final int i = bufferedinputstream.read(this.buf, 0, this.buf.length);
// / Sponge: START
if (i == -1) {
// continue to return EOF until we manually exit the loop.
break;
}
if (10 <= i) {
int j = 0;
final int k = PktUtils.intFromByteArray(this.buf, 0, i);
if (k != i - 4) {
break;
}
j += 4;
final int l = PktUtils.intFromByteArray(this.buf, j, i);
j += 4;
final int i1 = PktUtils.intFromByteArray(this.buf, j);
j += 4;
switch(i1) {
case 2:
if (this.authed) {
final String command = PktUtils.stringFromByteArray(this.buf, j, i);
try {
// / Sponge: START
// Execute the command on the main thread and wait for it
SpongeCommon.serverScheduler().execute(() -> {
final CauseStackManager causeStackManager = PhaseTracker.getCauseStackManager();
// Only add the RemoteConnection here, the RconSource
// will be added by the command manager
causeStackManager.pushCause(this);
SpongeCommon.server().getCommands().performCommand(this.impl$source.createCommandSourceStack(), command);
causeStackManager.popCause();
}).get();
final String logContents = this.impl$source.getCommandResponse();
this.impl$source.prepareForCommand();
this.shadow$sendCmdResponse(l, logContents);
// / Sponge: END
} catch (final Exception exception) {
this.shadow$sendCmdResponse(l, "Error executing: " + command + " (" + exception.getMessage() + ")");
}
continue;
}
this.shadow$sendAuthFailure();
// Sponge: 'continue' -> 'break', disconnect when a invalid operation is requested
break;
case 3:
final String password = PktUtils.stringFromByteArray(this.buf, j, i);
if (!password.isEmpty() && password.equals(this.rconPassword)) {
// / Sponge: START
final RconConnectionEvent.Auth event = SpongeCommon.serverScheduler().execute(() -> {
final CauseStackManager causeStackManager = PhaseTracker.getCauseStackManager();
causeStackManager.pushCause(this);
causeStackManager.pushCause(this.impl$source);
final RconConnectionEvent.Auth event1 = SpongeEventFactory.createRconConnectionEventAuth(causeStackManager.currentCause(), (RconConnection) this.impl$source);
SpongeCommon.post(event1);
causeStackManager.popCauses(2);
return event1;
}).get();
if (!event.isCancelled()) {
this.authed = true;
this.shadow$send(l, 2, "");
continue;
}
// / Sponge: END
}
this.authed = false;
this.shadow$sendAuthFailure();
// Sponge: 'continue' -> 'break', disconnect if login failed
break;
default:
this.shadow$sendCmdResponse(l, String.format("Unknown request %s", Integer.toHexString(i1)));
// Sponge: 'continue' -> 'break', disconnect when a invalid operation is requested
break;
}
}
} catch (final IOException e) {
break;
} catch (final Exception e) {
RconClientMixin.LOGGER.error("Exception whilst parsing RCON input", e);
break;
}
}
this.closeSocket();
}
use of org.spongepowered.api.event.CauseStackManager in project SpongeCommon by SpongePowered.
the class CommandSourceStackMixin method impl$updateCauseOnWithWorld.
/*
* A note on why we're doing this with the cause manually.
*
* When the object is first constructed, we get the cause from the stack manager. However, as the command processor
* works through the nodes, this entire source may get replaced. We want to keep some of the changes in sync,
* but the original cause may have gone by the time the source changes. Really, this command source is the analogue
* of our Cause, NOT our CauseStackManager, so we just need to do `Cause.with(...)` along with their select `with*(...)`
* methods.
*/
@Inject(method = "withLevel", at = @At("RETURN"))
private void impl$updateCauseOnWithWorld(final ServerLevel serverWorld, final CallbackInfoReturnable<CommandSourceStack> cir) {
if (cir.getReturnValue() != (Object) this) {
final ServerLocation location = this.impl$cause.context().get(EventContextKeys.LOCATION).map(x -> ServerLocation.of((org.spongepowered.api.world.server.ServerWorld) serverWorld, x.position())).orElseGet(() -> ServerLocation.of((org.spongepowered.api.world.server.ServerWorld) serverWorld, VecHelper.toVector3d(cir.getReturnValue().getPosition())));
((CommandSourceStackBridge) cir.getReturnValue()).bridge$setCause(this.impl$applyToCause(EventContextKeys.LOCATION, location));
}
}
use of org.spongepowered.api.event.CauseStackManager in project SpongeCommon by SpongePowered.
the class PlayerMixin method impl$postSleepingEvent.
@Redirect(method = "tick()V", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;isSleeping()Z"))
private boolean impl$postSleepingEvent(final net.minecraft.world.entity.player.Player self) {
if (self.isSleeping()) {
if (!((LevelBridge) this.level).bridge$isFake()) {
final CauseStackManager csm = PhaseTracker.getCauseStackManager();
csm.pushCause(this);
final BlockPos bedLocation = this.shadow$getSleepingPos().get();
final BlockSnapshot snapshot = ((ServerWorld) this.level).createSnapshot(bedLocation.getX(), bedLocation.getY(), bedLocation.getZ());
SpongeCommon.post(SpongeEventFactory.createSleepingEventTick(csm.currentCause(), snapshot, (Living) this));
csm.popCause();
}
return true;
}
return false;
}
Aggregations