use of org.spongepowered.api.event.Cause in project SpongeCommon by SpongePowered.
the class ServerLevelMixin method save.
/**
* @author zidane - December 17th, 2020 - Minecraft 1.16.4
* @reason Honor our serialization behavior in performing saves
*/
@Overwrite
public void save(@Nullable final ProgressListener progress, final boolean flush, final boolean skipSave) {
final Cause currentCause = Sponge.server().causeStackManager().currentCause();
if (Sponge.eventManager().post(SpongeEventFactory.createSaveWorldEventPre(currentCause, ((ServerWorld) this)))) {
// cancelled save
return;
}
final PrimaryLevelData levelData = (PrimaryLevelData) this.shadow$getLevelData();
final ServerChunkCache chunkProvider = ((ServerLevel) (Object) this).getChunkSource();
if (!skipSave) {
final SerializationBehavior behavior = ((PrimaryLevelDataBridge) levelData).bridge$serializationBehavior().orElse(SerializationBehavior.AUTOMATIC);
if (progress != null) {
progress.progressStartNoAbort(new TranslatableComponent("menu.savingLevel"));
}
// We always save the metadata unless it is NONE
if (behavior != SerializationBehavior.NONE) {
this.shadow$saveLevelData();
// Sponge Start - We do per-world WorldInfo/WorldBorders/BossBars
levelData.setWorldBorder(this.getWorldBorder().createSettings());
levelData.setCustomBossEvents(((ServerLevelBridge) this).bridge$getBossBarManager().save());
((ServerLevelBridge) this).bridge$getLevelSave().saveDataTag(SpongeCommon.server().registryAccess(), (PrimaryLevelData) this.shadow$getLevelData(), this.shadow$dimension() == Level.OVERWORLD ? SpongeCommon.server().getPlayerList().getSingleplayerData() : null);
// Sponge End
}
if (progress != null) {
progress.progressStage(new TranslatableComponent("menu.savingChunks"));
}
final boolean canAutomaticallySave = !this.impl$isManualSave && behavior == SerializationBehavior.AUTOMATIC;
final boolean canManuallySave = this.impl$isManualSave && behavior == SerializationBehavior.MANUAL;
if (canAutomaticallySave || canManuallySave) {
chunkProvider.save(flush);
}
Sponge.eventManager().post(SpongeEventFactory.createSaveWorldEventPost(currentCause, ((ServerWorld) this)));
}
this.impl$isManualSave = false;
}
use of org.spongepowered.api.event.Cause in project SpongeCommon by SpongePowered.
the class ContainerBasedTransaction method generateEvent.
@Override
public Optional<ClickContainerEvent> generateEvent(final PhaseContext<@NonNull ?> context, @Nullable final GameTransaction<@NonNull ?> parent, final ImmutableList<GameTransaction<ClickContainerEvent>> gameTransactions, final Cause currentCause) {
final ImmutableList<ContainerBasedTransaction> containerBasedTransactions = gameTransactions.stream().filter(tx -> tx instanceof ContainerBasedTransaction).map(tx -> (ContainerBasedTransaction) tx).filter(tx -> !tx.used).collect(ImmutableList.toImmutableList());
if (containerBasedTransactions.stream().map(c -> c.isContainerEventAllowed(context)).filter(b -> !b).findAny().orElse(false)) {
SpongeCommon.logger().warn("No event will be fired for existing ContainerBasedTransactions: {}", containerBasedTransactions.size());
return Optional.empty();
}
if (!((TrackedContainerBridge) this.menu).bridge$capturePossible()) {
// if (ContainerBasedTransaction.containersFailedCapture.add(this.menu.getClass())) {
// SpongeCommon.logger()
// .warn("Changes in modded Container were not captured. Inventory events will not fire for this. Container: " + this.menu.getClass());
// }
}
final List<Entity> entities = containerBasedTransactions.stream().map(ContainerBasedTransaction::getEntitiesSpawned).flatMap(List::stream).collect(Collectors.toList());
final List<SlotTransaction> slotTransactions = containerBasedTransactions.stream().map(ContainerBasedTransaction::getSlotTransactions).flatMap(List::stream).collect(Collectors.toList());
if (this.craftingInventory != null) {
// Event with Preview transaction on crafting inventory?
Slot slot = this.craftingInventory.result();
@Nullable final SlotTransaction preview = this.findPreviewTransaction(this.craftingInventory.result(), slotTransactions);
final ItemStackSnapshot previewItem = ItemStackUtil.snapshotOf(this.craftingInventory.peek());
if (preview != null) {
slot = preview.slot();
// Check if preview transaction is correct
if (!preview.defaultReplacement().equals(previewItem)) {
slotTransactions.remove(preview);
slotTransactions.add(new SlotTransaction(slot, preview.original(), previewItem));
}
} else if (!previewItem.isEmpty()) {
slotTransactions.add(new SlotTransaction(slot, previewItem, previewItem));
}
}
for (final ContainerBasedTransaction transaction : containerBasedTransactions) {
transaction.used = true;
}
final Optional<ClickContainerEvent> event = containerBasedTransactions.stream().map(t -> t.createInventoryEvent(slotTransactions, entities, context, currentCause)).filter(Optional::isPresent).map(Optional::get).findFirst();
if (!event.isPresent() && !slotTransactions.isEmpty()) {
SpongeCommon.logger().warn("Logged slot transactions without event! {} {}", gameTransactions.size(), this.menu.getClass().getName(), new Exception(""));
for (final SlotTransaction slotTransaction : slotTransactions) {
SpongeCommon.logger().warn(slotTransaction);
}
}
return event;
}
use of org.spongepowered.api.event.Cause in project SpongeCommon by SpongePowered.
the class ClickCreativeMenuTransaction method createInventoryEvent.
@Override
Optional<ClickContainerEvent> createInventoryEvent(final List<SlotTransaction> slotTransactions, final List<Entity> entities, final PhaseContext<@NonNull ?> context, final Cause cause) {
if (slotTransactions.isEmpty() && this.slotNum >= 0 && this.slot != null) {
// No SlotTransaction was captured. So we add the clicked slot as a transaction with the creative stack
final ItemStackSnapshot item = this.slot.peek().createSnapshot();
slotTransactions.add(new SlotTransaction(this.slot, item, this.creativeStack));
}
// Creative doesn't inform server of cursor status so there is no way of knowing what the final stack is
final Transaction<ItemStackSnapshot> cursorTransaction = new Transaction<>(this.originalCursor, ItemStackSnapshot.empty());
if (entities.isEmpty()) {
return Optional.of(SpongeEventFactory.createClickContainerEventCreativeSet(cause, (Container) this.menu, cursorTransaction, Optional.ofNullable(this.slot), slotTransactions));
}
final Cause causeWithSpawnType = Cause.builder().from(cause).build(EventContext.builder().from(cause.context()).add(EventContextKeys.SPAWN_TYPE, SpawnTypes.DROPPED_ITEM.get()).build());
return Optional.of(SpongeEventFactory.createClickContainerEventCreativeDrop(causeWithSpawnType, (Container) this.menu, cursorTransaction, this.creativeStack, entities, Optional.ofNullable(this.slot), slotTransactions));
}
use of org.spongepowered.api.event.Cause in project SpongeCommon by SpongePowered.
the class SpongeInventoryMenu method onClick.
public boolean onClick(int slotId, int dragType, ClickType clickTypeIn, Player player, Container container) {
try (CauseStackManager.StackFrame frame = PhaseTracker.getCauseStackManager().pushCauseFrame()) {
frame.pushCause(player);
Cause cause = frame.currentCause();
if (clickTypeIn == ClickType.QUICK_CRAFT) {
return this.onClickDrag(cause, slotId, dragType, container);
}
Optional<org.spongepowered.api.item.inventory.Slot> slot = container.slot(slotId);
if (slot.isPresent()) {
switch(clickTypeIn) {
case SWAP:
if (dragType >= 0 && dragType < 9) {
Optional<org.spongepowered.api.item.inventory.Slot> slot2 = container.slot(dragType);
if (slot2.isPresent() && this.keySwapHandler != null) {
return this.keySwapHandler.handle(cause, container, slot.get(), slotId, ClickTypes.KEY_SWAP.get(), slot2.get());
}
}
break;
case CLONE:
if (this.slotClickHandler != null) {
return this.slotClickHandler.handle(cause, container, slot.get(), slotId, ClickTypes.CLICK_MIDDLE.get());
}
break;
case PICKUP_ALL:
if (this.slotClickHandler != null) {
return this.slotClickHandler.handle(cause, container, slot.get(), slotId, ClickTypes.DOUBLE_CLICK.get());
}
break;
default:
if (this.slotClickHandler != null) {
if (dragType == 0) {
return this.onClickLeft(cause, this.slotClickHandler, clickTypeIn, container, slotId, slot.get());
} else if (dragType == 1) {
return this.onClickRight(cause, this.slotClickHandler, clickTypeIn, container, slotId, slot.get());
}
// else unknown drag-type
}
}
return true;
}
// else no slot present
switch(clickTypeIn) {
case PICKUP:
if (slotId == -999 && this.clickHandler != null) {
if (dragType == 0) {
return this.clickHandler.handle(cause, container, ClickTypes.CLICK_LEFT_OUTSIDE.get());
} else if (dragType == 1) {
return this.clickHandler.handle(cause, container, ClickTypes.CLICK_RIGHT_OUTSIDE.get());
}
}
// else unknown slotId/drag-type
break;
case THROW:
if (slotId == -999) {
// TODO check packets - does THROW with slotid -999 exist or is this actually PICKUP?
// its supposed to be l/r-click with nothing in hand
// TODO check if those exist
// /**
// * Throwing one item on the cursor by clicking outside the inventory window.
// */
// public static final org.spongepowered.api.item.inventory.menu.ClickType
// CLICK_THROW_ONE = DummyObjectProvider.createFor(org.spongepowered.api.item.inventory.menu.ClickType.class, "click_throw_one");
// /**
// * Throwing all items on the cursor by clicking outside the inventory window.
// */
// public static final org.spongepowered.api.item.inventory.menu.ClickType
// CLICK_THROW_ALL = DummyObjectProvider.createFor(org.spongepowered.api.item.inventory.menu.ClickType.class, "click_throw_all");
}
// else unknown slotId/drag-type
break;
}
return true;
}
}
use of org.spongepowered.api.event.Cause in project SpongeCommon by SpongePowered.
the class AdvancementProgressMixin method impl$revokeCriterion.
private boolean impl$revokeCriterion(String rawCriterion) {
final net.minecraft.advancements.CriterionProgress criterionProgress = this.criteria.get(rawCriterion);
if (criterionProgress == null || !criterionProgress.isDone()) {
return false;
}
if (SpongeScoreCriterion.BYPASS_EVENT) {
criterionProgress.revoke();
return true;
}
final Cause cause = PhaseTracker.getCauseStackManager().currentCause();
final ServerPlayer player = ((PlayerAdvancementsBridge) this.impl$playerAdvancements).bridge$getPlayer();
final CriterionProgress progress = (CriterionProgress) criterionProgress;
final AdvancementCriterion criterion = progress.criterion();
final CriterionBridge criterionBridge = (CriterionBridge) criterion;
// The score criterion needs special care
final SpongeScoreCriterion scoreCriterion = criterionBridge.bridge$getScoreCriterion();
final CriterionEvent event;
final Advancement advancement = ((org.spongepowered.api.advancement.AdvancementProgress) this).advancement();
if (scoreCriterion != null) {
final SpongeScoreCriterionProgress scoreProgress = (SpongeScoreCriterionProgress) this.impl$progressMap.get(scoreCriterion.name());
final int lastScore = scoreProgress.score();
final int score = lastScore + 1;
if (lastScore == scoreCriterion.goal()) {
event = SpongeEventFactory.createCriterionEventScoreRevoke(cause, advancement, scoreCriterion, player, lastScore, score);
} else if (score == scoreCriterion.goal()) {
event = SpongeEventFactory.createCriterionEventScoreGrant(cause, advancement, scoreCriterion, player, Instant.now(), lastScore, score);
} else {
event = SpongeEventFactory.createCriterionEventScoreChange(cause, advancement, scoreCriterion, player, lastScore, score);
}
} else {
event = SpongeEventFactory.createCriterionEventRevoke(cause, advancement, criterion, player);
}
if (SpongeCommon.post(event)) {
return false;
}
criterionProgress.revoke();
return true;
}
Aggregations