refactor(ALL): bump minecraft version to 1.21.5
trimmed unused feature: /gamerule CustomEntity API, Custom Item API We'll use Polymer for replacement in the future. Tests needed.
This commit is contained in:
39 files changed
+117
-651
No files matched your search
+1
-2
@@ -2,7 +2,7 @@ plugins {
|
||||
id 'maven-publish'
|
||||
id("io.freefair.lombok") version "8.6"
|
||||
id("com.github.johnrengelman.shadow") version "8.1.1"
|
||||
id 'fabric-loom' version '1.7.3'
|
||||
id 'fabric-loom' version '1.10.1'
|
||||
}
|
||||
|
||||
version = project.mod_version
|
||||
@@ -18,7 +18,6 @@ repositories {
|
||||
// Loom adds the essential maven repositories to download Minecraft and libraries from automatically.
|
||||
// See https://docs.gradle.org/current/userguide/declaring_repositories.html
|
||||
// for more information about repositories.
|
||||
maven { url 'https://maven.wispforest.io/releases/' }
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
+6
-14
@@ -1,19 +1,11 @@
|
||||
# Done to increase the memory available to gradle.
|
||||
org.gradle.jvmargs=-Xmx1G
|
||||
|
||||
# Fabric Properties
|
||||
# check these on https://modmuss50.me/fabric.html
|
||||
minecraft_version=1.21
|
||||
yarn_mappings=1.21+build.7
|
||||
loader_version=0.15.11
|
||||
|
||||
org.gradle.jvmargs=-Xmx4G
|
||||
minecraft_version=1.21.5
|
||||
yarn_mappings=1.21.5+build.1
|
||||
loader_version=0.16.10
|
||||
# Fabric API
|
||||
fabric_version=0.119.5+1.21.5
|
||||
# Mod Properties
|
||||
mod_version=1.0.0
|
||||
maven_group=io.ib67
|
||||
archives_base_name=sfcraft
|
||||
|
||||
# Dependencies
|
||||
# check this on https://modmuss50.me/fabric.html
|
||||
fabric_version=0.100.4+1.21
|
||||
owo_version=0.12.10+1.21
|
||||
|
||||
@@ -8,7 +8,6 @@ import io.ib67.sfcraft.module.chat.ChatPrefixModule;
|
||||
import io.ib67.sfcraft.module.chat.decorator.ChatPingModule;
|
||||
import io.ib67.sfcraft.module.chat.decorator.ChatSendLocModule;
|
||||
import io.ib67.sfcraft.module.compat.ModCompatModule;
|
||||
import io.ib67.sfcraft.module.randomevt.LongNightModule;
|
||||
import io.ib67.sfcraft.module.room.CreativeRoomModule;
|
||||
import io.ib67.sfcraft.module.supervisor.WebModule;
|
||||
import io.ib67.sfcraft.module.supervisor.web.SchematicUploader;
|
||||
@@ -25,9 +24,6 @@ import io.ib67.sfcraft.module.command.ManagementModule;
|
||||
import io.ib67.sfcraft.registry.room.SimpleRoomRegistry;
|
||||
import io.ib67.sfcraft.room.RoomTeleporter;
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
import net.fabricmc.fabric.api.event.registry.FabricRegistryBuilder;
|
||||
import net.minecraft.registry.Registries;
|
||||
import net.minecraft.registry.Registry;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
|
||||
@Log4j2
|
||||
@@ -61,12 +57,10 @@ public class SFCraftInitializer extends GuiceModInitializer {
|
||||
registerFeature(FartFertilizerModule.class);
|
||||
registerFeature(ChatPingModule.class);
|
||||
registerFeature(ChatSendLocModule.class);
|
||||
registerFeature(LongNightModule.class);
|
||||
registerFeature(ModCompatModule.class);
|
||||
registerFeature(RoomModule.class);
|
||||
registerFeature(CreativeRoomModule.class);
|
||||
registerFeature(ChatPrefixModule.class);
|
||||
registerFeature(CustomItemModule.class);
|
||||
registerWebModules();
|
||||
}
|
||||
|
||||
@@ -91,7 +85,6 @@ public class SFCraftInitializer extends GuiceModInitializer {
|
||||
|
||||
@Override
|
||||
protected Injector onInit() {
|
||||
SFEntityType.registerEntities();
|
||||
return SFCraft.injector = Guice.createInjector(
|
||||
new SFCraft(),
|
||||
this
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
package io.ib67.sfcraft;
|
||||
|
||||
import io.ib67.sfcraft.entity.SFGuiderEntity;
|
||||
import lombok.experimental.UtilityClass;
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
import net.fabricmc.fabric.api.object.builder.v1.entity.FabricDefaultAttributeRegistry;
|
||||
import net.fabricmc.fabric.api.object.builder.v1.entity.FabricEntityTypeBuilder;
|
||||
import net.minecraft.entity.EntityType;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.entity.SpawnGroup;
|
||||
import net.minecraft.entity.attribute.DefaultAttributeContainer;
|
||||
import net.minecraft.registry.Registries;
|
||||
import net.minecraft.registry.Registry;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
@Log4j2
|
||||
public class SFEntityType {
|
||||
public static final EntityType<SFGuiderEntity> GUIDER = Registry.register(
|
||||
Registries.ENTITY_TYPE,
|
||||
Identifier.of(SFCraft.MOD_ID , "guider"),
|
||||
EntityType.Builder.create(SFGuiderEntity::new, SpawnGroup.CREATURE)
|
||||
.dimensions(0.35F, 0.6F)
|
||||
.eyeHeight(0.36F)
|
||||
.vehicleAttachment(0.04F)
|
||||
.maxTrackingRange(8)
|
||||
.trackingTickInterval(2).build()
|
||||
);
|
||||
private static SFEntityType registry;
|
||||
private final Map<EntityType<?>, EntityType<?>> mappedEntityTypes = new ConcurrentHashMap<>();
|
||||
|
||||
private void init() {
|
||||
register(GUIDER, EntityType.ALLAY, SFGuiderEntity.createAllayAttributes().build());
|
||||
}
|
||||
|
||||
private <A extends LivingEntity, B extends LivingEntity> void register(EntityType<B> custom, EntityType<A> origin, DefaultAttributeContainer attr) {
|
||||
FabricDefaultAttributeRegistry.register(custom, attr);
|
||||
mappedEntityTypes.put(custom, origin);
|
||||
}
|
||||
|
||||
static void registerEntities() {
|
||||
registry = new SFEntityType();
|
||||
registry.init();
|
||||
}
|
||||
|
||||
public static <T extends LivingEntity> EntityType<T> mapToVanilla(EntityType<?> type) {
|
||||
return (EntityType<T>) registry.mappedEntityTypes.getOrDefault(type, type);
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
package io.ib67.sfcraft;
|
||||
|
||||
import io.ib67.sfcraft.item.AeroBackpack;
|
||||
import io.ib67.sfcraft.mixin.common.bridge.ItemBridge;
|
||||
import net.fabricmc.fabric.api.event.registry.FabricRegistryBuilder;
|
||||
import net.fabricmc.fabric.api.event.registry.RegistryAttribute;
|
||||
import net.minecraft.item.ArmorItem;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.registry.Registry;
|
||||
import net.minecraft.registry.RegistryKey;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import static io.ib67.sfcraft.SFRegistries.ITEMS;
|
||||
|
||||
public class SFItems {
|
||||
public static final Item AERO_BACKPACK = register(
|
||||
new AeroBackpack(new Item.Settings().maxDamage(ArmorItem.Type.CHESTPLATE.getMaxDamage(15))), "aero_backpack");
|
||||
public static final String SF_ITEM_TYPE_KEY = "sf_type";
|
||||
|
||||
public static void init() {
|
||||
}
|
||||
|
||||
private static Item register(Item item, String id) {
|
||||
Identifier itemID = Identifier.of(SFCraft.MOD_ID, id);
|
||||
Item registeredItem = Registry.register(ITEMS, itemID, item);
|
||||
((ItemBridge) registeredItem).setRegistryEntry(ITEMS.getEntry(itemID).get());
|
||||
return registeredItem;
|
||||
}
|
||||
|
||||
public static Item getById(Identifier item) {
|
||||
return ITEMS.get(item);
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package io.ib67.sfcraft.item;
|
||||
|
||||
import net.minecraft.entity.EquipmentSlot;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.*;
|
||||
import net.minecraft.registry.entry.RegistryEntry;
|
||||
import net.minecraft.text.Text;
|
||||
|
||||
public class AeroBackpack extends ArmorItem implements TickableItem, SFItem {
|
||||
private static final Text STATUS_MESSAGE = Text.of("You're wearing aero backpack!");
|
||||
|
||||
public AeroBackpack(Settings settings) {
|
||||
super(ArmorMaterials.IRON, Type.CHESTPLATE, settings);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpdate(PlayerEntity player, ItemStack stack, EquipmentSlot slot) {
|
||||
if (slot != EquipmentSlot.CHEST) return;
|
||||
player.sendMessage(STATUS_MESSAGE, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item getMappedItem() {
|
||||
return Items.IRON_CHESTPLATE;
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
package io.ib67.sfcraft.item;
|
||||
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.registry.entry.RegistryEntry;
|
||||
|
||||
public interface SFItem {
|
||||
Item getMappedItem();
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
package io.ib67.sfcraft.item;
|
||||
|
||||
import net.minecraft.entity.EquipmentSlot;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
|
||||
public interface TickableItem {
|
||||
void onUpdate(PlayerEntity player, ItemStack stack, EquipmentSlot slot);
|
||||
}
|
||||
@@ -7,7 +7,7 @@ import org.spongepowered.asm.mixin.gen.Invoker;
|
||||
|
||||
@Mixin(Entity.class)
|
||||
public interface EntityBridge {
|
||||
@Accessor("FALL_FLYING_FLAG_INDEX")
|
||||
@Accessor("GLIDING_FLAG_INDEX")
|
||||
static int sfcraft$getFlyingFlagIndex() {
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import net.minecraft.block.entity.AbstractFurnaceBlockEntity;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.block.entity.BlockEntityTicker;
|
||||
import net.minecraft.block.entity.BlockEntityType;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.GameRules;
|
||||
import net.minecraft.world.World;
|
||||
@@ -26,15 +27,17 @@ public abstract class AbstractFurnaceBlockMixin extends BlockWithEntity {
|
||||
* @author icybear
|
||||
* @reason to replace their ticker
|
||||
*/
|
||||
@Nullable
|
||||
@Overwrite
|
||||
public static <T extends BlockEntity> @Nullable BlockEntityTicker<T> validateTicker(
|
||||
public static <T extends BlockEntity> BlockEntityTicker<T> validateTicker(
|
||||
World world, BlockEntityType<T> givenType, BlockEntityType<? extends AbstractFurnaceBlockEntity> expectedType
|
||||
) {
|
||||
return world.isClient ? null : BlockWithEntity.validateTicker(givenType, expectedType, AbstractFurnaceBlockMixin::tickMultiple);
|
||||
return world instanceof ServerWorld sw ? BlockWithEntity.validateTicker(givenType, expectedType, AbstractFurnaceBlockMixin::tickMultiple) : null;
|
||||
}
|
||||
|
||||
@Unique
|
||||
private static void tickMultiple(World world, BlockPos pos, BlockState state, AbstractFurnaceBlockEntity blockEntity) {
|
||||
private static <E extends AbstractFurnaceBlockEntity> void tickMultiple(World _world, BlockPos pos, BlockState state, E blockEntity) {
|
||||
var world = (ServerWorld) _world;
|
||||
AbstractFurnaceBlockEntity.tick(world, pos, state, blockEntity);
|
||||
int i = world.getGameRules().getInt(GameRules.PLAYERS_SLEEPING_PERCENTAGE);
|
||||
if (((ServerWorldBridge) world).getSleepManager().canSkipNight(i)) {
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
package io.ib67.sfcraft.mixin.server;
|
||||
|
||||
import net.minecraft.server.world.ChunkLevelManager;
|
||||
import net.minecraft.server.world.ServerChunkManager;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
|
||||
@Mixin(ServerChunkManager.class)
|
||||
public interface ServerChunkManagerMixin {
|
||||
@Accessor("levelManager")
|
||||
ChunkLevelManager getLevelManager();
|
||||
}
|
||||
@@ -1,11 +1,19 @@
|
||||
package io.ib67.sfcraft.mixin.server;
|
||||
|
||||
import io.ib67.sfcraft.SFCraft;
|
||||
import io.ib67.sfcraft.mixin.common.bridge.ServerWorldBridge;
|
||||
import io.ib67.sfcraft.module.RoomModule;
|
||||
import io.ib67.sfcraft.util.MixinHelper;
|
||||
import net.minecraft.registry.RegistryKey;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.minecraft.world.GameRules;
|
||||
import net.minecraft.world.World;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.*;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
@Mixin(ServerWorld.class)
|
||||
public abstract class ServerWorldMixin {
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
package io.ib67.sfcraft.mixin.server.hack;
|
||||
|
||||
import io.ib67.sfcraft.SFCraftInitializer;
|
||||
import io.ib67.sfcraft.SFEntityType;
|
||||
import net.minecraft.entity.EntityType;
|
||||
import net.minecraft.network.packet.s2c.play.EntitySpawnS2CPacket;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.ModifyArg;
|
||||
|
||||
@Mixin(EntitySpawnS2CPacket.class)
|
||||
public class EntitySpawnS2CPacketMixin {
|
||||
@ModifyArg(method = "write", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/codec/PacketCodec;encode(Ljava/lang/Object;Ljava/lang/Object;)V"), index = 1)
|
||||
public Object mapModType(Object type) {
|
||||
return SFEntityType.mapToVanilla((EntityType<?>) type);
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
package io.ib67.sfcraft.mixin.server.hack;
|
||||
|
||||
import io.ib67.sfcraft.SFCraftInitializer;
|
||||
import io.ib67.sfcraft.SFEntityType;
|
||||
import net.minecraft.entity.EntityType;
|
||||
import net.minecraft.text.HoverEvent;
|
||||
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;
|
||||
|
||||
@Mixin(HoverEvent.EntityContent.class)
|
||||
public class HoverEntityContentMixin {
|
||||
@Inject(method = "method_54198", at = @At("HEAD"), cancellable = true)
|
||||
private static void sf$mapToVanilla(HoverEvent.EntityContent content, CallbackInfoReturnable<EntityType> cir) {
|
||||
cir.setReturnValue(SFEntityType.mapToVanilla(content.entityType));
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
package io.ib67.sfcraft.mixin.server.hack;
|
||||
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntMap;
|
||||
import net.fabricmc.fabric.impl.registry.sync.packet.DirectRegistryPacketHandler;
|
||||
import net.minecraft.util.Identifier;
|
||||
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.CallbackInfo;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Mixin(DirectRegistryPacketHandler.class)
|
||||
public abstract class RegistryHandlerMixin {
|
||||
@Inject(method = "sendPacket", at = @At("HEAD"), remap = false)
|
||||
public void sf$removeRegistry(Consumer<DirectRegistryPacketHandler.Payload> sender, Map<Identifier, Object2IntMap<Identifier>> registryMap, CallbackInfo ci) {
|
||||
registryMap.clear();
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
package io.ib67.sfcraft.mixin.server.item;
|
||||
|
||||
import io.ib67.sfcraft.item.SFItem;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.registry.DefaultedRegistry;
|
||||
import net.minecraft.registry.entry.RegistryEntry;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
|
||||
@Mixin(Item.class)
|
||||
public abstract class ItemMixin {
|
||||
@Redirect(
|
||||
method ="<init>",
|
||||
at= @At(value = "INVOKE", target = "Lnet/minecraft/registry/DefaultedRegistry;createEntry(Ljava/lang/Object;)Lnet/minecraft/registry/entry/RegistryEntry$Reference;")
|
||||
)
|
||||
public RegistryEntry.Reference sf$redirectCreateEntry(DefaultedRegistry instance, Object o){
|
||||
if(this instanceof SFItem) {
|
||||
return null;
|
||||
}
|
||||
return instance.createEntry(o);
|
||||
}
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
package io.ib67.sfcraft.mixin.server.item;
|
||||
|
||||
import io.ib67.sfcraft.SFCraft;
|
||||
import io.ib67.sfcraft.SFItems;
|
||||
import io.ib67.sfcraft.SFRegistries;
|
||||
import net.minecraft.component.ComponentHolder;
|
||||
import net.minecraft.component.ComponentMapImpl;
|
||||
import net.minecraft.component.DataComponentTypes;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemConvertible;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.Items;
|
||||
import net.minecraft.util.Identifier;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.slf4j.Logger;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
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.Redirect;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
@Mixin(ItemStack.class)
|
||||
public abstract class ItemStackMixin implements ComponentHolder {
|
||||
@Shadow
|
||||
@Final
|
||||
@Deprecated
|
||||
@Nullable
|
||||
private Item item;
|
||||
|
||||
@Shadow @Final private static Logger LOGGER;
|
||||
@Unique
|
||||
private Item sfItem;
|
||||
|
||||
@Shadow public abstract boolean isEmpty();
|
||||
|
||||
@Inject(method = "<init>(Lnet/minecraft/item/ItemConvertible;ILnet/minecraft/component/ComponentMapImpl;)V", at = @At("TAIL"))
|
||||
private void initSFItem(ItemConvertible item, int count, ComponentMapImpl components, CallbackInfo ci) {
|
||||
var _id = get(DataComponentTypes.CUSTOM_DATA);
|
||||
if (_id != null && _id.contains(SFItems.SF_ITEM_TYPE_KEY)) {
|
||||
var id = _id.copyNbt().getString(SFItems.SF_ITEM_TYPE_KEY);
|
||||
try {
|
||||
sfItem = SFRegistries.ITEMS.get(Identifier.of(SFCraft.MOD_ID, id));
|
||||
}catch(Exception e){
|
||||
e.printStackTrace();
|
||||
}
|
||||
if(sfItem == null){
|
||||
LOGGER.warn("A invalid sfItem is being created: {}", id);
|
||||
new IllegalStateException("Just stacktrace").printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "getItem", at = @At("HEAD"), cancellable = true)
|
||||
private void beforeGetItem(CallbackInfoReturnable<Item> cir) {
|
||||
if (sfItem != null) cir.setReturnValue(sfItem);
|
||||
}
|
||||
|
||||
@Redirect(method = "getRegistryEntry", at = @At(value = "INVOKE", target = "Lnet/minecraft/item/ItemStack;getItem()Lnet/minecraft/item/Item;"))
|
||||
private Item sf$getMappedEntry(ItemStack instance) {
|
||||
return isEmpty() ? Items.AIR : this.item;
|
||||
}
|
||||
|
||||
@Redirect(method = "copy", at= @At(value = "INVOKE", target = "Lnet/minecraft/item/ItemStack;getItem()Lnet/minecraft/item/Item;"))
|
||||
private Item sf$getCopySubject(ItemStack instance){
|
||||
return isEmpty() ? Items.AIR : this.item;
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
package io.ib67.sfcraft.mixin.server.item;
|
||||
|
||||
import io.ib67.sfcraft.item.TickableItem;
|
||||
import net.minecraft.entity.EquipmentSlot;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
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.CallbackInfo;
|
||||
|
||||
@Mixin(PlayerEntity.class)
|
||||
public abstract class PlayerEntityMixin {
|
||||
@Shadow
|
||||
public abstract ItemStack getEquippedStack(EquipmentSlot slot);
|
||||
|
||||
@Inject(method = "updateTurtleHelmet", at = @At("TAIL"))
|
||||
public void sf$tickMyItems(CallbackInfo ci) {
|
||||
checkAndUpdate(EquipmentSlot.OFFHAND);
|
||||
checkAndUpdate(EquipmentSlot.MAINHAND);
|
||||
checkAndUpdate(EquipmentSlot.HEAD);
|
||||
checkAndUpdate(EquipmentSlot.CHEST);
|
||||
checkAndUpdate(EquipmentSlot.LEGS);
|
||||
checkAndUpdate(EquipmentSlot.FEET);
|
||||
checkAndUpdate(EquipmentSlot.BODY);
|
||||
}
|
||||
|
||||
@Unique
|
||||
private void checkAndUpdate(EquipmentSlot equipmentSlot) {
|
||||
var item = getEquippedStack(equipmentSlot);
|
||||
if (item.getItem() instanceof TickableItem tickableItem) {
|
||||
tickableItem.onUpdate($this(), item, equipmentSlot);
|
||||
}
|
||||
}
|
||||
|
||||
@Unique
|
||||
private PlayerEntity $this() {
|
||||
return (PlayerEntity) (Object) this;
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ package io.ib67.sfcraft.mixin.server.subserver;
|
||||
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import io.ib67.sfcraft.SFCraft;
|
||||
import io.ib67.sfcraft.mixin.server.ServerChunkManagerMixin;
|
||||
import io.ib67.sfcraft.module.RoomModule;
|
||||
import io.ib67.sfcraft.registry.RoomRegistry;
|
||||
import io.ib67.sfcraft.util.Helper;
|
||||
@@ -70,8 +71,8 @@ public abstract class PlayerManagerMixin {
|
||||
private void teleportToRoom(ServerPlayerEntity player, GlobalPos spawn) {
|
||||
var world = player.getServer().getWorld(spawn.dimension());
|
||||
var pos = spawn.pos();
|
||||
world.getChunkManager().chunkLoadingManager.getTicketManager().handleChunkEnter(player.getWatchedSection(), player);
|
||||
player.teleport(world, pos.getX(), pos.getY(), pos.getZ(), Set.of(), 0, 0);
|
||||
((ServerChunkManagerMixin)world.getChunkManager()).getLevelManager().handleChunkEnter(player.getWatchedSection(), player);
|
||||
player.teleport(world, pos.getX(), pos.getY(), pos.getZ(), Set.of(), 0, 0, true);
|
||||
}
|
||||
|
||||
@Inject(method = "remove", at = @At("HEAD"))
|
||||
|
||||
@@ -15,8 +15,10 @@ import java.util.Set;
|
||||
|
||||
@Mixin(ServerPlayerEntity.class)
|
||||
public abstract class ServerPlayerEntityMixin {
|
||||
@Inject(at = @At("HEAD"), method = "teleport(Lnet/minecraft/server/world/ServerWorld;DDDLjava/util/Set;FF)Z", cancellable = true)
|
||||
public void sf$interceptTeleport(ServerWorld world, double destX, double destY, double destZ, Set<PositionFlag> flags, float yaw, float pitch, CallbackInfoReturnable<Boolean> cir) {
|
||||
//todo test this
|
||||
//todo fix playground operate players in main world
|
||||
@Inject(at=@At("HEAD"), method = "teleport(Lnet/minecraft/server/world/ServerWorld;DDDLjava/util/Set;FFZ)Z")
|
||||
public void sf$interceptTeleport(ServerWorld world, double destX, double destY, double destZ, Set<PositionFlag> flags, float yaw, float pitch, boolean resetCamera, CallbackInfoReturnable<Boolean> cir) {
|
||||
var room = roomRegistry().getRoomBy($this().getUuid());
|
||||
if (room != null) {
|
||||
if (world.getRegistryKey() != room.getSpawnPosition().dimension()) {
|
||||
@@ -25,16 +27,6 @@ public abstract class ServerPlayerEntityMixin {
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(at = @At("HEAD"), method = "teleport(Lnet/minecraft/server/world/ServerWorld;DDDFF)V", cancellable = true)
|
||||
public void sf$interceptTeleport(ServerWorld targetWorld, double x, double y, double z, float yaw, float pitch, CallbackInfo ci) {
|
||||
var room = roomRegistry().getRoomBy($this().getUuid());
|
||||
if (room != null) {
|
||||
if (targetWorld.getRegistryKey() != room.getSpawnPosition().dimension()) {
|
||||
ci.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private RoomRegistry roomRegistry() {
|
||||
return SFCraft.getInjector().getInstance(RoomRegistry.class);
|
||||
}
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
package io.ib67.sfcraft.mixin.server.subserver;
|
||||
|
||||
import io.ib67.sfcraft.SFCraft;
|
||||
import io.ib67.sfcraft.module.RoomModule;
|
||||
import net.minecraft.registry.RegistryKey;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.minecraft.world.GameRules;
|
||||
import net.minecraft.world.World;
|
||||
import org.spongepowered.asm.mixin.*;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
@Mixin(World.class)
|
||||
public abstract class WorldMixin {
|
||||
@Shadow
|
||||
public abstract boolean isClient();
|
||||
|
||||
@Shadow
|
||||
@Final
|
||||
private RegistryKey<World> registryKey;
|
||||
|
||||
@Unique
|
||||
private GameRules sfcraft$customGameRule;
|
||||
|
||||
@Inject(method = "getGameRules", at = @At("HEAD"), cancellable = true)
|
||||
private void beforeGetGameRules(CallbackInfoReturnable<GameRules> cir) {
|
||||
if (!isClient() && registryKey.getValue().getNamespace().equals(SFCraft.MOD_ID)) {
|
||||
if (sfcraft$customGameRule == null) {
|
||||
sfcraft$customGameRule = SFCraft.getInjector().getInstance(RoomModule.class).readGameRuleForRoom((ServerWorld) (Object) this);
|
||||
}
|
||||
cir.setReturnValue(sfcraft$customGameRule);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
package io.ib67.sfcraft.module;
|
||||
|
||||
import com.mojang.brigadier.CommandDispatcher;
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import io.ib67.sfcraft.SFItems;
|
||||
import io.ib67.sfcraft.ServerModule;
|
||||
import io.ib67.sfcraft.item.SFItem;
|
||||
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
|
||||
import net.minecraft.command.CommandRegistryAccess;
|
||||
import net.minecraft.command.argument.IdentifierArgumentType;
|
||||
import net.minecraft.component.DataComponentTypes;
|
||||
import net.minecraft.component.type.NbtComponent;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
import net.minecraft.server.command.CommandManager;
|
||||
import net.minecraft.server.command.ServerCommandSource;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
public class CustomItemModule extends ServerModule {
|
||||
@Override
|
||||
public void onInitialize() {
|
||||
SFItems.init();
|
||||
CommandRegistrationCallback.EVENT
|
||||
.register(this::registerCommand);
|
||||
}
|
||||
|
||||
private void registerCommand(CommandDispatcher<ServerCommandSource> dispatcher, CommandRegistryAccess registryAccess, CommandManager.RegistrationEnvironment environment) {
|
||||
dispatcher.register(
|
||||
CommandManager.literal("sfgive")
|
||||
.then(
|
||||
CommandManager.argument("item", IdentifierArgumentType.identifier())
|
||||
.executes(this::performGive)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private static ItemStack getItemByName(Identifier id) throws CommandSyntaxException {
|
||||
var item = SFItems.getById(id);
|
||||
if(item == null) return null;
|
||||
var stack = new ItemStack(((SFItem) item).getMappedItem());
|
||||
var cmp = new NbtCompound();
|
||||
cmp.putString(SFItems.SF_ITEM_TYPE_KEY, item.getRegistryEntry().getKey().map(it -> it.getValue().getPath()).orElseThrow());
|
||||
stack.set(DataComponentTypes.CUSTOM_DATA, NbtComponent.of(cmp));
|
||||
return stack.copy();
|
||||
}
|
||||
|
||||
|
||||
private int performGive(CommandContext<ServerCommandSource> context) throws CommandSyntaxException {
|
||||
var item = IdentifierArgumentType.getIdentifier(context, "item");
|
||||
if (!context.getSource().isExecutedByPlayer()) {
|
||||
context.getSource().sendMessage(Text.of("Can't be executed by non-players"));
|
||||
return 0;
|
||||
}
|
||||
var player = context.getSource().getPlayer();
|
||||
var itemStack = getItemByName(item);
|
||||
if (itemStack != null) {
|
||||
player.giveItemStack(itemStack);
|
||||
}else{
|
||||
player.sendMessage(Text.of("Item with id "+item.toString()+" not exists."));
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -2,16 +2,10 @@ package io.ib67.sfcraft.module;
|
||||
|
||||
import io.ib67.sfcraft.ServerModule;
|
||||
import io.ib67.sfcraft.callback.SFCallbacks;
|
||||
import io.ib67.sfcraft.util.ColorHelper;
|
||||
import it.unimi.dsi.fastutil.objects.*;
|
||||
import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents;
|
||||
import net.minecraft.entity.EquipmentSlot;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.entity.player.PlayerInventory;
|
||||
import net.minecraft.item.ElytraItem;
|
||||
import net.minecraft.network.packet.Packet;
|
||||
import net.minecraft.network.packet.s2c.play.SubtitleS2CPacket;
|
||||
import net.minecraft.network.packet.s2c.play.TitleFadeS2CPacket;
|
||||
import net.minecraft.network.packet.s2c.play.TitleS2CPacket;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.network.ServerPlayNetworkHandler;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
@@ -19,10 +13,6 @@ import net.minecraft.text.MutableText;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.util.Colors;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
|
||||
import java.awt.*;
|
||||
import java.text.DecimalFormat;
|
||||
|
||||
public class ElytraSpeedMeterModule extends ServerModule {
|
||||
private static final int BAR_LEN = 20;
|
||||
@@ -89,7 +79,7 @@ public class ElytraSpeedMeterModule extends ServerModule {
|
||||
}
|
||||
|
||||
private Text generateDurabilityMeter(long f, PlayerEntity player) {
|
||||
var stack = player.getInventory().getArmorStack(PlayerInventory.ARMOR_SLOTS[2]);
|
||||
var stack = player.getEquippedStack(EquipmentSlot.CHEST);
|
||||
if (stack.isDamageable() && stack.isDamaged()) {
|
||||
var remaining = stack.getMaxDamage() - stack.getDamage();
|
||||
var percent = (int) Math.ceil(((double) remaining / stack.getMaxDamage()) * 100);
|
||||
|
||||
@@ -2,48 +2,32 @@ package io.ib67.sfcraft.module;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import com.mojang.brigadier.Command;
|
||||
import com.mojang.brigadier.CommandDispatcher;
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
import io.ib67.sfcraft.ServerModule;
|
||||
import io.ib67.sfcraft.config.SFConfig;
|
||||
import io.ib67.sfcraft.inject.MinecraftServerSupplier;
|
||||
import io.ib67.sfcraft.room.RequestedRoom;
|
||||
import io.ib67.sfcraft.registry.RoomRegistry;
|
||||
import io.ib67.sfcraft.room.data.RoomWorldDataLoader;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
|
||||
import net.minecraft.command.CommandRegistryAccess;
|
||||
import net.minecraft.network.PacketCallbacks;
|
||||
import net.minecraft.network.codec.PacketCodecs;
|
||||
import net.minecraft.network.packet.s2c.common.ServerTransferS2CPacket;
|
||||
import net.minecraft.network.packet.s2c.common.StoreCookieS2CPacket;
|
||||
import net.minecraft.registry.RegistryKey;
|
||||
import net.minecraft.server.command.CommandManager;
|
||||
import net.minecraft.server.command.ServerCommandSource;
|
||||
import net.minecraft.server.world.ChunkTicketType;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.Pair;
|
||||
import net.minecraft.util.Unit;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.ChunkPos;
|
||||
import net.minecraft.world.GameRules;
|
||||
import net.minecraft.world.World;
|
||||
import org.apache.commons.lang3.RandomStringUtils;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.SecretKeyFactory;
|
||||
import javax.crypto.spec.PBEKeySpec;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.Key;
|
||||
import java.security.spec.KeySpec;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
@@ -76,7 +60,7 @@ public class RoomModule extends ServerModule {
|
||||
log.warn("Cannot find world {}", registryKeyBlockPosPair.getLeft());
|
||||
continue;
|
||||
}
|
||||
world.getChunkManager().addTicket(ChunkTicketType.START, new ChunkPos(registryKeyBlockPosPair.getRight()), 64, Unit.INSTANCE);
|
||||
world.getChunkManager().addTicket(ChunkTicketType.START, new ChunkPos(registryKeyBlockPosPair.getRight()), 64);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,6 +74,9 @@ public class RoomModule extends ServerModule {
|
||||
|
||||
private int onCleanReconnect(CommandContext<ServerCommandSource> serverCommandSourceCommandContext) {
|
||||
var player = serverCommandSourceCommandContext.getSource().getPlayer();
|
||||
if (player == null) {
|
||||
return 0;
|
||||
}
|
||||
if (!isVirtual(player.getUuid())) {
|
||||
player.sendMessage(Text.literal("你不在任何 \"房间\" 内。"));
|
||||
return 0;
|
||||
@@ -119,8 +106,4 @@ public class RoomModule extends ServerModule {
|
||||
public GameProfile devirtualize(UUID virtual) {
|
||||
return uuidMapper.get(virtual);
|
||||
}
|
||||
|
||||
public GameRules readGameRuleForRoom(ServerWorld world){
|
||||
return RoomWorldDataLoader.get(world).getGameRules();
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,7 @@ import net.minecraft.text.RawFilteredPair;
|
||||
import net.minecraft.text.Text;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.URI;
|
||||
import java.nio.file.Path;
|
||||
import java.time.Clock;
|
||||
import java.time.ZonedDateTime;
|
||||
@@ -51,7 +52,7 @@ public class WelcomeModule extends ServerModule {
|
||||
player.sendMessage(Text.of("§a您受本服务器成员邀请加入本服务器,以下是一些注意事项:"));
|
||||
player.sendMessage(Text.of(" - 服务器内已有的设施均为其他玩家的财产,(如可以)使用时请注意礼貌"));
|
||||
player.sendMessage(Text.literal(" - 服务器内有一些非原版特性,可以点击此条消息查看 [特性列表]")
|
||||
.styled(s -> s.withClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, "https://wiki.sfclub.cc/s/sfcraft-features"))));
|
||||
.styled(s -> s.withClickEvent(new ClickEvent.OpenUrl(URI.create("https://wiki.sfclub.cc/s/sfcraft-features")))));
|
||||
player.sendMessage(Text.of("§c - 邀请新成员即等同为其作担保"));
|
||||
player.sendMessage(Text.of("§7如果您想邀请朋友加入服务器, 可以向管理员提出申请§7 (需备注正/盗版/小号)"));
|
||||
player.sendMessage(Text.of("§7此外, 本服务器无密码登录,盗版账号安全责任自负"));
|
||||
|
||||
@@ -21,7 +21,7 @@ import java.util.regex.MatchResult;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class ChatPingModule extends ServerModule implements MessageDecorator {
|
||||
private static final Pattern PING = Pattern.compile("(@[\\w]+)?");
|
||||
private static final Pattern PING = Pattern.compile("(@[\\w]+)?"); //todo remove the need of prefix
|
||||
@Inject
|
||||
MinecraftServerSupplier serverSupplier;
|
||||
@Inject
|
||||
@@ -51,7 +51,7 @@ public class ChatPingModule extends ServerModule implements MessageDecorator {
|
||||
var r = Text.literal(match.replaceAll(it -> this.matchPlayer(it, names, foundPlayers)));
|
||||
for (PlayerEntity foundPlayer : foundPlayers) {
|
||||
if (sender != null) {
|
||||
foundPlayer.sendMessage(Text.literal(sender.getName().getLiteralString() + " 正在叫你。").withColor(Colors.LIGHT_GRAY));
|
||||
foundPlayer.sendMessage(Text.literal(sender.getName().getLiteralString() + " 正在叫你。").withColor(Colors.LIGHT_GRAY), true);
|
||||
}
|
||||
foundPlayer.playSoundToPlayer(
|
||||
SoundEvents.ENTITY_ITEM_PICKUP,
|
||||
|
||||
@@ -46,7 +46,7 @@ public class ChatSendLocModule extends ServerModule implements MessageDecorator
|
||||
return Text
|
||||
.literal(" " + x + ", " + y + ", " + z + world + " ")
|
||||
.withColor(Helper.fromRgb(63, 254, 254))
|
||||
.styled(style -> style.withClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/gps " + key + " " + x + " " + y + " " + z)));
|
||||
.styled(style -> style.withClickEvent(new ClickEvent.RunCommand("/gps " + key + " " + x + " " + y + " " + z)));
|
||||
}
|
||||
|
||||
private static String translate(RegistryKey<World> registryKey) {
|
||||
|
||||
@@ -55,7 +55,7 @@ public class BackModule extends ServerModule {
|
||||
|
||||
public void onPlayerDeath(PlayerEntity player, DamageSource damageSource) {
|
||||
if (this.isEnabled() && Helper.canBack((ServerPlayerEntity) player)) {
|
||||
player.sendMessage(Text.of("Tip: 死亡地点附近有玩家,可以使用 /back 传送到他们那里。(即使在对方也死亡的状态下)"));
|
||||
player.sendMessage(Text.of("Tip: 死亡地点附近有玩家,可以使用 /back 传送到他们那里。(即使在对方也死亡的状态下)"), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
package io.ib67.sfcraft.module.randomevt;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.mojang.datafixers.util.Either;
|
||||
import io.ib67.sfcraft.ServerModule;
|
||||
import io.ib67.sfcraft.callback.SFCallbacks;
|
||||
import io.ib67.sfcraft.module.randomevt.longnight.DawnAfterLongNightEvent;
|
||||
import io.ib67.sfcraft.module.randomevt.longnight.LongNightEvent;
|
||||
import io.ib67.sfcraft.registry.RandomEventRegistry;
|
||||
import net.fabricmc.fabric.api.event.player.UseItemCallback;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.Items;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.util.*;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class LongNightModule extends ServerModule {
|
||||
@Inject
|
||||
RandomEventRegistry registry;
|
||||
|
||||
@Override
|
||||
public void onInitialize() {
|
||||
registry.registerEvent(LongNightEvent::new, World.OVERWORLD
|
||||
, world -> !LongNightEvent.isRunning()
|
||||
&& isEnabled()
|
||||
&& world.getTimeOfDay() % 24000 == 18000
|
||||
&& world.getRandom().nextBetween(0, 100) < 5); // At midnight
|
||||
registry.registerEvent(DawnAfterLongNightEvent::new, World.OVERWORLD
|
||||
, world -> world.getTimeOfDay() % 22200 == 0); // At dawn
|
||||
SFCallbacks.PLAYER_SLEEP.register(this::onPlayerSleep);
|
||||
UseItemCallback.EVENT.register(this::onUseClock);
|
||||
}
|
||||
|
||||
private TypedActionResult<ItemStack> onUseClock(PlayerEntity player, World world, Hand hand) {
|
||||
if (player.isSpectator()) return TypedActionResult.pass(ItemStack.EMPTY);
|
||||
if (player.getStackInHand(hand).isOf(Items.CLOCK)) {
|
||||
if (LongNightEvent.isRunning())
|
||||
player.sendMessage(Text.literal("永夜还将持续约 " + LongNightEvent.getRemainingTicks() / 20 + " 秒。").withColor(Colors.LIGHT_GRAY));
|
||||
}
|
||||
return TypedActionResult.pass(ItemStack.EMPTY);
|
||||
}
|
||||
|
||||
public Either<PlayerEntity.SleepFailureReason, Unit> onPlayerSleep(PlayerEntity player, BlockPos pos) {
|
||||
if (!isEnabled()) return Either.right(Unit.INSTANCE);
|
||||
if (LongNightEvent.isRunning()) {
|
||||
player.sendMessage(Text.literal("你感到焦躁不安!").withColor(Colors.LIGHT_RED)
|
||||
.append(Text.literal(" (永夜事件期间无法睡觉)").withColor(Colors.LIGHT_GRAY)));
|
||||
return Either.left(PlayerEntity.SleepFailureReason.NOT_POSSIBLE_HERE);
|
||||
}
|
||||
return Either.right(Unit.INSTANCE);
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package io.ib67.sfcraft.module.randomevt.longnight;
|
||||
import io.ib67.sfcraft.module.randomevt.RandomEvent;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.util.Colors;
|
||||
import net.minecraft.world.GameRules;
|
||||
@@ -14,7 +15,7 @@ public class LongNightEvent extends RandomEvent {
|
||||
static boolean isAtLongNight;
|
||||
@Getter
|
||||
private static int remainingTicks;
|
||||
private final World world;
|
||||
private final ServerWorld world;
|
||||
private boolean doDaylightCycle;
|
||||
private boolean doTraderSpawning;
|
||||
|
||||
|
||||
@@ -45,7 +45,6 @@ import java.util.Set;
|
||||
|
||||
public class CreativeRoomModule extends ServerModule {
|
||||
private static final Set<String> BYPASS_PERMISSIONS = Set.of(
|
||||
"minecraft.command.gamerule",
|
||||
"carpet.command.player",
|
||||
"carpet.command.track",
|
||||
"minecraft.command.setblock",
|
||||
|
||||
@@ -30,6 +30,7 @@ import net.minecraft.text.Text;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.awt.*;
|
||||
import java.net.URI;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Base64;
|
||||
@@ -69,7 +70,7 @@ public class SchematicUploader extends WebHandler {
|
||||
}
|
||||
var url = generateSchematicUrl(source.isExecutedByPlayer() ? source.getPlayer().getName().getLiteralString() : "CONSOLE");
|
||||
source.sendMessage(Text.literal("Click this URL to upload schematic files.").withColor(Color.GREEN.getRGB()));
|
||||
source.sendMessage(Text.literal(url).styled(it -> it.withClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, url))));
|
||||
source.sendMessage(Text.literal(url).styled(it -> it.withClickEvent(new ClickEvent.OpenUrl(URI.create(url)))));
|
||||
return Command.SINGLE_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -174,7 +175,7 @@ public class SchematicUploader extends WebHandler {
|
||||
}
|
||||
player.sendMessage(Text.literal("Schematic " + fileName + " has been saved! Use //schem list to find it").withColor(Color.GREEN.getRGB()));
|
||||
player.sendMessage(Text.literal("Or you can click this").styled(it -> it.withUnderline(true).withClickEvent(
|
||||
new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "//schem load " + fileName)
|
||||
new ClickEvent.SuggestCommand("//schem load " + fileName)
|
||||
)));
|
||||
}
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
package io.ib67.sfcraft.room.data;
|
||||
|
||||
import com.mojang.serialization.Dynamic;
|
||||
import lombok.Getter;
|
||||
import net.minecraft.datafixer.DataFixTypes;
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
import net.minecraft.nbt.NbtOps;
|
||||
import net.minecraft.registry.RegistryWrapper;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.minecraft.world.GameRules;
|
||||
import net.minecraft.world.PersistentState;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
@Getter
|
||||
public class RoomWorldDataLoader extends PersistentState {
|
||||
|
||||
private static final String NAME = "sfcraft_room_data";
|
||||
private static final Type<RoomWorldDataLoader> TYPE = new Type<>(RoomWorldDataLoader::new, RoomWorldDataLoader::readNbt, DataFixTypes.LEVEL);
|
||||
|
||||
private static final String TAG_GAME_RULES = "gameRules";
|
||||
|
||||
private final GameRules gameRules;
|
||||
|
||||
public RoomWorldDataLoader() {
|
||||
this(new GameRules());
|
||||
}
|
||||
|
||||
public RoomWorldDataLoader(GameRules gameRules) {
|
||||
this.gameRules = gameRules;
|
||||
}
|
||||
|
||||
public static RoomWorldDataLoader get(ServerWorld world) {
|
||||
Objects.requireNonNull(world);
|
||||
var state = world.getPersistentStateManager().getOrCreate(TYPE, NAME);
|
||||
state.markDirty();
|
||||
return state;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NbtCompound writeNbt(NbtCompound nbt, RegistryWrapper.WrapperLookup registry) {
|
||||
nbt.put(TAG_GAME_RULES, gameRules.toNbt());
|
||||
return nbt;
|
||||
}
|
||||
|
||||
private static RoomWorldDataLoader readNbt(NbtCompound nbt, RegistryWrapper.WrapperLookup registry) {
|
||||
if (nbt.contains(TAG_GAME_RULES)) {
|
||||
var c = nbt.getCompound(TAG_GAME_RULES);
|
||||
var dynamic = new Dynamic<>(NbtOps.INSTANCE, c);
|
||||
var rule = new GameRules(dynamic);
|
||||
return new RoomWorldDataLoader(rule);
|
||||
}
|
||||
return new RoomWorldDataLoader();
|
||||
}
|
||||
}
|
||||
@@ -31,6 +31,7 @@ import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@@ -87,7 +88,7 @@ public class Helper {
|
||||
deltaZ = stand.getCollisionShape(world, pos).getMax(Direction.Axis.X);
|
||||
deltaZ = Double.isFinite(deltaZ) ? deltaZ / 2 : 0.5;
|
||||
}
|
||||
player.teleport(world, x + deltaX, y + deltaY, z + deltaZ, yaw, pitch);
|
||||
player.teleport(world, x + deltaX, y + deltaY, z + deltaZ, Set.of(), yaw, pitch, true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -8,13 +8,15 @@ import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
public class TypedNbtList extends NbtList {
|
||||
private final byte heldType;
|
||||
public TypedNbtList(List<NbtElement> list, byte type) {
|
||||
super(list, type);
|
||||
super(list);
|
||||
this.heldType = type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(DataOutput output) throws IOException {
|
||||
output.writeByte(this.getHeldType());
|
||||
output.writeByte(heldType);
|
||||
output.writeInt(this.size());
|
||||
|
||||
for (NbtElement nbtElement : this) {
|
||||
|
||||
@@ -10,6 +10,7 @@ import org.apache.commons.compress.utils.Lists;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -31,11 +32,14 @@ public class LitematicConverter implements AutoCloseable {
|
||||
BiConsumer<String, NbtCompound> schematicOutput
|
||||
) {
|
||||
var root = NbtIo.readCompressed(input, sizeTracker);
|
||||
var dataVersion = root.getInt("MinecraftDataVersion");
|
||||
var regionsNbt = root.getCompound("Regions");
|
||||
var dataVersion = root.getInt("MinecraftDataVersion")
|
||||
.orElseThrow(() -> new IllegalStateException("MinecraftDataVersion not found"));
|
||||
var regionsNbt = root.getCompound("Regions")
|
||||
.orElseThrow(() -> new IllegalStateException("Regions not found"));
|
||||
var i = 0;
|
||||
for (String regionName : regionsNbt.getKeys()) {
|
||||
var compound = regionsNbt.getCompound(regionName);
|
||||
var compound = regionsNbt.getCompound(regionName)
|
||||
.orElseThrow(() -> new IllegalStateException("Region " + regionName + " not found"));
|
||||
var j = i++;
|
||||
var schematic = convertRegionToSchematic(dataVersion, compound);
|
||||
schematicOutput.accept(regionName, schematic);
|
||||
@@ -56,11 +60,11 @@ public class LitematicConverter implements AutoCloseable {
|
||||
worldEditTag.putShort("Width", (short) Math.abs(size.x));
|
||||
|
||||
// block & tile entities
|
||||
var paletteNbt = region.getList("BlockStatePalette", NbtElement.COMPOUND_TYPE);
|
||||
var paletteNbt = region.getListOrEmpty("BlockStatePalette");
|
||||
var wePalette = convertToWEPalette(paletteNbt);
|
||||
worldEditTag.putInt("PaletteMax", wePalette.getKeys().size());
|
||||
worldEditTag.put("Palette", wePalette);
|
||||
var tileEntities = region.getList("TileEntities", NbtElement.COMPOUND_TYPE);
|
||||
var tileEntities = region.getListOrEmpty("TileEntities");
|
||||
worldEditTag.put("BlockEntities", convertToWETileEntities(tileEntities));
|
||||
worldEditTag.putInt("Version", 2);
|
||||
worldEditTag.putIntArray("Offset", new int[3]);
|
||||
@@ -72,9 +76,15 @@ public class LitematicConverter implements AutoCloseable {
|
||||
|
||||
protected SizeTuple readSizeTuple(NbtCompound region) {
|
||||
var size = (NbtCompound) region.get("Size");
|
||||
var sizeX = size.getInt("x");
|
||||
var sizeY = size.getInt("y");
|
||||
var sizeZ = size.getInt("z");
|
||||
if (size == null) {
|
||||
throw new IllegalStateException("Size not found");
|
||||
}
|
||||
var sizeX = size.getInt("x")
|
||||
.orElseThrow(() -> new IllegalStateException("Size X not found"));
|
||||
var sizeY = size.getInt("y")
|
||||
.orElseThrow(() -> new IllegalStateException("Size Y not found"));
|
||||
var sizeZ = size.getInt("z")
|
||||
.orElseThrow(() -> new IllegalStateException("Size Z not found"));
|
||||
return new SizeTuple(sizeX, sizeY, sizeZ);
|
||||
}
|
||||
|
||||
@@ -85,11 +95,14 @@ public class LitematicConverter implements AutoCloseable {
|
||||
var weTE = new NbtCompound();
|
||||
var tE = (NbtCompound) _tileEntity;
|
||||
weTE.putIntArray("Pos", new int[]{
|
||||
tE.getInt("x"),
|
||||
tE.getInt("y"),
|
||||
tE.getInt("x")
|
||||
.orElseThrow(() -> new IllegalStateException("Pos X not found")),
|
||||
tE.getInt("y")
|
||||
.orElseThrow(() -> new IllegalStateException("Pos Y not found")),
|
||||
tE.getInt("z")
|
||||
.orElseThrow(() -> new IllegalStateException("Pos Z not found"))
|
||||
});
|
||||
weTE.putString("Id", tE.getString("id"));
|
||||
weTE.putString("Id", tE.getString("id").orElseThrow(() -> new IllegalStateException("Id not found")));
|
||||
// other properties
|
||||
tE.remove("x");
|
||||
tE.remove("y");
|
||||
@@ -105,15 +118,15 @@ public class LitematicConverter implements AutoCloseable {
|
||||
var wePalette = new NbtCompound();
|
||||
for (int i = 0; i < paletteNbt.size(); i++) {
|
||||
var entry = (NbtCompound) paletteNbt.get(i);
|
||||
var name = new StringBuilder(entry.getString("Name"));
|
||||
var properties = entry.getCompound("Properties");
|
||||
var name = new StringBuilder(entry.getString("Name").orElseThrow(() -> new IllegalStateException("Name not found")));
|
||||
var properties = entry.getCompound("Properties").orElseThrow(() -> new IllegalStateException("Properties not found"));
|
||||
if (!properties.isEmpty()) {
|
||||
name.append("[");
|
||||
var props = new ArrayList<String>();
|
||||
for (String key : properties.getKeys()) {
|
||||
props.add(key + "=" + properties.getString(key));
|
||||
}
|
||||
name.append(props.stream().collect(Collectors.joining(",")));
|
||||
name.append(String.join(",", props));
|
||||
name.append("]");
|
||||
}
|
||||
wePalette.putInt(name.toString(), i);
|
||||
@@ -123,17 +136,20 @@ public class LitematicConverter implements AutoCloseable {
|
||||
|
||||
protected NbtElement convertToWeMeta(SizeTuple size, NbtCompound region) {
|
||||
var pos = (NbtCompound) region.get("Position");
|
||||
if (pos == null){
|
||||
throw new IllegalStateException("Pos not found");
|
||||
}
|
||||
var nbt = new NbtCompound();
|
||||
nbt.putInt("WEOffsetX", pos.getInt("x") + (size.x < 0 ? size.x + 1 : 0));
|
||||
nbt.putInt("WEOffsetY", pos.getInt("y") + (size.y < 0 ? size.y + 1 : 0));
|
||||
nbt.putInt("WEOffsetZ", pos.getInt("z") + (size.z < 0 ? size.z + 1 : 0));
|
||||
nbt.putInt("WEOffsetX", pos.getInt("x").orElseThrow() + (size.x < 0 ? size.x + 1 : 0));
|
||||
nbt.putInt("WEOffsetY", pos.getInt("y").orElseThrow() + (size.y < 0 ? size.y + 1 : 0));
|
||||
nbt.putInt("WEOffsetZ", pos.getInt("z").orElseThrow() + (size.z < 0 ? size.z + 1 : 0));
|
||||
return nbt;
|
||||
}
|
||||
|
||||
protected byte[] convertToWEBlocks(SizeTuple size, NbtCompound region) {
|
||||
var blockCount = Math.abs(size.x * size.y * size.z);
|
||||
var blockStates = region.getLongArray("BlockStates");
|
||||
int bitsPerBlock = region.getList("BlockStatePalette", NbtElement.COMPOUND_TYPE).size();
|
||||
var blockStates = region.getLongArray("BlockStates").orElse(new long[0]);
|
||||
int bitsPerBlock = region.getListOrEmpty("BlockStatePalette").size();
|
||||
bitsPerBlock = Math.max(2, Integer.SIZE - Integer.numberOfLeadingZeros(bitsPerBlock - 1));
|
||||
int maxEntryValue = (1 << bitsPerBlock) - 1;
|
||||
var buffer = new PacketByteBuf(Unpooled.buffer());
|
||||
|
||||
@@ -35,9 +35,9 @@ public class LitematicConverterV3 extends LitematicConverter {
|
||||
schematicsTag.putShort("Width", (short) Math.abs(size.x()));
|
||||
|
||||
// block & tile entities
|
||||
var paletteNbt = region.getList("BlockStatePalette", NbtElement.COMPOUND_TYPE);
|
||||
var paletteNbt = region.getListOrEmpty("BlockStatePalette");
|
||||
var wePalette = convertToWEPalette(paletteNbt);
|
||||
var tileEntities = region.getList("TileEntities", NbtElement.COMPOUND_TYPE);
|
||||
var tileEntities = region.getListOrEmpty("TileEntities");
|
||||
|
||||
var blocksNbt = new NbtCompound();
|
||||
blocksNbt.put("Palette", wePalette);
|
||||
@@ -63,7 +63,11 @@ public class LitematicConverterV3 extends LitematicConverter {
|
||||
var paletteIds = new Int2ObjectOpenHashMap<>();
|
||||
var touchedIds = new IntOpenHashSet();
|
||||
for (String key : wePalette.getKeys()) {
|
||||
paletteIds.put(wePalette.getInt(key), key);
|
||||
paletteIds.put(
|
||||
wePalette.getInt(key)
|
||||
.orElseThrow(() -> new IllegalStateException("Cannot find key " + key + " in palette from worldedit schematic"))
|
||||
, key
|
||||
);
|
||||
}
|
||||
int counter = 0;
|
||||
try {
|
||||
@@ -95,11 +99,14 @@ public class LitematicConverterV3 extends LitematicConverter {
|
||||
@Override
|
||||
protected NbtElement convertToWeMeta(SizeTuple size, NbtCompound region) {
|
||||
var pos = (NbtCompound) region.get("Position");
|
||||
if (pos == null) {
|
||||
throw new IllegalStateException("Cannot find Position");
|
||||
}
|
||||
var worldEditNbt = new NbtCompound();
|
||||
worldEditNbt.putIntArray("Origin", new int[]{
|
||||
pos.getInt("x") + (size.x() < 0 ? size.x() + 1 : 0),
|
||||
pos.getInt("y") + (size.y() < 0 ? size.y() + 1 : 0),
|
||||
pos.getInt("z") + (size.z() < 0 ? size.z() + 1 : 0)
|
||||
pos.getInt("x").orElseThrow() + (size.x() < 0 ? size.x() + 1 : 0),
|
||||
pos.getInt("y").orElseThrow() + (size.y() < 0 ? size.y() + 1 : 0),
|
||||
pos.getInt("z").orElseThrow() + (size.z() < 0 ? size.z() + 1 : 0)
|
||||
});
|
||||
var Metadata = new NbtCompound();
|
||||
Metadata.put("WorldEdit", worldEditNbt);
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
accessWidener v2 named
|
||||
mutable field net/minecraft/item/Item registryEntry Lnet/minecraft/registry/entry/RegistryEntry$Reference;
|
||||
accessible method net/minecraft/nbt/NbtList <init> (Ljava/util/List;B)V
|
||||
accessible method net/minecraft/nbt/NbtList <init> (Ljava/util/List;)V
|
||||
extendable class net/minecraft/nbt/NbtList
|
||||
@@ -7,7 +7,8 @@
|
||||
"common.bridge.EntityBridge",
|
||||
"common.bridge.ItemBridge",
|
||||
"common.bridge.ServerPlayerBridge",
|
||||
"common.bridge.ServerWorldBridge"
|
||||
"common.bridge.ServerWorldBridge",
|
||||
"server.ServerChunkManagerMixin"
|
||||
],
|
||||
"client": [
|
||||
],
|
||||
@@ -26,12 +27,6 @@
|
||||
"server.SleepManagerMixin",
|
||||
"server.fixes.EndermanEntityMixin",
|
||||
"server.fixes.ProjectileEntityMixin",
|
||||
"server.hack.EntitySpawnS2CPacketMixin",
|
||||
"server.hack.HoverEntityContentMixin",
|
||||
"server.hack.RegistryHandlerMixin",
|
||||
"server.item.ItemMixin",
|
||||
"server.item.ItemStackMixin",
|
||||
"server.item.PlayerEntityMixin",
|
||||
"server.optimize.LivingEntityMixin",
|
||||
"server.subserver.EntityMixin",
|
||||
"server.subserver.PlayerListS2CPacket$EntryMixin",
|
||||
@@ -39,7 +34,6 @@
|
||||
"server.subserver.PlayerSaveHandlerMixin",
|
||||
"server.subserver.ServerLoginNetworkHandlerMixin",
|
||||
"server.subserver.ServerPlayerEntityMixin",
|
||||
"server.subserver.WorldMixin",
|
||||
"server.subserver.command.GameRuleCommandMixin"
|
||||
],
|
||||
"injectors": {
|
||||
|
||||
Reference in new issue
Block a user