Skip to content

Commit

Permalink
Merge branch '1.18.2' of https://github.com/QuiltMC/quilted-fabric-api
Browse files Browse the repository at this point in the history
…into 1.18.2
  • Loading branch information
EnnuiL committed May 30, 2022
2 parents bb72c7e + 5a579be commit 0bbd00e
Show file tree
Hide file tree
Showing 31 changed files with 460 additions and 54 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import com.google.common.base.Preconditions;

import net.minecraft.entity.Entity;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.world.TeleportTarget;

Expand Down Expand Up @@ -49,6 +50,21 @@ public static <E extends Entity> E changeDimension(E teleported, ServerWorld dim

try {
currentTarget = target;

// Fast path for teleporting within the same dimension.
if (teleported.getWorld() == dimension) {
if (teleported instanceof ServerPlayerEntity serverPlayerEntity) {
serverPlayerEntity.networkHandler.requestTeleport(target.position.x, target.position.y, target.position.z, target.yaw, teleported.getPitch());
} else {
teleported.refreshPositionAndAngles(target.position.x, target.position.y, target.position.z, target.yaw, teleported.getPitch());
}

teleported.setVelocity(target.velocity);
teleported.setHeadYaw(target.yaw);

return teleported;
}

return (E) teleported.moveToWorld(dimension);
} finally {
currentTarget = null;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/*
* Copyright 2016, 2017, 2018, 2019 FabricMC
* Copyright 2022 QuiltMC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package net.fabricmc.fabric.mixin.dimension;

import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import com.mojang.datafixers.DataFixer;
import com.mojang.datafixers.util.Pair;
import com.mojang.serialization.Dynamic;
import com.mojang.serialization.Lifecycle;

import net.minecraft.nbt.NbtCompound;
import net.minecraft.nbt.NbtElement;
import net.minecraft.world.gen.GeneratorOptions;
import net.minecraft.world.level.storage.LevelStorage;

/**
* After removing a dimension mod or a dimension datapack, Minecraft may fail to enter
* the world, because it fails to deserialize the chunk generator of the custom dimensions in file {@code level.dat}
* This mixin will remove the custom dimensions from the nbt tag, so the deserializer and DFU cannot see custom
* dimensions and won't cause errors.
* The custom dimensions will be re-added later.
*
* <p>This Mixin changes a vanilla behavior that is deemed as a bug (MC-197860). In vanilla, the custom dimension
* is not removed after uninstalling the dimension datapack.
* This makes custom dimensions non-removable. Most players don't want this behavior.
* With this Mixin, custom dimensions will be removed when its datapack is removed.
*/
@Mixin(LevelStorage.class)
public class LevelStorageBugfixMixin {
@SuppressWarnings("unchecked")
@Inject(method = "readGeneratorProperties", at = @At("HEAD"))
private static <T> void onReadGeneratorProperties(
Dynamic<T> nbt, DataFixer dataFixer, int version,
CallbackInfoReturnable<Pair<GeneratorOptions, Lifecycle>> cir
) {
NbtElement nbtTag = ((Dynamic<NbtElement>) nbt).getValue();

NbtCompound worldGenSettings = ((NbtCompound) nbtTag).getCompound("WorldGenSettings");

removeNonVanillaDimensionsFromWorldGenSettingsTag(worldGenSettings);
}

/**
* Removes all non-vanilla dimensions from the tag. The custom dimensions will be re-added later from the datapacks.
*/
@Unique
private static void removeNonVanillaDimensionsFromWorldGenSettingsTag(NbtCompound worldGenSettings) {
String[] vanillaDimensionIds =
new String[]{"minecraft:overworld", "minecraft:the_nether", "minecraft:the_end"};

NbtCompound dimensions = worldGenSettings.getCompound("dimensions");

if (dimensions.getSize() > vanillaDimensionIds.length) {
NbtCompound newDimensions = new NbtCompound();

for (String dimId : vanillaDimensionIds) {
if (dimensions.contains(dimId)) {
newDimensions.put(dimId, dimensions.getCompound(dimId));
}
}

worldGenSettings.put("dimensions", newDimensions);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@
"compatibilityLevel": "JAVA_17",
"mixins": [
"EntityMixin",
"ServerPlayerEntityMixin",
"ServerBugfixMixin"
"LevelStorageBugfixMixin",
"ServerBugfixMixin",
"ServerPlayerEntityMixin"
],
"injectors": {
"defaultRequire": 1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,14 @@ public void onInitialize() {
CommandRegistrationCallback.EVENT.register((dispatcher, dedicated) ->
dispatcher.register(literal("fabric_dimension_test").executes(FabricDimensionTest.this::swapTargeted))
);

// Used to test https://github.com/FabricMC/fabric/issues/2239
CommandRegistrationCallback.EVENT.register((dispatcher, dedicated) -> dispatcher.register(literal("fabric_dimension_test_desync")
.executes(FabricDimensionTest.this::testDesync)));

// Used to test https://github.com/FabricMC/fabric/issues/2238
CommandRegistrationCallback.EVENT.register((dispatcher, dedicated) -> dispatcher.register(literal("fabric_dimension_test_entity")
.executes(FabricDimensionTest.this::testEntityTeleport)));
}

private int swapTargeted(CommandContext<ServerCommandSource> context) throws CommandSyntaxException {
Expand All @@ -129,6 +137,50 @@ private int swapTargeted(CommandContext<ServerCommandSource> context) throws Com
return 1;
}

private int testDesync(CommandContext<ServerCommandSource> context) throws CommandSyntaxException {
ServerPlayerEntity player = context.getSource().getPlayer();

if (player == null) {
context.getSource().sendFeedback(new LiteralText("You must be a player to execute this command."), false);
return 1;
}

if (!context.getSource().getServer().isDedicated()) {
context.getSource().sendFeedback(new LiteralText("This command can only be executed on dedicated servers."), false);
return 1;
}

TeleportTarget target = new TeleportTarget(player.getPos().add(5, 0, 0), player.getVelocity(), player.getYaw(), player.getPitch());
FabricDimensions.teleport(player, (ServerWorld) player.world, target);

return 1;
}

private int testEntityTeleport(CommandContext<ServerCommandSource> context) throws CommandSyntaxException {
ServerPlayerEntity player = context.getSource().getPlayer();

if (player == null) {
context.getSource().sendFeedback(new LiteralText("You must be a player to execute this command."), false);
return 1;
}

Entity entity = player.world
.getOtherEntities(player, player.getBoundingBox().expand(100, 100, 100))
.stream()
.findFirst()
.orElse(null);

if (entity == null) {
context.getSource().sendFeedback(new LiteralText("No entities found."), false);
return 1;
}

TeleportTarget target = new TeleportTarget(player.getPos(), player.getVelocity(), player.getYaw(), player.getPitch());
FabricDimensions.teleport(entity, (ServerWorld) entity.world, target);

return 1;
}

private ServerWorld getModWorld(CommandContext<ServerCommandSource> context) {
return getWorld(context, WORLD_KEY);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* Copyright 2016, 2017, 2018, 2019 FabricMC
* Copyright 2022 QuiltMC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package net.fabricmc.fabric.api.item.v1;

import com.google.common.collect.Multimap;

import net.minecraft.entity.EquipmentSlot;
import net.minecraft.entity.attribute.EntityAttribute;
import net.minecraft.entity.attribute.EntityAttributeModifier;
import net.minecraft.item.ItemStack;

import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;

/**
* Stack-aware attribute modifier callback for foreign items.
* Instead of using Mixin to change attribute modifiers in items not in your mod,
* you can use this event instead, either checking the Item itself or using a tag.
* This event provides you with a guaranteed mutable map you can put attribute modifiers in.
* Do not use for your own Item classes; see {@link FabricItem#getAttributeModifiers} instead.
* For example, the following code modifies a Diamond Helmet to give you five extra hearts when wearing.
*
* <pre>
* {@code
* ModifyItemAttributeModifiersCallback.EVENT.register((stack, slot, attributeModifiers) -> {
* if (stack.isOf(Items.DIAMOND_HELMET) && slot.getEntitySlotId() == HEAD_SLOT_ID) {
* attributeModifiers.put(EntityAttributes.GENERIC_MAX_HEALTH, MODIFIER);
* }
* });
* }
* </pre>
*/
@FunctionalInterface
public interface ModifyItemAttributeModifiersCallback {
void modifyAttributeModifiers(ItemStack stack, EquipmentSlot slot, Multimap<EntityAttribute, EntityAttributeModifier> attributeModifiers);

Event<ModifyItemAttributeModifiersCallback> EVENT = EventFactory.createArrayBacked(
ModifyItemAttributeModifiersCallback.class,
callbacks -> (stack, slot, attributeModifiers) -> {
for (ModifyItemAttributeModifiersCallback callback : callbacks) {
callback.modifyAttributeModifiers(stack, slot, attributeModifiers);
}
}
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* Copyright 2016, 2017, 2018, 2019 FabricMC
* Copyright 2022 QuiltMC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package net.fabricmc.fabric.test.item;

import org.quiltmc.loader.api.ModContainer;
import org.quiltmc.qsl.base.api.entrypoint.ModInitializer;

import net.minecraft.entity.attribute.EntityAttributeModifier;
import net.minecraft.entity.attribute.EntityAttributes;
import net.minecraft.item.Items;

import net.fabricmc.fabric.api.item.v1.ModifyItemAttributeModifiersCallback;

public class ModifyItemAttributeModifiersCallbackTest implements ModInitializer {
public static final int HEAD_SLOT_ID = 3;
public static final EntityAttributeModifier MODIFIER = new EntityAttributeModifier("generic_max_health_modifier", 5.0, EntityAttributeModifier.Operation.ADDITION);

@Override
public void onInitialize(ModContainer mod) {
ModifyItemAttributeModifiersCallback.EVENT.register((stack, slot, attributeModifiers) -> {
if (stack.isOf(Items.DIAMOND_HELMET) && slot.getEntitySlotId() == HEAD_SLOT_ID) {
attributeModifiers.put(EntityAttributes.GENERIC_MAX_HEALTH, MODIFIER);
}
});
}
}
3 changes: 2 additions & 1 deletion fabric-item-api-v1/src/testmod/resources/fabric.mod.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
"init": [
"net.fabricmc.fabric.test.item.CustomDamageTest",
"net.fabricmc.fabric.test.item.FabricItemSettingsTests",
"net.fabricmc.fabric.test.item.ItemUpdateAnimationTest"
"net.fabricmc.fabric.test.item.ItemUpdateAnimationTest",
"net.fabricmc.fabric.test.item.ModifyItemAttributeModifiersCallbackTest"
],
"client_init": [
"net.fabricmc.fabric.test.item.client.TooltipTests"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import net.minecraft.nbt.NbtCompound;
import net.minecraft.network.PacketByteBuf;
import net.minecraft.world.chunk.WorldChunk;
import net.minecraft.util.math.ChunkPos;

import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
Expand All @@ -51,6 +52,13 @@ private void onChunkLoad(int x, int z, PacketByteBuf packetByteBuf, NbtCompound
ClientChunkEvents.CHUNK_LOAD.invoker().onChunkLoad(this.world, info.getReturnValue());
}

@Inject(method = "loadChunkFromPacket", at = @At(value = "NEW", target = "net/minecraft/world/chunk/WorldChunk", shift = At.Shift.BEFORE), locals = LocalCapture.CAPTURE_FAILHARD)
private void onChunkUnload(int x, int z, PacketByteBuf buf, NbtCompound tag, Consumer<ChunkData.BlockEntityVisitor> consumer, CallbackInfoReturnable<WorldChunk> info, int index, WorldChunk worldChunk, ChunkPos chunkPos) {
if (worldChunk != null) {
ClientChunkEvents.CHUNK_UNLOAD.invoker().onChunkUnload(this.world, worldChunk);
}
}

@Inject(method = "unload", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/world/ClientChunkManager$ClientChunkMap;compareAndSet(ILnet/minecraft/world/chunk/WorldChunk;Lnet/minecraft/world/chunk/WorldChunk;)Lnet/minecraft/world/chunk/WorldChunk;", shift = At.Shift.AFTER), locals = LocalCapture.CAPTURE_FAILEXCEPTION)
private void onChunkUnload(int chunkX, int chunkZ, CallbackInfo ci, int i, WorldChunk chunk) {
ClientChunkEvents.CHUNK_UNLOAD.invoker().onChunkUnload(this.world, chunk);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@
* Fabric's version of Block.Settings. Adds additional methods and hooks
* not found in the original class.
*
* <p>Make note that this behaves slightly different from the
* vanilla counterpart, copying some settings that vanilla does not.
*
* <p>To use it, simply replace Block.Settings.of() with
* FabricBlockSettings.of().
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import net.minecraft.block.BlockState;
import net.minecraft.block.MapColor;
import net.minecraft.block.Material;
import net.minecraft.entity.EntityType;
import net.minecraft.sound.BlockSoundGroup;
import net.minecraft.util.Identifier;

Expand Down Expand Up @@ -75,6 +76,10 @@ public interface AbstractBlockSettingsAccessor {
@Accessor
float getVelocityMultiplier();

@Deprecated
@Accessor
float getJumpVelocityMultiplier();

@Deprecated
@Accessor
boolean getDynamicBounds();
Expand All @@ -91,6 +96,30 @@ public interface AbstractBlockSettingsAccessor {
@Accessor
boolean isToolRequired();

@Deprecated
@Accessor
AbstractBlock.TypedContextPredicate<EntityType<?>> getAllowsSpawningPredicate();

@Deprecated
@Accessor
AbstractBlock.ContextPredicate getSolidBlockPredicate();

@Deprecated
@Accessor
AbstractBlock.ContextPredicate getSuffocationPredicate();

@Deprecated
@Accessor
AbstractBlock.ContextPredicate getBlockVisionPredicate();

@Deprecated
@Accessor
AbstractBlock.ContextPredicate getPostProcessPredicate();

@Deprecated
@Accessor
AbstractBlock.ContextPredicate getEmissiveLightingPredicate();

/* SETTERS */
@Deprecated
@Accessor
Expand Down
Loading

0 comments on commit 0bbd00e

Please sign in to comment.