First pass computer prototype
This commit is contained in:
1 parent
8b86021a04
commit
c27e68c16a
46 files changed
+1242
-11
No files matched your search
@@ -545,9 +545,9 @@ public final class AntarchySettings {
|
||||
private static double manticoreHealth = 40.0D;
|
||||
private static double manticoreAttackDamage = 7.0D;
|
||||
private static int manticoreStingPoisonTicks = 100;
|
||||
private static int queenManticoreCap = 15;
|
||||
private static int queenManticoreSummonCooldownTicks = 600;
|
||||
private static int queenManticoreSummonCount = 3;
|
||||
private static int queenManticoreCap = 6;
|
||||
private static int queenManticoreSummonCooldownTicks = 800;
|
||||
private static int queenManticoreSummonCount = 2;
|
||||
private static double queenManticoreSummonRange = 24.0D;
|
||||
private static double queenBeamDamage = 45.0D;
|
||||
private static double queenBeamRange = 100.0D;
|
||||
|
||||
@@ -206,6 +206,16 @@ public final class AntarchyObjects {
|
||||
public static Supplier<net.minecraft.core.component.DataComponentType<com.craisinlord.antarchy.content.entity.glimmer.GlimmerVariant>> GLIMMER_VARIANT_COMPONENT =
|
||||
(Supplier<net.minecraft.core.component.DataComponentType<com.craisinlord.antarchy.content.entity.glimmer.GlimmerVariant>>) UNBOUND;
|
||||
@SuppressWarnings("unchecked")
|
||||
public static Supplier<net.minecraft.core.component.DataComponentType<net.minecraft.resources.ResourceLocation>> FLOPPY_DISK_COMPONENT =
|
||||
(Supplier<net.minecraft.core.component.DataComponentType<net.minecraft.resources.ResourceLocation>>) UNBOUND;
|
||||
@SuppressWarnings("unchecked")
|
||||
public static Supplier<Item> FLOPPY_DISK = (Supplier<Item>) UNBOUND;
|
||||
@SuppressWarnings("unchecked")
|
||||
public static Supplier<Block> COMPUTER = (Supplier<Block>) UNBOUND;
|
||||
@SuppressWarnings("unchecked")
|
||||
public static Supplier<BlockEntityType<com.craisinlord.antarchy.content.block.entity.ComputerBlockEntity>> COMPUTER_BLOCK_ENTITY =
|
||||
(Supplier<BlockEntityType<com.craisinlord.antarchy.content.block.entity.ComputerBlockEntity>>) UNBOUND;
|
||||
@SuppressWarnings("unchecked")
|
||||
public static Supplier<MenuType<com.craisinlord.antarchy.content.menu.DorrieInventoryMenu>> DORRIE_INVENTORY_MENU = (Supplier<MenuType<com.craisinlord.antarchy.content.menu.DorrieInventoryMenu>>) UNBOUND;
|
||||
@SuppressWarnings("unchecked")
|
||||
public static Supplier<MenuType<com.craisinlord.antarchy.content.menu.RoyalJudgmentMenu>> ROYAL_JUDGMENT_MENU = (Supplier<MenuType<com.craisinlord.antarchy.content.menu.RoyalJudgmentMenu>>) UNBOUND;
|
||||
@@ -897,6 +907,22 @@ public final class AntarchyObjects {
|
||||
GLIMMER_VARIANT_COMPONENT = supplier;
|
||||
}
|
||||
|
||||
public static void setFloppyDiskComponent(Supplier<net.minecraft.core.component.DataComponentType<net.minecraft.resources.ResourceLocation>> supplier) {
|
||||
FLOPPY_DISK_COMPONENT = supplier;
|
||||
}
|
||||
|
||||
public static void setFloppyDisk(Supplier<Item> supplier) {
|
||||
FLOPPY_DISK = supplier;
|
||||
}
|
||||
|
||||
public static void setComputer(Supplier<Block> supplier) {
|
||||
COMPUTER = supplier;
|
||||
}
|
||||
|
||||
public static void setComputerBlockEntity(Supplier<BlockEntityType<com.craisinlord.antarchy.content.block.entity.ComputerBlockEntity>> supplier) {
|
||||
COMPUTER_BLOCK_ENTITY = supplier;
|
||||
}
|
||||
|
||||
public static void setDorrieInventoryMenu(Supplier<MenuType<com.craisinlord.antarchy.content.menu.DorrieInventoryMenu>> supplier) {
|
||||
DORRIE_INVENTORY_MENU = supplier;
|
||||
}
|
||||
|
||||
+100
@@ -0,0 +1,100 @@
|
||||
package com.craisinlord.antarchy.content.block;
|
||||
|
||||
import com.craisinlord.antarchy.content.AntarchyObjects;
|
||||
import com.craisinlord.antarchy.content.block.entity.ComputerBlockEntity;
|
||||
import com.craisinlord.antarchy.content.client.AntarchyClientHooks;
|
||||
import com.mojang.serialization.MapCodec;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.ItemInteractionResult;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.BlockGetter;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.BaseEntityBlock;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.RenderShape;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityTicker;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import net.minecraft.world.level.block.state.BlockBehaviour;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraft.world.phys.shapes.CollisionContext;
|
||||
import net.minecraft.world.phys.shapes.VoxelShape;
|
||||
|
||||
public final class ComputerBlock extends BaseEntityBlock {
|
||||
public static final MapCodec<ComputerBlock> CODEC = Block.simpleCodec(ComputerBlock::new);
|
||||
private static final VoxelShape SHAPE = Block.box(1.0D, 0.0D, 1.0D, 15.0D, 16.0D, 15.0D);
|
||||
|
||||
public ComputerBlock(BlockBehaviour.Properties properties) {
|
||||
super(properties);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MapCodec<ComputerBlock> codec() {
|
||||
return CODEC;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RenderShape getRenderShape(BlockState state) {
|
||||
return RenderShape.ENTITYBLOCK_ANIMATED;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) {
|
||||
return SHAPE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean movedByPiston) {
|
||||
if (!state.is(newState.getBlock()) && level.getBlockEntity(pos) instanceof ComputerBlockEntity computer) {
|
||||
computer.dropDisks(level, pos);
|
||||
}
|
||||
super.onRemove(state, level, pos, newState, movedByPiston);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {
|
||||
return new ComputerBlockEntity(pos, state, AntarchyObjects.COMPUTER_BLOCK_ENTITY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends BlockEntity> BlockEntityTicker<T> getTicker(Level level, BlockState state, BlockEntityType<T> blockEntityType) {
|
||||
return createTickerHelper(blockEntityType, AntarchyObjects.COMPUTER_BLOCK_ENTITY.get(), ComputerBlockEntity::tick);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ItemInteractionResult useItemOn(ItemStack stack, BlockState state, Level level, BlockPos pos, Player player,
|
||||
InteractionHand hand, BlockHitResult hitResult) {
|
||||
if (level.getBlockEntity(pos) instanceof ComputerBlockEntity computer) {
|
||||
if (level.isClientSide) {
|
||||
if (stack.is(AntarchyObjects.FLOPPY_DISK.get())) {
|
||||
return ItemInteractionResult.SUCCESS;
|
||||
}
|
||||
} else if (computer.insert(stack, player)) {
|
||||
return ItemInteractionResult.CONSUME;
|
||||
}
|
||||
}
|
||||
return ItemInteractionResult.PASS_TO_DEFAULT_BLOCK_INTERACTION;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected net.minecraft.world.InteractionResult useWithoutItem(BlockState state, Level level, BlockPos pos, Player player,
|
||||
BlockHitResult hitResult) {
|
||||
if (level.getBlockEntity(pos) instanceof ComputerBlockEntity computer) {
|
||||
if (player.isShiftKeyDown()) {
|
||||
if (computer.ejectOne(player)) {
|
||||
return net.minecraft.world.InteractionResult.SUCCESS;
|
||||
}
|
||||
return net.minecraft.world.InteractionResult.PASS;
|
||||
}
|
||||
computer.activate();
|
||||
if (level.isClientSide) {
|
||||
AntarchyClientHooks.openComputer(pos);
|
||||
}
|
||||
return net.minecraft.world.InteractionResult.SUCCESS;
|
||||
}
|
||||
return net.minecraft.world.InteractionResult.PASS;
|
||||
}
|
||||
}
|
||||
+176
@@ -0,0 +1,176 @@
|
||||
package com.craisinlord.antarchy.content.block.entity;
|
||||
|
||||
import com.craisinlord.antarchy.content.AntarchyObjects;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.HolderLookup;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.ListTag;
|
||||
import net.minecraft.nbt.StringTag;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.Containers;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.Supplier;
|
||||
import software.bernie.geckolib.animatable.GeoBlockEntity;
|
||||
import software.bernie.geckolib.animatable.instance.AnimatableInstanceCache;
|
||||
import software.bernie.geckolib.animation.AnimatableManager;
|
||||
import software.bernie.geckolib.animation.AnimationController;
|
||||
import software.bernie.geckolib.animation.RawAnimation;
|
||||
import software.bernie.geckolib.animation.PlayState;
|
||||
import software.bernie.geckolib.util.GeckoLibUtil;
|
||||
|
||||
public final class ComputerBlockEntity extends BlockEntity implements GeoBlockEntity {
|
||||
private static final String DISKS_TAG = "Disks";
|
||||
private static final String ACTIVE_UNTIL_TAG = "ActiveUntil";
|
||||
private final Set<ResourceLocation> diskIds = new LinkedHashSet<>();
|
||||
private final AnimatableInstanceCache animatableCache = GeckoLibUtil.createInstanceCache(this);
|
||||
private static final RawAnimation ON = RawAnimation.begin().thenLoop("on_state");
|
||||
private static final RawAnimation OFF = RawAnimation.begin().thenLoop("off_state");
|
||||
private static final RawAnimation TURN_ON = RawAnimation.begin().thenPlay("turn_on");
|
||||
private static final RawAnimation TURN_OFF = RawAnimation.begin().thenPlay("turn_off");
|
||||
private long activeUntil;
|
||||
private boolean lastActive;
|
||||
|
||||
public ComputerBlockEntity(BlockPos pos, BlockState state, Supplier<? extends BlockEntityType<ComputerBlockEntity>> type) {
|
||||
super(type.get(), pos, state);
|
||||
}
|
||||
|
||||
public static void tick(Level level, BlockPos pos, BlockState state, ComputerBlockEntity computer) {
|
||||
boolean active = computer.isActive();
|
||||
if (active != computer.lastActive) {
|
||||
computer.lastActive = active;
|
||||
computer.triggerAnim("transitions", active ? "turn_on" : "turn_off");
|
||||
}
|
||||
if (!level.isClientSide && computer.activeUntil > 0L && level.getGameTime() >= computer.activeUntil && !level.hasNeighborSignal(pos)) {
|
||||
computer.activeUntil = 0L;
|
||||
computer.setChanged();
|
||||
level.sendBlockUpdated(pos, state, state, 3);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean insert(ItemStack stack, Player player) {
|
||||
if (!stack.is(AntarchyObjects.FLOPPY_DISK.get())) {
|
||||
return false;
|
||||
}
|
||||
ResourceLocation diskId = stack.get(AntarchyObjects.FLOPPY_DISK_COMPONENT.get());
|
||||
if (diskId == null || this.diskIds.contains(diskId)) {
|
||||
stack.shrink(1);
|
||||
activate();
|
||||
return true;
|
||||
}
|
||||
this.diskIds.add(diskId);
|
||||
stack.shrink(1);
|
||||
activate();
|
||||
setChanged();
|
||||
if (level != null) {
|
||||
level.sendBlockUpdated(worldPosition, getBlockState(), getBlockState(), 3);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void activate() {
|
||||
if (level != null && !level.isClientSide) {
|
||||
activeUntil = Math.max(activeUntil, level.getGameTime() + 40L);
|
||||
setChanged();
|
||||
level.sendBlockUpdated(worldPosition, getBlockState(), getBlockState(), 3);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isActive() {
|
||||
return level != null && (level.hasNeighborSignal(worldPosition) || level.getGameTime() < activeUntil);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerControllers(AnimatableManager.ControllerRegistrar controllers) {
|
||||
controllers.add(new AnimationController<>(this, "state", state -> state.setAndContinue(isActive() ? ON : OFF)));
|
||||
controllers.add(new AnimationController<>(this, "transitions", state -> PlayState.STOP)
|
||||
.triggerableAnim("turn_on", TURN_ON)
|
||||
.triggerableAnim("turn_off", TURN_OFF));
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnimatableInstanceCache getAnimatableInstanceCache() {
|
||||
return animatableCache;
|
||||
}
|
||||
|
||||
public List<ResourceLocation> diskIds() {
|
||||
return List.copyOf(diskIds);
|
||||
}
|
||||
|
||||
public boolean ejectOne(Player player) {
|
||||
if (level == null || level.isClientSide || diskIds.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
ResourceLocation diskId = diskIds.iterator().next();
|
||||
diskIds.remove(diskId);
|
||||
ItemStack disk = diskStack(diskId);
|
||||
if (!player.addItem(disk)) {
|
||||
player.drop(disk, false);
|
||||
}
|
||||
setChanged();
|
||||
level.sendBlockUpdated(worldPosition, getBlockState(), getBlockState(), 3);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void dropDisks(Level level, BlockPos pos) {
|
||||
if (level.isClientSide) {
|
||||
return;
|
||||
}
|
||||
for (ResourceLocation diskId : diskIds) {
|
||||
Containers.dropItemStack(level, pos.getX() + 0.5D, pos.getY() + 0.5D, pos.getZ() + 0.5D, diskStack(diskId));
|
||||
}
|
||||
diskIds.clear();
|
||||
}
|
||||
|
||||
private static ItemStack diskStack(ResourceLocation diskId) {
|
||||
ItemStack stack = new ItemStack(AntarchyObjects.FLOPPY_DISK.get());
|
||||
stack.set(AntarchyObjects.FLOPPY_DISK_COMPONENT.get(), diskId);
|
||||
return stack;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void loadAdditional(CompoundTag tag, HolderLookup.Provider registries) {
|
||||
super.loadAdditional(tag, registries);
|
||||
diskIds.clear();
|
||||
ListTag disks = tag.getList(DISKS_TAG, 8);
|
||||
for (int index = 0; index < disks.size(); index++) {
|
||||
try {
|
||||
diskIds.add(ResourceLocation.parse(disks.getString(index)));
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
activeUntil = tag.getLong(ACTIVE_UNTIL_TAG);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void saveAdditional(CompoundTag tag, HolderLookup.Provider registries) {
|
||||
super.saveAdditional(tag, registries);
|
||||
ListTag disks = new ListTag();
|
||||
for (ResourceLocation diskId : diskIds) {
|
||||
disks.add(StringTag.valueOf(diskId.toString()));
|
||||
}
|
||||
tag.put(DISKS_TAG, disks);
|
||||
tag.putLong(ACTIVE_UNTIL_TAG, activeUntil);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag getUpdateTag(HolderLookup.Provider registries) {
|
||||
CompoundTag tag = new CompoundTag();
|
||||
saveAdditional(tag, registries);
|
||||
return tag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public net.minecraft.network.protocol.Packet<net.minecraft.network.protocol.game.ClientGamePacketListener> getUpdatePacket() {
|
||||
return net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket.create(this);
|
||||
}
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
package com.craisinlord.antarchy.content.client;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public final class AntarchyClientHooks {
|
||||
private static Consumer<BlockPos> computerOpener = pos -> {
|
||||
};
|
||||
|
||||
private AntarchyClientHooks() {
|
||||
}
|
||||
|
||||
public static void setComputerOpener(Consumer<BlockPos> opener) {
|
||||
computerOpener = opener;
|
||||
}
|
||||
|
||||
public static void openComputer(BlockPos pos) {
|
||||
computerOpener.accept(pos);
|
||||
}
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
package com.craisinlord.antarchy.content.client.model;
|
||||
|
||||
import com.craisinlord.antarchy.Antarchy;
|
||||
import com.craisinlord.antarchy.content.block.entity.ComputerBlockEntity;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import software.bernie.geckolib.model.GeoModel;
|
||||
|
||||
public final class ComputerModel extends GeoModel<ComputerBlockEntity> {
|
||||
private static final ResourceLocation MODEL = ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "geo/computer.geo.json");
|
||||
private static final ResourceLocation TEXTURE = ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "textures/block/computer/computer.png");
|
||||
private static final ResourceLocation ANIMATION = ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "animations/computer.animation.json");
|
||||
|
||||
@Override
|
||||
public ResourceLocation getModelResource(ComputerBlockEntity animatable) {
|
||||
return MODEL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getTextureResource(ComputerBlockEntity animatable) {
|
||||
return TEXTURE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getAnimationResource(ComputerBlockEntity animatable) {
|
||||
return ANIMATION;
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
package com.craisinlord.antarchy.content.client.renderer;
|
||||
|
||||
import com.craisinlord.antarchy.content.block.entity.ComputerBlockEntity;
|
||||
import com.craisinlord.antarchy.content.client.model.ComputerModel;
|
||||
import software.bernie.geckolib.renderer.GeoBlockRenderer;
|
||||
|
||||
public final class ComputerRenderer extends GeoBlockRenderer<ComputerBlockEntity> {
|
||||
public ComputerRenderer(net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider.Context context) {
|
||||
super(new ComputerModel());
|
||||
}
|
||||
}
|
||||
+146
@@ -0,0 +1,146 @@
|
||||
package com.craisinlord.antarchy.content.client.screen;
|
||||
|
||||
import com.craisinlord.antarchy.content.AntarchyObjects;
|
||||
import com.craisinlord.antarchy.content.block.entity.ComputerBlockEntity;
|
||||
import com.craisinlord.antarchy.content.guide.ComputerGuideData;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiGraphics;
|
||||
import net.minecraft.client.gui.components.Button;
|
||||
import net.minecraft.client.gui.screens.Screen;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.util.FormattedCharSequence;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public final class ComputerScreen extends Screen {
|
||||
private static final int WIDTH = 320;
|
||||
private static final int HEIGHT = 210;
|
||||
private static final String[] CATEGORIES = {"general", "elythia", "thoraxis", "cavaryn"};
|
||||
private static final int[] COLORS = {0xFF65FF65, 0xFF65FF65, 0xFFFF5A5A, 0xFFFFA044};
|
||||
private final ResourceLocation positionDimension;
|
||||
private final net.minecraft.core.BlockPos position;
|
||||
private int categoryIndex;
|
||||
private int selectedIndex;
|
||||
private List<ComputerGuideData.Entry> visibleEntries = List.of();
|
||||
|
||||
public ComputerScreen(net.minecraft.core.BlockPos position) {
|
||||
super(Component.translatable("screen.antarchy.computer"));
|
||||
this.position = position;
|
||||
this.positionDimension = Minecraft.getInstance().level == null ? null : Minecraft.getInstance().level.dimension().location();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init() {
|
||||
refreshEntries();
|
||||
int left = (this.width - WIDTH) / 2;
|
||||
int top = (this.height - HEIGHT) / 2;
|
||||
for (int index = 0; index < CATEGORIES.length; index++) {
|
||||
int buttonIndex = index;
|
||||
addRenderableWidget(Button.builder(Component.translatable("guide.antarchy.category." + CATEGORIES[index]), button -> {
|
||||
categoryIndex = buttonIndex;
|
||||
selectedIndex = 0;
|
||||
refreshEntries();
|
||||
}).bounds(left + 10 + index * 75, top + 10, 70, 20).build());
|
||||
}
|
||||
}
|
||||
|
||||
private void refreshEntries() {
|
||||
if (Minecraft.getInstance().level != null && Minecraft.getInstance().level.getBlockEntity(position) instanceof ComputerBlockEntity computer) {
|
||||
visibleEntries = ComputerGuideData.entriesFor(computer.diskIds()).stream()
|
||||
.filter(entry -> entry.category().equals(CATEGORIES[categoryIndex]))
|
||||
.toList();
|
||||
} else {
|
||||
visibleEntries = List.of();
|
||||
}
|
||||
if (selectedIndex >= visibleEntries.size()) {
|
||||
selectedIndex = Math.max(0, visibleEntries.size() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
refreshEntries();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(GuiGraphics graphics, int mouseX, int mouseY, float partialTick) {
|
||||
int left = (this.width - WIDTH) / 2;
|
||||
int top = (this.height - HEIGHT) / 2;
|
||||
graphics.fill(0, 0, this.width, this.height, 0x99000000);
|
||||
graphics.fill(left, top, left + WIDTH, top + HEIGHT, 0xFF071007);
|
||||
graphics.fill(left + 4, top + 4, left + WIDTH - 4, top + HEIGHT - 4, 0xFF102010);
|
||||
int accent = COLORS[categoryIndex];
|
||||
graphics.fill(left + 8, top + 34, left + WIDTH - 8, top + 36, accent);
|
||||
graphics.drawString(this.font, Component.translatable("screen.antarchy.computer"), left + 12, top + 45, accent, false);
|
||||
graphics.drawString(this.font, Component.literal(positionDimension == null ? "ARCHIVE OFFLINE" : "ARCHIVE ONLINE"), left + WIDTH - 105, top + 45, 0xFF65FF65, false);
|
||||
graphics.fill(left + 10, top + 60, left + 112, top + HEIGHT - 12, 0xFF050805);
|
||||
for (int index = 0; index < visibleEntries.size() && index < 6; index++) {
|
||||
ComputerGuideData.Entry entry = visibleEntries.get(index);
|
||||
int y = top + 68 + index * 20;
|
||||
int color = index == selectedIndex ? accent : 0xFF65FF65;
|
||||
if (index == selectedIndex) {
|
||||
graphics.fill(left + 12, y - 2, left + 110, y + 14, 0xFF173817);
|
||||
}
|
||||
graphics.drawString(this.font, Component.literal("FILE_" + (index + 1)), left + 16, y, color, false);
|
||||
if (isMouseOver(left + 12, y - 2, 98, 16, mouseX, mouseY)) {
|
||||
graphics.renderTooltip(this.font, Component.translatable(entry.titleKey()), mouseX, mouseY);
|
||||
}
|
||||
}
|
||||
if (visibleEntries.isEmpty()) {
|
||||
graphics.drawString(this.font, Component.literal("NO DATA FOUND"), left + 22, top + 86, accent, false);
|
||||
graphics.drawString(this.font, Component.literal("INSERT FLOPPY DISKS"), left + 16, top + 104, 0xFF65FF65, false);
|
||||
} else {
|
||||
renderEntry(graphics, visibleEntries.get(selectedIndex), left + 124, top + 62, accent);
|
||||
}
|
||||
super.render(graphics, mouseX, mouseY, partialTick);
|
||||
}
|
||||
|
||||
private void renderEntry(GuiGraphics graphics, ComputerGuideData.Entry entry, int x, int y, int accent) {
|
||||
graphics.drawString(this.font, Component.translatable(entry.titleKey()), x, y, accent, false);
|
||||
if (!entry.subtitleKey().isEmpty()) {
|
||||
graphics.drawString(this.font, Component.translatable(entry.subtitleKey()), x, y + 16, 0xFF99FF99, false);
|
||||
}
|
||||
int line = y + 34;
|
||||
for (String descriptionKey : entry.descriptionKeys()) {
|
||||
for (FormattedCharSequence wrapped : this.font.split(Component.translatable(descriptionKey), 174)) {
|
||||
graphics.drawString(this.font, wrapped, x, line, 0xFFB8FFB8, false);
|
||||
line += 11;
|
||||
if (line > y + 125) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
line += 5;
|
||||
}
|
||||
if (entry.type().equals("item") && !entry.itemId().isEmpty()) {
|
||||
try {
|
||||
ItemStack stack = new ItemStack(net.minecraft.core.registries.BuiltInRegistries.ITEM.get(ResourceLocation.parse(entry.itemId())));
|
||||
graphics.renderItem(stack, x + 130, y + 122);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseClicked(double mouseX, double mouseY, int button) {
|
||||
int left = (this.width - WIDTH) / 2;
|
||||
int top = (this.height - HEIGHT) / 2;
|
||||
for (int index = 0; index < visibleEntries.size() && index < 6; index++) {
|
||||
if (isMouseOver(left + 12, top + 66 + index * 20, 98, 16, mouseX, mouseY)) {
|
||||
selectedIndex = index;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return super.mouseClicked(mouseX, mouseY, button);
|
||||
}
|
||||
|
||||
private static boolean isMouseOver(int x, int y, int width, int height, double mouseX, double mouseY) {
|
||||
return mouseX >= x && mouseX < x + width && mouseY >= y && mouseY < y + height;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPauseScreen() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
+8
@@ -1,5 +1,6 @@
|
||||
package com.craisinlord.antarchy.content.creative;
|
||||
|
||||
import com.craisinlord.antarchy.content.AntarchyObjects;
|
||||
import com.craisinlord.antarchy.content.entity.glimmer.GlimmerVariant;
|
||||
import com.craisinlord.antarchy.content.item.GlimmerBottleItem;
|
||||
import com.craisinlord.antarchy.content.item.royal.RoyalGearHelper;
|
||||
@@ -394,6 +395,8 @@ public final class CreativeTabContents {
|
||||
entry("lucid_anchor", "tools_and_utilities"),
|
||||
entry("undertrial_spawner", "tools_and_utilities"),
|
||||
entry("undervault", "tools_and_utilities"),
|
||||
entry("computer", "functional_blocks"),
|
||||
entry("floppy_disk", "tools_and_utilities"),
|
||||
entry("undertrial_key", "tools_and_utilities"),
|
||||
entry("reverie_bottle", "tools_and_utilities"),
|
||||
entry("glimmer_bottle", "tools_and_utilities"),
|
||||
@@ -636,6 +639,11 @@ public final class CreativeTabContents {
|
||||
for (String potionPath : ANTARCHY_POTION_FAMILIES) {
|
||||
acceptPotionFamily(output, potionPath);
|
||||
}
|
||||
for (String diskId : List.of("antarchy:introduction", "antarchy:chronosphere", "antarchy:toreterror_arena", "antarchy:high_fructose_corn_syrup")) {
|
||||
ItemStack disk = new ItemStack(AntarchyObjects.FLOPPY_DISK.get());
|
||||
disk.set(AntarchyObjects.FLOPPY_DISK_COMPONENT.get(), ResourceLocation.parse(diskId));
|
||||
output.accept(disk);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean populateNeoForgeVanillaTab(ResourceKey<CreativeModeTab> tabKey, HolderLookup.Provider holders,
|
||||
|
||||
+27
-1
@@ -93,6 +93,10 @@ public class KingEntity extends RoyalBossEntity {
|
||||
private static final double TREE_RETURN_RELEASE_RADIUS = 144.0D;
|
||||
private static final double TREE_ORBIT_ANGLE_STEP = 0.014D;
|
||||
private static final int TREE_ORBIT_PATH_SAMPLES = 16;
|
||||
private static final double KING_FOLLOW_RANGE = 192.0D;
|
||||
private static final double COME_NO_CLOSER_RADIUS = 16.0D;
|
||||
private static final int COME_NO_CLOSER_PARTICLE_INTERVAL = 4;
|
||||
private static final int COME_NO_CLOSER_PARTICLE_COUNT = 40;
|
||||
|
||||
@Nullable
|
||||
private Vec3 patrolCenter;
|
||||
@@ -147,7 +151,13 @@ public class KingEntity extends RoyalBossEntity {
|
||||
}
|
||||
|
||||
public static AttributeSupplier.Builder createAttributes() {
|
||||
return createBaseAttributes(AntarchySettings.kingHealth(), AntarchySettings.kingAttackDamage());
|
||||
return createBaseAttributes(AntarchySettings.kingHealth(), AntarchySettings.kingAttackDamage())
|
||||
.add(net.minecraft.world.entity.ai.attributes.Attributes.FOLLOW_RANGE, KING_FOLLOW_RANGE);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int maxConcurrentHeadAttacks(Phase phase) {
|
||||
return phase.maxConcurrentHeadAttacks();
|
||||
}
|
||||
|
||||
public void setTreePatrolHome(Vec3 center, double minimumY, double maximumY, double angle) {
|
||||
@@ -371,6 +381,7 @@ public class KingEntity extends RoyalBossEntity {
|
||||
if (this.level().isClientSide) {
|
||||
return;
|
||||
}
|
||||
this.tickComeNoCloserIndicator();
|
||||
this.tickRoyalPunishment();
|
||||
this.tickPendingExileAnimation();
|
||||
long gameTime = this.level().getGameTime();
|
||||
@@ -426,6 +437,21 @@ public class KingEntity extends RoyalBossEntity {
|
||||
}
|
||||
}
|
||||
|
||||
private void tickComeNoCloserIndicator() {
|
||||
if (!(this.activeDecree instanceof ComeNoCloserDecree)
|
||||
|| this.tickCount % COME_NO_CLOSER_PARTICLE_INTERVAL != 0
|
||||
|| !(this.level() instanceof ServerLevel serverLevel)) {
|
||||
return;
|
||||
}
|
||||
for (int index = 0; index < COME_NO_CLOSER_PARTICLE_COUNT; index++) {
|
||||
double angle = (Math.PI * 2.0D * index) / COME_NO_CLOSER_PARTICLE_COUNT;
|
||||
double x = this.getX() + Math.cos(angle) * COME_NO_CLOSER_RADIUS;
|
||||
double z = this.getZ() + Math.sin(angle) * COME_NO_CLOSER_RADIUS;
|
||||
serverLevel.sendParticles(ParticleTypes.END_ROD, x, this.getY() + 0.25D, z,
|
||||
1, 0.0D, 0.0D, 0.0D, 0.0D);
|
||||
}
|
||||
}
|
||||
|
||||
private void tickTreePatrol() {
|
||||
Vec3 center = this.treePatrolCenter;
|
||||
if (center == null) {
|
||||
|
||||
+14
@@ -67,6 +67,7 @@ public class QueenEntity extends RoyalBossEntity {
|
||||
private static final int ACCELERATION_COOLDOWN = 500;
|
||||
private static final int ACCELERATION_DURATION = 140;
|
||||
private static final int BLACK_HOLE_COOLDOWN = 340;
|
||||
private static final double QUEEN_BITE_COOLDOWN_MULTIPLIER = 1.5D;
|
||||
|
||||
private int manticoreSummonCooldownTicks;
|
||||
private int gravityStompCooldownTicks;
|
||||
@@ -111,6 +112,19 @@ public class QueenEntity extends RoyalBossEntity {
|
||||
return 1.55D;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int maxConcurrentHeadAttacks(Phase phase) {
|
||||
return switch (phase) {
|
||||
case ONE, TWO -> 1;
|
||||
case THREE -> 2;
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int biteCooldownTicks(Phase phase) {
|
||||
return Math.max(10, (int) Math.ceil(super.biteCooldownTicks(phase) * QUEEN_BITE_COOLDOWN_MULTIPLIER));
|
||||
}
|
||||
|
||||
protected void registerRoyalTargetGoals() {
|
||||
this.targetSelector.addGoal(1, new NearestAttackableTargetGoal<>(this, KingEntity.class, true));
|
||||
this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, true));
|
||||
|
||||
+12
-2
@@ -276,6 +276,16 @@ public abstract class RoyalBossEntity extends Monster implements GeoEntity, Mult
|
||||
return 1.3D;
|
||||
}
|
||||
|
||||
/** Allows a boss to tune its head-bite concurrency without changing the other royal boss. */
|
||||
protected int maxConcurrentHeadAttacks(Phase phase) {
|
||||
return phase.maxConcurrentHeadAttacks();
|
||||
}
|
||||
|
||||
/** Allows a boss to tune bite pacing without changing the other royal boss. */
|
||||
protected int biteCooldownTicks(Phase phase) {
|
||||
return Math.max(10, Mth.floor(AntarchySettings.royalBossBiteCooldownTicks() * phase.cooldownScale()));
|
||||
}
|
||||
|
||||
public String geoNameForRender() {
|
||||
return this.geoName();
|
||||
}
|
||||
@@ -472,7 +482,7 @@ public abstract class RoyalBossEntity extends Monster implements GeoEntity, Mult
|
||||
}
|
||||
|
||||
for (RoyalHead head : this.heads) {
|
||||
if (activeHeadAttacks >= phase.maxConcurrentHeadAttacks()) {
|
||||
if (activeHeadAttacks >= this.maxConcurrentHeadAttacks(phase)) {
|
||||
break;
|
||||
}
|
||||
if (!head.readyToAttack() || this.attackScheduler.laneBusy(this.headLane(head))) {
|
||||
@@ -810,7 +820,7 @@ public abstract class RoyalBossEntity extends Monster implements GeoEntity, Mult
|
||||
}
|
||||
|
||||
private void startBite(RoyalHead head, Phase phase) {
|
||||
int cooldown = Math.max(10, Mth.floor(AntarchySettings.royalBossBiteCooldownTicks() * phase.cooldownScale()));
|
||||
int cooldown = this.biteCooldownTicks(phase);
|
||||
if (!this.beginRoyalAttack("bite_" + head.slot().name(), headLane(head), cooldown,
|
||||
BITE_HIT_TICK, 1, BITE_DURATION_TICKS - BITE_HIT_TICK,
|
||||
new RoyalAttackScheduler.Action() {
|
||||
|
||||
+166
@@ -0,0 +1,166 @@
|
||||
package com.craisinlord.antarchy.content.guide;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.packs.resources.ResourceManager;
|
||||
import net.minecraft.server.packs.resources.SimplePreparableReloadListener;
|
||||
import net.minecraft.util.profiling.ProfilerFiller;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public final class ComputerGuideData extends SimplePreparableReloadListener<ComputerGuideData.LoadedData> {
|
||||
private static final ComputerGuideData INSTANCE = new ComputerGuideData();
|
||||
private static volatile Map<ResourceLocation, Entry> entries = Map.of();
|
||||
private static volatile Map<ResourceLocation, Disk> disks = Map.of();
|
||||
|
||||
private ComputerGuideData() {
|
||||
}
|
||||
|
||||
public static ComputerGuideData instance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
public static Entry entry(ResourceLocation id) {
|
||||
return entries.get(id);
|
||||
}
|
||||
|
||||
public static Disk disk(ResourceLocation id) {
|
||||
return disks.get(id);
|
||||
}
|
||||
|
||||
public static List<Entry> entriesFor(List<ResourceLocation> diskIds) {
|
||||
Map<ResourceLocation, Entry> result = new LinkedHashMap<>();
|
||||
for (ResourceLocation diskId : diskIds) {
|
||||
Disk disk = disks.get(diskId);
|
||||
if (disk == null) {
|
||||
continue;
|
||||
}
|
||||
for (ResourceLocation entryId : disk.entries()) {
|
||||
Entry entry = entries.get(entryId);
|
||||
if (entry != null) {
|
||||
result.putIfAbsent(entryId, entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.values().stream().sorted(Comparator.comparing(entry -> entry.titleKey().toString())).toList();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected LoadedData prepare(ResourceManager resourceManager, ProfilerFiller profiler) {
|
||||
Map<ResourceLocation, Entry> loadedEntries = new HashMap<>();
|
||||
Map<ResourceLocation, Disk> loadedDisks = new HashMap<>();
|
||||
for (Map.Entry<ResourceLocation, net.minecraft.server.packs.resources.Resource> resource : resourceManager.listResources("computer/entry", path -> path.getPath().endsWith(".json")).entrySet()) {
|
||||
ResourceLocation id = resourceId(resource.getKey(), "computer/entry");
|
||||
try {
|
||||
JsonElement json = JsonParser.parseReader(resource.getValue().openAsReader());
|
||||
parseEntry(id, json, loadedEntries);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
for (Map.Entry<ResourceLocation, net.minecraft.server.packs.resources.Resource> resource : resourceManager.listResources("computer/disk", path -> path.getPath().endsWith(".json")).entrySet()) {
|
||||
ResourceLocation id = resourceId(resource.getKey(), "computer/disk");
|
||||
try {
|
||||
JsonElement json = JsonParser.parseReader(resource.getValue().openAsReader());
|
||||
parseDisk(id, json, loadedDisks);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
return new LoadedData(Map.copyOf(loadedEntries), Map.copyOf(loadedDisks));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void apply(LoadedData data, ResourceManager resourceManager, ProfilerFiller profiler) {
|
||||
entries = data.entries();
|
||||
disks = data.disks();
|
||||
}
|
||||
|
||||
private static ResourceLocation resourceId(ResourceLocation path, String directory) {
|
||||
String prefix = directory + "/";
|
||||
String value = path.getPath().startsWith(prefix) ? path.getPath().substring(prefix.length()) : path.getPath();
|
||||
if (value.endsWith(".json")) {
|
||||
value = value.substring(0, value.length() - 5);
|
||||
}
|
||||
return ResourceLocation.fromNamespaceAndPath(path.getNamespace(), value);
|
||||
}
|
||||
|
||||
private static void parseEntry(ResourceLocation id, JsonElement element, Map<ResourceLocation, Entry> target) {
|
||||
if (!element.isJsonObject()) {
|
||||
return;
|
||||
}
|
||||
JsonObject object = element.getAsJsonObject();
|
||||
String type = string(object, "type", "article");
|
||||
String category = string(object, "category", "general");
|
||||
String title = string(object, "title", "guide.antarchy.missing_title");
|
||||
String subtitle = string(object, "subtitle", "");
|
||||
List<String> description = strings(object.get("description"));
|
||||
String item = string(object, "item", "");
|
||||
String structure = string(object, "structure", "");
|
||||
String dimension = string(object, "dimension", "");
|
||||
target.put(id, new Entry(id, type, category, title, subtitle, description, item, structure, dimension));
|
||||
}
|
||||
|
||||
private static void parseDisk(ResourceLocation id, JsonElement element, Map<ResourceLocation, Disk> target) {
|
||||
if (!element.isJsonObject()) {
|
||||
return;
|
||||
}
|
||||
JsonObject object = element.getAsJsonObject();
|
||||
String category = string(object, "category", "general");
|
||||
String title = string(object, "title", "guide.antarchy.missing_disk_title");
|
||||
List<ResourceLocation> entryIds = new ArrayList<>();
|
||||
JsonElement entriesElement = object.get("entries");
|
||||
if (entriesElement != null && entriesElement.isJsonArray()) {
|
||||
for (JsonElement entry : entriesElement.getAsJsonArray()) {
|
||||
if (entry.isJsonPrimitive() && entry.getAsJsonPrimitive().isString()) {
|
||||
try {
|
||||
entryIds.add(ResourceLocation.parse(entry.getAsString()));
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
target.put(id, new Disk(id, category, title, List.copyOf(entryIds)));
|
||||
}
|
||||
|
||||
private static String string(JsonObject object, String key, String fallback) {
|
||||
JsonElement element = object.get(key);
|
||||
return element != null && element.isJsonPrimitive() ? element.getAsString() : fallback;
|
||||
}
|
||||
|
||||
private static List<String> strings(JsonElement element) {
|
||||
if (element == null) {
|
||||
return List.of();
|
||||
}
|
||||
if (element.isJsonPrimitive()) {
|
||||
return List.of(element.getAsString());
|
||||
}
|
||||
if (!element.isJsonArray()) {
|
||||
return List.of();
|
||||
}
|
||||
List<String> values = new ArrayList<>();
|
||||
JsonArray array = element.getAsJsonArray();
|
||||
for (JsonElement value : array) {
|
||||
if (value.isJsonPrimitive()) {
|
||||
values.add(value.getAsString());
|
||||
}
|
||||
}
|
||||
return List.copyOf(values);
|
||||
}
|
||||
|
||||
public record Entry(ResourceLocation id, String type, String category, String titleKey, String subtitleKey,
|
||||
List<String> descriptionKeys, String itemId, String structureId, String dimensionId) {
|
||||
}
|
||||
|
||||
public record Disk(ResourceLocation id, String category, String titleKey, List<ResourceLocation> entries) {
|
||||
}
|
||||
|
||||
record LoadedData(Map<ResourceLocation, Entry> entries, Map<ResourceLocation, Disk> disks) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.craisinlord.antarchy.content.item;
|
||||
|
||||
import com.craisinlord.antarchy.content.AntarchyObjects;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.TooltipFlag;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public final class FloppyDiskItem extends Item {
|
||||
public FloppyDiskItem(Properties properties) {
|
||||
super(properties.stacksTo(1));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getName(ItemStack stack) {
|
||||
ResourceLocation id = stack.get(AntarchyObjects.FLOPPY_DISK_COMPONENT.get());
|
||||
if (id != null) {
|
||||
var disk = com.craisinlord.antarchy.content.guide.ComputerGuideData.disk(id);
|
||||
if (disk != null) {
|
||||
return Component.translatable(disk.titleKey());
|
||||
}
|
||||
}
|
||||
return Component.translatable("item.antarchy.floppy_disk");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void appendHoverText(ItemStack stack, TooltipContext context, List<Component> tooltip, TooltipFlag flag) {
|
||||
ResourceLocation id = stack.get(AntarchyObjects.FLOPPY_DISK_COMPONENT.get());
|
||||
if (id != null) {
|
||||
var disk = com.craisinlord.antarchy.content.guide.ComputerGuideData.disk(id);
|
||||
if (disk != null) {
|
||||
tooltip.add(Component.translatable("guide.antarchy.category." + disk.category()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
-1
@@ -144,7 +144,9 @@ public final class KingsTreeGridFeature extends Feature<NoneFeatureConfiguration
|
||||
}
|
||||
double minimumY = baseY + 24.0D;
|
||||
double maximumY = baseY + 304.0D;
|
||||
double spawnY = (minimumY + maximumY) * 0.5D;
|
||||
// Start near the lower trunk so players on the ground can reliably engage the King.
|
||||
// The patrol bounds remain unchanged, allowing him to retreat upward through the tree.
|
||||
double spawnY = minimumY + 48.0D;
|
||||
// Start just outside the central trunk, inside the tree's authored footprint.
|
||||
king.moveTo(centerX + 48.5D, spawnY, centerZ + 0.5D, 90.0F, 0.0F);
|
||||
king.setTreePatrolHome(treeCenter, minimumY, maximumY, 0.0D);
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
{
|
||||
"format_version": "1.8.0",
|
||||
"animations": {
|
||||
"on_state": {
|
||||
"loop": true,
|
||||
"bones": {
|
||||
"on": {"scale": {"vector": [1, 1, 1]}},
|
||||
"white_flash": {"scale": {"vector": [0, 0, 0]}},
|
||||
"off": {"scale": {"vector": [0, 0, 0]}},
|
||||
"computer_on": {"scale": {"vector": [1, 1, 1]}}
|
||||
}
|
||||
},
|
||||
"off_state": {
|
||||
"loop": true,
|
||||
"bones": {
|
||||
"on": {"scale": {"vector": [0, 0, 0]}},
|
||||
"white_flash": {"scale": {"vector": [0, 0, 0]}},
|
||||
"off": {"scale": {"vector": [1, 1, 1]}},
|
||||
"computer_on": {"scale": {"vector": [0, 0, 0]}}
|
||||
}
|
||||
},
|
||||
"turn_on": {
|
||||
"loop": "hold_on_last_frame",
|
||||
"animation_length": 0.4583,
|
||||
"bones": {
|
||||
"on": {"scale": {"0.0": {"vector": [1, 0, 0]}, "0.125": {"vector": [1, 0, 0]}, "0.2917": {"vector": [1, 1, 1], "easing": "easeInOutCubic"}}},
|
||||
"white_flash": {"scale": {"0.0": {"vector": [1, 0, 0]}, "0.0417": {"vector": [1, 0.2, 0.2]}, "0.2083": {"vector": [1, 1, 1], "easing": "easeInOutQuint"}}},
|
||||
"off": {"scale": {"0.0": {"vector": [1, 1, 1]}}},
|
||||
"computer_on": {"scale": {"0.0": {"vector": [0, 0, 0]}, "0.0417": {"vector": [1, 1, 1]}}}
|
||||
}
|
||||
},
|
||||
"turn_off": {
|
||||
"loop": "hold_on_last_frame",
|
||||
"animation_length": 0.4583,
|
||||
"bones": {
|
||||
"on": {"scale": {"0.0": {"vector": [1, 1, 1]}, "0.25": {"vector": [1, 0, 1], "easing": "easeInOutQuint"}}},
|
||||
"white_flash": {"scale": {"0.0": {"vector": [1, 1, 0]}, "0.125": {"vector": [1, 1, 0]}, "0.375": {"vector": [1, 0, 0], "easing": "easeInOutQuart"}}},
|
||||
"off": {"scale": {"0.0": {"vector": [0, 0, 0]}, "0.0417": {"vector": [1, 1, 1]}}},
|
||||
"computer_on": {"scale": {"0.0": {"vector": [1, 1, 1]}, "0.25": {"vector": [1, 1, 1]}, "0.2917": {"vector": [0, 0, 0]}}}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"variants": {
|
||||
"": {
|
||||
"model": "antarchy:block/computer"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,189 @@
|
||||
{
|
||||
"format_version": "1.12.0",
|
||||
"minecraft:geometry": [
|
||||
{
|
||||
"description": {
|
||||
"identifier": "geometry.unknown",
|
||||
"texture_width": 128,
|
||||
"texture_height": 128,
|
||||
"visible_bounds_width": 2,
|
||||
"visible_bounds_height": 2.5,
|
||||
"visible_bounds_offset": [0, 0.75, 0]
|
||||
},
|
||||
"bones": [
|
||||
{
|
||||
"name": "computer",
|
||||
"pivot": [-5, 3, 1],
|
||||
"cubes": [
|
||||
{
|
||||
"origin": [-7, 0, -7],
|
||||
"size": [14, 4, 14],
|
||||
"uv": {
|
||||
"north": {"uv": [14, 14], "uv_size": [14, 4]},
|
||||
"east": {"uv": [0, 14], "uv_size": [14, 4]},
|
||||
"south": {"uv": [42, 14], "uv_size": [14, 4]},
|
||||
"west": {"uv": [28, 14], "uv_size": [14, 4]},
|
||||
"up": {"uv": [14, 0], "uv_size": [14, 14]},
|
||||
"down": {"uv": [28, 14], "uv_size": [14, -14]}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "computer_on",
|
||||
"parent": "computer",
|
||||
"pivot": [0, -1, 0.95],
|
||||
"cubes": [
|
||||
{
|
||||
"origin": [-6, 2, -7.05],
|
||||
"size": [3, 1, 0],
|
||||
"uv": {
|
||||
"north": {"uv": [97, 14], "uv_size": [3, 1]},
|
||||
"east": {"uv": [83, 14], "uv_size": [0, 1]},
|
||||
"south": {"uv": [125, 14], "uv_size": [3, 1]},
|
||||
"west": {"uv": [111, 14], "uv_size": [0, 1]},
|
||||
"up": {"uv": [97, 0], "uv_size": [3, 0]},
|
||||
"down": {"uv": [111, 0], "uv_size": [3, 0]}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "cables",
|
||||
"parent": "computer",
|
||||
"pivot": [-5, 3, 1],
|
||||
"cubes": [
|
||||
{
|
||||
"origin": [-2, 1, 5],
|
||||
"size": [0, 8, 3],
|
||||
"uv": {
|
||||
"north": {"uv": [13, 66], "uv_size": [0, 8]},
|
||||
"east": {"uv": [0, 66], "uv_size": [3, 8]},
|
||||
"south": {"uv": [26, 66], "uv_size": [0, 8]},
|
||||
"west": {"uv": [13, 66], "uv_size": [13, 8]},
|
||||
"up": {"uv": [13, 53], "uv_size": [0, 13]},
|
||||
"down": {"uv": [13, 66], "uv_size": [0, -13]}
|
||||
}
|
||||
},
|
||||
{
|
||||
"origin": [2, 1, 5],
|
||||
"size": [0, 8, 3],
|
||||
"uv": {
|
||||
"north": {"uv": [45, 51], "uv_size": [0, 8]},
|
||||
"east": {"uv": [32, 51], "uv_size": [3, 8]},
|
||||
"south": {"uv": [58, 51], "uv_size": [0, 8]},
|
||||
"west": {"uv": [45, 51], "uv_size": [13, 8]},
|
||||
"up": {"uv": [45, 38], "uv_size": [0, 13]},
|
||||
"down": {"uv": [45, 51], "uv_size": [0, -13]}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "monitor",
|
||||
"parent": "computer",
|
||||
"pivot": [0, 3, 0],
|
||||
"cubes": [
|
||||
{
|
||||
"origin": [-6, 4, -6],
|
||||
"size": [12, 11, 4],
|
||||
"uv": {
|
||||
"north": {"uv": [4, 42], "uv_size": [12, 11]},
|
||||
"east": {"uv": [0, 42], "uv_size": [4, 11]},
|
||||
"south": {"uv": [20, 42], "uv_size": [12, 11]},
|
||||
"west": {"uv": [16, 42], "uv_size": [4, 11]},
|
||||
"up": {"uv": [4, 38], "uv_size": [12, 4]}
|
||||
}
|
||||
},
|
||||
{
|
||||
"origin": [-5, 4, -5],
|
||||
"size": [10, 10, 10],
|
||||
"uv": {
|
||||
"north": {"uv": [10, 28], "uv_size": [10, 10]},
|
||||
"east": {"uv": [0, 28], "uv_size": [10, 10]},
|
||||
"south": {"uv": [30, 28], "uv_size": [10, 10]},
|
||||
"west": {"uv": [20, 28], "uv_size": [10, 10]},
|
||||
"up": {"uv": [10, 18], "uv_size": [10, 10]},
|
||||
"down": {"uv": [20, 28], "uv_size": [10, -10]}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "screens",
|
||||
"parent": "monitor",
|
||||
"pivot": [0.5, 2.9, 0.5]
|
||||
},
|
||||
{
|
||||
"name": "on",
|
||||
"parent": "screens",
|
||||
"pivot": [0, 9.4, -5.625],
|
||||
"cubes": [
|
||||
{
|
||||
"origin": [-5.5, 3.9, -5.6],
|
||||
"size": [11, 11, 0],
|
||||
"uv": {
|
||||
"north": {"uv": [77, 33], "uv_size": [17, 17]},
|
||||
"east": {"uv": [40, 18], "uv_size": [0, 11]},
|
||||
"south": {"uv": [51, 18], "uv_size": [11, 11]},
|
||||
"west": {"uv": [51, 18], "uv_size": [0, 11]},
|
||||
"up": {"uv": [40, 18], "uv_size": [11, 0]},
|
||||
"down": {"uv": [51, 18], "uv_size": [11, 0]}
|
||||
}
|
||||
},
|
||||
{
|
||||
"origin": [-5.5, 3.9, -5.65],
|
||||
"size": [11, 11, 0],
|
||||
"uv": {
|
||||
"north": {"uv": [98, 31.5], "uv_size": [17, 17]},
|
||||
"east": {"uv": [40, 18], "uv_size": [0, 11]},
|
||||
"south": {"uv": [51, 18], "uv_size": [11, 11]},
|
||||
"west": {"uv": [51, 18], "uv_size": [0, 11]},
|
||||
"up": {"uv": [40, 18], "uv_size": [11, 0]},
|
||||
"down": {"uv": [51, 18], "uv_size": [11, 0]}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "off",
|
||||
"parent": "screens",
|
||||
"pivot": [0, 9.4, -5.4],
|
||||
"cubes": [
|
||||
{
|
||||
"origin": [-5.5, 3.9, -5.4],
|
||||
"size": [11, 11, 0],
|
||||
"uv": {
|
||||
"north": {"uv": [77, 50], "uv_size": [17, 17]},
|
||||
"east": {"uv": [58, 29], "uv_size": [0, 11]},
|
||||
"south": {"uv": [62, 46], "uv_size": [11, 11]},
|
||||
"west": {"uv": [69, 29], "uv_size": [0, 11]},
|
||||
"up": {"uv": [58, 29], "uv_size": [11, 0]},
|
||||
"down": {"uv": [69, 29], "uv_size": [11, 0]}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "white_flash",
|
||||
"parent": "screens",
|
||||
"pivot": [0, 9.4, -5.55],
|
||||
"cubes": [
|
||||
{
|
||||
"origin": [-5.5, 3.9, -5.55],
|
||||
"size": [11, 11, 0],
|
||||
"uv": {
|
||||
"north": {"uv": [56, 0], "uv_size": [11, 11]},
|
||||
"east": {"uv": [56, 0], "uv_size": [0, 11]},
|
||||
"south": {"uv": [67, 0], "uv_size": [11, 11]},
|
||||
"west": {"uv": [67, 0], "uv_size": [0, 11]},
|
||||
"up": {"uv": [56, 0], "uv_size": [11, 0]},
|
||||
"down": {"uv": [67, 0], "uv_size": [11, 0]}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1441,4 +1441,30 @@
|
||||
,"menu.antarchy.royal_judgment": "Royal Judgment"
|
||||
,"enchantment.antarchy.feather_rising": "Feather Rising"
|
||||
,"enchantment.antarchy.chronosphere": "Chronosphere"
|
||||
,"block.antarchy.computer": "Computer"
|
||||
,"item.antarchy.computer": "Computer"
|
||||
,"item.antarchy.floppy_disk": "Floppy Disk"
|
||||
,"screen.antarchy.computer": "ANTARCHY ARCHIVE"
|
||||
,"guide.antarchy.category.general": "GENERAL"
|
||||
,"guide.antarchy.category.elythia": "ELYTHIA"
|
||||
,"guide.antarchy.category.thoraxis": "THORAXIS"
|
||||
,"guide.antarchy.category.cavaryn": "CAVARYN"
|
||||
,"guide.antarchy.missing_title": "CORRUPTED FILE"
|
||||
,"guide.antarchy.missing_disk_title": "UNREADABLE DISK"
|
||||
,"guide.antarchy.disk.introduction.title": "INITIAL BOOT NOTES"
|
||||
,"guide.antarchy.disk.chronosphere.title": "CHRONOSPHERE DATA"
|
||||
,"guide.antarchy.disk.toreterror_arena.title": "TORETERROR ARENA DATA"
|
||||
,"guide.antarchy.disk.high_fructose_corn_syrup.title": "CORN SYRUP DATA"
|
||||
,"guide.antarchy.entry.introduction.title": "SYSTEM INITIALIZED"
|
||||
,"guide.antarchy.entry.introduction.subtitle": "A machine for remembering what should have stayed forgotten."
|
||||
,"guide.antarchy.entry.introduction.description": "Insert recovered floppy disks to expand this archive. The machine remembers. The machine does not forgive."
|
||||
,"guide.antarchy.entry.chronosphere.title": "Chronosphere"
|
||||
,"guide.antarchy.entry.chronosphere.subtitle": "Temporal equipment record"
|
||||
,"guide.antarchy.entry.chronosphere.description": "A record for the Chronosphere enchantment will be expanded here. Further data is pending."
|
||||
,"guide.antarchy.entry.toreterror_arena.title": "Toreterror Arena"
|
||||
,"guide.antarchy.entry.toreterror_arena.subtitle": "Structure location fragment"
|
||||
,"guide.antarchy.entry.toreterror_arena.description": "The nearest arena is rumored to lie beyond the current horizon. Directional analysis is pending in this prototype."
|
||||
,"guide.antarchy.entry.high_fructose_corn_syrup.title": "High Fructose Corn Syrup"
|
||||
,"guide.antarchy.entry.high_fructose_corn_syrup.subtitle": "Nutritional and operational notes"
|
||||
,"guide.antarchy.entry.high_fructose_corn_syrup.description": "A sweet substance of uncertain strategic value. Doctoral enthusiasm surrounding it is statistically suspicious."
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "minecraft:block/cube_all",
|
||||
"textures": {
|
||||
"all": "antarchy:block/computer/computer"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"parent": "antarchy:block/computer"
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "minecraft:item/generated",
|
||||
"textures": {
|
||||
"layer0": "antarchy:item/floppy_disk/floppy_disk"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"category": "general",
|
||||
"title": "guide.antarchy.disk.chronosphere.title",
|
||||
"entries": ["antarchy:chronosphere"]
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"category": "general",
|
||||
"title": "guide.antarchy.disk.high_fructose_corn_syrup.title",
|
||||
"entries": ["antarchy:high_fructose_corn_syrup"]
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"category": "general",
|
||||
"title": "guide.antarchy.disk.introduction.title",
|
||||
"entries": ["antarchy:introduction"]
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"category": "elythia",
|
||||
"title": "guide.antarchy.disk.toreterror_arena.title",
|
||||
"entries": ["antarchy:toreterror_arena"]
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"type": "item",
|
||||
"category": "general",
|
||||
"title": "guide.antarchy.entry.chronosphere.title",
|
||||
"subtitle": "guide.antarchy.entry.chronosphere.subtitle",
|
||||
"description": ["guide.antarchy.entry.chronosphere.description"],
|
||||
"item": "antarchy:chronosphere"
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"type": "article",
|
||||
"category": "general",
|
||||
"title": "guide.antarchy.entry.high_fructose_corn_syrup.title",
|
||||
"subtitle": "guide.antarchy.entry.high_fructose_corn_syrup.subtitle",
|
||||
"description": ["guide.antarchy.entry.high_fructose_corn_syrup.description"]
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"type": "article",
|
||||
"category": "general",
|
||||
"title": "guide.antarchy.entry.introduction.title",
|
||||
"subtitle": "guide.antarchy.entry.introduction.subtitle",
|
||||
"description": ["guide.antarchy.entry.introduction.description"]
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"type": "structure",
|
||||
"category": "elythia",
|
||||
"title": "guide.antarchy.entry.toreterror_arena.title",
|
||||
"subtitle": "guide.antarchy.entry.toreterror_arena.subtitle",
|
||||
"description": ["guide.antarchy.entry.toreterror_arena.description"],
|
||||
"structure": "antarchy:toreterror_arena",
|
||||
"dimension": "antarchy:elythia"
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"type": "minecraft:chest",
|
||||
"pools": [
|
||||
{
|
||||
"rolls": 1,
|
||||
"entries": [
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "antarchy:floppy_disk",
|
||||
"weight": 1,
|
||||
"functions": [
|
||||
{
|
||||
"function": "minecraft:set_components",
|
||||
"components": {
|
||||
"antarchy:floppy_disk": "antarchy:chronosphere"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"type": "minecraft:crafting_shapeless",
|
||||
"ingredients": [
|
||||
{"item": "minecraft:iron_block"},
|
||||
{"item": "minecraft:iron_block"},
|
||||
{"item": "minecraft:iron_block"},
|
||||
{"item": "minecraft:comparator"},
|
||||
{"item": "minecraft:iron_ingot"}
|
||||
],
|
||||
"result": {
|
||||
"id": "antarchy:computer",
|
||||
"count": 1
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user