Skip to content

Commit

Permalink
feat!: update content api to 25w05a
Browse files Browse the repository at this point in the history
Breaking Changes
- Raids no longer have a ServerWorld link

Notable changes
- Custom SaveData manipulation injections had to be changed, this is an
  estimated implementation that appears to function.
  • Loading branch information
gabizou committed Feb 1, 2025
1 parent bdfd8fc commit ebea9c0
Show file tree
Hide file tree
Showing 17 changed files with 113 additions and 76 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,15 @@ public static List<Generator> registryEntries(final Context context) {
Registries.PIG_VARIANT,
$ -> true,
RegistryScope.SERVER
),
new RegistryEntriesGenerator<>(
"data.type",
"CowVariants",
"COW_VARIANT",
context.relativeClass("data.type", "CowVariant"),
Registries.COW_VARIANT,
$ -> true,
RegistryScope.SERVER
)
);
}
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c
mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json
superClassChanges=common.superclasschange

minecraftVersion=25w04a
minecraftVersion=25w05a
recommendedVersion=0-SNAPSHOT

org.gradle.dependency.verification.console=verbose
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
import net.minecraft.core.BlockPos;
import net.minecraft.core.particles.ParticleOptions;
import net.minecraft.network.syncher.EntityDataAccessor;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.item.ItemStack;
import org.spongepowered.asm.mixin.Mixin;
Expand Down Expand Up @@ -76,8 +75,6 @@ public interface LivingEntityAccessor {
throw new UntransformedAccessorError();
}

@Accessor("dead") boolean accessor$dead();

@Accessor("lastHurt") float accessor$lastHurt();

@Accessor("lastHurt") void accessor$lastHurt(final float lastHurt);
Expand All @@ -91,6 +88,4 @@ public interface LivingEntityAccessor {

@Accessor("useItem") void accessor$useItem(final ItemStack useItem);

@Invoker("isDamageSourceBlocked") boolean invoker$isDamageSourceBlocked(final DamageSource source);

}
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,17 @@
*/
package org.spongepowered.common.accessor.world.entity.raid;

import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import net.minecraft.world.entity.raid.Raid;
import net.minecraft.world.entity.raid.Raids;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;

import java.util.Map;

