Add the insolator #17

Merged
BlakeRain merged 19 commits from BlakeRain/utamacraft:main into main 2023-12-01 18:20:57 +00:00
149 changed files with 3097 additions and 37 deletions

BIN
assets/bulb.afdesign Normal file

Binary file not shown.

BIN
assets/fiber_glass.afdesign Normal file

Binary file not shown.

BIN
assets/insolator.aup3 Normal file

Binary file not shown.

1
assets/insolator.bbmodel Normal file

File diff suppressed because one or more lines are too long

Binary file not shown.

BIN
assets/pcb.afdesign Normal file

Binary file not shown.

Binary file not shown.

View File

Before

Width:  |  Height:  |  Size: 266 B

After

Width:  |  Height:  |  Size: 266 B

View File

Before

Width:  |  Height:  |  Size: 408 B

After

Width:  |  Height:  |  Size: 408 B

View File

Before

Width:  |  Height:  |  Size: 560 B

After

Width:  |  Height:  |  Size: 560 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 970 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 974 B

Binary file not shown.

Binary file not shown.

View File

@ -2,6 +2,7 @@ plugins {
id 'eclipse'
id 'maven-publish'
id 'net.minecraftforge.gradle' version '6.0.+'
id 'org.parchmentmc.librarian.forgegradle' version '1.+'
}
wrapper {
@ -121,9 +122,6 @@ minecraft {
sourceSets.main.resources { srcDir 'src/generated/resources' }
repositories {
// Put repositories for dependencies here
// ForgeGradle automatically adds the Forge maven and Maven Central for you
// If you have mod jar dependencies in ./libs, you can declare them as a repository like so:
// flatDir {
// dir 'libs'
@ -135,6 +133,16 @@ repositories {
includeGroup("org.squiddev")
}
}
maven {
// location of the maven that hosts JEI files since January 2023
name = "Jared's maven"
url = "https://maven.blamejared.com/"
}
maven {
url 'https://modmaven.dev/'
}
}
dependencies {
@ -143,25 +151,17 @@ dependencies {
// The userdev artifact is a special name and will get all sorts of transformations applied to it.
minecraft "net.minecraftforge:forge:${minecraft_version}-${forge_version}"
// Real mod deobf dependency examples - these get remapped to your current mappings
// compileOnly fg.deobf("mezz.jei:jei-${mc_version}:${jei_version}:api") // Adds JEI API as a compile dependency
// runtimeOnly fg.deobf("mezz.jei:jei-${mc_version}:${jei_version}") // Adds the full JEI mod as a runtime dependency
// implementation fg.deobf("com.tterrag.registrate:Registrate:MC${mc_version}-${registrate_version}") // Adds registrate as a dependency
// compile against the JEI API but do not include it at runtime
compileOnly(fg.deobf("mezz.jei:jei-${minecraft_version}-common-api:${jei_version}"))
compileOnly(fg.deobf("mezz.jei:jei-${minecraft_version}-forge-api:${jei_version}"))
// at runtime, use the full JEI jar for Forge
runtimeOnly(fg.deobf("mezz.jei:jei-${minecraft_version}-forge:${jei_version}"))
// Examples using mod jars from ./libs
// implementation fg.deobf("blank:coolmod-${mc_version}:${coolmod_version}")
// CC:Tweaked API
implementation(fg.deobf("org.squiddev:cc-tweaked-${minecraft_version}:${cct_version}"))
// For more info...
// http://www.gradle.org/docs/current/userguide/artifact_dependencies_tutorial.html
// http://www.gradle.org/docs/current/userguide/dependency_management.html
// Vanilla (i.e. for multi-loader systems)
// compileOnly("cc.tweaked:cc-tweaked-${minecraft_version}-common-api:${cct_version}")
// Forge Gradle
// compileOnly("cc.tweaked:cc-tweaked-${minecraft_version}-core-api:${cct_version}")
// compileOnly(fg.deobf("cc.tweaked:cc-tweaked-${minecraft_version}-forge-api:${cct_version}"))
implementation fg.deobf("org.squiddev:cc-tweaked-${minecraft_version}:${cct_version}")
// Mekanism: useful for testing energy and so on.
runtimeOnly(fg.deobf("mekanism:Mekanism:${minecraft_version}-${mekanism_version}"))
}
// This task will expand all declared properties from Gradle (gradle.properties) in the specified resource targets.

View File

@ -30,15 +30,19 @@ loader_version_range=[41,)
#
# Parchment is an unofficial project maintained by ParchmentMC, separate from Minecraft Forge.
# Additional setup is needed to use their mappings, see https://parchmentmc.org/docs/getting-started
mapping_channel=official
mapping_channel=parchment
# The mapping version to query from the mapping channel.
# This must match the format required by the mapping channel.
mapping_version=1.19.2
mapping_version=2022.11.27-1.19.2
## Dependency Properties
# The version of CC:Tweaked we're building against
cct_version=1.101.3
# The version of JEI that we're building against
jei_version=11.6.0.1015
# The version of Mekanism we use when testing
mekanism_version=10.3.8.477
## Mod Properties
@ -50,7 +54,7 @@ mod_name=Utamacraft Mod
# The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default.
mod_license=MIT License
# The mod version. See https://semver.org/
mod_version=0.1.1-1.19
mod_version=0.2.0-1.19
# The group ID for the mod. It is only important when publishing as an artifact to a Maven repository.
# This should match the base package used for the mod sources.
# See https://maven.apache.org/guides/mini/guide-naming-conventions.html

View File

@ -2,5 +2,6 @@ pluginManagement {
repositories {
gradlePluginPortal()
maven { url = 'https://maven.minecraftforge.net/' }
maven { url = 'https://maven.parchmentmc.org' }
}
}

View File

@ -2,9 +2,17 @@ package net.banutama.utamacraft;
import com.mojang.logging.LogUtils;
import net.banutama.utamacraft.block.custom.InsolatorBlock;
import net.banutama.utamacraft.block.custom.ModBlocks;
import net.banutama.utamacraft.block.entity.ModBlockEntities;
import net.banutama.utamacraft.item.ModItems;
import net.banutama.utamacraft.block.ModBlocks;
import net.banutama.utamacraft.networking.ModMessages;
import net.banutama.utamacraft.recipe.ModRecipes;
import net.banutama.utamacraft.screen.InsolatorScreen;
import net.banutama.utamacraft.screen.ModMenuTypes;
import net.banutama.utamacraft.sound.ModSounds;
import net.minecraft.client.gui.screens.MenuScreens;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.eventbus.api.SubscribeEvent;
@ -28,19 +36,27 @@ public class Utamacraft {
ModItems.register(bus);
ModBlocks.register(bus);
ModBlockEntities.register(bus);
CCRegistration.register(bus);
ModMenuTypes.register(bus);
ModSounds.register(bus);
ModRecipes.register(bus);
bus.addListener(this::commonSetup);
MinecraftForge.EVENT_BUS.register(this);
}
private void commonSetup(final FMLCommonSetupEvent event) {
event.enqueueWork(() -> {
ModMessages.register();
});
}
@Mod.EventBusSubscriber(modid = MOD_ID, bus = Mod.EventBusSubscriber.Bus.MOD)
public static class ModEvents {
@SubscribeEvent
public static void onClientSetup(FMLClientSetupEvent event) {
MenuScreens.register(ModMenuTypes.INSOLATOR_MENU.get(), InsolatorScreen::new);
}
}
}

View File

@ -1,4 +1,4 @@
package net.banutama.utamacraft.block;
package net.banutama.utamacraft.block.custom;
import net.minecraft.ChatFormatting;
import net.minecraft.core.BlockPos;
@ -23,17 +23,17 @@ import org.jetbrains.annotations.Nullable;
import java.util.List;
public class EtherealGlass extends GlassBlock {
public EtherealGlass() {
public class EtherealGlassBlock extends GlassBlock {
public EtherealGlassBlock() {
super(getProperties());
}
private static Block.Properties getProperties() {
return Block.Properties.copy(Blocks.GLASS)
.isValidSpawn(EtherealGlass::blockSpawning)
.isRedstoneConductor(EtherealGlass::notSolid)
.isSuffocating(EtherealGlass::notSolid)
.isViewBlocking(EtherealGlass::notSolid);
.isValidSpawn(EtherealGlassBlock::blockSpawning)
.isRedstoneConductor(EtherealGlassBlock::notSolid)
.isSuffocating(EtherealGlassBlock::notSolid)
.isViewBlocking(EtherealGlassBlock::notSolid);
}
@Override

View File

@ -0,0 +1,138 @@
package net.banutama.utamacraft.block.custom;
import net.banutama.utamacraft.block.entity.InsolatorBlockEntity;
import net.banutama.utamacraft.block.entity.ModBlockEntities;
import net.banutama.utamacraft.sound.ModSounds;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.util.RandomSource;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.*;
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.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.block.state.properties.BooleanProperty;
import net.minecraft.world.level.block.state.properties.DirectionProperty;
import net.minecraft.world.level.material.Material;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
import net.minecraftforge.network.NetworkHooks;
import org.jetbrains.annotations.Nullable;
public class InsolatorBlock extends BaseEntityBlock {
public static final DirectionProperty FACING = BlockStateProperties.HORIZONTAL_FACING;
public static final BooleanProperty ACTIVE = BooleanProperty.create("active");
private static VoxelShape SHAPE =
Block.box(0, 0, 0, 16, 16, 16);
public InsolatorBlock() {
super(getProperties());
registerDefaultState(this.getStateDefinition().any().setValue(FACING, Direction.NORTH).setValue(ACTIVE, false));
}
private static Block.Properties getProperties() {
return Block.Properties.of(Material.METAL)
.strength(6.0f)
.requiresCorrectToolForDrops()
.noOcclusion()
.lightLevel(state -> state.getValue(ACTIVE) ? 15 : 0);
}
@Override
public VoxelShape getShape(BlockState state, BlockGetter getter, BlockPos pos, CollisionContext context) {
return SHAPE;
}
@Nullable
@Override
public BlockState getStateForPlacement(BlockPlaceContext context) {
return this.defaultBlockState().setValue(FACING, context.getHorizontalDirection().getOpposite());
}
@Override
public BlockState rotate(BlockState state, Rotation rotation) {
return state.setValue(FACING, rotation.rotate(state.getValue(FACING)));
}
@Override
public BlockState mirror(BlockState state, Mirror mirror) {
return state.rotate(mirror.getRotation(state.getValue(FACING)));
}
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
builder.add(FACING, ACTIVE);
}
@Override
public RenderShape getRenderShape(BlockState pState) {
return RenderShape.MODEL;
}
@Override
public void onRemove(BlockState pState, Level pLevel, BlockPos pPos, BlockState pNewState, boolean pIsMoving) {
if (!pState.is(pNewState.getBlock())) {
BlockEntity blockEntity = pLevel.getBlockEntity(pPos);
if (blockEntity instanceof InsolatorBlockEntity insolator) {
if (pLevel instanceof ServerLevel) {
insolator.drops();
}
pLevel.updateNeighbourForOutputSignal(pPos, this);
}
}
super.onRemove(pState, pLevel, pPos, pNewState, pIsMoving);
}
@Override
public InteractionResult use(BlockState pState, Level pLevel, BlockPos pPos, Player pPlayer, InteractionHand pHand, BlockHitResult pHit) {
if (!pLevel.isClientSide()) {
BlockEntity blockEntity = pLevel.getBlockEntity(pPos);
if (blockEntity instanceof InsolatorBlockEntity insolatorEntity) {
NetworkHooks.openScreen((ServerPlayer)pPlayer, insolatorEntity, pPos);
} else {
throw new IllegalStateException("Our container provider is missing");
}
}
return InteractionResult.sidedSuccess(pLevel.isClientSide());
}
@Nullable
@Override
public BlockEntity newBlockEntity(BlockPos pPos, BlockState pState) {
return new InsolatorBlockEntity(pPos, pState);
}
@Nullable
@Override
public <T extends BlockEntity> BlockEntityTicker<T> getTicker(Level pLevel, BlockState pState, BlockEntityType<T> pBlockEntityType) {
return pLevel.isClientSide ? null : createTickerHelper(pBlockEntityType, ModBlockEntities.INSOLATOR.get(), InsolatorBlockEntity::serverTick);
}
@Override
public void animateTick(BlockState pState, Level pLevel, BlockPos pPos, RandomSource pRandom) {
if (pState.getValue(ACTIVE)) {
if (pRandom.nextDouble() < 1.0d) {
pLevel.playLocalSound(
pPos.getX() + 0.5, pPos.getY() + 0.5, pPos.getZ() + 0.5,
ModSounds.INSOLATOR.get(), SoundSource.BLOCKS, 0.1f, 1.0f, false);
}
}
}
}

View File

@ -1,13 +1,18 @@
package net.banutama.utamacraft.block;
package net.banutama.utamacraft.block.custom;
import java.util.function.Supplier;
import net.banutama.utamacraft.Utamacraft;
import net.banutama.utamacraft.block.custom.EtherealGlassBlock;
import net.banutama.utamacraft.block.custom.TintedEtherealGlassBlock;
import net.banutama.utamacraft.block.custom.InsolatorBlock;
import net.banutama.utamacraft.item.ModCreativeModeTab;
import net.banutama.utamacraft.item.ModItems;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.Item;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.material.Material;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.ForgeRegistries;
@ -19,9 +24,16 @@ public class ModBlocks {
DeferredRegister.create(ForgeRegistries.BLOCKS, Utamacraft.MOD_ID);
public static final RegistryObject<Block> ETHEREAL_GLASS =
registerBlock("ethereal_glass", EtherealGlass::new);
registerBlock("ethereal_glass", EtherealGlassBlock::new);
public static final RegistryObject<Block> TINTED_ETHEREAL_GLASS =
registerBlock("tinted_ethereal_glass", TintedEtherealGlass::new);
registerBlock("tinted_ethereal_glass", TintedEtherealGlassBlock::new);
public static final RegistryObject<Block> TUNGSTEN_BLOCK =
registerBlock("tungsten_block",
() -> new Block(BlockBehaviour.Properties.of(Material.METAL)
.strength(12.0f)
.requiresCorrectToolForDrops()));
public static final RegistryObject<Block> INSOLATOR =
registerBlock("insolator", InsolatorBlock::new);
private static <T extends Block> RegistryObject<T> registerBlock(String name, Supplier<T> block) {
RegistryObject<T> registered_block = BLOCKS.register(name, block);

View File

@ -1,10 +1,10 @@
package net.banutama.utamacraft.block;
package net.banutama.utamacraft.block.custom;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.block.state.BlockState;
public class TintedEtherealGlass extends EtherealGlass {
public class TintedEtherealGlassBlock extends EtherealGlassBlock {
@Override
public int getLightBlock(BlockState state, BlockGetter world, BlockPos pos) {
return world.getMaxLightLevel();

View File

@ -0,0 +1,365 @@
package net.banutama.utamacraft.block.entity;
import com.mojang.logging.LogUtils;
import net.banutama.utamacraft.block.custom.InsolatorBlock;
import net.banutama.utamacraft.networking.ModMessages;
import net.banutama.utamacraft.networking.packet.EnergySyncPacket;
import net.banutama.utamacraft.networking.packet.FluidSyncPacket;
import net.banutama.utamacraft.networking.packet.ItemStackSyncPacket;
import net.banutama.utamacraft.recipe.InsolatorRecipe;
import net.banutama.utamacraft.screen.InsolatorMenu;
import net.banutama.utamacraft.util.ModEnergyStorage;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.NonNullList;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component;
import net.minecraft.world.Containers;
import net.minecraft.world.MenuProvider;
import net.minecraft.world.SimpleContainer;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.inventory.ContainerData;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.material.Fluids;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.ForgeCapabilities;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.energy.IEnergyStorage;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.capability.IFluidHandler;
import net.minecraftforge.fluids.capability.templates.FluidTank;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.ItemHandlerHelper;
import net.minecraftforge.items.ItemStackHandler;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import java.util.Optional;
public class InsolatorBlockEntity extends BlockEntity implements MenuProvider, EnergySyncPacket.EnergySyncReceiver, FluidSyncPacket.FluidSyncReceiver, ItemStackSyncPacket.ItemStackSyncReceiver {
private static final Logger LOGGER = LogUtils.getLogger();
private final ItemStackHandler itemHandler = new ItemStackHandler(3) {
@Override
protected void onContentsChanged(int slot) {
setChanged();
if (level != null && !level.isClientSide()) {
ModMessages.sendToClients(new ItemStackSyncPacket(this, worldPosition));
}
}
@Override
public boolean isItemValid(int slot, @NotNull ItemStack stack) {
return switch (slot) {
case 0 -> stack.getCapability(ForgeCapabilities.FLUID_HANDLER_ITEM).isPresent();
case 1 -> true;
case 2 -> false;
default -> super.isItemValid(slot, stack);
};
}
};
@Override
public void receiveItemStack(NonNullList<ItemStack> stacks) {
for (int slot = 0; slot < stacks.size(); ++slot) {
itemHandler.setStackInSlot(slot, stacks.get(slot));
}
}
private static final int ENERGY_REQUIRED = 32;
private final ModEnergyStorage energyStorage = new ModEnergyStorage(60000, 256) {
@Override
public void onEnergyChanged() {
setChanged();
ModMessages.sendToClients(new EnergySyncPacket(energy, capacity, getBlockPos()));
}
};
public IEnergyStorage getEnergyStorage() {
return this.energyStorage;
}
@Override
public void receiveEnergySync(int energy, int capacity) {
energyStorage.setEnergy(energy);
}
private final FluidTank fluidTank = new FluidTank(64000) {
@Override
protected void onContentsChanged() {
setChanged();
if (level != null && !level.isClientSide()) {
ModMessages.sendToClients(new FluidSyncPacket(fluid, worldPosition));
}
}
@Override
public boolean isFluidValid(FluidStack stack) {
return stack.getFluid() == Fluids.WATER;
}
};
public FluidStack getFluidStack() {
return fluidTank.getFluid();
}
@Override
public void receiveFluidSync(FluidStack fluid) {
fluidTank.setFluid(fluid);
}
private LazyOptional<IItemHandler> lazyItemHandler = LazyOptional.empty();
private LazyOptional<IEnergyStorage> lazyEnergyStorage = LazyOptional.empty();
private LazyOptional<IFluidHandler> lazyFluidHandler = LazyOptional.empty();
protected final ContainerData data;
private int progress = 0;
private int maxProgress = 500;
private boolean active = false;
public InsolatorBlockEntity(BlockPos pPos, BlockState pBlockState) {
super(ModBlockEntities.INSOLATOR.get(), pPos, pBlockState);
this.data = new ContainerData() {
@Override
public int get(int pIndex) {
return switch (pIndex) {
case 0 -> InsolatorBlockEntity.this.progress;
case 1 -> InsolatorBlockEntity.this.maxProgress;
case 2 -> InsolatorBlockEntity.this.active ? 1 : 0;
default -> 0;
};
}
@Override
public void set(int pIndex, int pValue) {
switch (pIndex) {
case 0 -> InsolatorBlockEntity.this.progress = pValue;
case 1 -> InsolatorBlockEntity.this.maxProgress = pValue;
case 2 -> InsolatorBlockEntity.this.active = pValue != 0;
}
}
@Override
public int getCount() {
return 3;
}
};
}
@Override
public @NotNull Component getDisplayName() {
return Component.translatable("block_entity.utamacraft.insolator");
}
@Nullable
@Override
public AbstractContainerMenu createMenu(int pContainerId, @NotNull Inventory pPlayerInventory, @NotNull Player pPlayer) {
ModMessages.sendToClients(new EnergySyncPacket(this.energyStorage.getEnergyStored(), this.energyStorage.getMaxEnergyStored(), getBlockPos()));
ModMessages.sendToClients(new FluidSyncPacket(this.fluidTank.getFluid(), getBlockPos()));
return new InsolatorMenu(pContainerId, pPlayerInventory, this, this.data);
}
@Override
public @NotNull <T> LazyOptional<T> getCapability(@NotNull Capability<T> cap, @Nullable Direction side) {
if (cap == ForgeCapabilities.ENERGY) {
return lazyEnergyStorage.cast();
}
if (cap == ForgeCapabilities.ITEM_HANDLER) {
return lazyItemHandler.cast();
}
if (cap == ForgeCapabilities.FLUID_HANDLER) {
return lazyFluidHandler.cast();
}
return super.getCapability(cap, side);
}
@Override
public void onLoad() {
super.onLoad();
lazyItemHandler = LazyOptional.of(() -> itemHandler);
lazyEnergyStorage = LazyOptional.of(() -> energyStorage);
lazyFluidHandler = LazyOptional.of(() -> fluidTank);
}
@Override
public void invalidateCaps() {
super.invalidateCaps();
lazyItemHandler.invalidate();
lazyEnergyStorage.invalidate();
lazyFluidHandler.invalidate();
}
@Override
protected void saveAdditional(CompoundTag nbt) {
nbt.put("inventory", itemHandler.serializeNBT());
nbt.putInt("insolator.progress", progress);
nbt.putInt("insolator.energy", energyStorage.getEnergyStored());
fluidTank.writeToNBT(nbt);
super.saveAdditional(nbt);
}
@Override
public void load(@NotNull CompoundTag nbt) {
super.load(nbt);
itemHandler.deserializeNBT(nbt.getCompound("inventory"));
progress = nbt.getInt("insolator.progress");
energyStorage.setEnergy(nbt.getInt("insolator.energy"));
fluidTank.readFromNBT(nbt);
}
public void drops() {
SimpleContainer inventory = new SimpleContainer(itemHandler.getSlots());
for (int slot = 0; slot < itemHandler.getSlots(); ++slot) {
inventory.setItem(slot, itemHandler.getStackInSlot(slot));
}
if (this.level != null) {
Containers.dropContents(this.level, this.worldPosition, inventory);
} else {
LOGGER.warn("Unable to drop inventory contents due to lack of level");
}
}
public static void serverTick(Level level, BlockPos pos, BlockState state, InsolatorBlockEntity entity) {
if (level.isClientSide()) {
return;
}
boolean newActive;
if (entity.canCraft().isPresent() && entity.hasEnoughEnergy()) {
++entity.progress;
newActive = true;
entity.energyStorage.extractEnergy(ENERGY_REQUIRED, false);
setChanged(level, pos, state);
if (entity.progress >= entity.maxProgress) {
entity.craftItem();
}
} else {
entity.resetProgress();
newActive = false;
setChanged(level, pos, state);
}
if (newActive != entity.active) {
entity.active = newActive;
state = state.setValue(InsolatorBlock.ACTIVE, newActive);
level.setBlock(pos, state, 3);
}
ItemStack fluid = entity.itemHandler.getStackInSlot(0);
if (fluid.getCount() > 0) {
fluid.getCapability(ForgeCapabilities.FLUID_HANDLER_ITEM).ifPresent(handler -> {
// Remove as much as we need, but no more than a bucket
int amount = Math.min(entity.fluidTank.getSpace(), 1000);
// Simulate removal of that amount from the IFluidHandlerItem
FluidStack stack = handler.drain(amount, IFluidHandler.FluidAction.SIMULATE);
// Ensure that the fluid we would use is valid
if (entity.fluidTank.isFluidValid(stack)) {
// Remove the amount of fluid from the IFluidHandlerItem
stack = handler.drain(amount, IFluidHandler.FluidAction.EXECUTE);
// Fill our fluid tank with the fluid stack we drained from the IFluidHandlerItem
entity.fluidTank.fill(stack, IFluidHandler.FluidAction.EXECUTE);
// Extract the current item from the fluid slot? TODO: Should this be when empty?
entity.itemHandler.extractItem(0, 1, false);
entity.itemHandler.insertItem(0, handler.getContainer(), false);
}
});
}
}
private void resetProgress() {
this.progress = 0;
}
private void craftItem() {
Optional<InsolatorRecipe> recipe = canCraft();
if (recipe.isEmpty()) {
return;
}
// Drain the amount of fluid specified in our recipe from the fluid tank
fluidTank.drain(recipe.get().getFluid().getAmount(), IFluidHandler.FluidAction.EXECUTE);
// Remove an item from the input slot.
itemHandler.extractItem(1, 1, false);
// Insert the recipe output in to the output slot.
ItemStack output = itemHandler.getStackInSlot(2);
if (output.isEmpty()) {
itemHandler.setStackInSlot(2, recipe.get().getResultItem().copy());
} else {
output.grow(recipe.get().getResultItem().getCount());
}
resetProgress();
}
private boolean hasEnoughEnergy() {
return energyStorage.getEnergyStored() >= ENERGY_REQUIRED * maxProgress;
}
private Optional<InsolatorRecipe> canCraft() {
Optional<InsolatorRecipe> recipe = getRecipe();
if (recipe.isEmpty()) {
// LOGGER.info("Insolator cannot find recipe");
return Optional.empty();
}
// Make sure that the correct fluid is in the tank.
if (!fluidTank.getFluid().equals(recipe.get().getFluid())) {
// LOGGER.info("Insolator does not have correct fluid; contains {}, expected {}",
// fluidTank.getFluid().getFluid(), recipe.get().getFluid().getFluid());
return Optional.empty();
}
// Ensure that we have enough fluid
if (fluidTank.getFluidAmount() < recipe.get().getFluid().getAmount()) {
// LOGGER.info("Insolator has {} of fluid; recipe requires {}", fluidTank.getFluidAmount(), recipe.get().getFluid().getAmount());
return Optional.empty();
}
ItemStack output = itemHandler.getStackInSlot(2);
// If the output isn't empty, and the item in the output is different to the output of the recipe, we cannot process.
if (!output.isEmpty() && output.getItem() != recipe.get().getResultItem().getItem()) {
// LOGGER.info("Cannot run insolator, as output item is not the same as the recipe output");
return Optional.empty();
}
// Make sure that the output is not saturated.
if (output.getCount() + recipe.get().getResultItem().getCount() > output.getMaxStackSize()) {
// LOGGER.info("Cannot run insolator, as output of {} items exceeds maximum of {}", output.getCount(), output.getMaxStackSize());
return Optional.empty();
}
return recipe;
}
private Optional<InsolatorRecipe> getRecipe() {
if (level == null) {
return Optional.empty();
}
SimpleContainer inventory = new SimpleContainer(itemHandler.getSlots());
for (int slot = 0; slot < itemHandler.getSlots(); ++slot) {
inventory.setItem(slot, itemHandler.getStackInSlot(slot));
}
return level.getRecipeManager()
.getRecipeFor(InsolatorRecipe.Type.INSTANCE, inventory, level);
}
}

View File

@ -0,0 +1,22 @@
package net.banutama.utamacraft.block.entity;
import net.banutama.utamacraft.Utamacraft;
import net.banutama.utamacraft.block.custom.ModBlocks;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.registries.RegistryObject;
public class ModBlockEntities {
public static final DeferredRegister<BlockEntityType<?>> BLOCK_ENTITIES =
DeferredRegister.create(ForgeRegistries.BLOCK_ENTITY_TYPES, Utamacraft.MOD_ID);
public static final RegistryObject<BlockEntityType<InsolatorBlockEntity>> INSOLATOR =
BLOCK_ENTITIES.register("insolator", () ->
BlockEntityType.Builder.of(InsolatorBlockEntity::new, ModBlocks.INSOLATOR.get()).build(null));
public static void register(IEventBus bus) {
BLOCK_ENTITIES.register(bus);
}
}

View File

@ -13,9 +13,18 @@ public class ModItems {
public static final RegistryObject<Item> LOGO =
ITEMS.register("utamacraft_logo", () -> new Item(new Item.Properties()));
public static final RegistryObject<Item> PLAYER_PERIPHERAL =
ITEMS.register("player_peripheral", PlayerPeripheralItem::new);
public static final RegistryObject<Item> TUNGSTEN_INGOT =
ITEMS.register("tungsten_ingot", () -> new Item(new Item.Properties().tab(ModCreativeModeTab.TAB)));
public static final RegistryObject<Item> RAW_TUNGSTEN =
ITEMS.register("raw_tungsten", () -> new Item(new Item.Properties().tab(ModCreativeModeTab.TAB)));
public static final RegistryObject<Item> FIBER_GLASS =
ITEMS.register("fiber_glass", () -> new Item(new Item.Properties().tab(ModCreativeModeTab.TAB)));
public static final RegistryObject<Item> PCB =
ITEMS.register("pcb", () -> new Item(new Item.Properties().tab(ModCreativeModeTab.TAB)));
public static final RegistryObject<Item> BULB =
ITEMS.register("bulb", () -> new Item(new Item.Properties().tab(ModCreativeModeTab.TAB)));
public static void register(IEventBus eventBus) {
ITEMS.register(eventBus);

View File

@ -0,0 +1,55 @@
package net.banutama.utamacraft.networking;
import net.banutama.utamacraft.Utamacraft;
import net.banutama.utamacraft.networking.packet.EnergySyncPacket;
import net.banutama.utamacraft.networking.packet.FluidSyncPacket;
import net.banutama.utamacraft.networking.packet.ItemStackSyncPacket;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerPlayer;
import net.minecraftforge.network.NetworkDirection;
import net.minecraftforge.network.NetworkRegistry;
import net.minecraftforge.network.PacketDistributor;
import net.minecraftforge.network.simple.SimpleChannel;
public class ModMessages {
public static SimpleChannel INSTANCE;
public static void register() {
INSTANCE = NetworkRegistry.ChannelBuilder
.named(new ResourceLocation(Utamacraft.MOD_ID, "messages"))
.networkProtocolVersion(() -> "1.0")
.clientAcceptedVersions(s -> true)
.serverAcceptedVersions(s -> true)
.simpleChannel();
INSTANCE.messageBuilder(EnergySyncPacket.class, 0x0001, NetworkDirection.PLAY_TO_CLIENT)
.encoder(EnergySyncPacket::toBytes)
.decoder(EnergySyncPacket::new)
.consumerMainThread(EnergySyncPacket::handle)
.add();
INSTANCE.messageBuilder(FluidSyncPacket.class, 0x0002, NetworkDirection.PLAY_TO_CLIENT)
.encoder(FluidSyncPacket::toBytes)
.decoder(FluidSyncPacket::new)
.consumerMainThread(FluidSyncPacket::handle)
.add();
INSTANCE.messageBuilder(ItemStackSyncPacket.class, 0x0003, NetworkDirection.PLAY_TO_CLIENT)
.encoder(ItemStackSyncPacket::toBytes)
.decoder(ItemStackSyncPacket::new)
.consumerMainThread(ItemStackSyncPacket::handle)
.add();
}
public static <T> void sendToServer(T message) {
INSTANCE.sendToServer(message);
}
public static <T> void sendToPlayer(T message, ServerPlayer player) {
INSTANCE.send(PacketDistributor.PLAYER.with(() -> player), message);
}
public static <T> void sendToClients(T message) {
INSTANCE.send(PacketDistributor.ALL.noArg(), message);
}
}

View File

@ -0,0 +1,11 @@
package net.banutama.utamacraft.networking.packet;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraftforge.network.NetworkEvent;
import java.util.function.Supplier;
public abstract class BasePacket {
public abstract void toBytes(FriendlyByteBuf buf);
public abstract boolean handle(Supplier<NetworkEvent.Context> supplier);
}

View File

@ -0,0 +1,73 @@
package net.banutama.utamacraft.networking.packet;
import net.minecraft.client.Minecraft;
import net.minecraft.core.BlockPos;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraftforge.network.NetworkEvent;
import org.jetbrains.annotations.NotNull;
import java.util.function.Supplier;
public class EnergySyncPacket extends BasePacket {
private final int energy;
private final int capacity;
private final BlockPos pos;
public EnergySyncPacket(int energy, int capacity, BlockPos pos) {
this.energy = energy;
this.capacity = capacity;
this.pos = pos;
}
public EnergySyncPacket(@NotNull FriendlyByteBuf buf) {
this.energy = buf.readInt();
this.capacity = buf.readInt();
this.pos = buf.readBlockPos();
}
@Override
public void toBytes(@NotNull FriendlyByteBuf buf) {
buf.writeInt(energy);
buf.writeInt(capacity);
buf.writeBlockPos(pos);
}
@Override
public boolean handle(@NotNull Supplier<NetworkEvent.Context> supplier) {
NetworkEvent.Context context = supplier.get();
context.enqueueWork(() -> {
Level level = Minecraft.getInstance().level;
if (level == null) {
return;
}
BlockEntity blockEntity = level.getBlockEntity(pos);
if (blockEntity instanceof EnergySyncReceiver energyReceiver) {
energyReceiver.receiveEnergySync(energy, capacity);
Player player = Minecraft.getInstance().player;
if (player == null) {
return;
}
if (player.containerMenu instanceof EnergySyncReceiverMenu menu &&
menu.getBlockEntity().getBlockPos().equals(pos)) {
menu.receiveEnergySync(energy, capacity);
}
}
});
return true;
}
public interface EnergySyncReceiver {
void receiveEnergySync(int energy, int capacity);
}
public interface EnergySyncReceiverMenu extends EnergySyncReceiver {
BlockEntity getBlockEntity();
}
}

View File

@ -0,0 +1,70 @@
package net.banutama.utamacraft.networking.packet;
import net.minecraft.client.Minecraft;
import net.minecraft.core.BlockPos;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.network.NetworkEvent;
import org.jetbrains.annotations.NotNull;
import java.util.function.Supplier;
public class FluidSyncPacket extends BasePacket {
private final FluidStack fluid;
private final BlockPos pos;
public FluidSyncPacket(FluidStack fluid, BlockPos pos) {
this.fluid = fluid;
this.pos = pos;
}
public FluidSyncPacket(@NotNull FriendlyByteBuf buf) {
this.fluid = buf.readFluidStack();
this.pos = buf.readBlockPos();
}
@Override
public void toBytes(@NotNull FriendlyByteBuf buf) {
buf.writeFluidStack(fluid);
buf.writeBlockPos(pos);
}
@Override
public boolean handle(@NotNull Supplier<NetworkEvent.Context> supplier) {
NetworkEvent.Context context = supplier.get();
context.enqueueWork(() -> {
Level level = Minecraft.getInstance().level;
if (level == null) {
return;
}
BlockEntity blockEntity = level.getBlockEntity(pos);
if (blockEntity instanceof FluidSyncReceiver fluidSyncReceiver) {
fluidSyncReceiver.receiveFluidSync(fluid.copy());
Player player = Minecraft.getInstance().player;
if (player == null) {
return;
}
if (player.containerMenu instanceof FluidSyncReceiverMenu menu &&
menu.getBlockEntity().getBlockPos().equals(pos)) {
menu.receiveFluidSync(fluid);
}
}
});
return true;
}
public interface FluidSyncReceiver {
void receiveFluidSync(FluidStack fluid);
}
public interface FluidSyncReceiverMenu extends FluidSyncReceiver {
BlockEntity getBlockEntity();
}
}

View File

@ -0,0 +1,73 @@
package net.banutama.utamacraft.networking.packet;
import net.minecraft.client.Minecraft;
import net.minecraft.core.BlockPos;
import net.minecraft.core.NonNullList;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.network.NetworkEvent;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Supplier;
public class ItemStackSyncPacket extends BasePacket {
private final NonNullList<ItemStack> stacks;
private final BlockPos pos;
public ItemStackSyncPacket(NonNullList<ItemStack> stacks, BlockPos pos) {
this.stacks = stacks;
this.pos = pos;
}
public ItemStackSyncPacket(IItemHandler handler, BlockPos pos) {
this.stacks = NonNullList.create();
for (int slot = 0; slot < handler.getSlots(); ++slot) {
this.stacks.add(handler.getStackInSlot(slot));
}
this.pos = pos;
}
public ItemStackSyncPacket(@NotNull FriendlyByteBuf buf) {
List<ItemStack> stacks = buf.readCollection(ArrayList::new, FriendlyByteBuf::readItem);
this.stacks = NonNullList.withSize(stacks.size(), ItemStack.EMPTY);
for (int slot = 0; slot < stacks.size(); ++slot) {
this.stacks.set(slot, stacks.get(slot));
}
this.pos = buf.readBlockPos();
}
@Override
public void toBytes(FriendlyByteBuf buf) {
buf.writeCollection(this.stacks, FriendlyByteBuf::writeItem);
buf.writeBlockPos(pos);
}
@Override
public boolean handle(@NotNull Supplier<NetworkEvent.Context> supplier) {
NetworkEvent.Context context = supplier.get();
context.enqueueWork(() -> {
Level level = Minecraft.getInstance().level;
if (level == null) {
return;
}
BlockEntity blockEntity = level.getBlockEntity(pos);
if (blockEntity instanceof ItemStackSyncReceiver receiver) {
receiver.receiveItemStack(stacks);
}
});
return true;
}
public interface ItemStackSyncReceiver {
void receiveItemStack(NonNullList<ItemStack> handler);
}
}

View File

@ -0,0 +1,108 @@
package net.banutama.utamacraft.recipe;
import com.google.gson.JsonObject;
import com.mojang.serialization.JsonOps;
import net.banutama.utamacraft.Utamacraft;
import net.minecraft.core.NonNullList;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.GsonHelper;
import net.minecraft.world.SimpleContainer;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.*;
import net.minecraft.world.level.Level;
import net.minecraftforge.fluids.FluidStack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class InsolatorRecipe implements Recipe<SimpleContainer> {
private final ResourceLocation id;
private final ItemStack output;
private final Ingredient input;
private final FluidStack fluid;
public InsolatorRecipe(ResourceLocation id, ItemStack output, Ingredient input, FluidStack fluid) {
this.id = id;
this.output = output;
this.input = input;
this.fluid = fluid;
}
@Override
public boolean matches(@NotNull SimpleContainer pContainer, @NotNull Level pLevel) {
if (pLevel.isClientSide()) {
return false;
}
return input.test(pContainer.getItem(1));
}
@Override
public @NotNull ItemStack assemble(@NotNull SimpleContainer pContainer) {
return output;
}
@Override
public boolean canCraftInDimensions(int pWidth, int pHeight) {
return true;
}
public FluidStack getFluid() {
return fluid;
}
@Override
public @NotNull ItemStack getResultItem() {
return output.copy();
}
@Override
public @NotNull ResourceLocation getId() {
return id;
}
@Override
public @NotNull RecipeSerializer<?> getSerializer() {
return Serializer.INSTANCE;
}
@Override
public @NotNull RecipeType<?> getType() {
return Type.INSTANCE;
}
public static class Type implements RecipeType<InsolatorRecipe> {
public static final Type INSTANCE = new Type();
public static final String ID = "insolator";
private Type() {
}
}
public static class Serializer implements RecipeSerializer<InsolatorRecipe> {
public static final Serializer INSTANCE = new Serializer();
public static final ResourceLocation ID = new ResourceLocation(Utamacraft.MOD_ID, "insolator");
@Override
public @NotNull InsolatorRecipe fromJson(@NotNull ResourceLocation pRecipeId, @NotNull JsonObject pSerializedRecipe) {
ItemStack output = ShapedRecipe.itemStackFromJson(GsonHelper.getAsJsonObject(pSerializedRecipe, "output"));
Ingredient input = Ingredient.fromJson(pSerializedRecipe.getAsJsonObject("input"));
FluidStack fluid = FluidStack.CODEC.decode(JsonOps.INSTANCE, pSerializedRecipe.get("fluid")).result().orElseThrow().getFirst();
return new InsolatorRecipe(pRecipeId, output, input, fluid);
}
@Override
public @Nullable InsolatorRecipe fromNetwork(@NotNull ResourceLocation pRecipeId, @NotNull FriendlyByteBuf pBuffer) {
ItemStack output = pBuffer.readItem();
Ingredient input = Ingredient.fromNetwork(pBuffer);
FluidStack fluid = pBuffer.readFluidStack();
return new InsolatorRecipe(pRecipeId, output, input, fluid);
}
@Override
public void toNetwork(@NotNull FriendlyByteBuf pBuffer, @NotNull InsolatorRecipe pRecipe) {
pBuffer.writeItemStack(pRecipe.output, false);
pRecipe.input.toNetwork(pBuffer);
pBuffer.writeFluidStack(pRecipe.fluid);
}
}
}

View File

@ -0,0 +1,20 @@
package net.banutama.utamacraft.recipe;
import net.banutama.utamacraft.Utamacraft;
import net.minecraft.world.item.crafting.RecipeSerializer;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.registries.RegistryObject;
public class ModRecipes {
public static final DeferredRegister<RecipeSerializer<?>> SERIALIZERS =
DeferredRegister.create(ForgeRegistries.RECIPE_SERIALIZERS, Utamacraft.MOD_ID);
public static final RegistryObject<RecipeSerializer<InsolatorRecipe>> INSOLATOR_SERIALIZER =
SERIALIZERS.register("insolator", () -> InsolatorRecipe.Serializer.INSTANCE);
public static void register(IEventBus bus) {
SERIALIZERS.register(bus);
}
}

View File

@ -0,0 +1,164 @@
package net.banutama.utamacraft.screen;
import com.mojang.logging.LogUtils;
import net.banutama.utamacraft.block.custom.ModBlocks;
import net.banutama.utamacraft.block.entity.InsolatorBlockEntity;
import net.banutama.utamacraft.networking.packet.EnergySyncPacket;
import net.banutama.utamacraft.networking.packet.FluidSyncPacket;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.*;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraftforge.common.capabilities.ForgeCapabilities;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.items.SlotItemHandler;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
public class InsolatorMenu extends AbstractContainerMenu implements FluidSyncPacket.FluidSyncReceiverMenu, EnergySyncPacket.EnergySyncReceiverMenu {
private static final Logger LOGGER = LogUtils.getLogger();
public final InsolatorBlockEntity blockEntity;
private final Level level;
private final ContainerData data;
private FluidStack fluid;
private int energy = 0;
private int capacity = 0;
public InsolatorMenu(int id, Inventory inventory, FriendlyByteBuf extraData) {
this(id, inventory, inventory.player.level.getBlockEntity(extraData.readBlockPos()), new SimpleContainerData(3));
}
public InsolatorMenu(int id, Inventory inventory, BlockEntity entity, ContainerData data) {
super(ModMenuTypes.INSOLATOR_MENU.get(), id);
if (entity instanceof InsolatorBlockEntity insolator) {
checkContainerSize(inventory, 3);
this.level = inventory.player.level;
this.data = data;
this.blockEntity = insolator;
this.fluid = insolator.getFluidStack();
this.energy = insolator.getEnergyStorage().getEnergyStored();
this.capacity = insolator.getEnergyStorage().getMaxEnergyStored();
addPlayerInventory(inventory);
addPlayerHotbar(inventory);
this.blockEntity.getCapability(ForgeCapabilities.ITEM_HANDLER).ifPresent(handler -> {
this.addSlot(new SlotItemHandler(handler, 0, 12, 15));
this.addSlot(new SlotItemHandler(handler, 1, 86, 15));
this.addSlot(new SlotItemHandler(handler, 2, 86, 60));
});
addDataSlots(data);
} else {
throw new IllegalArgumentException("Block entity must be an InsolatorBlockEntity");
}
}
@Override
public void receiveFluidSync(FluidStack fluid) {
this.fluid = fluid;
}
@Override
public void receiveEnergySync(int energy, int capacity) {
this.energy = energy;
this.capacity = capacity;
}
@Override
public BlockEntity getBlockEntity() {
return blockEntity;
}
public FluidStack getFluid() {
return fluid;
}
public int getEnergy() {
return energy;
}
public int getEnergyCapacity() {
return capacity;
}
public boolean isCrafting() {
return data.get(2) == 1;
}
public float getScaledProgress() {
int progress = this.data.get(0);
int maxProgress = this.data.get(1);
return maxProgress != 0 && progress != 0 ? (float)progress / (float)maxProgress : 0;
}
@Override
public boolean stillValid(@NotNull Player player) {
return stillValid(ContainerLevelAccess.create(level, blockEntity.getBlockPos()), player, ModBlocks.INSOLATOR.get());
}
private static final int HOTBAR_SLOT_COUNT = 9;
private static final int PLAYER_INVENTORY_ROW_COUNT = 3;
private static final int PLAYER_INVENTORY_COLUMN_COUNT = 9;
private static final int PLAYER_INVENTORY_SLOT_COUNT = PLAYER_INVENTORY_ROW_COUNT * PLAYER_INVENTORY_COLUMN_COUNT;
private static final int VANILLA_SLOT_COUNT = HOTBAR_SLOT_COUNT + PLAYER_INVENTORY_SLOT_COUNT;
private static final int TILE_ENTITY_START_SLOT = VANILLA_SLOT_COUNT;
private static final int TILE_ENTITY_SLOT_COUNT = 3;
@Override
public @NotNull ItemStack quickMoveStack(@NotNull Player player, int index) {
Slot source = slots.get(index);
if (!source.hasItem()) {
return ItemStack.EMPTY;
}
ItemStack sourceStack = source.getItem();
ItemStack sourceCopy = sourceStack.copy();
if (index < VANILLA_SLOT_COUNT) {
// This is a vanilla container slot, so merge the stack into the tile inventory.
if (!moveItemStackTo(sourceStack, TILE_ENTITY_START_SLOT, TILE_ENTITY_START_SLOT + TILE_ENTITY_SLOT_COUNT, false)) {
return ItemStack.EMPTY;
}
} else if (index < TILE_ENTITY_START_SLOT + TILE_ENTITY_SLOT_COUNT) {
// This is a tile-entity slot, so merge the stack into the players inventory.
if (!moveItemStackTo(sourceStack, 0, VANILLA_SLOT_COUNT, false)) {
return ItemStack.EMPTY;
}
} else {
LOGGER.error("Invalid slot index {}", index);
return ItemStack.EMPTY;
}
// If the stack size is zero, the entire stack was moved, so set the slot contents to null.
if (sourceStack.getCount() == 0) {
source.set(ItemStack.EMPTY);
} else {
source.setChanged();
}
source.onTake(player, sourceStack);
return sourceCopy;
}
private void addPlayerInventory(Inventory inventory) {
for (int row = 0; row < PLAYER_INVENTORY_ROW_COUNT; ++row) {
for (int col = 0; col < PLAYER_INVENTORY_COLUMN_COUNT; ++col) {
this.addSlot(new Slot(inventory, col + row * 9 + 9, 8 + col * 18, 86 + row * 18));
}
}
}
private void addPlayerHotbar(Inventory inventory) {
for (int slot = 0; slot < HOTBAR_SLOT_COUNT; ++slot) {
this.addSlot(new Slot(inventory, slot, 8 + slot * 18, 144));
}
}
}

View File

@ -0,0 +1,116 @@
package net.banutama.utamacraft.screen;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.PoseStack;
import net.banutama.utamacraft.Utamacraft;
import net.banutama.utamacraft.screen.utils.FluidSprite;
import net.banutama.utamacraft.screen.utils.MouseUtils;
import net.banutama.utamacraft.screen.utils.TiledSprite;
import net.banutama.utamacraft.screen.utils.TooltipUtils;
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.level.material.Fluids;
import net.minecraftforge.fluids.FluidStack;
import org.jetbrains.annotations.NotNull;
import java.util.List;
import java.util.Optional;
public class InsolatorScreen extends AbstractContainerScreen<InsolatorMenu> {
private static final ResourceLocation TEXTURE =
new ResourceLocation(Utamacraft.MOD_ID, "textures/gui/insolator_gui.png");
public InsolatorScreen(InsolatorMenu menu, Inventory inventory, Component component) {
super(menu, inventory, component);
inventoryLabelY += 5;
}
@Override
protected void renderBg(@NotNull PoseStack stack, float partialTick, int mouseX, int mouseY) {
RenderSystem.setShader(GameRenderer::getPositionTexShader);
RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f);
RenderSystem.setShaderTexture(0, TEXTURE);
int x = (width - imageWidth) / 2;
int y = (height - imageHeight) / 2;
blit(stack, x, y, 0, 0, imageWidth, imageHeight);
renderBulb(stack, x, y);
renderProgressArrow(stack, x, y);
renderFluid(stack, x + 33, y + 16);
renderEnergy(stack, x + 46, y + 16);
}
@Override
protected void renderLabels(@NotNull PoseStack pPoseStack, int pMouseX, int pMouseY) {
int x = (width - imageWidth) / 2;
int y = (height - imageHeight) / 2;
if (MouseUtils.isMouseOver(pMouseX, pMouseY, x + 32, y + 15, 11, 61)) {
List<Component> components = TooltipUtils.getFluidTooltip(menu.getFluid(), 64000);
renderTooltip(pPoseStack, components, Optional.empty(),
pMouseX - x, pMouseY - y);
}
if (MouseUtils.isMouseOver(pMouseX, pMouseY, x + 45, y + 15, 11, 61)) {
List<Component> components = TooltipUtils.getEnergyTooltip(getMenu().getEnergy(), getMenu().getEnergyCapacity());
renderTooltip(pPoseStack, components, Optional.empty(), pMouseX - x, pMouseY - y);
}
}
private void renderEnergy(@NotNull PoseStack stack, int x, int y) {
if (menu.getEnergy() <= 0 || menu.getEnergyCapacity() <= 0) {
return;
}
final int ENERGY_HEIGHT = 60;
int stored = (int)(ENERGY_HEIGHT * ((float)menu.getEnergy() / (float)menu.getEnergyCapacity()));
fillGradient(stack, x, y + (ENERGY_HEIGHT - stored), x + 9, y + 60, 0xffb51500, 0xff600b00);
}
private void renderFluid(@NotNull PoseStack stack, int x, int y) {
FluidStack fluid = menu.getFluid();
if (fluid.getFluid().isSame(Fluids.EMPTY)) {
return;
}
final int FLUID_HEIGHT = 60;
TextureAtlasSprite sprite = FluidSprite.getStillFluidSprite(fluid);
int tint = FluidSprite.getTint(fluid);
int amount = fluid.getAmount();
int scaled = Math.min(FLUID_HEIGHT, Math.max(amount > 0 ? 1 : 0, (amount * FLUID_HEIGHT) / 64000));
RenderSystem.enableBlend();
stack.pushPose();
stack.translate(x, y, 0);
TiledSprite.drawTiledSprite(stack, 9, FLUID_HEIGHT, tint, scaled, sprite, 16);
stack.popPose();
RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f);
RenderSystem.disableBlend();
}
private void renderProgressArrow(PoseStack stack, int x, int y) {
if (menu.isCrafting()) {
blit(stack, x + 90, y + 33, 176, 0, 8, (int)(25.0f * menu.getScaledProgress()));
}
}
private void renderBulb(PoseStack stack, int x, int y) {
if (menu.isCrafting()) {
blit(stack, x + 67, y + 38, 176, 25, 9, 14);
}
}
@Override
public void render(@NotNull PoseStack stack, int mouseX, int mouseY, float delta) {
renderBackground(stack);
super.render(stack, mouseX, mouseY, delta);
renderTooltip(stack, mouseX, mouseY);
}
}

View File

@ -0,0 +1,27 @@
package net.banutama.utamacraft.screen;
import net.banutama.utamacraft.Utamacraft;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.inventory.MenuType;
import net.minecraftforge.common.extensions.IForgeMenuType;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.network.IContainerFactory;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.registries.RegistryObject;
public class ModMenuTypes {
public static final DeferredRegister<MenuType<?>> MENUS =
DeferredRegister.create(ForgeRegistries.MENU_TYPES, Utamacraft.MOD_ID);
public static final RegistryObject<MenuType<InsolatorMenu>> INSOLATOR_MENU =
registerMenuType("insolator_menu", InsolatorMenu::new);
private static <T extends AbstractContainerMenu> RegistryObject<MenuType<T>> registerMenuType(String name, IContainerFactory<T> factory) {
return MENUS.register(name, () -> IForgeMenuType.create(factory));
}
public static void register(IEventBus bus) {
MENUS.register(bus);
}
}

View File

@ -0,0 +1,29 @@
package net.banutama.utamacraft.screen.utils;
import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.inventory.InventoryMenu;
import net.minecraft.world.level.material.Fluid;
import net.minecraftforge.client.extensions.common.IClientFluidTypeExtensions;
import net.minecraftforge.fluids.FluidStack;
public class FluidSprite {
public static int getTint(FluidStack fluid) {
return IClientFluidTypeExtensions.of(fluid.getFluid()).getTintColor(fluid);
}
public static void setColorFromTint(int tint) {
float a = ((tint >> 24) & 0xff) / 255.0f;
float r = ((tint >> 16) & 0xff) / 255.0f;
float g = ((tint >> 8) & 0xff) / 255.0f;
float b = (tint & 0xff) / 255.0f;
RenderSystem.setShaderColor(r, g, b, a);
}
public static TextureAtlasSprite getStillFluidSprite(FluidStack fluid) {
ResourceLocation texture = IClientFluidTypeExtensions.of(fluid.getFluid()).getStillTexture(fluid);
return Minecraft.getInstance().getTextureAtlas(InventoryMenu.BLOCK_ATLAS).apply(texture);
}
}

View File

@ -0,0 +1,7 @@
package net.banutama.utamacraft.screen.utils;
public class MouseUtils {
public static boolean isMouseOver(double mouseX, double mouseY, int x, int y, int w, int h) {
return mouseX >= x && mouseX <= x + w && mouseY >= y && mouseY <= y + h;
}
}

View File

@ -0,0 +1,60 @@
package net.banutama.utamacraft.screen.utils;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.*;
import com.mojang.math.Matrix4f;
import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.world.inventory.InventoryMenu;
public class TiledSprite {
public static void drawTiledSprite(PoseStack stack, int tiledWidth, int tiledHeight, int tint, int scaledAmount, TextureAtlasSprite sprite, int textureSize) {
RenderSystem.setShaderTexture(0, InventoryMenu.BLOCK_ATLAS);
Matrix4f m = stack.last().pose();
FluidSprite.setColorFromTint(tint);
int xTileCount = tiledWidth / textureSize;
int xRemainder = tiledWidth - (xTileCount * textureSize);
int yTileCount = scaledAmount / textureSize;
int yRemainder = scaledAmount - (yTileCount * textureSize);
for (int xTile = 0; xTile <= xTileCount; ++xTile) {
for (int yTile = 0; yTile <= yTileCount; ++yTile) {
int width = (xTile == xTileCount) ? xRemainder : textureSize;
if (width <= 0) {
continue;
}
int height = (yTile == yTileCount) ? yRemainder : textureSize;
if (height <= 0) {
continue;
}
int x = xTile * textureSize;
int y = tiledHeight - ((yTile + 1) * textureSize);
drawTextureWithMasking(m, x, y, sprite, textureSize - height, textureSize - width, 100);
}
}
}
private static void drawTextureWithMasking(Matrix4f m, float x, float y, TextureAtlasSprite sprite, int maskTop, int maskRight, float z) {
float u0 = sprite.getU0();
float u1 = sprite.getU1();
float v0 = sprite.getV0();
float v1 = sprite.getV1();
u1 = u1 - (maskRight / 16.0f * (u1 - u0));
v1 = v1 - (maskTop / 16.0f * (v1 - v0));
RenderSystem.setShader(GameRenderer::getPositionTexShader);
Tesselator tesselator = Tesselator.getInstance();
BufferBuilder builder = tesselator.getBuilder();
builder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX);
builder.vertex(m, x, y + 16, z).uv(u0, v1).endVertex();
builder.vertex(m, x + 16 - maskRight, y + 16, z).uv(u1, v1).endVertex();
builder.vertex(m, x + 16 - maskRight, y + maskTop, z).uv(u1, v0).endVertex();
builder.vertex(m, x, y + maskTop, z).uv(u0, v0).endVertex();
tesselator.end();
}
}

View File

@ -0,0 +1,71 @@
package net.banutama.utamacraft.screen.utils;
import net.minecraft.ChatFormatting;
import net.minecraft.network.chat.Component;
import net.minecraft.world.level.material.Fluid;
import net.minecraft.world.level.material.Fluids;
import net.minecraftforge.energy.IEnergyStorage;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.FluidType;
import org.jetbrains.annotations.NotNull;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
public class TooltipUtils {
private static final NumberFormat nf = NumberFormat.getIntegerInstance();
private static @NotNull List<Component> startFluidTooltip(@NotNull FluidStack stack) {
List<Component> tooltip = new ArrayList<>();
Fluid fluid = stack.getFluid();
if (fluid.isSame(Fluids.EMPTY)) {
tooltip.add(Component.translatable("tooltip.utamacraft.fluid.empty")
.withStyle(ChatFormatting.ITALIC)
.withStyle(ChatFormatting.GRAY));
return tooltip;
}
tooltip.add(stack.getDisplayName());
return tooltip;
}
public static @NotNull List<Component> getFluidTooltip(@NotNull FluidStack stack, int capacity) {
List<Component> tooltip = startFluidTooltip(stack);
int amount = stack.getAmount();
int mb = (amount * 1000) / FluidType.BUCKET_VOLUME;
tooltip.add(Component.translatable("tooltip.utamacraft.fluid.amount.with_capacity",
nf.format(mb), nf.format(capacity))
.withStyle(ChatFormatting.GRAY));
return tooltip;
}
public static @NotNull List<Component> getFluidTooltip(@NotNull FluidStack stack) {
List<Component> tooltip = startFluidTooltip(stack);
int amount = stack.getAmount();
int mb = (amount * 1000) / FluidType.BUCKET_VOLUME;
tooltip.add(Component.translatable("tooltip.utamacraft.fluid.amount", nf.format(mb))
.withStyle(ChatFormatting.GRAY));
return tooltip;
}
public static @NotNull List<Component> getEnergyTooltip(int energy) {
return List.of(Component.translatable("tooltip.utamacraft.energy.amount",
nf.format(energy)).withStyle(ChatFormatting.GRAY));
}
public static @NotNull List<Component> getEnergyTooltip(int energy, int capacity) {
return List.of(
Component.translatable(("tooltip.utamacraft.energy")),
Component.translatable("tooltip.utamacraft.energy.amount.with_capacity",
nf.format(energy), nf.format(capacity)).withStyle(ChatFormatting.GRAY));
}
}

View File

@ -0,0 +1,22 @@
package net.banutama.utamacraft.sound;
import net.banutama.utamacraft.Utamacraft;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.sounds.SoundEvent;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.registries.RegistryObject;
public class ModSounds {
public static final DeferredRegister<SoundEvent> SOUNDS =
DeferredRegister.create(ForgeRegistries.SOUND_EVENTS, Utamacraft.MOD_ID);
public static final RegistryObject<SoundEvent> INSOLATOR =
SOUNDS.register("insolator", () -> new SoundEvent(new ResourceLocation(Utamacraft.MOD_ID, "insolator")));
public static void register(IEventBus eventBus) {
SOUNDS.register(eventBus);
}
}

View File

@ -0,0 +1,36 @@
package net.banutama.utamacraft.util;
import net.minecraftforge.energy.EnergyStorage;
public abstract class ModEnergyStorage extends EnergyStorage {
public ModEnergyStorage(int capacity, int maxTransfer) {
super(capacity, maxTransfer);
}
@Override
public int extractEnergy(int maxExtract, boolean simulate) {
int extracted = super.extractEnergy(maxExtract, simulate);
if (extracted != 0) {
onEnergyChanged();
}
return extracted;
}
@Override
public int receiveEnergy(int maxReceive, boolean simulate) {
int received = super.receiveEnergy(maxReceive, simulate);
if (received != 0) {
onEnergyChanged();
}
return received;
}
public int setEnergy(int energy) {
this.energy = energy;
return energy;
}
public abstract void onEnergyChanged();
}

View File

@ -0,0 +1,34 @@
{
"variants": {
"facing=north,active=false": {
"model": "utamacraft:block/insolator"
},
"facing=north,active=true": {
"model": "utamacraft:block/insolator_active"
},
"facing=east,active=false": {
"model": "utamacraft:block/insolator",
"y": 90
},
"facing=east,active=true": {
"model": "utamacraft:block/insolator_active",
"y": 90
},
"facing=south,active=false": {
"model": "utamacraft:block/insolator",
"y": 180
},
"facing=south,active=true": {
"model": "utamacraft:block/insolator_active",
"y": 180
},
"facing=west,active=false": {
"model": "utamacraft:block/insolator",
"y": 270
},
"facing=west,active=true": {
"model": "utamacraft:block/insolator_active",
"y": 270
}
}
}

View File

@ -0,0 +1,5 @@
{
"variants": {
"": { "model": "utamacraft:block/tungsten_block" }
}
}

View File

@ -1,10 +1,26 @@
{
"block.utamacraft.ethereal_glass": "Ethereal Glass",
"block.utamacraft.insolator": "Insolator",
"block.utamacraft.tinted_ethereal_glass": "Tinted Ethereal Glass",
"block.utamacraft.tungsten_block": "Tungsten Block",
"block_entity.utamacraft.insolator": "Insolator",
"item.utamacraft.bulb": "Bulb",
"item.utamacraft.fiber_glass": "Fiberglass",
"item.utamacraft.insolator": "Insolator",
"item.utamacraft.pcb": "Printed Circuit Board",
"item.utamacraft.player_peripheral": "Player peripheral",
"item.utamacraft.raw_tungsten": "Raw Tungsten",
"item.utamacraft.tungsten_block": "Tungsten Block",
"item.utamacraft.tungsten_ingot": "Tungsten Ingot",
"item.utamacraft.utamacraft_logo": "Utamacraft",
"itemGroup.utamacraft_tab": "Utamacraft",
"tooltip.utamacraft.energy": "Energy",
"tooltip.utamacraft.energy.amount": "%s FE",
"tooltip.utamacraft.energy.amount.with_capacity": "%s / %s FE",
"tooltip.utamacraft.ethereal_glass": "Glass that is not solid to players",
"tooltip.utamacraft.fluid.empty": "Empty",
"tooltip.utamacraft.fluid.amount": "%s mB",
"tooltip.utamacraft.fluid.amount.with_capacity": "%s / %s mB",
"tooltip.utamacraft.tinted_ethereal_glass": "Glass that is not solid to players and blocks light",
"turtle.utamacraft.player_turtle": "Player"
}

View File

@ -0,0 +1,226 @@
{
"credit": "Made with Blockbench",
"texture_size": [128, 128],
"textures": {
"5": "utamacraft:block/insolator"
},
"elements": [
{
"name": "Top",
"from": [0, 13, 0],
"to": [16, 16, 16],
"faces": {
"north": {"uv": [6, 4.25, 8, 4.625], "texture": "#5"},
"east": {"uv": [6, 4.625, 8, 5], "texture": "#5"},
"south": {"uv": [6, 5, 8, 5.375], "texture": "#5"},
"west": {"uv": [6, 5.375, 8, 5.75], "texture": "#5"},
"up": {"uv": [4, 6, 2, 4], "texture": "#5"},
"down": {"uv": [6, 2, 4, 4], "texture": "#5"}
}
},
{
"name": "Base",
"from": [0, 0, 0],
"to": [16, 3, 16],
"faces": {
"north": {"uv": [6, 2.75, 8, 3.125], "texture": "#5"},
"east": {"uv": [6, 3.125, 8, 3.5], "texture": "#5"},
"south": {"uv": [6, 3.5, 8, 3.875], "texture": "#5"},
"west": {"uv": [6, 3.875, 8, 4.25], "texture": "#5"},
"up": {"uv": [2, 2, 0, 0], "texture": "#5"},
"down": {"uv": [2, 2, 0, 4], "texture": "#5"}
}
},
{
"name": "Top",
"from": [0, 5, 0],
"to": [16, 7, 16],
"faces": {
"north": {"uv": [6, 6.25, 8, 6.5], "texture": "#5"},
"east": {"uv": [6, 6.5, 8, 6.75], "texture": "#5"},
"south": {"uv": [4, 6.75, 6, 7], "texture": "#5"},
"west": {"uv": [6, 6.75, 8, 7], "texture": "#5"},
"up": {"uv": [4, 2, 2, 0], "texture": "#5"},
"down": {"uv": [4, 2, 2, 4], "texture": "#5"}
}
},
{
"name": "Slab",
"from": [0, 3, 5],
"to": [16, 5, 16],
"faces": {
"north": {"uv": [6, 5.75, 8, 6], "texture": "#5"},
"east": {"uv": [0, 7.625, 1.375, 7.875], "texture": "#5"},
"south": {"uv": [6, 6, 8, 6.25], "texture": "#5"},
"west": {"uv": [1.375, 7.625, 2.75, 7.875], "texture": "#5"},
"up": {"uv": [6, 5.375, 4, 4], "texture": "#5"},
"down": {"uv": [6, 5.375, 4, 6.75], "texture": "#5"}
}
},
{
"name": "Leg",
"from": [0, 3, 0],
"to": [2, 5, 2],
"faces": {
"north": {"uv": [1.5, 7.875, 1.75, 8.125], "texture": "#5"},
"east": {"uv": [1.75, 7.875, 2, 8.125], "texture": "#5"},
"south": {"uv": [2, 7.875, 2.25, 8.125], "texture": "#5"},
"west": {"uv": [2.25, 7.875, 2.5, 8.125], "texture": "#5"},
"up": {"uv": [2.75, 8.125, 2.5, 7.875], "texture": "#5"},
"down": {"uv": [8.25, 0, 8, 0.25], "texture": "#5"}
}
},
{
"name": "Leg",
"from": [14, 3, 0],
"to": [16, 5, 2],
"faces": {
"north": {"uv": [0, 7.875, 0.25, 8.125], "texture": "#5"},
"east": {"uv": [0.25, 7.875, 0.5, 8.125], "texture": "#5"},
"south": {"uv": [0.5, 7.875, 0.75, 8.125], "texture": "#5"},
"west": {"uv": [0.75, 7.875, 1, 8.125], "texture": "#5"},
"up": {"uv": [1.25, 8.125, 1, 7.875], "texture": "#5"},
"down": {"uv": [1.5, 7.875, 1.25, 8.125], "texture": "#5"}
}
},
{
"name": "Top",
"from": [0, 9, 0],
"to": [16, 11, 16],
"faces": {
"north": {"uv": [4, 7, 6, 7.25], "texture": "#5"},
"east": {"uv": [6, 7, 8, 7.25], "texture": "#5"},
"south": {"uv": [4, 7.25, 6, 7.5], "texture": "#5"},
"west": {"uv": [6, 7.25, 8, 7.5], "texture": "#5"},
"up": {"uv": [2, 6, 0, 4], "texture": "#5"},
"down": {"uv": [6, 0, 4, 2], "texture": "#5"}
}
},
{
"name": "Slab",
"from": [0, 7, 5],
"to": [16, 9, 16],
"faces": {
"north": {"uv": [0, 7.375, 2, 7.625], "texture": "#5"},
"east": {"uv": [2.75, 7.75, 4.125, 8], "texture": "#5"},
"south": {"uv": [2, 7.375, 4, 7.625], "texture": "#5"},
"west": {"uv": [4.125, 7.75, 5.5, 8], "texture": "#5"},
"up": {"uv": [2, 7.375, 0, 6], "texture": "#5"},
"down": {"uv": [8, 0, 6, 1.375], "texture": "#5"}
}
},
{
"name": "Leg",
"from": [0, 7, 0],
"to": [2, 9, 2],
"faces": {
"north": {"uv": [8, 0.25, 8.25, 0.5], "texture": "#5"},
"east": {"uv": [8, 0.5, 8.25, 0.75], "texture": "#5"},
"south": {"uv": [8, 0.75, 8.25, 1], "texture": "#5"},
"west": {"uv": [8, 1, 8.25, 1.25], "texture": "#5"},
"up": {"uv": [8.25, 1.5, 8, 1.25], "texture": "#5"},
"down": {"uv": [8.25, 1.5, 8, 1.75], "texture": "#5"}
}
},
{
"name": "Leg",
"from": [14, 7, 0],
"to": [16, 9, 2],
"faces": {
"north": {"uv": [8, 1.75, 8.25, 2], "texture": "#5"},
"east": {"uv": [8, 2, 8.25, 2.25], "texture": "#5"},
"south": {"uv": [8, 2.25, 8.25, 2.5], "texture": "#5"},
"west": {"uv": [8, 2.5, 8.25, 2.75], "texture": "#5"},
"up": {"uv": [3, 8.25, 2.75, 8], "texture": "#5"},
"down": {"uv": [8.25, 2.75, 8, 3], "texture": "#5"}
}
},
{
"name": "Slab",
"from": [0, 11, 5],
"to": [16, 13, 16],
"faces": {
"north": {"uv": [4, 7.5, 6, 7.75], "texture": "#5"},
"east": {"uv": [5.5, 7.75, 6.875, 8], "texture": "#5"},
"south": {"uv": [6, 7.5, 8, 7.75], "texture": "#5"},
"west": {"uv": [6.875, 7.75, 8.25, 8], "texture": "#5"},
"up": {"uv": [8, 2.75, 6, 1.375], "texture": "#5"},
"down": {"uv": [4, 6, 2, 7.375], "texture": "#5"}
}
},
{
"name": "Leg",
"from": [0, 11, 0],
"to": [2, 13, 2],
"faces": {
"north": {"uv": [3, 8, 3.25, 8.25], "texture": "#5"},
"east": {"uv": [8, 3, 8.25, 3.25], "texture": "#5"},
"south": {"uv": [3.25, 8, 3.5, 8.25], "texture": "#5"},
"west": {"uv": [8, 3.25, 8.25, 3.5], "texture": "#5"},
"up": {"uv": [3.75, 8.25, 3.5, 8], "texture": "#5"},
"down": {"uv": [8.25, 3.5, 8, 3.75], "texture": "#5"}
}
},
{
"name": "Leg",
"from": [14, 11, 0],
"to": [16, 13, 2],
"faces": {
"north": {"uv": [3.75, 8, 4, 8.25], "texture": "#5"},
"east": {"uv": [8, 3.75, 8.25, 4], "texture": "#5"},
"south": {"uv": [4, 8, 4.25, 8.25], "texture": "#5"},
"west": {"uv": [8, 4, 8.25, 4.25], "texture": "#5"},
"up": {"uv": [4.5, 8.25, 4.25, 8], "texture": "#5"},
"down": {"uv": [8.25, 4.25, 8, 4.5], "texture": "#5"}
}
}
],
"display": {
"thirdperson_righthand": {
"scale": [0.25, 0.25, 0.25]
},
"thirdperson_lefthand": {
"scale": [0.25, 0.25, 0.25]
},
"firstperson_righthand": {
"rotation": [0, 105, 0],
"scale": [0.75, 0.75, 0.75]
},
"firstperson_lefthand": {
"rotation": [0, 105, 0],
"scale": [0.75, 0.75, 0.75]
},
"ground": {
"scale": [0.5, 0.5, 0.5]
},
"gui": {
"rotation": [21, 137, 0],
"scale": [0.66, 0.66, 0.66]
},
"fixed": {
"scale": [1, 1, 0.5]
}
},
"groups": [
0,
1,
{
"name": "Layer 1",
"origin": [0, 0, 0],
"color": 0,
"children": [2, 3, 4, 5]
},
{
"name": "Layer 2",
"origin": [0, 0, 0],
"color": 0,
"children": [6, 7, 8, 9]
},
{
"name": "Layer 3",
"origin": [0, 0, 0],
"color": 0,
"children": [10, 11, 12]
}
]
}

View File

@ -0,0 +1,6 @@
{
"parent": "utamacraft:block/insolator",
"textures": {
"5": "utamacraft:block/insolator_active"
}
}

View File

@ -0,0 +1,6 @@
{
"parent": "block/cube_all",
"textures": {
"all": "utamacraft:block/tungsten_block"
}
}

View File

@ -0,0 +1,6 @@
{
"parent": "item/generated",
"textures": {
"layer0": "utamacraft:item/bulb"
}
}

View File

@ -0,0 +1,6 @@
{
"parent": "item/generated",
"textures": {
"layer0": "utamacraft:item/fiber_glass"
}
}

View File

@ -0,0 +1,3 @@
{
"parent": "utamacraft:block/insolator"
}

View File

@ -0,0 +1,6 @@
{
"parent": "item/generated",
"textures": {
"layer0": "utamacraft:item/pcb"
}
}

View File

@ -0,0 +1,6 @@
{
"parent": "item/generated",
"textures": {
"layer0": "utamacraft:item/raw_tungsten"
}
}

View File

@ -0,0 +1,3 @@
{
"parent": "utamacraft:block/tungsten_block"
}

View File

@ -0,0 +1,6 @@
{
"parent": "item/generated",
"textures": {
"layer0": "utamacraft:item/tungsten_ingot"
}
}

View File

@ -0,0 +1,8 @@
{
"insolator": {
"category": "block",
"sounds": [
"utamacraft:insolator"
]
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 970 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 974 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@ -0,0 +1,23 @@
{
"type": "minecraft:crafting_shaped",
"pattern": [
" # ",
"#T#",
" C "
],
"key": {
"#": {
"item": "minecraft:glass"
},
"T": {
"item": "utamacraft:tungsten_ingot"
},
"C": {
"item": "minecraft:copper_ingot"
}
},
"result": {
"item": "utamacraft:bulb",
"count": 1
}
}

View File

@ -0,0 +1,19 @@
{
"type": "minecraft:crafting_shaped",
"pattern": [
"SK",
"KS"
],
"key": {
"S": {
"item": "minecraft:sugar_cane"
},
"K": {
"item": "minecraft:kelp"
}
},
"result": {
"item": "utamacraft:fiber_glass",
"count": 1
}
}

View File

@ -0,0 +1,29 @@
{
"type": "minecraft:crafting_shaped",
"pattern": [
"TCT",
"TB ",
"sPs"
],
"key": {
"T": {
"item": "utamacraft:tungsten_ingot"
},
"C": {
"item": "minecraft:copper_ingot"
},
"B": {
"item": "utamacraft:bulb"
},
"P": {
"item": "utamacraft:pcb"
},
"s": {
"item": "minecraft:stone_slab"
}
},
"result": {
"item": "utamacraft:insolator",
"count": 1
}
}

View File

@ -0,0 +1,14 @@
{
"type": "utamacraft:insolator",
"input": {
"item": "minecraft:acacia_leaves"
},
"fluid": {
"FluidName": "minecraft:water",
"Amount": 500
},
"output": {
"item": "minecraft:acacia_leaves",
"count": 2
}
}

View File

@ -0,0 +1,14 @@
{
"type": "utamacraft:insolator",
"input": {
"item": "minecraft:acacia_sapling"
},
"fluid": {
"FluidName": "minecraft:water",
"Amount": 500
},
"output": {
"item": "minecraft:acacia_sapling",
"count": 2
}
}

View File

@ -0,0 +1,14 @@
{
"type": "utamacraft:insolator",
"input": {
"item": "minecraft:allium"
},
"fluid": {
"FluidName": "minecraft:water",
"Amount": 500
},
"output": {
"item": "minecraft:allium",
"count": 2
}
}

View File

@ -0,0 +1,14 @@
{
"type": "utamacraft:insolator",
"input": {
"item": "minecraft:azalea"
},
"fluid": {
"FluidName": "minecraft:water",
"Amount": 500
},
"output": {
"item": "minecraft:azalea",
"count": 2
}
}

View File

@ -0,0 +1,14 @@
{
"type": "utamacraft:insolator",
"input": {
"item": "minecraft:azalea_leaves"
},
"fluid": {
"FluidName": "minecraft:water",
"Amount": 500
},
"output": {
"item": "minecraft:azalea_leaves",
"count": 2
}
}

View File

@ -0,0 +1,14 @@
{
"type": "utamacraft:insolator",
"input": {
"item": "minecraft:azure_bluet"
},
"fluid": {
"FluidName": "minecraft:water",
"Amount": 500
},
"output": {
"item": "minecraft:azure_bluet",
"count": 2
}
}

View File

@ -0,0 +1,14 @@
{
"type": "utamacraft:insolator",
"input": {
"item": "minecraft:bamboo"
},
"fluid": {
"FluidName": "minecraft:water",
"Amount": 500
},
"output": {
"item": "minecraft:bamboo",
"count": 2
}
}

View File

@ -0,0 +1,14 @@
{
"type": "utamacraft:insolator",
"input": {
"item": "minecraft:beetroot_seeds"
},
"fluid": {
"FluidName": "minecraft:water",
"Amount": 500
},
"output": {
"item": "minecraft:beetroot_seeds",
"count": 2
}
}

View File

@ -0,0 +1,14 @@
{
"type": "utamacraft:insolator",
"input": {
"item": "minecraft:big_dripleaf"
},
"fluid": {
"FluidName": "minecraft:water",
"Amount": 500
},
"output": {
"item": "minecraft:big_dripleaf",
"count": 2
}
}

View File

@ -0,0 +1,14 @@
{
"type": "utamacraft:insolator",
"input": {
"item": "minecraft:birch_leaves"
},
"fluid": {
"FluidName": "minecraft:water",
"Amount": 500
},
"output": {
"item": "minecraft:birch_leaves",
"count": 2
}
}

View File

@ -0,0 +1,14 @@
{
"type": "utamacraft:insolator",
"input": {
"item": "minecraft:birch_sapling"
},
"fluid": {
"FluidName": "minecraft:water",
"Amount": 500
},
"output": {
"item": "minecraft:birch_sapling",
"count": 2
}
}

View File

@ -0,0 +1,14 @@
{
"type": "utamacraft:insolator",
"input": {
"item": "minecraft:blue_orchid"
},
"fluid": {
"FluidName": "minecraft:water",
"Amount": 500
},
"output": {
"item": "minecraft:blue_orchid",
"count": 2
}
}

View File

@ -0,0 +1,14 @@
{
"type": "utamacraft:insolator",
"input": {
"item": "minecraft:brown_mushroom"
},
"fluid": {
"FluidName": "minecraft:water",
"Amount": 500
},
"output": {
"item": "minecraft:brown_mushroom",
"count": 2
}
}

View File

@ -0,0 +1,14 @@
{
"type": "utamacraft:insolator",
"input": {
"item": "minecraft:cactus"
},
"fluid": {
"FluidName": "minecraft:water",
"Amount": 500
},
"output": {
"item": "minecraft:cactus",
"count": 2
}
}

View File

@ -0,0 +1,14 @@
{
"type": "utamacraft:insolator",
"input": {
"item": "minecraft:chorus_flower"
},
"fluid": {
"FluidName": "minecraft:water",
"Amount": 500
},
"output": {
"item": "minecraft:chorus_flower",
"count": 2
}
}

View File

@ -0,0 +1,14 @@
{
"type": "utamacraft:insolator",
"input": {
"item": "minecraft:cornflower"
},
"fluid": {
"FluidName": "minecraft:water",
"Amount": 500
},
"output": {
"item": "minecraft:cornflower",
"count": 2
}
}

View File

@ -0,0 +1,14 @@
{
"type": "utamacraft:insolator",
"input": {
"item": "minecraft:crimson_fungus"
},
"fluid": {
"FluidName": "minecraft:water",
"Amount": 500
},
"output": {
"item": "minecraft:crimson_fungus",
"count": 2
}
}

View File

@ -0,0 +1,14 @@
{
"type": "utamacraft:insolator",
"input": {
"item": "minecraft:crimson_roots"
},
"fluid": {
"FluidName": "minecraft:water",
"Amount": 500
},
"output": {
"item": "minecraft:crimson_roots",
"count": 2
}
}

View File

@ -0,0 +1,14 @@
{
"type": "utamacraft:insolator",
"input": {
"item": "minecraft:dandelion"
},
"fluid": {
"FluidName": "minecraft:water",
"Amount": 500
},
"output": {
"item": "minecraft:dandelion",
"count": 2
}
}

View File

@ -0,0 +1,14 @@
{
"type": "utamacraft:insolator",
"input": {
"item": "minecraft:dark_oak_leaves"
},
"fluid": {
"FluidName": "minecraft:water",
"Amount": 500
},
"output": {
"item": "minecraft:dark_oak_leaves",
"count": 2
}
}

View File

@ -0,0 +1,14 @@
{
"type": "utamacraft:insolator",
"input": {
"item": "minecraft:dark_oak_sapling"
},
"fluid": {
"FluidName": "minecraft:water",
"Amount": 500
},
"output": {
"item": "minecraft:dark_oak_sapling",
"count": 2
}
}

View File

@ -0,0 +1,14 @@
{
"type": "utamacraft:insolator",
"input": {
"item": "minecraft:fern"
},
"fluid": {
"FluidName": "minecraft:water",
"Amount": 500
},
"output": {
"item": "minecraft:fern",
"count": 2
}
}

View File

@ -0,0 +1,14 @@
{
"type": "utamacraft:insolator",
"input": {
"item": "minecraft:flowering_azalea"
},
"fluid": {
"FluidName": "minecraft:water",
"Amount": 500
},
"output": {
"item": "minecraft:flowering_azalea",
"count": 2
}
}

View File

@ -0,0 +1,14 @@
{
"type": "utamacraft:insolator",
"input": {
"item": "minecraft:flowering_azalea_leaves"
},
"fluid": {
"FluidName": "minecraft:water",
"Amount": 500
},
"output": {
"item": "minecraft:flowering_azalea_leaves",
"count": 2
}
}

View File

@ -0,0 +1,14 @@
{
"type": "utamacraft:insolator",
"input": {
"item": "minecraft:glow_lichen"
},
"fluid": {
"FluidName": "minecraft:water",
"Amount": 500
},
"output": {
"item": "minecraft:glow_lichen",
"count": 2
}
}

View File

@ -0,0 +1,14 @@
{
"type": "utamacraft:insolator",
"input": {
"item": "minecraft:grass"
},
"fluid": {
"FluidName": "minecraft:water",
"Amount": 500
},
"output": {
"item": "minecraft:grass",
"count": 2
}
}

View File

@ -0,0 +1,14 @@
{
"type": "utamacraft:insolator",
"input": {
"item": "minecraft:hanging_roots"
},
"fluid": {
"FluidName": "minecraft:water",
"Amount": 500
},
"output": {
"item": "minecraft:hanging_roots",
"count": 2
}
}

View File

@ -0,0 +1,14 @@
{
"type": "utamacraft:insolator",
"input": {
"item": "minecraft:jungle_leaves"
},
"fluid": {
"FluidName": "minecraft:water",
"Amount": 500
},
"output": {
"item": "minecraft:jungle_leaves",
"count": 2
}
}

Some files were not shown because too many files have changed in this diff Show More