add the mod
This commit is contained in:
		
							parent
							
								
									300d509baa
								
							
						
					
					
						commit
						871c10bba3
					
				@ -11,7 +11,7 @@ loader_version=0.14.25
 | 
			
		||||
# Mod Properties
 | 
			
		||||
mod_version=1.0.0
 | 
			
		||||
maven_group=net.touhoudiscord
 | 
			
		||||
archives_base_name=hardcore-redeploy
 | 
			
		||||
archives_base_name=hardcore_redeploy
 | 
			
		||||
 | 
			
		||||
# Dependencies
 | 
			
		||||
fabric_version=0.91.0+1.20.1
 | 
			
		||||
							
								
								
									
										9
									
								
								src/main/java/net/touhoudiscord/BuyStationCapable.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/main/java/net/touhoudiscord/BuyStationCapable.java
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,9 @@
 | 
			
		||||
package net.touhoudiscord;
 | 
			
		||||
 | 
			
		||||
import net.minecraft.util.math.BlockPos;
 | 
			
		||||
 | 
			
		||||
public interface BuyStationCapable {
 | 
			
		||||
    default void hardcoreredeploy_openBuyStationScreen(BlockPos blockPos) {
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -1,19 +1,33 @@
 | 
			
		||||
package net.touhoudiscord;
 | 
			
		||||
 | 
			
		||||
import net.fabricmc.api.ModInitializer;
 | 
			
		||||
 | 
			
		||||
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
 | 
			
		||||
import net.fabricmc.fabric.api.item.v1.FabricItemSettings;
 | 
			
		||||
import net.fabricmc.fabric.api.networking.v1.PacketByteBufs;
 | 
			
		||||
import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents;
 | 
			
		||||
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
 | 
			
		||||
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
 | 
			
		||||
import net.fabricmc.fabric.api.object.builder.v1.block.entity.FabricBlockEntityTypeBuilder;
 | 
			
		||||
import net.minecraft.block.Block;
 | 
			
		||||
import net.minecraft.block.Blocks;
 | 
			
		||||
import net.minecraft.block.BlockState;
 | 
			
		||||
import net.minecraft.block.HorizontalFacingBlock;
 | 
			
		||||
import net.minecraft.block.entity.BlockEntityType;
 | 
			
		||||
import net.minecraft.entity.effect.StatusEffect;
 | 
			
		||||
import net.minecraft.entity.projectile.FireworkRocketEntity;
 | 
			
		||||
import net.minecraft.item.Item;
 | 
			
		||||
import net.minecraft.item.ItemStack;
 | 
			
		||||
import net.minecraft.nbt.NbtCompound;
 | 
			
		||||
import net.minecraft.network.PacketByteBuf;
 | 
			
		||||
import net.minecraft.registry.Registries;
 | 
			
		||||
import net.minecraft.registry.Registry;
 | 
			
		||||
import net.minecraft.server.MinecraftServer;
 | 
			
		||||
import net.minecraft.server.network.ServerPlayerEntity;
 | 
			
		||||
import net.minecraft.sound.SoundEvent;
 | 
			
		||||
import net.minecraft.util.Identifier;
 | 
			
		||||
import net.minecraft.util.math.BlockPos;
 | 
			
		||||
import net.minecraft.util.math.Direction;
 | 
			
		||||
import net.minecraft.util.math.Vec3d;
 | 
			
		||||
import net.minecraft.world.GameMode;
 | 
			
		||||
import net.touhoudiscord.block.BuyStation;
 | 
			
		||||
import net.touhoudiscord.block.BuyStationEntity;
 | 
			
		||||
import net.touhoudiscord.commands.RedeployPlayerCommand;
 | 
			
		||||
@ -23,26 +37,104 @@ import org.slf4j.Logger;
 | 
			
		||||
import org.slf4j.LoggerFactory;
 | 
			
		||||
import software.bernie.geckolib.GeckoLib;
 | 
			
		||||
 | 
			
		||||
import java.util.UUID;
 | 
			
		||||
 | 
			
		||||
import static net.touhoudiscord.HardcoreRedeployConfigHandler.config;
 | 
			
		||||
import static net.touhoudiscord.block.BuyStation.BUY_STATION_PART;
 | 
			
		||||
 | 
			
		||||
public class HardcoreRedeploy implements ModInitializer {
 | 
			
		||||
	public static final String MOD_ID = "hardcore-redeploy";
 | 
			
		||||
    public static final Logger LOGGER = LoggerFactory.getLogger("hardcore-redeploy");
 | 
			
		||||
	public static final String MOD_ID = "hardcore_redeploy";
 | 
			
		||||
    public static final Logger LOGGER = LoggerFactory.getLogger("hardcore_redeploy");
 | 
			
		||||
 | 
			
		||||
	public static final StatusEffect REDEPLOYING = new RedeployingStatusEffect();
 | 
			
		||||
	public static final Block BUY_STATION = Registry.register(Registries.BLOCK, new Identifier(HardcoreRedeploy.MOD_ID, "buy_station"), new BuyStation(FabricBlockSettings.copyOf(Blocks.HOPPER).nonOpaque()));
 | 
			
		||||
	public static final Block BUY_STATION = Registry.register(Registries.BLOCK, new Identifier(HardcoreRedeploy.MOD_ID, "buy_station"), new BuyStation(FabricBlockSettings.create().nonOpaque().requiresTool().resistance(6).hardness(3)));
 | 
			
		||||
	public static final Item BUY_STATION_ITEM = Registry.register(Registries.ITEM, new Identifier(HardcoreRedeploy.MOD_ID, "buy_station"), new BuyStationItem(HardcoreRedeploy.BUY_STATION, new FabricItemSettings()));
 | 
			
		||||
	public static final Identifier BUY_STATION_SOUND_ID = new Identifier(HardcoreRedeploy.MOD_ID, "buy_station");
 | 
			
		||||
	public static SoundEvent BUY_STATION_SOUND_EVENT = SoundEvent.of(BUY_STATION_SOUND_ID);
 | 
			
		||||
	public static BlockEntityType<BuyStationEntity> BUY_STATION_ENTITY;
 | 
			
		||||
 | 
			
		||||
	public static final Identifier SEND_REVIVES_UPDATE = new Identifier(HardcoreRedeploy.MOD_ID, "send_revives_update");
 | 
			
		||||
	public static final Identifier REQUEST_REVIVE = new Identifier(HardcoreRedeploy.MOD_ID, "request_revive");
 | 
			
		||||
	public static final Identifier SEND_REVIVE = new Identifier(HardcoreRedeploy.MOD_ID, "send_revive");
 | 
			
		||||
	public static final Identifier SYNC_CONFIG = new Identifier(HardcoreRedeploy.MOD_ID, "sync_config");
 | 
			
		||||
 | 
			
		||||
	private static final ItemStack firework;
 | 
			
		||||
	static {
 | 
			
		||||
		firework = new ItemStack(Registries.ITEM.get(new Identifier("minecraft", "firework_rocket")));
 | 
			
		||||
		NbtCompound nbt = new NbtCompound();
 | 
			
		||||
		nbt.putByte("Flight", (byte)3);
 | 
			
		||||
		firework.setSubNbt("Fireworks", nbt);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public void onInitialize() {
 | 
			
		||||
		LOGGER.info("Initializing Hardcore Redeploy");
 | 
			
		||||
 | 
			
		||||
		GeckoLib.initialize();
 | 
			
		||||
 | 
			
		||||
		ServerPlayNetworking.registerGlobalReceiver(REQUEST_REVIVE, (server, player, handler, buf, responseSender) -> {
 | 
			
		||||
			ServerPlayerEntity spectator = server.getPlayerManager().getPlayer(buf.readUuid());
 | 
			
		||||
			if (spectator == null) return;
 | 
			
		||||
 | 
			
		||||
			BlockPos blockPos = buf.readBlockPos();
 | 
			
		||||
			BlockState invokingBlock = player.getWorld().getBlockState(blockPos);
 | 
			
		||||
 | 
			
		||||
			if (invokingBlock.getBlock() instanceof BuyStation && player.getPos().isInRange(blockPos.toCenterPos(), 5)) {
 | 
			
		||||
 | 
			
		||||
				int cost = config.baseCost+config.additiveCost*RedeployStateSaver.getPlayerState(spectator).timesRevived;
 | 
			
		||||
				boolean isCreative = player.interactionManager.getGameMode() == GameMode.CREATIVE;
 | 
			
		||||
				if (!isCreative && player.experienceLevel < cost) return;
 | 
			
		||||
 | 
			
		||||
				Vec3d fireworkPos = blockPos.toCenterPos();
 | 
			
		||||
				BlockState blockState = player.getWorld().getBlockState(blockPos);
 | 
			
		||||
				Direction offset = blockState.get(HorizontalFacingBlock.FACING).rotateYClockwise();
 | 
			
		||||
				if (blockState.get(BUY_STATION_PART) == BuyStation.BuyStationPart.AUX) offset = offset.getOpposite();
 | 
			
		||||
				FireworkRocketEntity fireworkRocketEntity = new FireworkRocketEntity(player.getWorld(), fireworkPos.x+offset.getOffsetX()/2., fireworkPos.y, fireworkPos.z+offset.getOffsetZ()/2., firework);
 | 
			
		||||
				player.getWorld().spawnEntity(fireworkRocketEntity);
 | 
			
		||||
 | 
			
		||||
				if (!isCreative) player.setExperienceLevel(player.experienceLevel-cost);
 | 
			
		||||
				((TimerAccess) server).hardcoreredeploy_redeployInTicks(spectator, player, 60L);
 | 
			
		||||
				server.execute(() -> {
 | 
			
		||||
					PacketByteBuf buf1 = PacketByteBufs.create();
 | 
			
		||||
					ServerPlayNetworking.send(spectator, SEND_REVIVE, buf1);
 | 
			
		||||
				});
 | 
			
		||||
			}
 | 
			
		||||
		});
 | 
			
		||||
 | 
			
		||||
		ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> {
 | 
			
		||||
			syncConfig(server, handler.getPlayer());
 | 
			
		||||
 | 
			
		||||
			RedeployStateSaver.getServerState(server).players.forEach((uuid, playerData) -> {
 | 
			
		||||
				syncRevives(server, handler.getPlayer(), uuid);
 | 
			
		||||
			});
 | 
			
		||||
		});
 | 
			
		||||
 | 
			
		||||
		BUY_STATION_ENTITY = Registry.register(Registries.BLOCK_ENTITY_TYPE,
 | 
			
		||||
				new Identifier(HardcoreRedeploy.MOD_ID, "buy_station_entity"),
 | 
			
		||||
				FabricBlockEntityTypeBuilder.create(BuyStationEntity::new,
 | 
			
		||||
						HardcoreRedeploy.BUY_STATION).build());
 | 
			
		||||
		Registry.register(Registries.STATUS_EFFECT, new Identifier(HardcoreRedeploy.MOD_ID, "redeploying"), REDEPLOYING);
 | 
			
		||||
		CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> RedeployPlayerCommand.register(dispatcher));
 | 
			
		||||
		Registry.register(Registries.SOUND_EVENT, BUY_STATION_SOUND_ID, BUY_STATION_SOUND_EVENT);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public static void syncConfig(MinecraftServer server, ServerPlayerEntity receiver) {
 | 
			
		||||
		PacketByteBuf buf = PacketByteBufs.create();
 | 
			
		||||
		buf.writeInt(HardcoreRedeployConfigHandler.config.baseCost);
 | 
			
		||||
		buf.writeInt(HardcoreRedeployConfigHandler.config.additiveCost);
 | 
			
		||||
		server.execute(() -> {
 | 
			
		||||
			ServerPlayNetworking.send(receiver, SYNC_CONFIG, buf);
 | 
			
		||||
		});
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public static void syncRevives(MinecraftServer server, ServerPlayerEntity receiver, UUID uuid) {
 | 
			
		||||
		PlayerData playerData = RedeployStateSaver.getPlayerState(server, uuid);
 | 
			
		||||
		PacketByteBuf buf = PacketByteBufs.create();
 | 
			
		||||
		buf.writeUuid(uuid);
 | 
			
		||||
		buf.writeInt(playerData.timesRevived);
 | 
			
		||||
		server.execute(() -> {
 | 
			
		||||
			ServerPlayNetworking.send(receiver, SEND_REVIVES_UPDATE, buf);
 | 
			
		||||
		});
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@ -1,12 +1,45 @@
 | 
			
		||||
package net.touhoudiscord;
 | 
			
		||||
 | 
			
		||||
import net.fabricmc.api.ClientModInitializer;
 | 
			
		||||
import net.fabricmc.api.EnvType;
 | 
			
		||||
import net.fabricmc.api.Environment;
 | 
			
		||||
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
 | 
			
		||||
import net.minecraft.client.render.block.entity.BlockEntityRendererFactories;
 | 
			
		||||
import net.touhoudiscord.HardcoreRedeployConfigHandler.HardcoreRedeployConfig;
 | 
			
		||||
import net.touhoudiscord.block.client.BuyStationRenderer;
 | 
			
		||||
import net.touhoudiscord.screen.RedeployingScreen;
 | 
			
		||||
 | 
			
		||||
import java.util.HashMap;
 | 
			
		||||
import java.util.UUID;
 | 
			
		||||
 | 
			
		||||
@Environment(EnvType.CLIENT)
 | 
			
		||||
public class HardcoreRedeployClient implements ClientModInitializer {
 | 
			
		||||
 | 
			
		||||
	public static HashMap<UUID, Integer> reviveMap = new HashMap<>();
 | 
			
		||||
	public static HardcoreRedeployConfig serverConfig = HardcoreRedeployConfigHandler.config;
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public void onInitializeClient() {
 | 
			
		||||
		BlockEntityRendererFactories.register(HardcoreRedeploy.BUY_STATION_ENTITY, BuyStationRenderer::new);
 | 
			
		||||
 | 
			
		||||
		ClientPlayNetworking.registerGlobalReceiver(HardcoreRedeploy.SEND_REVIVES_UPDATE, (client, handler, buf, responseSender) -> {
 | 
			
		||||
			reviveMap.put(buf.readUuid(), buf.readInt());
 | 
			
		||||
 | 
			
		||||
			HardcoreRedeploy.LOGGER.info("Synced player revives");
 | 
			
		||||
		});
 | 
			
		||||
 | 
			
		||||
		ClientPlayNetworking.registerGlobalReceiver(HardcoreRedeploy.SEND_REVIVE, (client, handler, buf, responseSender) -> {
 | 
			
		||||
			client.execute(() -> {
 | 
			
		||||
				client.setScreen(new RedeployingScreen(6*20));
 | 
			
		||||
			});
 | 
			
		||||
		});
 | 
			
		||||
 | 
			
		||||
		ClientPlayNetworking.registerGlobalReceiver(HardcoreRedeploy.SYNC_CONFIG, (client, handler, buf, responseSender) -> {
 | 
			
		||||
			serverConfig = new HardcoreRedeployConfig();
 | 
			
		||||
			serverConfig.baseCost = buf.readInt();
 | 
			
		||||
			serverConfig.additiveCost = buf.readInt();
 | 
			
		||||
 | 
			
		||||
			HardcoreRedeploy.LOGGER.info("Synced server config");
 | 
			
		||||
		});
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,39 @@
 | 
			
		||||
package net.touhoudiscord;
 | 
			
		||||
 | 
			
		||||
import com.google.gson.Gson;
 | 
			
		||||
import net.fabricmc.loader.api.FabricLoader;
 | 
			
		||||
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.nio.file.Files;
 | 
			
		||||
import java.nio.file.Path;
 | 
			
		||||
import java.nio.file.StandardOpenOption;
 | 
			
		||||
 | 
			
		||||
public class HardcoreRedeployConfigHandler {
 | 
			
		||||
    private static final Path configPath = FabricLoader.getInstance().getConfigDir().resolve("hardcore_redeploy.json");
 | 
			
		||||
    private static final Gson gson = new Gson();
 | 
			
		||||
    public static HardcoreRedeployConfig config = readOrCreateConfig();
 | 
			
		||||
 | 
			
		||||
    public HardcoreRedeployConfigHandler() {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static HardcoreRedeployConfig readOrCreateConfig() {
 | 
			
		||||
        try {
 | 
			
		||||
            return gson.fromJson(Files.readString(configPath), HardcoreRedeployConfig.class);
 | 
			
		||||
        }
 | 
			
		||||
        catch(IOException e) {
 | 
			
		||||
            HardcoreRedeployConfig newConfig = new HardcoreRedeployConfig();
 | 
			
		||||
            try {
 | 
			
		||||
                Files.writeString(configPath, gson.toJson(newConfig), StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.CREATE);
 | 
			
		||||
            } catch (IOException ex) {
 | 
			
		||||
                throw new RuntimeException(ex);
 | 
			
		||||
            }
 | 
			
		||||
            return newConfig;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static class HardcoreRedeployConfig {
 | 
			
		||||
        public int baseCost = 10;
 | 
			
		||||
        public int additiveCost = 10;
 | 
			
		||||
        HardcoreRedeployConfig(){}
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										5
									
								
								src/main/java/net/touhoudiscord/PlayerData.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								src/main/java/net/touhoudiscord/PlayerData.java
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,5 @@
 | 
			
		||||
package net.touhoudiscord;
 | 
			
		||||
 | 
			
		||||
public class PlayerData {
 | 
			
		||||
    public int timesRevived = 0;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										13
									
								
								src/main/java/net/touhoudiscord/PlayerTimer.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								src/main/java/net/touhoudiscord/PlayerTimer.java
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,13 @@
 | 
			
		||||
package net.touhoudiscord;
 | 
			
		||||
 | 
			
		||||
import java.util.UUID;
 | 
			
		||||
 | 
			
		||||
public class PlayerTimer {
 | 
			
		||||
    public UUID target;
 | 
			
		||||
    public Long ticks;
 | 
			
		||||
 | 
			
		||||
    public PlayerTimer(UUID target, Long ticks) {
 | 
			
		||||
        this.target = target;
 | 
			
		||||
        this.ticks = ticks;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -6,8 +6,15 @@ import net.minecraft.world.GameMode;
 | 
			
		||||
 | 
			
		||||
public class RedeployPlayer {
 | 
			
		||||
    public static void redeploy(ServerPlayerEntity spectator, ServerPlayerEntity target) {
 | 
			
		||||
        if (!(spectator.interactionManager.getGameMode() == GameMode.SPECTATOR)) return;
 | 
			
		||||
 | 
			
		||||
        if (!target.getServerWorld().getDimension().hasCeiling()) spectator.addStatusEffect(new StatusEffectInstance(HardcoreRedeploy.REDEPLOYING, 20*20, 0));
 | 
			
		||||
        spectator.teleport(target.getServerWorld(), target.getPos().x, target.getServerWorld().getDimension().hasCeiling() ? target.getPos().y : 320, target.getPos().z, 0, 30);
 | 
			
		||||
        spectator.changeGameMode(GameMode.SURVIVAL);
 | 
			
		||||
 | 
			
		||||
        RedeployStateSaver.getPlayerState(spectator).timesRevived++;
 | 
			
		||||
        spectator.server.getPlayerManager().getPlayerList().forEach(player -> {
 | 
			
		||||
            HardcoreRedeploy.syncRevives(player.server, player, spectator.getUuid());
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										74
									
								
								src/main/java/net/touhoudiscord/RedeployStateSaver.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								src/main/java/net/touhoudiscord/RedeployStateSaver.java
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,74 @@
 | 
			
		||||
package net.touhoudiscord;
 | 
			
		||||
 | 
			
		||||
import net.minecraft.entity.LivingEntity;
 | 
			
		||||
import net.minecraft.nbt.NbtCompound;
 | 
			
		||||
import net.minecraft.server.MinecraftServer;
 | 
			
		||||
import net.minecraft.world.PersistentState;
 | 
			
		||||
import net.minecraft.world.PersistentStateManager;
 | 
			
		||||
import net.minecraft.world.World;
 | 
			
		||||
 | 
			
		||||
import java.util.HashMap;
 | 
			
		||||
import java.util.UUID;
 | 
			
		||||
 | 
			
		||||
public class RedeployStateSaver extends PersistentState {
 | 
			
		||||
 | 
			
		||||
    public HashMap<UUID, PlayerData> players = new HashMap<>();
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public NbtCompound writeNbt(NbtCompound nbt) {
 | 
			
		||||
 | 
			
		||||
        NbtCompound playersNbt = new NbtCompound();
 | 
			
		||||
        players.forEach((uuid, playerData) -> {
 | 
			
		||||
            NbtCompound playerNbt = new NbtCompound();
 | 
			
		||||
 | 
			
		||||
            playerNbt.putInt("timesRevived", playerData.timesRevived);
 | 
			
		||||
 | 
			
		||||
            playersNbt.put(uuid.toString(), playerNbt);
 | 
			
		||||
        });
 | 
			
		||||
        nbt.put("players", playersNbt);
 | 
			
		||||
 | 
			
		||||
        return nbt;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static RedeployStateSaver createFromNbt(NbtCompound tag) {
 | 
			
		||||
        RedeployStateSaver state = new RedeployStateSaver();
 | 
			
		||||
 | 
			
		||||
        NbtCompound playersNbt = tag.getCompound("players");
 | 
			
		||||
        playersNbt.getKeys().forEach(key -> {
 | 
			
		||||
            PlayerData playerData = new PlayerData();
 | 
			
		||||
 | 
			
		||||
            playerData.timesRevived = playersNbt.getCompound(key).getInt("timesRevived");
 | 
			
		||||
 | 
			
		||||
            UUID uuid = UUID.fromString(key);
 | 
			
		||||
            state.players.put(uuid, playerData);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        return state;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static RedeployStateSaver getServerState(MinecraftServer server) {
 | 
			
		||||
        PersistentStateManager persistentStateManager = server.getWorld(World.OVERWORLD).getPersistentStateManager();
 | 
			
		||||
 | 
			
		||||
        RedeployStateSaver state = persistentStateManager.getOrCreate(RedeployStateSaver::createFromNbt, RedeployStateSaver::new, HardcoreRedeploy.MOD_ID);
 | 
			
		||||
 | 
			
		||||
        state.markDirty();
 | 
			
		||||
 | 
			
		||||
        return state;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static PlayerData getPlayerState(LivingEntity player) {
 | 
			
		||||
        RedeployStateSaver serverState = getServerState(player.getWorld().getServer());
 | 
			
		||||
 | 
			
		||||
        PlayerData playerState = serverState.players.computeIfAbsent(player.getUuid(), uuid -> new PlayerData());
 | 
			
		||||
 | 
			
		||||
        return playerState;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static PlayerData getPlayerState(MinecraftServer server, UUID uuid) {
 | 
			
		||||
        RedeployStateSaver serverState = getServerState(server);
 | 
			
		||||
 | 
			
		||||
        PlayerData playerState = serverState.players.computeIfAbsent(uuid, i -> new PlayerData());
 | 
			
		||||
 | 
			
		||||
        return playerState;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										7
									
								
								src/main/java/net/touhoudiscord/TimerAccess.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								src/main/java/net/touhoudiscord/TimerAccess.java
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,7 @@
 | 
			
		||||
package net.touhoudiscord;
 | 
			
		||||
 | 
			
		||||
import net.minecraft.server.network.ServerPlayerEntity;
 | 
			
		||||
 | 
			
		||||
public interface TimerAccess {
 | 
			
		||||
    void hardcoreredeploy_redeployInTicks(ServerPlayerEntity spectator, ServerPlayerEntity target, Long ticks);
 | 
			
		||||
}
 | 
			
		||||
@ -1,31 +1,144 @@
 | 
			
		||||
package net.touhoudiscord.block;
 | 
			
		||||
 | 
			
		||||
import net.minecraft.block.BlockRenderType;
 | 
			
		||||
import net.minecraft.block.BlockState;
 | 
			
		||||
import net.minecraft.block.BlockWithEntity;
 | 
			
		||||
import net.minecraft.block.*;
 | 
			
		||||
import net.minecraft.block.entity.BlockEntity;
 | 
			
		||||
import net.minecraft.entity.LivingEntity;
 | 
			
		||||
import net.minecraft.entity.player.PlayerEntity;
 | 
			
		||||
import net.minecraft.item.ItemPlacementContext;
 | 
			
		||||
import net.minecraft.item.ItemStack;
 | 
			
		||||
import net.minecraft.state.StateManager;
 | 
			
		||||
import net.minecraft.state.property.EnumProperty;
 | 
			
		||||
import net.minecraft.util.ActionResult;
 | 
			
		||||
import net.minecraft.util.Hand;
 | 
			
		||||
import net.minecraft.util.StringIdentifiable;
 | 
			
		||||
import net.minecraft.util.hit.BlockHitResult;
 | 
			
		||||
import net.minecraft.util.math.BlockPos;
 | 
			
		||||
import net.minecraft.util.math.Direction;
 | 
			
		||||
import net.minecraft.util.shape.VoxelShape;
 | 
			
		||||
import net.minecraft.world.BlockView;
 | 
			
		||||
import net.minecraft.world.World;
 | 
			
		||||
import net.minecraft.world.WorldEvents;
 | 
			
		||||
import net.minecraft.world.WorldView;
 | 
			
		||||
import net.touhoudiscord.BuyStationCapable;
 | 
			
		||||
import org.jetbrains.annotations.Nullable;
 | 
			
		||||
 | 
			
		||||
public class BuyStation extends BlockWithEntity {
 | 
			
		||||
    public static final EnumProperty<BuyStationPart> BUY_STATION_PART = EnumProperty.of("part", BuyStationPart.class);
 | 
			
		||||
 | 
			
		||||
    protected static final VoxelShape NORTH_SHAPE = Block.createCuboidShape(1.0, 0.0, 1.0, 16.0, 12.0, 15.0);
 | 
			
		||||
    protected static final VoxelShape SOUTH_SHAPE = Block.createCuboidShape(0.0, 0.0, 1.0, 15.0, 12.0, 15.0);
 | 
			
		||||
    protected static final VoxelShape WEST_SHAPE = Block.createCuboidShape(1.0, 0.0, 0.0, 15.0, 12.0, 15.0);
 | 
			
		||||
    protected static final VoxelShape EAST_SHAPE = Block.createCuboidShape(1.0, 0.0, 1.0, 15.0, 12.0, 16.0);
 | 
			
		||||
 | 
			
		||||
    public BuyStation(Settings settings) {
 | 
			
		||||
        super(settings);
 | 
			
		||||
        this.setDefaultState(this.getDefaultState()
 | 
			
		||||
                .with(HorizontalFacingBlock.FACING, Direction.NORTH)
 | 
			
		||||
                .with(BUY_STATION_PART, BuyStationPart.MAIN));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Nullable
 | 
			
		||||
    @Override
 | 
			
		||||
    public BlockState getPlacementState(ItemPlacementContext ctx) {
 | 
			
		||||
        return this.getDefaultState().with(HorizontalFacingBlock.FACING, ctx.getHorizontalPlayerFacing());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onPlaced(World world, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack itemStack) {
 | 
			
		||||
        super.onPlaced(world, pos, state, placer, itemStack);
 | 
			
		||||
        if (!world.isClient) {
 | 
			
		||||
            BlockPos blockPos = pos.offset(state.get(HorizontalFacingBlock.FACING).rotateYClockwise());
 | 
			
		||||
            world.setBlockState(blockPos, state.with(BUY_STATION_PART, BuyStationPart.AUX), Block.NOTIFY_ALL);
 | 
			
		||||
            world.updateNeighbors(pos, Blocks.AIR);
 | 
			
		||||
            state.updateNeighbors(world, pos, Block.NOTIFY_ALL);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onBreak(World world, BlockPos pos, BlockState state, PlayerEntity player) {
 | 
			
		||||
        if (world.isClient()) {
 | 
			
		||||
            super.onBreak(world, pos, state, player);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        BuyStationPart part = state.get(BUY_STATION_PART);
 | 
			
		||||
        if (part == BuyStationPart.MAIN) {
 | 
			
		||||
            BlockPos otherpos = pos.offset(state.get(HorizontalFacingBlock.FACING).rotateYClockwise());
 | 
			
		||||
            BlockState otherstate = world.getBlockState(otherpos);
 | 
			
		||||
            if (otherstate.getBlock() == this) {
 | 
			
		||||
                world.setBlockState(otherpos, Blocks.AIR.getDefaultState(), Block.NOTIFY_ALL);
 | 
			
		||||
                world.syncWorldEvent(player, WorldEvents.BLOCK_BROKEN, otherpos, Block.getRawIdFromState(otherstate));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        else if (part == BuyStationPart.AUX) {
 | 
			
		||||
            BlockPos otherpos = pos.offset(state.get(HorizontalFacingBlock.FACING).rotateYCounterclockwise());
 | 
			
		||||
            BlockState otherstate = world.getBlockState(otherpos);
 | 
			
		||||
            if (otherstate.getBlock() == this) {
 | 
			
		||||
                world.setBlockState(otherpos, Blocks.AIR.getDefaultState(), Block.NOTIFY_ALL);
 | 
			
		||||
                world.syncWorldEvent(player, WorldEvents.BLOCK_BROKEN, otherpos, Block.getRawIdFromState(otherstate));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
 | 
			
		||||
        Direction direction = state.get(HorizontalFacingBlock.FACING);
 | 
			
		||||
        BuyStationPart part = state.get(BUY_STATION_PART);
 | 
			
		||||
        if (part == BuyStationPart.AUX) direction = direction.getOpposite();
 | 
			
		||||
        return switch (direction) {
 | 
			
		||||
            default -> NORTH_SHAPE;
 | 
			
		||||
            case SOUTH -> SOUTH_SHAPE;
 | 
			
		||||
            case WEST -> WEST_SHAPE;
 | 
			
		||||
            case EAST -> EAST_SHAPE;
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) {
 | 
			
		||||
        Block block = world.getBlockState(pos).getBlock();
 | 
			
		||||
        if (block instanceof BuyStation) {
 | 
			
		||||
            ((BuyStationCapable) player).hardcoreredeploy_openBuyStationScreen(pos);
 | 
			
		||||
            return ActionResult.success(world.isClient);
 | 
			
		||||
        } else {
 | 
			
		||||
            return ActionResult.PASS;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
 | 
			
		||||
        builder.add(HorizontalFacingBlock.FACING, BUY_STATION_PART);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Nullable
 | 
			
		||||
    @Override
 | 
			
		||||
    public BlockEntity createBlockEntity(BlockPos pos, BlockState state) {
 | 
			
		||||
        return new BuyStationEntity(pos, state);
 | 
			
		||||
        return state.get(BUY_STATION_PART) == BuyStationPart.MAIN ? new BuyStationEntity(pos, state) : null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public BlockRenderType getRenderType(BlockState state) {
 | 
			
		||||
        return BlockRenderType.MODEL;
 | 
			
		||||
        return state.get(BUY_STATION_PART) == BuyStationPart.MAIN ? BlockRenderType.MODEL : BlockRenderType.INVISIBLE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public boolean canPlaceAt(BlockState state, WorldView world, BlockPos pos) {
 | 
			
		||||
        return super.canPlaceAt(state, world, pos);
 | 
			
		||||
        return world.getBlockState(pos.offset(state.get(HorizontalFacingBlock.FACING).rotateYClockwise())).isReplaceable() && super.canPlaceAt(state, world, pos);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public enum BuyStationPart implements StringIdentifiable {
 | 
			
		||||
        MAIN("main"),
 | 
			
		||||
        AUX("aux");
 | 
			
		||||
 | 
			
		||||
        private final String name;
 | 
			
		||||
 | 
			
		||||
        BuyStationPart(String name) {
 | 
			
		||||
            this.name = name;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public String toString() {
 | 
			
		||||
            return this.name;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public String asString() {
 | 
			
		||||
            return this.name;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -3,17 +3,21 @@ package net.touhoudiscord.block;
 | 
			
		||||
import net.minecraft.block.BlockState;
 | 
			
		||||
import net.minecraft.block.entity.BlockEntity;
 | 
			
		||||
import net.minecraft.entity.player.PlayerEntity;
 | 
			
		||||
import net.minecraft.sound.SoundCategory;
 | 
			
		||||
import net.minecraft.util.math.BlockPos;
 | 
			
		||||
import net.minecraft.util.math.Vec3d;
 | 
			
		||||
import net.touhoudiscord.HardcoreRedeploy;
 | 
			
		||||
import software.bernie.geckolib.animatable.GeoBlockEntity;
 | 
			
		||||
import software.bernie.geckolib.core.animatable.instance.AnimatableInstanceCache;
 | 
			
		||||
import software.bernie.geckolib.core.animatable.instance.SingletonAnimatableInstanceCache;
 | 
			
		||||
import software.bernie.geckolib.core.animation.*;
 | 
			
		||||
import software.bernie.geckolib.core.animation.AnimatableManager;
 | 
			
		||||
import software.bernie.geckolib.core.animation.AnimationController;
 | 
			
		||||
import software.bernie.geckolib.core.animation.RawAnimation;
 | 
			
		||||
import software.bernie.geckolib.util.ClientUtils;
 | 
			
		||||
import software.bernie.geckolib.util.RenderUtils;
 | 
			
		||||
 | 
			
		||||
public class BuyStationEntity extends BlockEntity implements GeoBlockEntity {
 | 
			
		||||
    private AnimatableInstanceCache cache = new SingletonAnimatableInstanceCache(this);
 | 
			
		||||
    private final AnimatableInstanceCache cache = new SingletonAnimatableInstanceCache(this);
 | 
			
		||||
 | 
			
		||||
    private static final RawAnimation OPEN = RawAnimation.begin().thenPlay("animation.model.open").thenLoop("animation.model.idle");
 | 
			
		||||
    private static final RawAnimation CLOSE = RawAnimation.begin().thenPlay("animation.model.close");
 | 
			
		||||
@ -26,11 +30,20 @@ public class BuyStationEntity extends BlockEntity implements GeoBlockEntity {
 | 
			
		||||
    public void registerControllers(AnimatableManager.ControllerRegistrar controllers) {
 | 
			
		||||
        controllers.add(new AnimationController<>(this, "buystationcontroller", 0, state -> {
 | 
			
		||||
            Vec3d pos = state.getAnimatable().getPos().toCenterPos();
 | 
			
		||||
            if (state.getAnimatable().getWorld().getClosestPlayer(pos.x, pos.y, pos.z, 5, false) instanceof PlayerEntity)
 | 
			
		||||
            if (state.getAnimatable().getWorld().getClosestPlayer(pos.x, pos.y, pos.z, 5, false) instanceof PlayerEntity) {
 | 
			
		||||
                return state.setAndContinue(OPEN);
 | 
			
		||||
            else
 | 
			
		||||
            }
 | 
			
		||||
            else {
 | 
			
		||||
                return state.setAndContinue(CLOSE);
 | 
			
		||||
        }));
 | 
			
		||||
            }
 | 
			
		||||
        })
 | 
			
		||||
                .setSoundKeyframeHandler(event -> {
 | 
			
		||||
                    PlayerEntity player = ClientUtils.getClientPlayer();
 | 
			
		||||
 | 
			
		||||
                    if (player != null) {
 | 
			
		||||
                        player.getWorld().playSound(player, this.getPos(), HardcoreRedeploy.BUY_STATION_SOUND_EVENT, SoundCategory.BLOCKS, 1, 1);
 | 
			
		||||
                    }
 | 
			
		||||
                }));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
 | 
			
		||||
@ -1,10 +1,13 @@
 | 
			
		||||
package net.touhoudiscord.block.client;
 | 
			
		||||
 | 
			
		||||
import net.fabricmc.api.EnvType;
 | 
			
		||||
import net.fabricmc.api.Environment;
 | 
			
		||||
import net.minecraft.util.Identifier;
 | 
			
		||||
import net.touhoudiscord.HardcoreRedeploy;
 | 
			
		||||
import net.touhoudiscord.block.BuyStationEntity;
 | 
			
		||||
import software.bernie.geckolib.model.GeoModel;
 | 
			
		||||
 | 
			
		||||
@Environment(EnvType.CLIENT)
 | 
			
		||||
public class BuyStationModel extends GeoModel<BuyStationEntity> {
 | 
			
		||||
    @Override
 | 
			
		||||
    public Identifier getModelResource(BuyStationEntity animatable) {
 | 
			
		||||
 | 
			
		||||
@ -1,11 +1,27 @@
 | 
			
		||||
package net.touhoudiscord.block.client;
 | 
			
		||||
 | 
			
		||||
import net.fabricmc.api.EnvType;
 | 
			
		||||
import net.fabricmc.api.Environment;
 | 
			
		||||
import net.minecraft.block.HorizontalFacingBlock;
 | 
			
		||||
import net.minecraft.client.render.VertexConsumer;
 | 
			
		||||
import net.minecraft.client.render.VertexConsumerProvider;
 | 
			
		||||
import net.minecraft.client.render.block.entity.BlockEntityRendererFactory;
 | 
			
		||||
import net.minecraft.client.util.math.MatrixStack;
 | 
			
		||||
import net.minecraft.util.math.Direction;
 | 
			
		||||
import net.touhoudiscord.block.BuyStationEntity;
 | 
			
		||||
import software.bernie.geckolib.cache.object.BakedGeoModel;
 | 
			
		||||
import software.bernie.geckolib.renderer.GeoBlockRenderer;
 | 
			
		||||
 | 
			
		||||
@Environment(EnvType.CLIENT)
 | 
			
		||||
public class BuyStationRenderer extends GeoBlockRenderer<BuyStationEntity> {
 | 
			
		||||
    public BuyStationRenderer(BlockEntityRendererFactory.Context context) {
 | 
			
		||||
        super(new BuyStationModel());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void preRender(MatrixStack poseStack, BuyStationEntity animatable, BakedGeoModel model, VertexConsumerProvider bufferSource, VertexConsumer buffer, boolean isReRender, float partialTick, int packedLight, int packedOverlay, float red, float green, float blue, float alpha) {
 | 
			
		||||
        Direction direction = animatable.getCachedState().get(HorizontalFacingBlock.FACING).rotateYClockwise();
 | 
			
		||||
        poseStack.translate(direction.getOffsetX()/2., 0, direction.getOffsetZ()/2.);
 | 
			
		||||
        super.preRender(poseStack, animatable, model, bufferSource, buffer, isReRender, partialTick, packedLight, packedOverlay, red, green, blue, alpha);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -8,10 +8,10 @@ import net.minecraft.server.command.ServerCommandSource;
 | 
			
		||||
import net.minecraft.server.network.ServerPlayerEntity;
 | 
			
		||||
import net.minecraft.text.Text;
 | 
			
		||||
import net.minecraft.world.GameMode;
 | 
			
		||||
import net.touhoudiscord.HardcoreRedeploy;
 | 
			
		||||
import net.touhoudiscord.RedeployPlayer;
 | 
			
		||||
 | 
			
		||||
import static net.minecraft.server.command.CommandManager.*;
 | 
			
		||||
import static net.minecraft.server.command.CommandManager.argument;
 | 
			
		||||
import static net.minecraft.server.command.CommandManager.literal;
 | 
			
		||||
 | 
			
		||||
public class RedeployPlayerCommand {
 | 
			
		||||
 | 
			
		||||
@ -36,7 +36,5 @@ public class RedeployPlayerCommand {
 | 
			
		||||
 | 
			
		||||
            return 1;
 | 
			
		||||
        })));
 | 
			
		||||
 | 
			
		||||
        HardcoreRedeploy.LOGGER.info("Registered RedeployPlayer command");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -9,7 +9,8 @@ import software.bernie.geckolib.animatable.SingletonGeoAnimatable;
 | 
			
		||||
import software.bernie.geckolib.animatable.client.RenderProvider;
 | 
			
		||||
import software.bernie.geckolib.core.animatable.instance.AnimatableInstanceCache;
 | 
			
		||||
import software.bernie.geckolib.core.animatable.instance.SingletonAnimatableInstanceCache;
 | 
			
		||||
import software.bernie.geckolib.core.animation.*;
 | 
			
		||||
import software.bernie.geckolib.core.animation.AnimatableManager;
 | 
			
		||||
import software.bernie.geckolib.core.animation.AnimationController;
 | 
			
		||||
import software.bernie.geckolib.core.object.PlayState;
 | 
			
		||||
import software.bernie.geckolib.util.RenderUtils;
 | 
			
		||||
 | 
			
		||||
@ -17,7 +18,7 @@ import java.util.function.Consumer;
 | 
			
		||||
import java.util.function.Supplier;
 | 
			
		||||
 | 
			
		||||
public class BuyStationItem extends BlockItem implements GeoItem {
 | 
			
		||||
    private AnimatableInstanceCache cache = new SingletonAnimatableInstanceCache(this);
 | 
			
		||||
    private final AnimatableInstanceCache cache = new SingletonAnimatableInstanceCache(this);
 | 
			
		||||
    private final Supplier<Object> renderProvider = GeoItem.makeRenderer(this);
 | 
			
		||||
 | 
			
		||||
    public BuyStationItem(Block block, Settings settings) {
 | 
			
		||||
 | 
			
		||||
@ -1,10 +1,13 @@
 | 
			
		||||
package net.touhoudiscord.item.client;
 | 
			
		||||
 | 
			
		||||
import net.fabricmc.api.EnvType;
 | 
			
		||||
import net.fabricmc.api.Environment;
 | 
			
		||||
import net.minecraft.util.Identifier;
 | 
			
		||||
import net.touhoudiscord.HardcoreRedeploy;
 | 
			
		||||
import net.touhoudiscord.item.BuyStationItem;
 | 
			
		||||
import software.bernie.geckolib.model.GeoModel;
 | 
			
		||||
 | 
			
		||||
@Environment(EnvType.CLIENT)
 | 
			
		||||
public class BuyStationItemModel extends GeoModel<BuyStationItem> {
 | 
			
		||||
    @Override
 | 
			
		||||
    public Identifier getModelResource(BuyStationItem animatable) {
 | 
			
		||||
 | 
			
		||||
@ -1,8 +1,11 @@
 | 
			
		||||
package net.touhoudiscord.item.client;
 | 
			
		||||
 | 
			
		||||
import net.fabricmc.api.EnvType;
 | 
			
		||||
import net.fabricmc.api.Environment;
 | 
			
		||||
import net.touhoudiscord.item.BuyStationItem;
 | 
			
		||||
import software.bernie.geckolib.renderer.GeoItemRenderer;
 | 
			
		||||
 | 
			
		||||
@Environment(EnvType.CLIENT)
 | 
			
		||||
public class BuyStationItemRenderer extends GeoItemRenderer<BuyStationItem> {
 | 
			
		||||
    public BuyStationItemRenderer() {
 | 
			
		||||
        super(new BuyStationItemModel());
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,13 @@
 | 
			
		||||
package net.touhoudiscord.mixin;
 | 
			
		||||
 | 
			
		||||
import net.minecraft.entity.player.PlayerEntity;
 | 
			
		||||
import net.minecraft.util.math.BlockPos;
 | 
			
		||||
import net.touhoudiscord.BuyStationCapable;
 | 
			
		||||
import org.spongepowered.asm.mixin.Mixin;
 | 
			
		||||
 | 
			
		||||
@Mixin(PlayerEntity.class)
 | 
			
		||||
public class BuyStationScreenMixin implements BuyStationCapable {
 | 
			
		||||
    @Override
 | 
			
		||||
    public void hardcoreredeploy_openBuyStationScreen(BlockPos blockPos) {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,20 @@
 | 
			
		||||
package net.touhoudiscord.mixin;
 | 
			
		||||
 | 
			
		||||
import net.minecraft.client.MinecraftClient;
 | 
			
		||||
import net.minecraft.client.network.ClientPlayerEntity;
 | 
			
		||||
import net.minecraft.util.math.BlockPos;
 | 
			
		||||
import net.touhoudiscord.BuyStationCapable;
 | 
			
		||||
import net.touhoudiscord.screen.BuyStationScreen;
 | 
			
		||||
import org.spongepowered.asm.mixin.Final;
 | 
			
		||||
import org.spongepowered.asm.mixin.Mixin;
 | 
			
		||||
import org.spongepowered.asm.mixin.Shadow;
 | 
			
		||||
 | 
			
		||||
@Mixin(ClientPlayerEntity.class)
 | 
			
		||||
public class ClientBuyStationScreenMixin implements BuyStationCapable {
 | 
			
		||||
    @Shadow @Final protected MinecraftClient client;
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void hardcoreredeploy_openBuyStationScreen(BlockPos blockPos) {
 | 
			
		||||
        this.client.setScreen(new BuyStationScreen(blockPos));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,41 @@
 | 
			
		||||
package net.touhoudiscord.mixin;
 | 
			
		||||
 | 
			
		||||
import net.minecraft.server.MinecraftServer;
 | 
			
		||||
import net.minecraft.server.PlayerManager;
 | 
			
		||||
import net.minecraft.server.network.ServerPlayerEntity;
 | 
			
		||||
import net.touhoudiscord.PlayerTimer;
 | 
			
		||||
import net.touhoudiscord.RedeployPlayer;
 | 
			
		||||
import net.touhoudiscord.TimerAccess;
 | 
			
		||||
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;
 | 
			
		||||
 | 
			
		||||
import java.util.HashMap;
 | 
			
		||||
import java.util.UUID;
 | 
			
		||||
 | 
			
		||||
@Mixin(MinecraftServer.class)
 | 
			
		||||
public abstract class RedeployTimerMixin implements TimerAccess {
 | 
			
		||||
    @Shadow public abstract PlayerManager getPlayerManager();
 | 
			
		||||
 | 
			
		||||
    @Unique
 | 
			
		||||
    private final HashMap<UUID, PlayerTimer> playerTimers = new HashMap<>();
 | 
			
		||||
 | 
			
		||||
    @Inject(method = "tick", at = @At("TAIL"))
 | 
			
		||||
    private void onTick(CallbackInfo ci) {
 | 
			
		||||
        this.playerTimers.forEach((uuid, timer) -> {
 | 
			
		||||
            if (--timer.ticks == 0L) {
 | 
			
		||||
                ServerPlayerEntity spectator = this.getPlayerManager().getPlayer(uuid);
 | 
			
		||||
                ServerPlayerEntity target = this.getPlayerManager().getPlayer(timer.target);
 | 
			
		||||
                if (spectator != null && target != null) RedeployPlayer.redeploy(spectator, target);
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void hardcoreredeploy_redeployInTicks(ServerPlayerEntity spectator, ServerPlayerEntity target, Long ticks) {
 | 
			
		||||
        this.playerTimers.put(spectator.getUuid(), new PlayerTimer(target.getUuid(), ticks));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										125
									
								
								src/main/java/net/touhoudiscord/screen/BuyStationScreen.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										125
									
								
								src/main/java/net/touhoudiscord/screen/BuyStationScreen.java
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,125 @@
 | 
			
		||||
package net.touhoudiscord.screen;
 | 
			
		||||
 | 
			
		||||
import net.fabricmc.api.EnvType;
 | 
			
		||||
import net.fabricmc.api.Environment;
 | 
			
		||||
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
 | 
			
		||||
import net.fabricmc.fabric.api.networking.v1.PacketByteBufs;
 | 
			
		||||
import net.minecraft.client.MinecraftClient;
 | 
			
		||||
import net.minecraft.client.gui.DrawContext;
 | 
			
		||||
import net.minecraft.client.gui.Element;
 | 
			
		||||
import net.minecraft.client.gui.Selectable;
 | 
			
		||||
import net.minecraft.client.gui.screen.Screen;
 | 
			
		||||
import net.minecraft.client.gui.widget.ButtonWidget;
 | 
			
		||||
import net.minecraft.client.gui.widget.ElementListWidget;
 | 
			
		||||
import net.minecraft.network.PacketByteBuf;
 | 
			
		||||
import net.minecraft.text.Text;
 | 
			
		||||
import net.minecraft.util.math.BlockPos;
 | 
			
		||||
import net.minecraft.world.GameMode;
 | 
			
		||||
import net.touhoudiscord.HardcoreRedeploy;
 | 
			
		||||
import net.touhoudiscord.HardcoreRedeployClient;
 | 
			
		||||
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.UUID;
 | 
			
		||||
 | 
			
		||||
import static net.touhoudiscord.HardcoreRedeployClient.serverConfig;
 | 
			
		||||
 | 
			
		||||
@Environment(EnvType.CLIENT)
 | 
			
		||||
public class BuyStationScreen extends Screen {
 | 
			
		||||
    private final BlockPos blockPos;
 | 
			
		||||
 | 
			
		||||
    private PlayerListWidget playerList;
 | 
			
		||||
 | 
			
		||||
    public BuyStationScreen(BlockPos blockPos) {
 | 
			
		||||
        super(Text.literal("Buy Station"));
 | 
			
		||||
        this.blockPos = blockPos;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected void init() {
 | 
			
		||||
        super.init();
 | 
			
		||||
        playerList = new PlayerListWidget(client, width+38, height, height/2-58, height/2+84, 28);
 | 
			
		||||
        client.player.networkHandler.getListedPlayerListEntries().forEach(entry -> {
 | 
			
		||||
            if (entry.getGameMode() == GameMode.SPECTATOR) playerList.addPlayerEntry(new PlayerListEntry(Text.literal(entry.getProfile().getName()), entry.getProfile().getId()));
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        addDrawableChild(playerList);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void render(DrawContext context, int mouseX, int mouseY, float delta) {
 | 
			
		||||
        renderBackground(context);
 | 
			
		||||
        context.fill(width/2-93, height/2-84, width/2+93, height/2+84, 0x8F_000000);
 | 
			
		||||
        context.fill(width/2-93, height/2-84, width/2+93, height/2-58, 0xA0_000000);
 | 
			
		||||
        context.getMatrices().push();
 | 
			
		||||
        context.getMatrices().scale(1.5f, 1.5f, 1f);
 | 
			
		||||
        context.drawText(textRenderer, Text.literal("Buy Station"), Math.round((width/2-80)/1.5f), Math.round((height/2-75)/1.5f), 0xFF_73c0e7, false);
 | 
			
		||||
        context.getMatrices().pop();
 | 
			
		||||
        Text money = Text.literal("$").append(Text.literal(String.valueOf(client.player.experienceLevel*100)));
 | 
			
		||||
        context.drawText(textRenderer, money, width/2+80-textRenderer.getWidth(money), height/2-72, 0xFF_FFFFFF, false);
 | 
			
		||||
        playerList.render(context, mouseX, mouseY, delta);
 | 
			
		||||
        super.render(context, mouseX, mouseY, delta);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public boolean shouldPause() {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public class PlayerListWidget extends ElementListWidget<PlayerListEntry> {
 | 
			
		||||
        public PlayerListWidget(MinecraftClient minecraftClient, int i, int j, int k, int l, int m) {
 | 
			
		||||
            super(minecraftClient, i, j, k, l, m);
 | 
			
		||||
            this.setRenderBackground(false);
 | 
			
		||||
            this.setRenderHorizontalShadows(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void addPlayerEntry(PlayerListEntry entry) {
 | 
			
		||||
            this.addEntry(entry);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public class PlayerListEntry extends ElementListWidget.Entry<PlayerListEntry> {
 | 
			
		||||
        private final ButtonWidget button;
 | 
			
		||||
        private final Text name;
 | 
			
		||||
        private final UUID uuid;
 | 
			
		||||
 | 
			
		||||
        public PlayerListEntry(Text name, UUID uuid) {
 | 
			
		||||
            this.button = ButtonWidget.builder(name, button1 -> {
 | 
			
		||||
                        PacketByteBuf buf = PacketByteBufs.create();
 | 
			
		||||
                        buf.writeUuid(uuid);
 | 
			
		||||
                        buf.writeBlockPos(blockPos);
 | 
			
		||||
                        ClientPlayNetworking.send(HardcoreRedeploy.REQUEST_REVIVE, buf);
 | 
			
		||||
                        client.setScreen(null);
 | 
			
		||||
                    })
 | 
			
		||||
                    .position(4,2)
 | 
			
		||||
                    .size(178, 18)
 | 
			
		||||
                    .build();
 | 
			
		||||
            this.name = name;
 | 
			
		||||
            this.uuid = uuid;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        @Override
 | 
			
		||||
        public List<? extends Selectable> selectableChildren() {
 | 
			
		||||
            return List.of(button);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        @Override
 | 
			
		||||
        public List<? extends Element> children() {
 | 
			
		||||
            return List.of(button);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        @Override
 | 
			
		||||
        public void render(DrawContext context, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta) {
 | 
			
		||||
            button.setX(x);
 | 
			
		||||
            button.setY(y);
 | 
			
		||||
            boolean isHovered = mouseX >= x && mouseX <= x+178 && mouseY >= y && mouseY <= y+18;
 | 
			
		||||
            Integer revives = HardcoreRedeployClient.reviveMap.get(this.uuid);
 | 
			
		||||
            int cost = serverConfig.baseCost+(revives == null ? 0 : revives)*serverConfig.additiveCost;
 | 
			
		||||
            int backgroundColor = ((isHovered ? 0x30 : 0x20) << 24) +
 | 
			
		||||
                    ((client.player.experienceLevel >= cost) ? 0x2397d1 : 0xa3a3a3);
 | 
			
		||||
            context.fill(x, y, x+178, y+18, backgroundColor);
 | 
			
		||||
            context.drawText(textRenderer, button.getMessage(), x+4, y+5, 0xFF_73c0e7, false);
 | 
			
		||||
            Text money = Text.literal("$").append(Text.literal(String.valueOf(cost*100)));
 | 
			
		||||
            context.drawText(textRenderer, money, x+178-4-textRenderer.getWidth(money), y+5, 0xFF_7efc20, false);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,34 @@
 | 
			
		||||
package net.touhoudiscord.screen;
 | 
			
		||||
 | 
			
		||||
import net.minecraft.client.gui.DrawContext;
 | 
			
		||||
import net.minecraft.client.gui.screen.Screen;
 | 
			
		||||
import net.minecraft.text.Text;
 | 
			
		||||
 | 
			
		||||
public class RedeployingScreen extends Screen {
 | 
			
		||||
 | 
			
		||||
    private final float duration;
 | 
			
		||||
    private float time;
 | 
			
		||||
 | 
			
		||||
    public RedeployingScreen(float duration) {
 | 
			
		||||
        super(Text.empty());
 | 
			
		||||
        this.duration = duration;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void render(DrawContext context, int mouseX, int mouseY, float delta) {
 | 
			
		||||
        time += delta;
 | 
			
		||||
        context.fill(0, 0, width, height, Math.round((1-Math.abs((float)Math.sin(((time/(duration/2))-1)*(Math.PI/2))))*255)<<24);
 | 
			
		||||
        super.render(context, mouseX, mouseY, delta);
 | 
			
		||||
        if (time > duration) client.setScreen(null);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public boolean shouldPause() {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public boolean shouldCloseOnEsc() {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -1,5 +0,0 @@
 | 
			
		||||
{
 | 
			
		||||
  "variants": {
 | 
			
		||||
    "": { "model": "hardcore-redeploy:block/buy_station" }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -1,4 +0,0 @@
 | 
			
		||||
{
 | 
			
		||||
  "block.hardcore-redeploy.buy_station": "Buy Station",
 | 
			
		||||
  "effect.hardcore-redeploy.redeploying": "Redeploying"
 | 
			
		||||
}
 | 
			
		||||
@ -1,11 +0,0 @@
 | 
			
		||||
{
 | 
			
		||||
  "credit": "Made with Blockbench",
 | 
			
		||||
  "parent": "builtin/entity",
 | 
			
		||||
  "texture_size": [
 | 
			
		||||
    64,
 | 
			
		||||
    64
 | 
			
		||||
  ],
 | 
			
		||||
  "textures": {
 | 
			
		||||
    "particle": "minecraft:block/hopper_outside"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -1,3 +0,0 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "hardcore-redeploy:block/buy_station"
 | 
			
		||||
}
 | 
			
		||||
@ -28,7 +28,7 @@
 | 
			
		||||
							"vector": [0, 0, 0]
 | 
			
		||||
						},
 | 
			
		||||
						"0.25": {
 | 
			
		||||
							"vector": [-25, 0, 0]
 | 
			
		||||
							"vector": [-37.5, 0, 0]
 | 
			
		||||
						},
 | 
			
		||||
						"1.0": {
 | 
			
		||||
							"vector": [-10, 0, 0]
 | 
			
		||||
@ -58,7 +58,8 @@
 | 
			
		||||
							"vector": [0, 0, 0]
 | 
			
		||||
						},
 | 
			
		||||
						"0.3333": {
 | 
			
		||||
							"vector": [0, 2, 0]
 | 
			
		||||
							"vector": [0, 2, 0],
 | 
			
		||||
							"easing": "easeOutBack"
 | 
			
		||||
						},
 | 
			
		||||
						"0.6667": {
 | 
			
		||||
							"vector": [-11, 3, 0],
 | 
			
		||||
@ -72,7 +73,8 @@
 | 
			
		||||
							"vector": [0, 0, 0]
 | 
			
		||||
						},
 | 
			
		||||
						"0.3333": {
 | 
			
		||||
							"vector": [0, 2, 0]
 | 
			
		||||
							"vector": [0, 2, 0],
 | 
			
		||||
							"easing": "easeOutBack"
 | 
			
		||||
						},
 | 
			
		||||
						"0.6667": {
 | 
			
		||||
							"vector": [11, 3, 0],
 | 
			
		||||
@ -108,6 +110,11 @@
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			},
 | 
			
		||||
			"sound_effects": {
 | 
			
		||||
				"0.0": {
 | 
			
		||||
					"effect": "buy_station"
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
		"animation.model.idle": {
 | 
			
		||||
@ -182,7 +189,7 @@
 | 
			
		||||
							"vector": [-10, 0, 0]
 | 
			
		||||
						},
 | 
			
		||||
						"0.5833": {
 | 
			
		||||
							"vector": [-25, 0, 0]
 | 
			
		||||
							"vector": [-35, 0, 0]
 | 
			
		||||
						},
 | 
			
		||||
						"1.0": {
 | 
			
		||||
							"vector": [0, 0, 0]
 | 
			
		||||
@ -199,69 +206,86 @@
 | 
			
		||||
							"vector": [0, 6, -2]
 | 
			
		||||
						},
 | 
			
		||||
						"0.5833": {
 | 
			
		||||
							"vector": [0, 6, -2]
 | 
			
		||||
							"vector": [0, 6, -2],
 | 
			
		||||
							"easing": "easeOutBack"
 | 
			
		||||
						},
 | 
			
		||||
						"1.0": {
 | 
			
		||||
							"vector": [0, 0, 0]
 | 
			
		||||
							"vector": [0, 0, 0],
 | 
			
		||||
							"easing": "linear"
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				},
 | 
			
		||||
				"botshelfR": {
 | 
			
		||||
					"position": {
 | 
			
		||||
						"0.0": {
 | 
			
		||||
						"0.25": {
 | 
			
		||||
							"vector": [-11, 3, 0],
 | 
			
		||||
							"easing": "easeOutBack"
 | 
			
		||||
						},
 | 
			
		||||
						"0.2917": {
 | 
			
		||||
							"vector": [0, 2, 0]
 | 
			
		||||
						},
 | 
			
		||||
						"0.5417": {
 | 
			
		||||
							"vector": [0, 0, 0]
 | 
			
		||||
							"vector": [0, 2, 0],
 | 
			
		||||
							"easing": "easeOutBack"
 | 
			
		||||
						},
 | 
			
		||||
						"0.7917": {
 | 
			
		||||
							"vector": [0, 0, 0],
 | 
			
		||||
							"easing": "easeOutBack"
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				},
 | 
			
		||||
				"botshelfL": {
 | 
			
		||||
					"position": {
 | 
			
		||||
						"0.0": {
 | 
			
		||||
						"0.25": {
 | 
			
		||||
							"vector": [11, 3, 0],
 | 
			
		||||
							"easing": "easeOutBack"
 | 
			
		||||
						},
 | 
			
		||||
						"0.2917": {
 | 
			
		||||
							"vector": [0, 2, 0]
 | 
			
		||||
						},
 | 
			
		||||
						"0.5417": {
 | 
			
		||||
							"vector": [0, 0, 0]
 | 
			
		||||
							"vector": [0, 2, 0],
 | 
			
		||||
							"easing": "easeOutBack"
 | 
			
		||||
						},
 | 
			
		||||
						"0.7917": {
 | 
			
		||||
							"vector": [0, 0, 0],
 | 
			
		||||
							"easing": "easeOutBack"
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				},
 | 
			
		||||
				"hingeL": {
 | 
			
		||||
					"position": {
 | 
			
		||||
						"0.0": {
 | 
			
		||||
						"0.25": {
 | 
			
		||||
							"vector": [1, 3, 0],
 | 
			
		||||
							"easing": "easeOutBack"
 | 
			
		||||
						},
 | 
			
		||||
						"0.2917": {
 | 
			
		||||
						"0.4167": {
 | 
			
		||||
							"vector": [-1.57, 2.43, 0]
 | 
			
		||||
						},
 | 
			
		||||
						"0.5417": {
 | 
			
		||||
							"vector": [0, 2, 0]
 | 
			
		||||
						},
 | 
			
		||||
						"0.5833": {
 | 
			
		||||
						"0.8333": {
 | 
			
		||||
							"vector": [0, 0, 0]
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				},
 | 
			
		||||
				"hingeR": {
 | 
			
		||||
					"position": {
 | 
			
		||||
						"0.0": {
 | 
			
		||||
						"0.25": {
 | 
			
		||||
							"vector": [-1, 3, 0],
 | 
			
		||||
							"easing": "easeOutBack"
 | 
			
		||||
						},
 | 
			
		||||
						"0.2917": {
 | 
			
		||||
						"0.4167": {
 | 
			
		||||
							"vector": [1.57, 2.43, 0]
 | 
			
		||||
						},
 | 
			
		||||
						"0.5417": {
 | 
			
		||||
							"vector": [0, 2, 0]
 | 
			
		||||
						},
 | 
			
		||||
						"0.5833": {
 | 
			
		||||
						"0.8333": {
 | 
			
		||||
							"vector": [0, 0, 0]
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			},
 | 
			
		||||
			"sound_effects": {
 | 
			
		||||
				"0.0": {
 | 
			
		||||
					"effect": "buy_station"
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
@ -0,0 +1,5 @@
 | 
			
		||||
{
 | 
			
		||||
  "variants": {
 | 
			
		||||
    "": { "model": "hardcore_redeploy:block/buy_station" }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								src/main/resources/assets/hardcore_redeploy/icon.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								src/main/resources/assets/hardcore_redeploy/icon.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 15 KiB  | 
@ -0,0 +1,5 @@
 | 
			
		||||
{
 | 
			
		||||
  "block.hardcore_redeploy.buy_station": "Buy Station",
 | 
			
		||||
  "effect.hardcore_redeploy.redeploying": "Redeploying",
 | 
			
		||||
  "subtitles.hardcore_redeploy.buy_station": "Buy station noise"
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,72 @@
 | 
			
		||||
{
 | 
			
		||||
  "credit": "Made with Blockbench",
 | 
			
		||||
  "parent": "builtin/entity",
 | 
			
		||||
  "texture_size": [
 | 
			
		||||
    64,
 | 
			
		||||
    64
 | 
			
		||||
  ],
 | 
			
		||||
  "textures": {
 | 
			
		||||
    "particle": "minecraft:block/hopper_outside"
 | 
			
		||||
  },
 | 
			
		||||
  "display": {
 | 
			
		||||
    "thirdperson_righthand": {
 | 
			
		||||
      "scale": [
 | 
			
		||||
        0.3,
 | 
			
		||||
        0.3,
 | 
			
		||||
        0.3
 | 
			
		||||
      ]
 | 
			
		||||
    },
 | 
			
		||||
    "thirdperson_lefthand": {
 | 
			
		||||
      "scale": [
 | 
			
		||||
        0.3,
 | 
			
		||||
        0.3,
 | 
			
		||||
        0.3
 | 
			
		||||
      ]
 | 
			
		||||
    },
 | 
			
		||||
    "firstperson_righthand": {
 | 
			
		||||
      "scale": [
 | 
			
		||||
        0.2,
 | 
			
		||||
        0.2,
 | 
			
		||||
        0.2
 | 
			
		||||
      ]
 | 
			
		||||
    },
 | 
			
		||||
    "firstperson_lefthand": {
 | 
			
		||||
      "scale": [
 | 
			
		||||
        0.2,
 | 
			
		||||
        0.2,
 | 
			
		||||
        0.2
 | 
			
		||||
      ]
 | 
			
		||||
    },
 | 
			
		||||
    "ground": {
 | 
			
		||||
      "scale": [
 | 
			
		||||
        0.7,
 | 
			
		||||
        0.7,
 | 
			
		||||
        0.7
 | 
			
		||||
      ]
 | 
			
		||||
    },
 | 
			
		||||
    "gui": {
 | 
			
		||||
      "rotation": [
 | 
			
		||||
        0,
 | 
			
		||||
        23,
 | 
			
		||||
        21
 | 
			
		||||
      ],
 | 
			
		||||
      "translation": [
 | 
			
		||||
        1,
 | 
			
		||||
        -2.75,
 | 
			
		||||
        0
 | 
			
		||||
      ],
 | 
			
		||||
      "scale": [
 | 
			
		||||
        0.5,
 | 
			
		||||
        0.5,
 | 
			
		||||
        0.5
 | 
			
		||||
      ]
 | 
			
		||||
    },
 | 
			
		||||
    "fixed": {
 | 
			
		||||
      "rotation": [
 | 
			
		||||
        -90,
 | 
			
		||||
        0,
 | 
			
		||||
        0
 | 
			
		||||
      ]
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,3 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "hardcore_redeploy:block/buy_station"
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										8
									
								
								src/main/resources/assets/hardcore_redeploy/sounds.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								src/main/resources/assets/hardcore_redeploy/sounds.json
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,8 @@
 | 
			
		||||
{
 | 
			
		||||
  "buy_station": {
 | 
			
		||||
    "subtitle": "subtitles.hardcore_redeploy.buy_station",
 | 
			
		||||
    "sounds": [
 | 
			
		||||
      "hardcore_redeploy:buy_station"
 | 
			
		||||
    ]
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							| 
		 Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 3.8 KiB  | 
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 928 B  | 
@ -0,0 +1,19 @@
 | 
			
		||||
{
 | 
			
		||||
  "type": "minecraft:block",
 | 
			
		||||
  "pools": [
 | 
			
		||||
    {
 | 
			
		||||
      "rolls": 1,
 | 
			
		||||
      "entries": [
 | 
			
		||||
        {
 | 
			
		||||
          "type": "minecraft:item",
 | 
			
		||||
          "name": "hardcore_redeploy:buy_station"
 | 
			
		||||
        }
 | 
			
		||||
      ],
 | 
			
		||||
      "conditions": [
 | 
			
		||||
        {
 | 
			
		||||
          "condition": "minecraft:survives_explosion"
 | 
			
		||||
        }
 | 
			
		||||
      ]
 | 
			
		||||
    }
 | 
			
		||||
  ]
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,21 @@
 | 
			
		||||
{
 | 
			
		||||
  "type": "minecraft:crafting_shaped",
 | 
			
		||||
  "pattern": [
 | 
			
		||||
    "III",
 | 
			
		||||
    "ICI",
 | 
			
		||||
    "III"
 | 
			
		||||
  ],
 | 
			
		||||
  "key": {
 | 
			
		||||
    "I": {
 | 
			
		||||
      "item": "minecraft:iron_ingot"
 | 
			
		||||
    },
 | 
			
		||||
    "C": {
 | 
			
		||||
      "item": "minecraft:crafting_table"
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  "result": {
 | 
			
		||||
    "item": "hardcore_redeploy:buy_station",
 | 
			
		||||
    "count": 1
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
  "replace": false,
 | 
			
		||||
  "values": [
 | 
			
		||||
    "hardcore_redeploy:buy_station"
 | 
			
		||||
  ]
 | 
			
		||||
}
 | 
			
		||||
@ -1,19 +1,19 @@
 | 
			
		||||
{
 | 
			
		||||
	"schemaVersion": 1,
 | 
			
		||||
	"id": "hardcore-redeploy",
 | 
			
		||||
	"id": "hardcore_redeploy",
 | 
			
		||||
	"version": "${version}",
 | 
			
		||||
	"name": "Hardcore Redeploy",
 | 
			
		||||
	"description": "A mod that allows reviving players in hardcore servers, at a cost",
 | 
			
		||||
	"authors": [
 | 
			
		||||
		"Hexugory",
 | 
			
		||||
		"Kaptcha"
 | 
			
		||||
		"Kaptchadelta"
 | 
			
		||||
	],
 | 
			
		||||
	"contact": {
 | 
			
		||||
		"homepage": "",
 | 
			
		||||
		"sources": "https://git.touhoudiscord.net/Hexugory/HardcoreRedeploy"
 | 
			
		||||
	},
 | 
			
		||||
	"license": "LGPL-3.0",
 | 
			
		||||
	"icon": "assets/hardcore-redeploy/icon.png",
 | 
			
		||||
	"icon": "assets/hardcore_redeploy/icon.png",
 | 
			
		||||
	"environment": "*",
 | 
			
		||||
	"entrypoints": {
 | 
			
		||||
		"main": [
 | 
			
		||||
@ -24,15 +24,19 @@
 | 
			
		||||
		]
 | 
			
		||||
	},
 | 
			
		||||
	"mixins": [
 | 
			
		||||
		"hardcore-redeploy.mixins.json"
 | 
			
		||||
		"hardcore_redeploy.mixins.json"
 | 
			
		||||
	],
 | 
			
		||||
	"depends": {
 | 
			
		||||
		"fabricloader": ">=0.14.25",
 | 
			
		||||
		"minecraft": "~1.20.1",
 | 
			
		||||
		"java": ">=17",
 | 
			
		||||
		"fabric-api": "*"
 | 
			
		||||
		"fabric-api": "*",
 | 
			
		||||
		"geckolib": "^4.4.2"
 | 
			
		||||
	},
 | 
			
		||||
	"suggests": {
 | 
			
		||||
		"another-mod": "*"
 | 
			
		||||
	"custom": {
 | 
			
		||||
	"loom:injected_interfaces": {
 | 
			
		||||
		"net/minecraft/class_1657": ["net/touhoudiscord/BuyStationCapable"],
 | 
			
		||||
		"net/minecraft/class_746": ["net/touhoudiscord/BuyStationCapable"]
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
@ -1,11 +0,0 @@
 | 
			
		||||
{
 | 
			
		||||
	"required": true,
 | 
			
		||||
	"package": "net.touhoudiscord.mixin",
 | 
			
		||||
	"compatibilityLevel": "JAVA_17",
 | 
			
		||||
	"mixins": [
 | 
			
		||||
		"RedeployingMixin"
 | 
			
		||||
	],
 | 
			
		||||
	"injectors": {
 | 
			
		||||
		"defaultRequire": 1
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										16
									
								
								src/main/resources/hardcore_redeploy.mixins.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								src/main/resources/hardcore_redeploy.mixins.json
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,16 @@
 | 
			
		||||
{
 | 
			
		||||
  "required": true,
 | 
			
		||||
  "package": "net.touhoudiscord.mixin",
 | 
			
		||||
  "compatibilityLevel": "JAVA_17",
 | 
			
		||||
  "mixins": [
 | 
			
		||||
    "BuyStationScreenMixin",
 | 
			
		||||
    "RedeployingMixin",
 | 
			
		||||
    "RedeployTimerMixin"
 | 
			
		||||
  ],
 | 
			
		||||
  "injectors": {
 | 
			
		||||
    "defaultRequire": 1
 | 
			
		||||
  },
 | 
			
		||||
  "client": [
 | 
			
		||||
    "ClientBuyStationScreenMixin"
 | 
			
		||||
  ]
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user