@Mixin(Raids.class)
public interface RaidsAccessor {

@Accessor("raidMap") Map<Integer, Raid> accessor$raidMap();
@Accessor("raidMap")
Int2ObjectMap<Raid> accessor$raidMap();

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* This file is part of Sponge, licensed under the MIT License (MIT).
*
* Copyright (c) SpongePowered <https://www.spongepowered.org>
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package org.spongepowered.common.accessor.world.level.saveddata.maps;

import net.minecraft.world.level.saveddata.maps.MapIndex;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;

@Mixin(MapIndex.class)
public interface MapIndexAccessor {

@Accessor("lastMapId") int accessor$getLastIndexID();

}
1 change: 1 addition & 0 deletions src/accessors/resources/mixins.sponge.accessors.json
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@
"world.level.levelgen.flat.FlatLevelGeneratorSettingsAccessor",
"world.level.levelgen.structure.pools.StructureTemplatePoolAccessor",
"world.level.portal.TeleportTransitionAccessor",
"world.level.saveddata.maps.MapIndexAccessor",
"world.level.saveddata.maps.MapItemSavedDataAccessor",
"world.level.storage.LevelStorageSource_LevelStorageAccessAccessor",
"world.level.storage.PlayerDataStorageAccessor",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -743,7 +743,7 @@ public static Optional<MapInfo> fireCreateMapEvent(final Cause cause, final Set<

final ServerLevel defaultWorld = (ServerLevel) Sponge.server().worldManager().world(DefaultWorldKeys.DEFAULT).get();
final MapIdTrackerBridge mapIdTrackerBridge = (MapIdTrackerBridge) defaultWorld.getDataStorage()
.computeIfAbsent(MapIndex.factory(), Constants.Map.MAP_INDEX_DATA_NAME);
.computeIfAbsent(MapIndex.TYPE);

final MapItemSavedData mapData = MapItemSavedData.createFresh(0, 0, (byte) 0, false, false, Level.END);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,10 @@
import org.spongepowered.api.map.MapStorage;
import org.spongepowered.api.world.DefaultWorldKeys;
import org.spongepowered.common.SpongeCommon;
import org.spongepowered.common.bridge.map.MapIdTrackerBridge;
import org.spongepowered.common.accessor.world.level.saveddata.maps.MapIndexAccessor;
import org.spongepowered.common.bridge.world.level.storage.PrimaryLevelDataBridge;
import org.spongepowered.common.event.SpongeCommonEventFactory;
import org.spongepowered.common.event.tracking.PhaseTracker;
import org.spongepowered.common.util.Constants;

import java.util.Collection;
import java.util.HashMap;
Expand All @@ -64,8 +63,7 @@ public Collection<MapInfo> allMapInfos() {
final Set<MapInfo> mapInfos = new HashSet<>();
final ServerLevel defaultWorld = (ServerLevel) Sponge.server().worldManager().world(DefaultWorldKeys.DEFAULT).get();

final int highestId = ((MapIdTrackerBridge) defaultWorld.getDataStorage()
.computeIfAbsent(MapIndex.factory(), Constants.Map.MAP_INDEX_DATA_NAME)).bridge$getHighestMapId().orElse(-1);
final int highestId = ((MapIndexAccessor) defaultWorld.getDataStorage().computeIfAbsent(MapIndex.TYPE)).accessor$getLastIndexID();
for (int i = 0; i <= highestId; i++) {
final @Nullable MapInfo mapInfo = (MapInfo) defaultWorld.getMapData(new MapId(i));
if (mapInfo == null) {
Expand Down
22 changes: 11 additions & 11 deletions src/main/java/org/spongepowered/common/raid/SpongeRaidWave.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
package org.spongepowered.common.raid;


import net.minecraft.server.level.ServerLevel;
import org.spongepowered.api.entity.living.monster.raider.Raider;
import org.spongepowered.api.raid.Raid;
import org.spongepowered.api.raid.RaidWave;
Expand Down Expand Up @@ -56,11 +57,7 @@ public boolean isBonus() {
* If the wave is not a final wave, the bonus waves occur after the final wave.
* If our wave was before the final wave, the amount of normal raids (which is set by the difficulty) would be greater than our wave's id.
*/
if (this.isFinal() || this.waveId < ((RaidAccessor) this.raid).accessor$numGroups()) {
return false;
}

return true;
return !this.isFinal() && this.waveId >= ((RaidAccessor) this.raid).accessor$numGroups();
}

@Override
Expand All @@ -78,14 +75,18 @@ public Optional<Raider> leader() {
@Override
public boolean addRaider(Raider raider, boolean addToRaidHealth) {
Objects.requireNonNull(raider, "Raider cannot be null.");
return this.raid.addWaveMob(this.waveId, (net.minecraft.world.entity.raid.Raider) raider, addToRaidHealth);
// We only support adding raiders to server worlds
if (raider.world() instanceof ServerLevel sl) {
return this.raid.addWaveMob(sl, this.waveId, (net.minecraft.world.entity.raid.Raider) raider, addToRaidHealth);
}
return false;
}

@Override
public boolean removeRaider(Raider raider) {
Objects.requireNonNull(raider, "Raider cannot be null.");
if (raider.raidWave().isPresent() && this.equals(raider.raidWave().get().get())) {
this.raid.removeFromRaid((net.minecraft.world.entity.raid.Raider) raider, true);
if (raider.raidWave().isPresent() && this.equals(raider.raidWave().get().get()) && raider.world() instanceof ServerLevel sl) {
this.raid.removeFromRaid(sl, (net.minecraft.world.entity.raid.Raider) raider, true);
return true;
}

Expand All @@ -94,11 +95,10 @@ public boolean removeRaider(Raider raider) {

@Override
public boolean equals(Object obj) {
if (obj instanceof SpongeRaidWave) {
SpongeRaidWave other = (SpongeRaidWave) obj;
if (obj instanceof SpongeRaidWave other) {
// Minecraft Tracks it's raids via an ID which is handled by the RaidManager.
// Each world has it's own raid manager so we have to verify that the world the raids are in is also equal.
if (this.waveId == other.waveId && this.raid.getLevel() == other.raid.getLevel() && this.raid.getId() == other.raid.getId()) {
if (this.waveId == other.waveId && this.raid == other.raid && this.raid.getCenter() == other.raid.getCenter()) {
return true;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1035,7 +1035,7 @@ private void loadSpawnChunks(final ServerLevel world) {
}

private void updateForcedChunks(final ServerLevel world, final ServerChunkCache serverChunkProvider) {
final @Nullable TicketStorage forcedChunksSaveData = world.getDataStorage().get(TicketStorage.factory(), "chunks");
final @Nullable TicketStorage forcedChunksSaveData = world.getDataStorage().get(TicketStorage.TYPE);
if (forcedChunksSaveData != null) {
final LongIterator longIterator = forcedChunksSaveData.getForceLoadedChunks().iterator();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,8 @@
import net.minecraft.server.level.ServerBossEvent;
import net.minecraft.world.entity.raid.Raid;
import net.minecraft.world.entity.raid.Raider;
import net.minecraft.world.level.Level;
import org.spongepowered.api.data.type.RaidStatus;
import org.spongepowered.api.raid.RaidWave;
import org.spongepowered.api.world.server.ServerWorld;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
Expand All @@ -53,16 +51,10 @@ public abstract class RaidMixin_API implements org.spongepowered.api.raid.Raid {
@Shadow @Final private ServerBossEvent raidEvent;
@Shadow private Raid.RaidStatus status;

@Shadow public abstract Level shadow$getLevel();
@Shadow public abstract float shadow$getHealthOfLivingRaiders();
@Shadow public abstract int shadow$getGroupsSpawned();
//@formatter:on

@Override
public ServerWorld world() {
return (ServerWorld) this.shadow$getLevel();
}

@Override
public BossBar bossBar() {
return SpongeAdventure.asAdventure(this.raidEvent);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ public abstract class LivingEntityMixin_Attack_Impl extends EntityMixin implemen
* Prevents shield usage before event
* Captures the blocked damage as a function
*/
@Redirect(method = "hurtServer", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/component/BlocksAttacks;hurtBlockingItem(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/InteractionHand;F)V"))
@Redirect(method = "applyItemBlocking", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/component/BlocksAttacks;hurtBlockingItem(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/InteractionHand;F)V"))
private void attackImpl$preventEarlyBlock1(
final BlocksAttacks instance, final net.minecraft.world.level.Level level,
final ItemStack stack, final LivingEntity target, final InteractionHand hand, final float damage) {
Expand All @@ -124,7 +124,7 @@ public abstract class LivingEntityMixin_Attack_Impl extends EntityMixin implemen
/**
* Prevents shield usage before event
*/
@Redirect(method = "hurtServer", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;blockUsingItem(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/entity/LivingEntity;)V"))
@Redirect(method = "applyItemBlocking", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;blockUsingItem(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/entity/LivingEntity;)V"))
private void attackImpl$preventEarlyBlock2(final LivingEntity instance, final ServerLevel level, final LivingEntity shooter) {
// TODO - 25w04a
// this.blockUsingItem($$0, $$8);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,7 @@
*/
package org.spongepowered.common.mixin.core.world.level.saveddata;

import it.unimi.dsi.fastutil.objects.Object2IntMap;
import net.minecraft.world.level.saveddata.maps.MapIndex;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.common.bridge.map.MapIdTrackerBridge;
Expand All @@ -37,20 +35,20 @@
@Mixin(MapIndex.class)
public abstract class MapIdTrackerMixin implements MapIdTrackerBridge {

@Shadow @Final private Object2IntMap<String> usedAuxIds;
@Shadow
private int lastMapId;

@Override
public void bridge$setHighestMapId(final int id) {
this.usedAuxIds.put(Constants.Map.ID_COUNTS_KEY, id);
this.lastMapId = id;
}

@Override
public OptionalInt bridge$getHighestMapId() {
final int id = this.usedAuxIds.getInt(Constants.Map.ID_COUNTS_KEY);
if (id == this.usedAuxIds.defaultReturnValue()) {
return OptionalInt.empty(); // Default return value is -1
if (this.lastMapId == -1) {
return OptionalInt.empty();
}
return OptionalInt.of(id);
return OptionalInt.of(this.lastMapId);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -22,30 +22,39 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package org.spongepowered.common.mixin.core.world.level;
package org.spongepowered.common.mixin.core.world.level.storage;

import net.minecraft.core.HolderLookup;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.Tag;
import net.minecraft.resources.RegistryOps;
import net.minecraft.world.level.saveddata.SavedData;
import net.minecraft.world.level.saveddata.SavedDataType;
import net.minecraft.world.level.storage.DimensionDataStorage;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
import org.spongepowered.common.bridge.data.DataCompoundHolder;
import org.spongepowered.common.data.DataUtil;

@Mixin(SavedData.class)
public abstract class SavedDataMixin {
@Mixin(DimensionDataStorage.class)
public abstract class DimensionDataSotrageMixin {

@Inject(method = "save(Lnet/minecraft/core/HolderLookup$Provider;)Lnet/minecraft/nbt/CompoundTag;",
at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/saveddata/SavedData;save(Lnet/minecraft/nbt/CompoundTag;Lnet/minecraft/core/HolderLookup$Provider;)Lnet/minecraft/nbt/CompoundTag;"),
locals = LocalCapture.CAPTURE_FAILHARD)
public void impl$writeAdditionalMapNBT(HolderLookup.Provider registry, final CallbackInfoReturnable<CompoundTag> cir, CompoundTag compound) {
if (this instanceof DataCompoundHolder) {
if (DataUtil.syncDataToTag(this)) {
compound.merge(((DataCompoundHolder) this).data$getCompound());
@WrapOperation(method = "encodeUnchecked",
at = @At(value = "INVOKE",
target = "Lnet/minecraft/nbt/CompoundTag;put(Ljava/lang/String;Lnet/minecraft/nbt/Tag;)Lnet/minecraft/nbt/Tag;"
)
)
public <T extends SavedData> Tag impl$writeAdditionalMapNBT(
final CompoundTag instance, final String key, final Tag encoded,
final Operation<Tag> original, final SavedDataType<T> type,
final SavedData data, final RegistryOps<Tag> registry
) {
if (data instanceof DataCompoundHolder dch) {
if (DataUtil.syncDataToTag(dch)) {
instance.merge(dch.data$getCompound());
}
}
return original.call(instance, key, encoded);
}
}
Loading

0 comments on commit ebea9c0

Please sign in to comment.