Compare commits
40 Commits
71899c0013
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 97ed29fc23 | |||
| 1c03653fee | |||
| c016cebb0f | |||
| 885f594ca0 | |||
| 45831b780a | |||
| 6b0c4468ec | |||
| d15b34939e | |||
| 3f95944314 | |||
| 21493fec04 | |||
| 42331390e7 | |||
| cdb98bd85e | |||
| 7f58fdf55b | |||
| 17bc614eb9 | |||
| b78cc44d89 | |||
| 4d37483057 | |||
| 4d84ec2ed4 | |||
| 5249832bd6 | |||
| e9885940e2 | |||
| c63912c1f3 | |||
| 323d213291 | |||
| b8968942f8 | |||
| 0eee9f5163 | |||
| 9fd6ea8881 | |||
| c6fc9ed9e9 | |||
| 9ea3727dfb | |||
| 21516ee923 | |||
| d8e79d8719 | |||
| 5dbd0b8734 | |||
| 710547a014 | |||
| 424f77ba10 | |||
| 02c0c5d60c | |||
| 0b33eda8a8 | |||
| cd909dbd80 | |||
| 8fb4921e30 | |||
| 86b3486622 | |||
| 9a733e0a81 | |||
| 740318c020 | |||
| 149cfec3ed | |||
| 4d2cb14e45 | |||
| 7c27955c14 |
37
TODO.md
@@ -1,31 +1,21 @@
|
||||
# Networking
|
||||
> Pretty important here
|
||||
> All that is left is optimization
|
||||
|
||||
## Auto-connect
|
||||
## Mergeable device nodes
|
||||
|
||||
Rework the auto-connect system of device blocks to be more stable.
|
||||
Prob re-scan the network continuously
|
||||
For optimization of screen grouping and cables, we should add a system that allows merging nodes
|
||||
|
||||
## Synchronization
|
||||
## Copy the networking optimizations of OC
|
||||
> https://github.com/MightyPirates/OpenComputers/blob/master-MC1.7.10/src/main/scala/li/cil/oc/server/network/Network.scala
|
||||
|
||||
Move the state logic into the node, as it was meant to be.
|
||||
Note, addresses on the client are allowed to be complete bullshit at least for a bit of time.
|
||||
`ComponentItem`s should no longer allow a node on the client (at least for now), it serves no
|
||||
purpose currently, and also is not designed well.
|
||||
We should implement this, as it not only makes behavior match better, but also optimizes
|
||||
it a lot. We do need to replace the NEIGHBORS rule with implementing the SOME visibility.
|
||||
A direct port is not needed, just taking heavy inspiration from OC.
|
||||
|
||||
## Get rid of NodeBlockEntity
|
||||
## Optimize power balancing
|
||||
|
||||
It is basically throw-away stitched together garbage.
|
||||
Replace it with a new abstract class, which allows different nodes on different sides,
|
||||
handles synchronizing those nodes according to their state changes.
|
||||
|
||||
Also implement an equivalent for LivingEntities, like drones or other addon stuff.
|
||||
|
||||
## Optimizations
|
||||
|
||||
Optimize the networking, both synchronization using smaller encodings,
|
||||
and emitting messages or adding/removing nodes. The goal is to have as little of
|
||||
the CPU time on the server thread taken by NC as we can.
|
||||
Use a smarter algorithm to prevent N storage nodes from iterating N^2 nodes each tick
|
||||
to balance power.
|
||||
|
||||
# Computation
|
||||
> Pretty important for a computer mod
|
||||
@@ -38,3 +28,8 @@ Also because it is a capable engine and has a good API for architectures, and NC
|
||||
## Worker threads
|
||||
|
||||
Computers need worker threads for running non-synchronized code, because otherwise we're cooked
|
||||
|
||||
## Entities as machines
|
||||
|
||||
Aside from blocks like cases and robots, we should also support entities like drones.
|
||||
Not only for OC parity, but also as addons would def love that.
|
||||
@@ -13,8 +13,7 @@ import org.neoflock.neocomputers.NeoComputers;
|
||||
import org.neoflock.neocomputers.block.Blocks;
|
||||
import org.neoflock.neocomputers.block.CableBlock;
|
||||
import org.neoflock.neocomputers.entity.BlockEntities;
|
||||
import org.neoflock.neocomputers.entity.render.CaseEntityRenderer;
|
||||
import org.neoflock.neocomputers.entity.render.ScreenEntityRenderer;
|
||||
import org.neoflock.neocomputers.entity.render.*;
|
||||
import org.neoflock.neocomputers.item.Items;
|
||||
import org.neoflock.neocomputers.platforms.fabric.client.model.ModelLoader;
|
||||
|
||||
@@ -22,8 +21,11 @@ public class NeoComputersFabricClient implements ClientModInitializer {
|
||||
@Override
|
||||
public void onInitializeClient() {
|
||||
ModelLoadingPlugin.register(new ModelLoader());
|
||||
BlockEntityRenderers.register(BlockEntities.INSTANCE.getSCREEN_ENTITY().get(), ScreenEntityRenderer::new);
|
||||
BlockEntityRenderers.register(BlockEntities.INSTANCE.getSCREEN_ENTITY().get(), ScreenEntityRenderer::new); // TODO: put this in common
|
||||
BlockEntityRenderers.register(BlockEntities.INSTANCE.getCASE_ENTITY().get(), CaseEntityRenderer::new);
|
||||
BlockEntityRenderers.register(BlockEntities.INSTANCE.getRELAY_ENTITY().get(), RelayEntityRenderer::new);
|
||||
BlockEntityRenderers.register(BlockEntities.INSTANCE.getROBOT_ENTITY().get(), RobotEntityRenderer::new);
|
||||
BlockEntityRenderers.register(BlockEntities.INSTANCE.getRACK_ENTITY().get(), RackEntityRenderer::new);
|
||||
|
||||
ColorProviderRegistry.BLOCK.register((state, world, pos, index) -> {
|
||||
if (index == 0) {
|
||||
|
||||
@@ -1,138 +0,0 @@
|
||||
//package org.neoflock.neocomputers.platforms.fabric.client.model;
|
||||
//
|
||||
//import net.fabricmc.fabric.api.renderer.v1.Renderer;
|
||||
//import net.fabricmc.fabric.api.renderer.v1.RendererAccess;
|
||||
//import net.fabricmc.fabric.api.renderer.v1.mesh.Mesh;
|
||||
//import net.fabricmc.fabric.api.renderer.v1.mesh.MeshBuilder;
|
||||
//import net.fabricmc.fabric.api.renderer.v1.mesh.MutableQuadView;
|
||||
//import net.fabricmc.fabric.api.renderer.v1.mesh.QuadEmitter;
|
||||
//import net.fabricmc.fabric.api.renderer.v1.model.FabricBakedModel;
|
||||
//import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
|
||||
//import net.minecraft.client.Minecraft;
|
||||
//import net.minecraft.client.renderer.block.model.BakedQuad;
|
||||
//import net.minecraft.client.renderer.block.model.ItemOverrides;
|
||||
//import net.minecraft.client.renderer.block.model.ItemTransforms;
|
||||
//import net.minecraft.client.renderer.texture.TextureAtlas;
|
||||
//import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
//import net.minecraft.client.resources.model.*;
|
||||
//import net.minecraft.core.BlockPos;
|
||||
//import net.minecraft.core.Direction;
|
||||
//import net.minecraft.resources.ResourceLocation;
|
||||
//import net.minecraft.util.RandomSource;
|
||||
//import net.minecraft.world.level.BlockAndTintGetter;
|
||||
//import net.minecraft.world.level.block.state.BlockState;
|
||||
//import org.jetbrains.annotations.Nullable;
|
||||
//import org.neoflock.neocomputers.NeoComputers;
|
||||
//
|
||||
//import java.util.ArrayList;
|
||||
//import java.util.Collection;
|
||||
//import java.util.List;
|
||||
//import java.util.function.Function;
|
||||
//import java.util.function.Supplier;
|
||||
//
|
||||
//// this totally could have been done with datagen, why do i do this
|
||||
//public class CableModel implements BakedModel, UnbakedModel, FabricBakedModel {
|
||||
//// private TextureAtlasSprite sprite = Minecraft
|
||||
//// TextureAtlasSprite sprite = atlas.apply(new Material(TextureAtlas.LOCATION_BLOCKS, ResourceLocation.withDefaultNamespace("block/furnace_top")));
|
||||
//
|
||||
// private float MIN = 6/16F;
|
||||
// private float MAX = 10/16F;
|
||||
//
|
||||
// private BlockState state;
|
||||
//
|
||||
// private Mesh mesh;
|
||||
// @Override
|
||||
// public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction direction, RandomSource random) {
|
||||
//// NeoComputers.INSTANCE.getLOGGER().info("Obtained blockstate!");
|
||||
// this.state = state;
|
||||
// return List.of();
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public boolean useAmbientOcclusion() {
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public boolean isGui3d() {
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public boolean usesBlockLight() {
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public boolean isCustomRenderer() {
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public TextureAtlasSprite getParticleIcon() {
|
||||
// Function<ResourceLocation, TextureAtlasSprite> atlas = Minecraft.getInstance().getTextureAtlas(TextureAtlas.LOCATION_BLOCKS);
|
||||
// return atlas.apply(ResourceLocation.fromNamespaceAndPath(NeoComputers.MODID, "block/teto"));
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public ItemTransforms getTransforms() {
|
||||
// return ItemTransforms.NO_TRANSFORMS;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public ItemOverrides getOverrides() {
|
||||
// return ItemOverrides.EMPTY;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public Collection<ResourceLocation> getDependencies() {
|
||||
// return List.of();
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void resolveParents(Function<ResourceLocation, UnbakedModel> resolver) {
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public @Nullable BakedModel bake(ModelBaker baker, Function<Material, TextureAtlasSprite> spriteGetter, ModelState state) {
|
||||
// TextureAtlasSprite sprite = spriteGetter.apply(new Material(TextureAtlas.LOCATION_BLOCKS, ResourceLocation.fromNamespaceAndPath(NeoComputers.MODID, "block/teto")));
|
||||
//
|
||||
// Renderer renderer = RendererAccess.INSTANCE.getRenderer();
|
||||
// MeshBuilder builder = renderer.meshBuilder();
|
||||
// QuadEmitter emitter = builder.getEmitter();
|
||||
//
|
||||
// bakeCenter(emitter, sprite);
|
||||
//
|
||||
//
|
||||
// mesh = builder.build();
|
||||
// return this;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void emitBlockQuads(BlockAndTintGetter blockView, BlockState state, BlockPos pos, Supplier<RandomSource> randomSupplier, RenderContext context) {
|
||||
// mesh.outputTo(context.getEmitter());
|
||||
// }
|
||||
//
|
||||
// public void bakeCenter(QuadEmitter emitter, TextureAtlasSprite sprite) {
|
||||
// for (Direction dir : Direction.values()) {
|
||||
// emitter.square(dir, MIN, MIN, MAX, MAX, MIN);
|
||||
// emitter.spriteBake(sprite, MutableQuadView.BAKE_LOCK_UV);
|
||||
// emitter.color(-1, -1, -1, -1);
|
||||
// emitter.emit();
|
||||
// }
|
||||
// }
|
||||
// public void bakeConnection(Direction dir, QuadEmitter emitter, TextureAtlasSprite sprite) {
|
||||
// int mag = dir.getStepX()+dir.getStepZ(); // i dont want to hear it
|
||||
// float bottom = dir.getStepY()==0 ? 6/16F : (dir.getStepY()==1 ? 10/16F : 0F);
|
||||
//
|
||||
// for (Direction d : dir.getAxis().getPlane().faces) {
|
||||
// emitter.square(d, (6/16F)+0.5F*mag, bottom, 6/16F)
|
||||
// }
|
||||
//
|
||||
// }
|
||||
//
|
||||
//// @Override
|
||||
//// public boolean isVanillaAdapter() {
|
||||
//// return false; // TODO: let this be true so maybe forge and fabric can be unified
|
||||
//// }
|
||||
//}
|
||||
@@ -0,0 +1,59 @@
|
||||
package org.neoflock.neocomputers.platforms.fabric.client.model;
|
||||
|
||||
import kotlin.jvm.functions.Function1;
|
||||
import net.fabricmc.fabric.api.renderer.v1.model.FabricBakedModel;
|
||||
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
|
||||
import net.fabricmc.fabric.impl.renderer.VanillaModelEncoder;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlas;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.client.resources.model.*;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.BlockAndTintGetter;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.neoflock.neocomputers.NeoComputers;
|
||||
import org.neoflock.neocomputers.block.model.AbstractModel;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class FabricModelWrapper implements FabricBakedModel, UnbakedModel {
|
||||
private AbstractModel model;
|
||||
|
||||
public FabricModelWrapper(AbstractModel model) {
|
||||
this.model = model;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void emitBlockQuads(BlockAndTintGetter blockView, BlockState state, BlockPos pos, Supplier<RandomSource> randomSupplier, RenderContext context) {
|
||||
VanillaModelEncoder.emitBlockQuads(model, state, randomSupplier, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void emitItemQuads(ItemStack stack, Supplier<RandomSource> randomSupplier, RenderContext context) {
|
||||
VanillaModelEncoder.emitItemQuads(model, null, randomSupplier, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<ResourceLocation> getDependencies() {
|
||||
return List.of();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resolveParents(Function<ResourceLocation, UnbakedModel> resolver) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable BakedModel bake(ModelBaker baker, Function<Material, TextureAtlasSprite> spriteGetter, ModelState state) {
|
||||
// NeoComputers.INSTANCE.getLOGGER().info("{}", spriteGetter.apply(new Material()));
|
||||
model._bake(spriteGetter);
|
||||
// model.bake((Function1<? super ResourceLocation, ? extends TextureAtlasSprite>) Minecraft.getInstance().getTextureAtlas(TextureAtlas.LOCATION_BLOCKS));
|
||||
return model;
|
||||
}
|
||||
}
|
||||
@@ -1,24 +1,22 @@
|
||||
package org.neoflock.neocomputers.platforms.fabric.client.model;
|
||||
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||
import net.fabricmc.fabric.api.client.model.loading.v1.ModelLoadingPlugin;
|
||||
import net.minecraft.client.resources.model.ModelResourceLocation;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import org.neoflock.neocomputers.NeoComputers;
|
||||
import org.neoflock.neocomputers.block.model.RobotModel;
|
||||
|
||||
public class ModelLoader implements ModelLoadingPlugin {
|
||||
public static final ResourceLocation CABLE = ResourceLocation.fromNamespaceAndPath(NeoComputers.MODID, "cable");
|
||||
public static final ResourceLocation ROBOT = ResourceLocation.fromNamespaceAndPath(NeoComputers.MODID, "robot");
|
||||
|
||||
@Override
|
||||
public void onInitializeModelLoader(Context pluginContext) {
|
||||
pluginContext.modifyModelOnLoad().register((original, context) -> {
|
||||
// final ModelResourceLocation id = context.topLevelId();
|
||||
////// if (id != null && id.id().getNamespace().equals(NeoComputers.MODID)) NeoComputers.INSTANCE.getLOGGER().info("{} {} {}", id.id().getNamespace(), id.id().getPath(), id.id().getPath().equals(CABLE.id().getPath()));
|
||||
// if (id != null && id.id().equals(CABLE)) {
|
||||
////// NeoComputers.INSTANCE.getLOGGER().error("DOING CABLEEEEEEE");
|
||||
// original.
|
||||
// } else {
|
||||
// return original;
|
||||
// }
|
||||
final ModelResourceLocation id = context.topLevelId();
|
||||
if (id != null && id.id().equals(ROBOT)) {
|
||||
return new FabricModelWrapper(new RobotModel());
|
||||
}
|
||||
return original;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -56,6 +56,9 @@ object NeoComputers {
|
||||
EnvExecutor.runInEnv(Env.CLIENT) {{
|
||||
ClientLifecycleEvent.CLIENT_SETUP.register {
|
||||
Menus.registerScreens()
|
||||
Networking.allNodes.remove()
|
||||
Networking.wirelessNodes.remove()
|
||||
Networking.channels.remove()
|
||||
}
|
||||
ClientLifecycleEvent.CLIENT_STARTED.register {
|
||||
FontProvider.load(ResourceLocation.fromNamespaceAndPath(MODID, "font/unscii.hex"))
|
||||
@@ -81,12 +84,6 @@ object NeoComputers {
|
||||
Networking.channels.remove()
|
||||
}
|
||||
|
||||
ClientLifecycleEvent.CLIENT_SETUP.register {
|
||||
Networking.allNodes.remove()
|
||||
Networking.wirelessNodes.remove()
|
||||
Networking.channels.remove()
|
||||
}
|
||||
|
||||
PlayerEvent.CLOSE_MENU.register {
|
||||
player, menu ->
|
||||
if(player is ServerPlayer) NodeSynchronizer.playerScreenClosed(player)
|
||||
|
||||
@@ -35,6 +35,8 @@ object Blocks {
|
||||
val REDSTONEIO_BLOCK: RegistrySupplier<Block> = BaseBlock.register("redio") { RedstoneIOBlock() }
|
||||
val CABLE_BLOCK: RegistrySupplier<Block> = BaseBlock.register("cable") { CableBlock() }
|
||||
val RELAY_BLOCK: RegistrySupplier<Block> = BaseBlock.register("relay") { RelayBlock() }
|
||||
val ROBOT_BLOCK: RegistrySupplier<Block> = BaseBlock.register("robot") { RobotBlock() }
|
||||
val RACK_BLOCK: RegistrySupplier<Block> = BaseBlock.register("rack") { RackBlock() }
|
||||
|
||||
fun registerBlockItems() {
|
||||
BLOCKS.forEach(Consumer { sup: RegistrySupplier<Block> ->
|
||||
|
||||
@@ -152,6 +152,7 @@ class CableBlock() : DeviceBlock(Properties.of()), EntityBlock {
|
||||
// val ent = level.getBlockEntity(blockPos.relative(dir))
|
||||
// level.setBlockAndUpdate(blockPos, blockState.setValue(getPropByDirection(dir), (ent is NodeBlockEntity || ent is CableEntity)))
|
||||
// }
|
||||
super.neighborChanged(state, level, pos, neighborBlock, neighborPos, movedByPiston)
|
||||
val diff = pos.subtract(neighborPos)
|
||||
val dir = Direction.fromDelta(diff.x, diff.y, diff.z)!!.opposite
|
||||
val ent = level.getBlockEntity(neighborPos)
|
||||
@@ -164,6 +165,10 @@ class CableBlock() : DeviceBlock(Properties.of()), EntityBlock {
|
||||
if (stack.item is DyeItem) {
|
||||
val dyeitem = stack.item as DyeItem
|
||||
level.setBlockAndUpdate(pos, state.setValue(COLOR, dyeitem.dyeColor))
|
||||
val ent = level.getBlockEntity(pos)
|
||||
if(ent is CableEntity) {
|
||||
ent.connectionsAreDirty = true
|
||||
}
|
||||
return ItemInteractionResult.SUCCESS
|
||||
}
|
||||
return ItemInteractionResult.PASS_TO_DEFAULT_BLOCK_INTERACTION
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package org.neoflock.neocomputers.block
|
||||
|
||||
import net.minecraft.client.player.LocalPlayer
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.core.Direction
|
||||
import net.minecraft.core.HolderLookup
|
||||
@@ -8,7 +7,6 @@ import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.network.FriendlyByteBuf
|
||||
import net.minecraft.network.chat.OutgoingChatMessage
|
||||
import net.minecraft.network.chat.PlayerChatMessage
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.world.InteractionResult
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.level.Level
|
||||
@@ -42,9 +40,9 @@ open class CapacitorEntity(val capacity: Long, type: BlockEntityType<*>, pos: Bl
|
||||
override fun getDeviceNodes() = listOf(deviceNode)
|
||||
override fun getNodeFromSide(directionToRequester: Direction) = deviceNode
|
||||
|
||||
override fun loadAdditional(compoundTag: CompoundTag, provider: HolderLookup.Provider) {
|
||||
super.loadAdditional(compoundTag, provider)
|
||||
deviceNode.energy = min(compoundTag.getLong("energy"), deviceNode.energyCapacity)
|
||||
override fun loadAdditional(tag: CompoundTag, registries: HolderLookup.Provider) {
|
||||
super.loadAdditional(tag, registries)
|
||||
deviceNode.energy = min(tag.getLong("energy"), deviceNode.energyCapacity)
|
||||
}
|
||||
|
||||
override fun saveAdditional(compoundTag: CompoundTag, provider: HolderLookup.Provider) {
|
||||
|
||||
@@ -34,7 +34,7 @@ import org.neoflock.neocomputers.entity.MachineEntity
|
||||
import org.neoflock.neocomputers.network.NodeSynchronizer
|
||||
import org.neoflock.neocomputers.sounds.Sounds
|
||||
|
||||
class CaseBlock() : DeviceBlock(Properties.of().sound(SoundType.METAL).lightLevel(CaseBlock::getLuminance)) { // placeholder stuff
|
||||
class CaseBlock() : DeviceBlock(Properties.of().sound(SoundType.METAL).lightLevel(CaseBlock::getLuminance).noOcclusion()) { // placeholder stuff
|
||||
companion object {
|
||||
val FACING: EnumProperty<Direction> = EnumProperty.create<Direction>("facing", Direction::class.java)
|
||||
val COMPUTER_RUNNING = BooleanProperty.create("running")!!
|
||||
@@ -59,6 +59,8 @@ class CaseBlock() : DeviceBlock(Properties.of().sound(SoundType.METAL).lightLeve
|
||||
return level.getBlockEntity(blockPos) as CaseBlockEntity
|
||||
}
|
||||
|
||||
override fun isSignalSource(state: BlockState): Boolean = true
|
||||
|
||||
override fun getSignal(
|
||||
blockState: BlockState,
|
||||
blockGetter: BlockGetter,
|
||||
|
||||
@@ -9,8 +9,11 @@ import net.minecraft.core.Direction
|
||||
import net.minecraft.core.HolderLookup
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.network.FriendlyByteBuf
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.server.level.ServerLevel
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.world.InteractionResult
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.level.Level
|
||||
import net.minecraft.world.level.block.Block
|
||||
import net.minecraft.world.level.block.EntityBlock
|
||||
@@ -18,6 +21,8 @@ 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.phys.BlockHitResult
|
||||
import org.neoflock.neocomputers.NeoComputers
|
||||
import org.neoflock.neocomputers.network.DeviceNode
|
||||
import org.neoflock.neocomputers.network.Networking
|
||||
import org.neoflock.neocomputers.network.NodeSynchronizer
|
||||
@@ -31,8 +36,10 @@ abstract class SingleDeviceBlockEntity(type: BlockEntityType<*>, pos: BlockPos,
|
||||
|
||||
abstract class DeviceBlockEntity(type: BlockEntityType<*>, pos: BlockPos, state: BlockState): BlockEntity(type, pos, state) {
|
||||
val connetionsInDir = MutableList<DeviceNode?>(Direction.entries.size) { null }
|
||||
val nodesInDir = MutableList<DeviceNode?>(Direction.entries.size) { null }
|
||||
var alreadySetup = false
|
||||
var receivedServerState = false
|
||||
var connectionsAreDirty = true
|
||||
|
||||
abstract fun getDeviceNodes(): List<DeviceNode>
|
||||
|
||||
@@ -72,20 +79,35 @@ abstract class DeviceBlockEntity(type: BlockEntityType<*>, pos: BlockPos, state:
|
||||
|
||||
open fun handleConnectionsFor(direction: Direction) {
|
||||
// refuse connections on no node to reduce CPU load
|
||||
val node = getNodeFromSide(direction.opposite) ?: return
|
||||
val node = getNodeFromSide(direction)
|
||||
val oldNode = nodesInDir[direction.ordinal]
|
||||
nodesInDir[direction.ordinal] = node
|
||||
val old = connetionsInDir[direction.ordinal]
|
||||
val now = getCurrentlyConnectedNodeIn(direction)
|
||||
if(node == null) {
|
||||
if(old != null) oldNode?.disconnectFrom(old)
|
||||
if(now != null) oldNode?.disconnectFrom(now)
|
||||
return
|
||||
}
|
||||
if(oldNode != null && oldNode.address != node.address) {
|
||||
if(old != null) oldNode.disconnectFrom(old)
|
||||
if(now != null) oldNode.disconnectFrom(now)
|
||||
}
|
||||
|
||||
if(old?.address != now?.address) {
|
||||
if(old?.address != now?.address || oldNode == null) {
|
||||
if(old != null) node.disconnectFrom(old)
|
||||
if(now != null) node.connectTo(now)
|
||||
}
|
||||
// bullshit hack
|
||||
if(now != null) {
|
||||
node.connectTo(now)
|
||||
}
|
||||
connetionsInDir[direction.ordinal] = now
|
||||
}
|
||||
|
||||
// TODO: optimize this sometime before our test computers melt
|
||||
open fun tickDevice(level: Level) {
|
||||
// Handles device connections and sync here
|
||||
// Handles device connections
|
||||
|
||||
// we do it like this because stinky MC will call stuff before world is fully setup
|
||||
// and then not notify us of neighbour changes
|
||||
@@ -93,6 +115,10 @@ abstract class DeviceBlockEntity(type: BlockEntityType<*>, pos: BlockPos, state:
|
||||
if(!alreadySetup) {
|
||||
initNetworking()
|
||||
}
|
||||
if(connectionsAreDirty) {
|
||||
connectionsAreDirty = false
|
||||
Direction.entries.forEach { handleConnectionsFor(it) }
|
||||
}
|
||||
}
|
||||
|
||||
open fun sendCommitsToClient(level: Level) {
|
||||
@@ -159,6 +185,7 @@ abstract class DeviceBlockEntity(type: BlockEntityType<*>, pos: BlockPos, state:
|
||||
for (node in getDeviceNodes()) {
|
||||
node.markChanged()
|
||||
}
|
||||
connectionsAreDirty = true
|
||||
receivedServerState = false
|
||||
}
|
||||
}
|
||||
@@ -186,9 +213,30 @@ abstract class DeviceBlock(properties: Properties = Properties.of()): BaseBlock(
|
||||
val ent = level.getBlockEntity(pos)
|
||||
if(ent is DeviceBlockEntity) {
|
||||
ent.initNetworking()
|
||||
ent.connectionsAreDirty = true
|
||||
}
|
||||
}
|
||||
|
||||
override fun useWithoutItem(
|
||||
state: BlockState,
|
||||
level: Level,
|
||||
pos: BlockPos,
|
||||
player: Player,
|
||||
hitResult: BlockHitResult
|
||||
): InteractionResult? {
|
||||
val ent = level.getBlockEntity(pos)
|
||||
if(ent is DeviceBlockEntity && player is ServerPlayer) {
|
||||
val dir = hitResult.direction
|
||||
val node = ent.getNodeFromSide(dir)
|
||||
if(node == null) {
|
||||
player.sendSystemMessage(Component.literal("no node for dir $dir"))
|
||||
} else {
|
||||
player.sendSystemMessage(Component.literal("dir: $dir, address: ${node.address}, connections: ${node.connections.joinToString(", ")}"))
|
||||
}
|
||||
}
|
||||
return super.useWithoutItem(state, level, pos, player, hitResult)
|
||||
}
|
||||
|
||||
override fun neighborChanged(
|
||||
state: BlockState,
|
||||
level: Level,
|
||||
|
||||
69
src/main/kotlin/org/neoflock/neocomputers/block/RackBlock.kt
Normal file
@@ -0,0 +1,69 @@
|
||||
package org.neoflock.neocomputers.block
|
||||
|
||||
import dev.architectury.registry.menu.MenuRegistry
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.world.InteractionResult
|
||||
import net.minecraft.world.MenuProvider
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.level.BlockGetter
|
||||
import net.minecraft.world.level.Level
|
||||
import net.minecraft.world.level.block.EntityBlock
|
||||
import net.minecraft.world.level.block.RenderShape
|
||||
import net.minecraft.world.level.block.entity.BlockEntity
|
||||
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.Shapes
|
||||
import net.minecraft.world.phys.shapes.VoxelShape
|
||||
import org.neoflock.neocomputers.NeoComputers
|
||||
import org.neoflock.neocomputers.entity.BlockEntities
|
||||
import org.neoflock.neocomputers.entity.RackEntity
|
||||
import org.neoflock.neocomputers.network.NodeSynchronizer
|
||||
|
||||
class RackBlock : DeviceBlock(Properties.of().noOcclusion()), EntityBlock {
|
||||
override fun newBlockEntity(
|
||||
pos: BlockPos,
|
||||
state: BlockState
|
||||
): BlockEntity? {
|
||||
return RackEntity(pos, state)
|
||||
}
|
||||
|
||||
// override fun getShape(
|
||||
// state: BlockState,
|
||||
// level: BlockGetter,
|
||||
// pos: BlockPos,
|
||||
// context: CollisionContext
|
||||
// ): VoxelShape? {
|
||||
// return Shapes.box(0.0,0.0,0.0,0.01,0.01,0.01)
|
||||
// }
|
||||
|
||||
// override fun getRenderShape(state: BlockState): RenderShape? {
|
||||
// return RenderShape
|
||||
// }
|
||||
|
||||
|
||||
override fun useWithoutItem(state: BlockState, level: Level, pos: BlockPos, player: Player, hitResult: BlockHitResult): InteractionResult? {
|
||||
val res = hitResult.location
|
||||
val ent = level.getBlockEntity(pos, BlockEntities.RACK_ENTITY.get()).get()
|
||||
if(res.x == 18.0) { // TODO: handle rotation
|
||||
NeoComputers.LOGGER.info("{} > {} > {}, {} > {} > {}", pos.z+15/16f, res.z, pos.z+1/16f, pos.y+14/16f, res.y, pos.y+2/16f)
|
||||
if (pos.z + 15 / 16f > res.z && res.z > pos.z + 1 / 16f && pos.y + 14 / 16f > res.y && res.y > pos.y + 2 / 16f) {
|
||||
var rack = 0
|
||||
rack += if(res.y < pos.y+5/16f) 1 else 0
|
||||
rack += if(res.y < pos.y+8/16f) 1 else 0
|
||||
rack += if(res.y < pos.y+12/16f) 1 else 0
|
||||
|
||||
player.sendSystemMessage(Component.literal(String.format("Hit server #%d", rack))) // TODO: call some RackItem method
|
||||
return InteractionResult.SUCCESS
|
||||
}
|
||||
}
|
||||
|
||||
if (!level.isClientSide) {
|
||||
MenuRegistry.openExtendedMenu(player as ServerPlayer, ent)
|
||||
NodeSynchronizer.registerPlayerScreen(player as ServerPlayer, ent.node)
|
||||
}
|
||||
return InteractionResult.SUCCESS
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@ import net.minecraft.network.chat.Component
|
||||
import net.minecraft.server.level.ServerLevel
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.world.ContainerHelper
|
||||
import net.minecraft.world.Containers
|
||||
import net.minecraft.world.InteractionResult
|
||||
import net.minecraft.world.MenuProvider
|
||||
import net.minecraft.world.entity.player.Inventory
|
||||
@@ -27,6 +28,7 @@ import org.neoflock.neocomputers.gui.menu.RelayMenu
|
||||
import org.neoflock.neocomputers.item.RelayUpgrade
|
||||
import org.neoflock.neocomputers.network.ConventionalNetworkDevice
|
||||
import org.neoflock.neocomputers.network.DeviceNode
|
||||
import org.neoflock.neocomputers.network.NNComponent
|
||||
import org.neoflock.neocomputers.network.Networking
|
||||
import org.neoflock.neocomputers.network.NodeSynchronizer
|
||||
import org.neoflock.neocomputers.utils.GenericContainer
|
||||
@@ -59,7 +61,8 @@ class RelayEntity(blockPos: BlockPos, blockState: BlockState): SingleDeviceBlock
|
||||
fun computeRelayCapacity(): Int = computeRelayBufferSize() + computeRelayQueueSize()
|
||||
|
||||
val queue = mutableListOf<Networking.ClassicPacket>()
|
||||
var active = false
|
||||
val justReceived = mutableListOf<Networking.ClassicPacket>()
|
||||
var activityTickLeft = 0
|
||||
var ticksUntilQueue = 0
|
||||
|
||||
override val deviceNode = object : DeviceNode() {
|
||||
@@ -67,8 +70,10 @@ class RelayEntity(blockPos: BlockPos, blockState: BlockState): SingleDeviceBlock
|
||||
override fun received(message: Networking.Message) {
|
||||
super.received(message)
|
||||
if(message.sender == this) return
|
||||
if(message is Networking.ClassicPacket && message.hopCount <= 5 && queue.size < computeRelayCapacity()) {
|
||||
queue.addLast(message)
|
||||
if(message is Networking.ClassicPacket && message.hopCount < 5 && (queue.size + justReceived.size) < computeRelayCapacity()) {
|
||||
justReceived.addLast(message)
|
||||
activityTickLeft = 20
|
||||
markChanged()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,18 +82,20 @@ class RelayEntity(blockPos: BlockPos, blockState: BlockState): SingleDeviceBlock
|
||||
buf.writeVarInt(computeRelayInterval())
|
||||
buf.writeVarInt(computeRelayBufferSize())
|
||||
buf.writeVarInt(computeRelayQueueSize())
|
||||
buf.writeVarInt(queue.size)
|
||||
buf.writeVarInt(queue.size + justReceived.size)
|
||||
}
|
||||
|
||||
override fun writeFullStateCommit(buf: FriendlyByteBuf) {
|
||||
super.writeFullStateCommit(buf)
|
||||
buf.writeBoolean(active)
|
||||
buf.writeVarInt(activityTickLeft)
|
||||
}
|
||||
|
||||
override fun processCommit(buf: FriendlyByteBuf) {
|
||||
super.processCommit(buf)
|
||||
active = buf.readBoolean()
|
||||
activityTickLeft = buf.readVarInt()
|
||||
}
|
||||
|
||||
override fun getComponent() = NNComponent("relay")
|
||||
}
|
||||
|
||||
fun sendQueuedPacket() {
|
||||
@@ -97,13 +104,13 @@ class RelayEntity(blockPos: BlockPos, blockState: BlockState): SingleDeviceBlock
|
||||
|
||||
for(connection in deviceNode.connections) {
|
||||
// skip unwanted loopback
|
||||
if(connection !in pack.sender.getReachable()) continue
|
||||
if(connection in pack.sender.getReachable()) continue
|
||||
val hopped = pack.hop(pack.sender)
|
||||
|
||||
if(connection is ConventionalNetworkDevice) {
|
||||
connection.sendClassicPacket(hopped)
|
||||
} else {
|
||||
Networking.emitMessage(connection, hopped)
|
||||
Networking.emitMessage(connection, hopped, setOf(deviceNode))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -111,6 +118,14 @@ class RelayEntity(blockPos: BlockPos, blockState: BlockState): SingleDeviceBlock
|
||||
override fun tickDevice(level: Level) {
|
||||
super.tickDevice(level)
|
||||
if(level !is ServerLevel) return
|
||||
if(activityTickLeft > 0) {
|
||||
activityTickLeft--
|
||||
deviceNode.markChanged()
|
||||
}
|
||||
queue.addAll(justReceived)
|
||||
justReceived.clear()
|
||||
val cap = computeRelayCapacity()
|
||||
while(queue.size > cap) queue.removeLast()
|
||||
ticksUntilQueue--
|
||||
if(ticksUntilQueue <= 0) {
|
||||
ticksUntilQueue = computeRelayInterval()
|
||||
@@ -119,9 +134,7 @@ class RelayEntity(blockPos: BlockPos, blockState: BlockState): SingleDeviceBlock
|
||||
sendQueuedPacket()
|
||||
}
|
||||
}
|
||||
val cap = computeRelayCapacity()
|
||||
while(queue.size > cap) queue.removeLast()
|
||||
active = queue.isNotEmpty()
|
||||
deviceNode.markChanged()
|
||||
}
|
||||
|
||||
override fun getMachineBlockPosition() = blockPos!!
|
||||
@@ -167,4 +180,15 @@ class RelayBlock: DeviceBlock(Properties.of().sound(SoundType.METAL)) {
|
||||
}
|
||||
return InteractionResult.SUCCESS
|
||||
}
|
||||
|
||||
override fun onRemove(
|
||||
blockState: BlockState,
|
||||
level: Level,
|
||||
blockPos: BlockPos,
|
||||
blockState2: BlockState,
|
||||
bl: Boolean
|
||||
) {
|
||||
Containers.dropContentsOnDestroy(blockState, blockState2, level, blockPos)
|
||||
super.onRemove(blockState, level, blockPos, blockState2, bl)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package org.neoflock.neocomputers.block
|
||||
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.world.level.BlockGetter
|
||||
import net.minecraft.world.level.block.Blocks
|
||||
import net.minecraft.world.level.block.EntityBlock
|
||||
import net.minecraft.world.level.block.RenderShape
|
||||
import net.minecraft.world.level.block.entity.BlockEntity
|
||||
import net.minecraft.world.level.block.state.BlockBehaviour
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import net.minecraft.world.phys.shapes.CollisionContext
|
||||
import net.minecraft.world.phys.shapes.Shapes
|
||||
import net.minecraft.world.phys.shapes.VoxelShape
|
||||
import org.neoflock.neocomputers.NeoComputers
|
||||
import org.neoflock.neocomputers.entity.RobotEntity
|
||||
|
||||
class RobotBlock : BaseBlock(Properties.of().noOcclusion()), EntityBlock { // todo: node stuff
|
||||
override fun newBlockEntity(pos: BlockPos, state: BlockState): BlockEntity {
|
||||
NeoComputers.LOGGER.info("block entity created..")
|
||||
return RobotEntity(pos, state)
|
||||
}
|
||||
|
||||
override fun getShape(state: BlockState, level: BlockGetter, pos: BlockPos, context: CollisionContext): VoxelShape? {
|
||||
return Shapes.box(0.1, 0.1, 0.1, 0.9, 0.9, 0.9)
|
||||
}
|
||||
|
||||
override fun getRenderShape(state: BlockState): RenderShape {
|
||||
return RenderShape.INVISIBLE // this is so not good
|
||||
}
|
||||
// public RenderShape getRenderShape(BlockState state) {
|
||||
// return RenderShape.ENTITYBLOCK_ANIMATED;
|
||||
// }
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
package org.neoflock.neocomputers.block.model
|
||||
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.model.geom.ModelPart
|
||||
import net.minecraft.client.renderer.block.model.BakedQuad
|
||||
import net.minecraft.client.renderer.block.model.ItemOverrides
|
||||
import net.minecraft.client.renderer.block.model.ItemTransforms
|
||||
import net.minecraft.client.renderer.texture.TextureAtlas
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite
|
||||
import net.minecraft.client.resources.model.BakedModel
|
||||
import net.minecraft.client.resources.model.Material
|
||||
import net.minecraft.client.resources.model.ModelBaker
|
||||
import net.minecraft.client.resources.model.ModelState
|
||||
import net.minecraft.client.resources.model.UnbakedModel
|
||||
import net.minecraft.core.Direction
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.util.RandomSource
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import org.neoflock.neocomputers.NeoComputers
|
||||
import java.util.function.Function
|
||||
|
||||
abstract class AbstractModel : BakedModel {
|
||||
val atlas = Minecraft.getInstance().getTextureAtlas(TextureAtlas.LOCATION_BLOCKS)
|
||||
var baker: ModelBaker? = null;
|
||||
var mesh: Map<Direction, List<BakedQuad>> = mapOf(
|
||||
Direction.UP to listOf(),
|
||||
Direction.DOWN to listOf(),
|
||||
Direction.EAST to listOf(),
|
||||
Direction.WEST to listOf(),
|
||||
Direction.SOUTH to listOf(),
|
||||
Direction.NORTH to listOf(),
|
||||
);
|
||||
|
||||
override fun getQuads(state: BlockState?, direction: Direction?, random: RandomSource): List<BakedQuad?>? { // perf? what's that?
|
||||
if (direction != null) {
|
||||
return mesh[direction]
|
||||
} else {
|
||||
var allquads: MutableList<BakedQuad> = mutableListOf()
|
||||
mesh.forEach { (_, quads) ->
|
||||
allquads.addAll(quads)
|
||||
}
|
||||
return allquads
|
||||
}
|
||||
}
|
||||
|
||||
fun _bake(spriteGetter: Function<Material, TextureAtlasSprite>): BakedModel {
|
||||
bake { r: Material -> spriteGetter.apply(r) }
|
||||
return this
|
||||
}
|
||||
|
||||
override fun getParticleIcon(): TextureAtlasSprite? {
|
||||
return atlas.apply(particle())
|
||||
}
|
||||
|
||||
abstract fun bake(atlas: (Material) -> TextureAtlasSprite)
|
||||
|
||||
abstract fun particle(): ResourceLocation
|
||||
|
||||
}
|
||||
|
||||
class SchizoConsumer {
|
||||
var mesh: Map<Direction, MutableList<BakedQuad>> = mapOf(
|
||||
Direction.UP to mutableListOf(),
|
||||
Direction.DOWN to mutableListOf(),
|
||||
Direction.EAST to mutableListOf(),
|
||||
Direction.WEST to mutableListOf(),
|
||||
Direction.SOUTH to mutableListOf(),
|
||||
Direction.NORTH to mutableListOf(),
|
||||
);
|
||||
|
||||
var vertices: MutableList<Int> = mutableListOf();
|
||||
var sprite: TextureAtlasSprite? = null;
|
||||
var normal: Direction? = null;
|
||||
var tint_index = -1
|
||||
var shade = false
|
||||
|
||||
fun startQuad(normal: Direction, sprite: TextureAtlasSprite, tint_index: Int = -1, shade: Boolean = false): SchizoConsumer {
|
||||
this.sprite = sprite
|
||||
this.normal = normal
|
||||
this.tint_index = tint_index
|
||||
this.shade = shade
|
||||
return this
|
||||
}
|
||||
|
||||
fun vertex(x: Float, y: Float, z:Float, colorABGR: Int, u: Float, v: Float) { // uv are normalized
|
||||
if (sprite == null || normal == null) {
|
||||
throw Error("quad not started")
|
||||
}
|
||||
|
||||
// NeoComputers.LOGGER.info("{} {} -> {} {} ", u, v, sprite!!.getU(u), sprite!!.getV(v))
|
||||
vertices.add(x.toBits())
|
||||
vertices.add(y.toBits())
|
||||
vertices.add(z.toBits())
|
||||
vertices.add(colorABGR)
|
||||
vertices.add(sprite!!.getU(u).toBits())
|
||||
vertices.add(sprite!!.getV(v).toBits())
|
||||
vertices.add(0)
|
||||
vertices.add(0)
|
||||
|
||||
if (vertices.size == 4 * 8) {
|
||||
var quad = BakedQuad(vertices.toIntArray(), tint_index, normal!!, sprite!!, shade)
|
||||
mesh.get(normal)!!.add(quad)
|
||||
normal = null
|
||||
sprite = null
|
||||
vertices.clear()
|
||||
}
|
||||
} // TODO: add stuff like squares
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package org.neoflock.neocomputers.block.model
|
||||
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.renderer.block.model.BakedQuad
|
||||
import net.minecraft.client.renderer.block.model.ItemOverrides
|
||||
import net.minecraft.client.renderer.block.model.ItemTransforms
|
||||
import net.minecraft.client.renderer.texture.TextureAtlas
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite
|
||||
import net.minecraft.client.resources.model.BakedModel
|
||||
import net.minecraft.client.resources.model.Material
|
||||
import net.minecraft.client.resources.model.ModelBaker
|
||||
import net.minecraft.client.resources.model.ModelState
|
||||
import net.minecraft.client.resources.model.UnbakedModel
|
||||
import net.minecraft.core.Direction
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.util.RandomSource
|
||||
import net.minecraft.util.ResourceLocationPattern
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import org.neoflock.neocomputers.NeoComputers
|
||||
import java.util.function.Function
|
||||
|
||||
class RobotModel() : AbstractModel() {
|
||||
val size = 0.4f
|
||||
val l = 0.5f-size;
|
||||
val h = 0.5f+size;
|
||||
|
||||
// TODO: fix dimensions (i eyeballed it)
|
||||
override fun bake(atlas: (Material) -> TextureAtlasSprite) {
|
||||
// override fun bake(atlas: Function<Material?, TextureAtlasSprite?>, state: ModelState): BakedModel {
|
||||
val sprite = atlas(Material(TextureAtlas.LOCATION_BLOCKS, ResourceLocation.fromNamespaceAndPath(NeoComputers.MODID, "block/robot")))
|
||||
// val sprite = atlas.apply(Material(TextureAtlas.LOCATION_BLOCKS, ResourceLocation.fromNamespaceAndPath(NeoComputers.MODID, "robot")))!!
|
||||
var verts: SchizoConsumer = SchizoConsumer()
|
||||
|
||||
// top pyramid, enjoy reading this schizo mess
|
||||
bakeTri(verts, Direction.WEST, sprite, l,l, l, h, 9f/16f,1f, 0f, 0f, 0f, 16f/32f)
|
||||
bakeTri(verts, Direction.EAST, sprite, h, h, h, l, 9f/16f, 1f, 16/32f, 16/32f, 16/32f, 0f)
|
||||
bakeTri(verts, Direction.SOUTH, sprite, l, h, h, h, 9f/16f, 1f, 0f, 16f/32f, 16f/32f, 16f/32f)
|
||||
bakeTri(verts, Direction.NORTH, sprite, h, l, l,l, 9f/16f, 1f, 16/32f, 0f, 0f, 0f)
|
||||
|
||||
verts.startQuad(Direction.DOWN, sprite, 0)
|
||||
verts.vertex(l, 9f/16F, h, 0xFFFFFFFF.toInt(), 16f/32f, 16/32F)
|
||||
verts.vertex(l, 9f/16f, l, 0xFFFFFFFF.toInt(), 0F, 16/32F)
|
||||
verts.vertex(h, 9f/16f, l, 0xFFFFFFFF.toInt(), 0F, 1F)
|
||||
verts.vertex(h, 9f/16f, h, 0xFFFFFFFF.toInt(), 16/32F, 1F)
|
||||
|
||||
// bottom
|
||||
bakeTri(verts, Direction.WEST, sprite, l, h, l, l, 8f/16f, 1/16f, 0f, 0f, 0f, 16f/32f)
|
||||
bakeTri(verts, Direction.EAST, sprite, h, l, h, h, 8f/16f, 1/16f, 0f, 0f, 0f, 16f/32f)
|
||||
bakeTri(verts, Direction.SOUTH, sprite, h, h, l, h, 8f/16f, 1/16f, 0f, 0f, 0f, 16f/32f)
|
||||
bakeTri(verts, Direction.NORTH, sprite, l, l, h,l, 8f/16f, 1/16f, 0f, 0f, 0f, 16f/32f)
|
||||
|
||||
verts.startQuad(Direction.UP, sprite, 0)
|
||||
verts.vertex(h, 8f/16F, l, 0xFFFFFFFF.toInt(), 16/32F, 16/32F)
|
||||
verts.vertex(l, 8f/16f, l, 0xFFFFFFFF.toInt(), 0F, 16/32F)
|
||||
verts.vertex(l, 8f/16f, h, 0xFFFFFFFF.toInt(), 0F, 1F)
|
||||
verts.vertex(h, 8f/16f, h, 0xFFFFFFFF.toInt(), 16/32F, 1F)
|
||||
|
||||
|
||||
this.mesh = verts.mesh
|
||||
}
|
||||
|
||||
fun bakeTri(verts: SchizoConsumer, normal: Direction, sprite: TextureAtlasSprite, lx: Float, lz: Float, rx: Float, rz: Float, dy: Float, uy: Float, lu: Float, lv: Float, ru: Float, rv: Float) {
|
||||
verts.startQuad(normal, sprite, 0)
|
||||
verts.vertex(0.5F, uy, 0.5F, 0xFFFFFFFF.toInt(), 8F/32F, 8F/32F)
|
||||
verts.vertex(0.5F, uy, 0.5F, 0xFFFFFFFF.toInt(), 8F/32F, 8F/32F)
|
||||
verts.vertex(lx, dy, lz, 0xFFFFFFFF.toInt(), lu, lv)
|
||||
verts.vertex(rx, dy, rz, 0xFFFFFFFF.toInt(), ru, rv)
|
||||
}
|
||||
|
||||
override fun particle(): ResourceLocation = ResourceLocation.fromNamespaceAndPath(NeoComputers.MODID, "block/teto")
|
||||
|
||||
override fun useAmbientOcclusion(): Boolean = true
|
||||
|
||||
override fun isGui3d(): Boolean = true
|
||||
|
||||
override fun usesBlockLight(): Boolean = true
|
||||
|
||||
override fun isCustomRenderer(): Boolean = false
|
||||
|
||||
override fun getTransforms(): ItemTransforms? = ItemTransforms.NO_TRANSFORMS
|
||||
|
||||
override fun getOverrides(): ItemOverrides? = ItemOverrides.EMPTY // TODO: item
|
||||
}
|
||||
@@ -4,15 +4,19 @@ import net.fabricmc.fabric.api.datagen.v1.FabricDataOutput
|
||||
import net.fabricmc.fabric.api.datagen.v1.provider.FabricModelProvider
|
||||
import net.minecraft.data.models.BlockModelGenerators
|
||||
import net.minecraft.data.models.ItemModelGenerators
|
||||
import net.minecraft.data.models.model.ModelTemplate
|
||||
import net.minecraft.data.models.model.ModelTemplates
|
||||
import org.neoflock.neocomputers.block.Blocks
|
||||
import org.neoflock.neocomputers.item.Items
|
||||
|
||||
class ModelGenerator(output: FabricDataOutput) : FabricModelProvider(output) {
|
||||
override fun generateBlockStateModels(blockStateModelGenerator: BlockModelGenerators) {
|
||||
blockStateModelGenerator.createGenericCube(Blocks.CASE_BLOCK.get())
|
||||
// blockStateModelGenerator.createGenericCube(Blocks.CASE_BLOCK.get())
|
||||
|
||||
}
|
||||
|
||||
override fun generateItemModels(itemModelGenerator: ItemModelGenerators) {
|
||||
itemModelGenerator.generateFlatItem(Items.SERVER0.get(), ModelTemplates.FLAT_ITEM)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -94,6 +94,18 @@ object BlockEntities {
|
||||
)
|
||||
}
|
||||
|
||||
val ROBOT_ENTITY: RegistrySupplier<BlockEntityType<RobotEntity>> = BLOCKENTITIES.register("robot") {
|
||||
BlockEntityType(
|
||||
::RobotEntity, setOf(Blocks.ROBOT_BLOCK.get()), BullshitFix()
|
||||
)
|
||||
}
|
||||
|
||||
val RACK_ENTITY: RegistrySupplier<BlockEntityType<RackEntity>> = BLOCKENTITIES.register("rack") {
|
||||
BlockEntityType(
|
||||
::RackEntity, setOf(Blocks.RACK_BLOCK.get()), BullshitFix()
|
||||
)
|
||||
}
|
||||
|
||||
fun registerPowerBlocks() {
|
||||
PowerManager.registerPowerDevice(CAPACITOR_ENTITY.get())
|
||||
PowerManager.registerPowerDevice(CAPACITOR2_ENTITY.get())
|
||||
|
||||
@@ -10,6 +10,7 @@ import net.minecraft.world.level.block.state.BlockState
|
||||
import org.neoflock.neocomputers.block.CableBlock
|
||||
import org.neoflock.neocomputers.block.CableBlock.Companion.COLOR
|
||||
import org.neoflock.neocomputers.block.CableBlock.Companion.getPropByDirection
|
||||
import org.neoflock.neocomputers.block.DeviceBlockEntity
|
||||
import org.neoflock.neocomputers.block.SingleDeviceBlockEntity
|
||||
import org.neoflock.neocomputers.network.DeviceNode
|
||||
|
||||
@@ -38,6 +39,9 @@ class CableEntity(pos: BlockPos, state: BlockState) : SingleDeviceBlockEntity(Bl
|
||||
for (dir in Direction.entries) {
|
||||
val ent = level!!.getBlockEntity(blockPos.relative(dir))
|
||||
level!!.setBlockAndUpdate(blockPos, blockState.setValue(getPropByDirection(dir), CableBlock.shouldConnect(blockPos, blockPos.relative(dir), level!!)))
|
||||
if(ent is DeviceBlockEntity) {
|
||||
ent.connectionsAreDirty = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,7 @@ import org.neoflock.neocomputers.block.SingleDeviceBlockEntity
|
||||
import org.neoflock.neocomputers.gui.menu.CaseMenu
|
||||
import org.neoflock.neocomputers.item.ComponentItem
|
||||
import org.neoflock.neocomputers.network.DeviceNode
|
||||
import org.neoflock.neocomputers.network.NNComponent
|
||||
import org.neoflock.neocomputers.network.Networking
|
||||
import org.neoflock.neocomputers.network.PowerRole
|
||||
import org.neoflock.neocomputers.sounds.ComputerRunningSoundInstance
|
||||
@@ -106,6 +107,15 @@ class CaseBlockEntity(blockPos: BlockPos, blockState: BlockState): SingleDeviceB
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun received(message: Networking.Message) {
|
||||
super.received(message)
|
||||
if(message is Networking.ClassicPacket) {
|
||||
NeoComputers.LOGGER.info("machine $address got $message from ${message.sender.address}")
|
||||
}
|
||||
}
|
||||
|
||||
override fun getComponent() = NNComponent("computer")
|
||||
}
|
||||
|
||||
val redstoneIn = Array(Direction.entries.size) {0}
|
||||
@@ -170,6 +180,7 @@ class CaseBlockEntity(blockPos: BlockPos, blockState: BlockState): SingleDeviceB
|
||||
}
|
||||
// Server-side stuff!!
|
||||
sendMachineEvent(MachinePowerEvent(this, isOn))
|
||||
Networking.emitMessage(deviceNode, Networking.ClassicPacket(deviceNode, deviceNode.address.toString(), null, 1, listOf(), 0))
|
||||
}
|
||||
|
||||
override fun start(): Boolean {
|
||||
@@ -252,7 +263,7 @@ class CaseBlockEntity(blockPos: BlockPos, blockState: BlockState): SingleDeviceB
|
||||
|
||||
override fun getMachineMemoryTotal(): Long = stacks.mapNotNull { (it.item as? ComponentItem)?.getMemoryCapacity(it) }.sum().toLong()
|
||||
override fun getMachineMemoryUsed(): Long = 0
|
||||
override fun getMachineComponentsUsed(): Long = deviceNode.getReachable().size.toLong()
|
||||
override fun getMachineComponentsUsed(): Long = deviceNode.getReachable().count { it.getComponent() != null }.toLong()
|
||||
override fun getMachineComponentsTotal(): Long = stacks.mapNotNull { (it.item as? ComponentItem)?.getComponentCapacity(it) }.sum().toLong()
|
||||
override fun getMachineArchitecture() = arch
|
||||
override fun getMachineArchitectures() = stacks.mapNotNull { (it.item as? ComponentItem)?.getArchitecturesProvided(it) }.flatten().toSet()
|
||||
@@ -269,11 +280,11 @@ class CaseBlockEntity(blockPos: BlockPos, blockState: BlockState): SingleDeviceB
|
||||
|
||||
override fun stillValid(player: Player): Boolean = !this.isRemoved
|
||||
|
||||
override fun loadAdditional(compoundTag: CompoundTag, provider: HolderLookup.Provider) {
|
||||
super.loadAdditional(compoundTag, provider)
|
||||
deviceNode.energy = min(deviceNode.energyCapacity, compoundTag.getLong("energy"))
|
||||
override fun loadAdditional(tag: CompoundTag, registries: HolderLookup.Provider) {
|
||||
super.loadAdditional(tag, registries)
|
||||
deviceNode.energy = min(deviceNode.energyCapacity, tag.getLong("energy"))
|
||||
//isOn = compoundTag.getBoolean("powerOn")
|
||||
ContainerHelper.loadAllItems(compoundTag, getItems(), provider)
|
||||
ContainerHelper.loadAllItems(tag, getItems(), registries)
|
||||
}
|
||||
|
||||
override fun saveAdditional(compoundTag: CompoundTag, provider: HolderLookup.Provider) {
|
||||
|
||||
134
src/main/kotlin/org/neoflock/neocomputers/entity/RackEntity.kt
Normal file
@@ -0,0 +1,134 @@
|
||||
package org.neoflock.neocomputers.entity
|
||||
|
||||
import dev.architectury.registry.menu.ExtendedMenuProvider
|
||||
import net.minecraft.client.renderer.RenderType
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.core.Direction
|
||||
import net.minecraft.core.HolderLookup
|
||||
import net.minecraft.core.NonNullList
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.network.FriendlyByteBuf
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.network.protocol.Packet
|
||||
import net.minecraft.network.protocol.game.ClientGamePacketListener
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.world.ContainerHelper
|
||||
import net.minecraft.world.MenuProvider
|
||||
import net.minecraft.world.entity.player.Inventory
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.level.block.entity.AbstractFurnaceBlockEntity
|
||||
import net.minecraft.world.level.block.entity.BlockEntity
|
||||
import net.minecraft.world.level.block.entity.ChestBlockEntity
|
||||
import net.minecraft.world.level.block.entity.FurnaceBlockEntity
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import org.neoflock.neocomputers.NeoComputers
|
||||
import org.neoflock.neocomputers.block.DeviceBlockEntity
|
||||
import org.neoflock.neocomputers.gui.menu.RackMenu
|
||||
import org.neoflock.neocomputers.network.DeviceNode
|
||||
import org.neoflock.neocomputers.network.Networking
|
||||
import org.neoflock.neocomputers.utils.ContainerUtils
|
||||
import org.neoflock.neocomputers.utils.GenericContainer
|
||||
|
||||
class RackEntity(pos: BlockPos, state: BlockState) : DeviceBlockEntity(BlockEntities.RACK_ENTITY.get(), pos, state), ExtendedMenuProvider, GenericContainer {
|
||||
val stacks: NonNullList<ItemStack> = NonNullList<ItemStack>.withSize(4, ItemStack.EMPTY)
|
||||
|
||||
var conns = mutableListOf(
|
||||
-1, -1, -1, -1,
|
||||
-1, -1, -1, -1,
|
||||
-1, -1, -1, -1,
|
||||
-1, -1, -1, -1
|
||||
)
|
||||
|
||||
var relayMode = false
|
||||
|
||||
val node: DeviceNode = object : DeviceNode() {
|
||||
override var reachability: Networking.Visibility = Networking.Visibility.NONE
|
||||
|
||||
override fun writeFullStateCommit(buf: FriendlyByteBuf) {
|
||||
super.writeFullStateCommit(buf)
|
||||
buf.writeBoolean(relayMode)
|
||||
|
||||
val tag = CompoundTag() // better way to do this, a better way i do not care to find atm
|
||||
ContainerHelper.saveAllItems(tag, stacks, level!!.registryAccess())
|
||||
buf.writeNbt(tag)
|
||||
|
||||
|
||||
for (conn in conns) {
|
||||
buf.writeInt(conn)
|
||||
}
|
||||
}
|
||||
|
||||
override fun processCommit(buf: FriendlyByteBuf) {
|
||||
super.processCommit(buf)
|
||||
relayMode = buf.readBoolean()
|
||||
val tag = buf.readNbt()
|
||||
ContainerHelper.loadAllItems(tag!!, stacks, level!!.registryAccess())
|
||||
|
||||
for (i in 0..15) {
|
||||
conns[i] = buf.readInt()
|
||||
}
|
||||
markChanged()
|
||||
setChanged()
|
||||
}
|
||||
|
||||
override fun processScreenInteraction(player: ServerPlayer, buf: FriendlyByteBuf) {
|
||||
super.processScreenInteraction(player, buf)
|
||||
relayMode = buf.readBoolean()
|
||||
|
||||
val slot = buf.readInt()
|
||||
conns[slot*4+0] = buf.readInt()
|
||||
conns[slot*4+1] = buf.readInt()
|
||||
conns[slot*4+2] = buf.readInt()
|
||||
conns[slot*4+3] = buf.readInt()
|
||||
|
||||
markChanged()
|
||||
setChanged()
|
||||
}
|
||||
override fun encodeScreenData(player: ServerPlayer, buf: FriendlyByteBuf) { // TODO: set this up so other players can mess with racks
|
||||
super.encodeScreenData(player, buf)
|
||||
}
|
||||
}
|
||||
|
||||
override fun setChanged() {
|
||||
super.setChanged()
|
||||
node.markChanged()
|
||||
}
|
||||
|
||||
override fun getDisplayName(): Component? = Component.literal("Rack")
|
||||
|
||||
override fun createMenu(i: Int, inventory: Inventory, player: Player): AbstractContainerMenu {
|
||||
return RackMenu(i, inventory, this)
|
||||
}
|
||||
|
||||
override fun getDeviceNodes(): List<DeviceNode> = listOf(node)
|
||||
|
||||
override fun getNodeFromSide(directionToRequester: Direction): DeviceNode? = node
|
||||
|
||||
|
||||
override fun loadAdditional(tag: CompoundTag, registries: HolderLookup.Provider) {
|
||||
super.loadAdditional(tag, registries)
|
||||
ContainerHelper.loadAllItems(tag, getItems(), registries)
|
||||
relayMode = tag.getBoolean("relay")
|
||||
|
||||
val connarray = tag.getIntArray("conns")
|
||||
if (connarray.size == 16) conns = connarray.toMutableList()
|
||||
setChanged()
|
||||
}
|
||||
|
||||
override fun saveAdditional(tag: CompoundTag, registries: HolderLookup.Provider) {
|
||||
super.saveAdditional(tag, registries)
|
||||
ContainerHelper.saveAllItems(tag, getItems(), registries)
|
||||
tag.putBoolean("relay", relayMode)
|
||||
tag.putIntArray("conns", conns.toIntArray())
|
||||
}
|
||||
|
||||
// override fun getItems(): NonNullList<ItemStack> = items
|
||||
override fun getItems(): NonNullList<ItemStack> = stacks
|
||||
|
||||
override fun stillValid(player: Player): Boolean = true
|
||||
override fun saveExtraData(buf: FriendlyByteBuf?) {
|
||||
buf!!.writeBlockPos(blockPos)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package org.neoflock.neocomputers.entity
|
||||
|
||||
import net.minecraft.client.model.geom.ModelPart
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.world.level.block.entity.BlockEntity
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import org.neoflock.neocomputers.NeoComputers
|
||||
|
||||
class RobotEntity(pos: BlockPos, state: BlockState) : BlockEntity(BlockEntities.ROBOT_ENTITY.get(), pos, state,) {
|
||||
val body: ModelPart? = null
|
||||
val name = "Diddyx" //TODO: names
|
||||
|
||||
init {
|
||||
NeoComputers.LOGGER.info("yooo")
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.neoflock.neocomputers.entity;
|
||||
package org.neoflock.neocomputers.entity
|
||||
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.locale.Language
|
||||
@@ -11,6 +11,7 @@ import org.neoflock.neocomputers.NeoComputers
|
||||
import org.neoflock.neocomputers.block.SingleDeviceBlockEntity
|
||||
import org.neoflock.neocomputers.gui.buffer.BufferRenderer
|
||||
import org.neoflock.neocomputers.network.DeviceNode
|
||||
import org.neoflock.neocomputers.network.NNComponent
|
||||
import org.neoflock.neocomputers.network.Networking
|
||||
import org.neoflock.neocomputers.utils.GPUChar
|
||||
import org.neoflock.neocomputers.utils.TextBuffer
|
||||
@@ -59,40 +60,42 @@ class ScreenEntity(blockPos: BlockPos, blockState: BlockState) :
|
||||
|
||||
override fun processCommit(buf: FriendlyByteBuf) {
|
||||
super.processCommit(buf)
|
||||
if(Networking.changeNodeAddress(this, buf.readUUID())) createscreenstuffs()
|
||||
if(Networking.changeNodeAddress(this, buf.readUUID())) createScreenTexture()
|
||||
isOn = buf.readBoolean()
|
||||
lastError = buf.readUtf().ifEmpty { null }
|
||||
textBuf.decodeContents(buf)
|
||||
}
|
||||
|
||||
override fun getComponent() = NNComponent("screen")
|
||||
}
|
||||
var bound = "screen/unbound"
|
||||
|
||||
val textBuf = TextBuffer(50, 16)
|
||||
|
||||
private var cleanrenderer: () -> Unit = { }; // TODO: THIS SUCKS, FIND A BETTER WAY
|
||||
private var cleanRenderer: () -> Unit = { } // TODO: THIS SUCKS, FIND A BETTER WAY
|
||||
|
||||
override fun tickDevice(level: Level) {
|
||||
super.tickDevice(level)
|
||||
cleanrenderer()
|
||||
createscreenstuffs()
|
||||
cleanRenderer()
|
||||
createScreenTexture()
|
||||
}
|
||||
|
||||
override fun setRemoved() {
|
||||
super.setRemoved()
|
||||
bound = "screen/unbound" // ensure no missing texture is displayed
|
||||
cleanrenderer()
|
||||
cleanRenderer()
|
||||
}
|
||||
|
||||
private fun createscreenstuffs() {
|
||||
private fun createScreenTexture() {
|
||||
bound = "screen/"+deviceNode.address.toString().replace("-", "_")
|
||||
if (level!!.isClientSide) {
|
||||
if(lastError == null) {
|
||||
if(!isOn) {
|
||||
textBuf.fill(0, 0, textBuf.width, textBuf.height)
|
||||
}
|
||||
var renderer = BufferRenderer(ResourceLocation.fromNamespaceAndPath(NeoComputers.MODID, bound), textBuf)
|
||||
val renderer = BufferRenderer(ResourceLocation.fromNamespaceAndPath(NeoComputers.MODID, bound), textBuf)
|
||||
renderer.drawBuffer()
|
||||
cleanrenderer = { renderer.clean() }
|
||||
cleanRenderer = { renderer.clean() }
|
||||
} else {
|
||||
var trueError = lastError!!
|
||||
if(trueError.startsWith("@")) {
|
||||
@@ -105,9 +108,9 @@ class ScreenEntity(blockPos: BlockPos, blockState: BlockState) :
|
||||
val bg = 0x2B68A6
|
||||
throwAwayBuf.fill(0, 0, throwAwayBuf.width, throwAwayBuf.height, GPUChar(' ', fg, bg))
|
||||
throwAwayBuf.set((throwAwayBuf.width - trueError.length) / 2, throwAwayBuf.height/2, trueError, fg, bg)
|
||||
var renderer = BufferRenderer(ResourceLocation.fromNamespaceAndPath(NeoComputers.MODID, bound), throwAwayBuf)
|
||||
val renderer = BufferRenderer(ResourceLocation.fromNamespaceAndPath(NeoComputers.MODID, bound), throwAwayBuf)
|
||||
renderer.drawBuffer()
|
||||
cleanrenderer = { renderer.clean() }
|
||||
cleanRenderer = { renderer.clean() }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,12 +5,14 @@ import com.mojang.blaze3d.vertex.PoseStack
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer
|
||||
import com.mojang.blaze3d.vertex.VertexFormat
|
||||
import com.mojang.math.Axis
|
||||
import net.minecraft.client.renderer.LightTexture
|
||||
import net.minecraft.client.renderer.MultiBufferSource
|
||||
import net.minecraft.client.renderer.RenderStateShard
|
||||
import net.minecraft.client.renderer.RenderType
|
||||
import net.minecraft.client.renderer.blockentity.BlockEntityRenderer
|
||||
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider
|
||||
import net.minecraft.core.Direction
|
||||
import org.neoflock.neocomputers.NeoComputers
|
||||
import org.neoflock.neocomputers.block.CaseBlock
|
||||
import org.neoflock.neocomputers.entity.CaseBlockEntity
|
||||
|
||||
@@ -23,9 +25,10 @@ class CaseEntityRenderer(private val context: BlockEntityRendererProvider.Contex
|
||||
|
||||
val BLINKTIME: Long = 10 // in ticks
|
||||
|
||||
val RENDER_TYPE = RenderType.create("nc_case", DefaultVertexFormat.POSITION_COLOR, VertexFormat.Mode.QUADS,
|
||||
val RENDER_TYPE = RenderType.create("nc_case", DefaultVertexFormat.POSITION_COLOR_LIGHTMAP, VertexFormat.Mode.QUADS,
|
||||
RenderType.TRANSIENT_BUFFER_SIZE, RenderType.CompositeState.builder()
|
||||
.setShaderState(RenderStateShard.POSITION_COLOR_SHADER)
|
||||
.setShaderState(RenderStateShard.POSITION_COLOR_LIGHTMAP_SHADER)
|
||||
.setLightmapState(RenderStateShard.LightmapStateShard.LIGHTMAP)
|
||||
.createCompositeState(false))
|
||||
|
||||
override fun render(ent: CaseBlockEntity, partialTick: Float, mat: PoseStack, bufferSource: MultiBufferSource, packedLight: Int, packedOverlay: Int) {
|
||||
@@ -38,20 +41,20 @@ class CaseEntityRenderer(private val context: BlockEntityRendererProvider.Contex
|
||||
if (ent.isOn) drawLED(buffer, mat.last(), 3F)
|
||||
else if (ent.getLastError() != null) { // if else hell
|
||||
if ((ent.level!!.dayTime/BLINKTIME) % 2 == 1.toLong()) drawLED(buffer, mat.last(), 3F, RED)
|
||||
else drawLED(buffer, mat.last(), 3F, OFF)
|
||||
} else drawLED(buffer, mat.last(), 3F, OFF)
|
||||
else drawLED(buffer, mat.last(), 3F, OFF, packedLight)
|
||||
} else drawLED(buffer, mat.last(), 3F, OFF, packedLight)
|
||||
|
||||
mat.translate(6/16F, 0F, 0F)
|
||||
drawLED(buffer, mat.last(), 2F, if (ent.diskActivityTime > 0) GREEN else OFF)
|
||||
drawLED(buffer, mat.last(), 2F, if (ent.diskActivityTime > 0) GREEN else OFF, if (ent.diskActivityTime > 0) LightTexture.FULL_BRIGHT else packedLight)
|
||||
|
||||
mat.popPose()
|
||||
|
||||
}
|
||||
private fun drawLED(buffer: VertexConsumer, mat: PoseStack.Pose, width: Float, color: Int = GREEN) {
|
||||
buffer.addVertex(mat, width/16F, 0F, 0F).setColor(color)
|
||||
buffer.addVertex(mat, width/16F, 1/16F, 0F).setColor(color)
|
||||
buffer.addVertex(mat, 0F, 1/16F, 0F).setColor(color)
|
||||
buffer.addVertex(mat, 0F, 0F, 0F).setColor(color)
|
||||
private fun drawLED(buffer: VertexConsumer, mat: PoseStack.Pose, width: Float, color: Int = GREEN, light: Int = LightTexture.FULL_BRIGHT) {
|
||||
buffer.addVertex(mat, width/16F, 0F, 0F).setColor(color).setLight(light)
|
||||
buffer.addVertex(mat, width/16F, 1/16F, 0F).setColor(color).setLight(light)
|
||||
buffer.addVertex(mat, 0F, 1/16F, 0F).setColor(color).setLight(light)
|
||||
buffer.addVertex(mat, 0F, 0F, 0F).setColor(color).setLight(light)
|
||||
}
|
||||
|
||||
private fun handleDirection(facing: Direction, mat: PoseStack) {
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
package org.neoflock.neocomputers.entity.render
|
||||
|
||||
import com.mojang.authlib.minecraft.client.MinecraftClient
|
||||
import com.mojang.blaze3d.vertex.PoseStack
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.renderer.LevelRenderer
|
||||
import net.minecraft.client.renderer.LightTexture
|
||||
import net.minecraft.client.renderer.MultiBufferSource
|
||||
import net.minecraft.client.renderer.block.ModelBlockRenderer
|
||||
import net.minecraft.client.renderer.blockentity.BlockEntityRenderer
|
||||
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider
|
||||
import net.minecraft.world.level.LightLayer
|
||||
import net.minecraft.world.level.dimension.DimensionType
|
||||
import net.minecraft.world.level.lighting.BlockLightEngine
|
||||
import org.neoflock.neocomputers.NeoComputers
|
||||
import org.neoflock.neocomputers.entity.RackEntity
|
||||
import org.neoflock.neocomputers.item.RackItem
|
||||
|
||||
class RackEntityRenderer(val context: BlockEntityRendererProvider.Context) : BlockEntityRenderer<RackEntity> {
|
||||
|
||||
override fun render(ent: RackEntity, partialTick: Float, poseStack: PoseStack, source: MultiBufferSource, packedLight: Int, packedOverlay: Int) {
|
||||
poseStack.pushPose()
|
||||
poseStack.translate(1/16f, 11/16f, 1/16f)
|
||||
|
||||
val items = ent.stacks
|
||||
for (i in 0..3) {
|
||||
if (items[i].item is RackItem) {
|
||||
val item = items[i].item as RackItem
|
||||
item.render(source, poseStack, packedLight, 2f+(3*i))
|
||||
}
|
||||
poseStack.translate(0f, -3/16f, 0f)
|
||||
}
|
||||
// val render_slot = (ent.level!!.dayTime/40)%4 // this is purely temporary type shit like true alpha shit, anyway it go to 0-3, change and test it if you want
|
||||
// poseStack.translate(0f, (render_slot)*-3/16f, 0f)
|
||||
// val server = object : RackItem { override fun render_lights(source: MultiBufferSource, stack: PoseStack, light: Int) { } }
|
||||
// server.render(source, poseStack, packedLight, 2f+(3*render_slot)) // who knows atp
|
||||
poseStack.popPose()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package org.neoflock.neocomputers.entity.render
|
||||
|
||||
import com.mojang.blaze3d.vertex.DefaultVertexFormat
|
||||
import com.mojang.blaze3d.vertex.PoseStack
|
||||
import com.mojang.blaze3d.vertex.VertexFormat
|
||||
import com.mojang.math.Axis
|
||||
import net.minecraft.client.renderer.GameRenderer
|
||||
import net.minecraft.client.renderer.MultiBufferSource
|
||||
import net.minecraft.client.renderer.RenderStateShard
|
||||
import net.minecraft.client.renderer.RenderType
|
||||
import net.minecraft.client.renderer.blockentity.BlockEntityRenderer
|
||||
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import org.neoflock.neocomputers.NeoComputers
|
||||
import org.neoflock.neocomputers.block.RelayEntity
|
||||
import java.util.Timer
|
||||
import kotlin.math.min
|
||||
|
||||
class RelayEntityRenderer(val context: BlockEntityRendererProvider.Context?): BlockEntityRenderer<RelayEntity> {
|
||||
val RELAY_ON_TEX = ResourceLocation.fromNamespaceAndPath(NeoComputers.MODID, "textures/block/relay_side_on.png")
|
||||
|
||||
val RENDER_TYPE: RenderType =
|
||||
RenderType.create(
|
||||
"nc_screen",
|
||||
DefaultVertexFormat.POSITION_TEX_COLOR,
|
||||
VertexFormat.Mode.QUADS,
|
||||
RenderType.TRANSIENT_BUFFER_SIZE, RenderType.CompositeState.builder().
|
||||
setShaderState(RenderStateShard.ShaderStateShard(GameRenderer::getPositionTexColorShader)).
|
||||
setTextureState(RenderStateShard.TextureStateShard(RELAY_ON_TEX, false, false))
|
||||
.createCompositeState(false))
|
||||
|
||||
override fun render(
|
||||
blockEntity: RelayEntity,
|
||||
partialTick: Float,
|
||||
mat: PoseStack,
|
||||
bufferSource: MultiBufferSource,
|
||||
packedLight: Int,
|
||||
packedOverlay: Int
|
||||
) {
|
||||
if(blockEntity.activityTickLeft == 0) return
|
||||
|
||||
val alpha = min((blockEntity.activityTickLeft.toFloat() * 255 / 20).toInt(), 255)
|
||||
|
||||
for(i in 0..<4) {
|
||||
mat.pushPose()
|
||||
|
||||
val antiZFight = 0.001F
|
||||
|
||||
mat.rotateAround(Axis.YN.rotationDegrees(90F * i), 0.5F, 0.5F, 0.5F)
|
||||
mat.translate(0F, 0F, 1F + antiZFight)
|
||||
|
||||
val width = 1F
|
||||
val height = 1F
|
||||
val bx = 0F
|
||||
val by = 0F
|
||||
|
||||
val buffer = bufferSource.getBuffer(RENDER_TYPE)
|
||||
buffer.addVertex(mat.last(), bx + width, by, 0f).setUv(1f, 1f).setColor(alpha, alpha, alpha, alpha)
|
||||
buffer.addVertex(mat.last(), bx + width, by + height, 0f).setUv(1f, 0f).setColor(alpha, alpha, alpha, alpha)
|
||||
buffer.addVertex(mat.last(), bx, by + height, 0f).setUv(0f, 0f).setColor(alpha, alpha, alpha, alpha)
|
||||
buffer.addVertex(mat.last(), bx, by, 0f).setUv(0f, 1f).setColor(alpha, alpha, alpha, alpha)
|
||||
|
||||
mat.popPose()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
package org.neoflock.neocomputers.entity.render
|
||||
|
||||
import com.mojang.blaze3d.systems.RenderSystem
|
||||
import com.mojang.blaze3d.vertex.DefaultVertexFormat
|
||||
import com.mojang.blaze3d.vertex.PoseStack
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer
|
||||
import com.mojang.blaze3d.vertex.VertexFormat
|
||||
import com.mojang.math.Axis
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.gui.Font
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.client.model.geom.ModelPart
|
||||
import net.minecraft.client.renderer.GameRenderer
|
||||
import net.minecraft.client.renderer.ItemBlockRenderTypes
|
||||
import net.minecraft.client.renderer.MultiBufferSource
|
||||
import net.minecraft.client.renderer.RenderStateShard
|
||||
import net.minecraft.client.renderer.RenderType
|
||||
import net.minecraft.client.renderer.RenderType.CompositeState
|
||||
import net.minecraft.client.renderer.block.ModelBlockRenderer
|
||||
import net.minecraft.client.renderer.block.model.BakedQuad
|
||||
import net.minecraft.client.renderer.blockentity.BlockEntityRenderer
|
||||
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider
|
||||
import net.minecraft.client.renderer.entity.LivingEntityRenderer
|
||||
import net.minecraft.client.renderer.texture.OverlayTexture
|
||||
import net.minecraft.client.renderer.texture.TextureAtlas
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite
|
||||
import net.minecraft.client.resources.model.BakedModel
|
||||
import net.minecraft.client.resources.model.Material
|
||||
import net.minecraft.client.resources.model.ModelResourceLocation
|
||||
import net.minecraft.client.resources.model.ModelState
|
||||
import net.minecraft.core.Direction
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.util.RandomSource
|
||||
import net.minecraft.world.item.DyeColor
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import org.neoflock.neocomputers.NeoComputers
|
||||
import org.neoflock.neocomputers.block.model.RobotModel
|
||||
import org.neoflock.neocomputers.entity.RobotEntity
|
||||
import kotlin.math.sin
|
||||
|
||||
class RobotEntityRenderer(val context: BlockEntityRendererProvider.Context) : BlockEntityRenderer<RobotEntity> {
|
||||
val atlas: (Material) -> TextureAtlasSprite = { m ->
|
||||
Minecraft.getInstance().getTextureAtlas(m.atlasLocation()).apply(m.texture())
|
||||
}
|
||||
val loc: ResourceLocation = ResourceLocation.fromNamespaceAndPath(NeoComputers.MODID, "robot")
|
||||
var model: BakedModel? = Minecraft.getInstance().modelManager.getModel(ModelResourceLocation.inventory(loc))
|
||||
val renderer: ModelBlockRenderer = ModelBlockRenderer(Minecraft.getInstance().blockColors) // so ass
|
||||
|
||||
val STREAK_RENDER_TYPE = RenderType.create("nc_robot_streak", DefaultVertexFormat.POSITION_TEX_COLOR, VertexFormat.Mode.QUADS, RenderType.TRANSIENT_BUFFER_SIZE,
|
||||
CompositeState.builder()
|
||||
.setShaderState(RenderStateShard.ShaderStateShard { GameRenderer.getPositionTexColorShader() })
|
||||
.setTransparencyState(RenderStateShard.ADDITIVE_TRANSPARENCY)
|
||||
.setTextureState(RenderStateShard.TextureStateShard(ResourceLocation.fromNamespaceAndPath(NeoComputers.MODID, "textures/block/robot.png"), false, false))
|
||||
.createCompositeState(false))
|
||||
|
||||
override fun render(ent: RobotEntity, partialTick: Float, poseStack: PoseStack, bufferSource: MultiBufferSource, packedLight: Int, packedOverlay: Int) {
|
||||
poseStack.pushPose()
|
||||
// poseStack.translate(0f, sin(ent.level!!.dayTime.toFloat()/20F)*0.02F, 0f)
|
||||
val modelbuffer = bufferSource.getBuffer(RenderType.entitySolid(TextureAtlas.LOCATION_BLOCKS))
|
||||
val colorbuffer = bufferSource.getBuffer(STREAK_RENDER_TYPE)
|
||||
|
||||
val col = DyeColor.LIGHT_GRAY.fireworkColor
|
||||
val red = ((col and 0xFF0000) shr 8*2) / 255f
|
||||
val green = ((col and 0xFF00) shr 8) / 255f
|
||||
val blue = ((col and 0xFF)) / 255f
|
||||
|
||||
renderer.renderModel(poseStack.last(), modelbuffer, ent.blockState, model!!, red, green, blue, packedLight, packedOverlay)
|
||||
renderLight(poseStack, colorbuffer, (ent.level!!.dayTime%16).toInt())
|
||||
|
||||
|
||||
// TODO: crafting table and chest little models
|
||||
|
||||
poseStack.popPose()
|
||||
renderTag(ent, Component.literal(ent.name), poseStack, bufferSource, packedLight, partialTick)
|
||||
}
|
||||
|
||||
// offset is 0-15
|
||||
fun renderLight(poseStack: PoseStack, buffer: VertexConsumer, offset: Int) {
|
||||
poseStack.pushPose()
|
||||
|
||||
val u1 = 0.5f
|
||||
val v1 = 0.5f + offset*1/32f
|
||||
val u2 = 1F
|
||||
val v2 = 17/32f + offset*1/32f
|
||||
|
||||
for (i in 0..3) {
|
||||
poseStack.rotateAround(Axis.YP.rotationDegrees(90f), 0.5f, 0.5f, 0.5f)
|
||||
|
||||
buffer.addVertex(poseStack.last(),0.1f+2/16f, 7/16f, 0.9f-2/16f).setColor(1f, 0f, 0f, 1f).setUv(u2, v2)
|
||||
buffer.addVertex(poseStack.last(),0.1f+2/16f, 9/16f, 0.9f-2/16f).setColor(1f, 0f, 0f, 1f).setUv(u2, v1)
|
||||
buffer.addVertex(poseStack.last(),0.1f+2/16f, 9/16f, 0.1f+2/16f).setColor(1f, 0f, 0f, 1f).setUv(u1, v1)
|
||||
buffer.addVertex(poseStack.last(),0.1f+2/16f, 7/16f, 0.1f+2/16f).setColor(1f, 0f, 0f, 1f).setUv(u1, v2)
|
||||
}
|
||||
|
||||
poseStack.popPose()
|
||||
|
||||
|
||||
}
|
||||
|
||||
fun renderTag(ent: RobotEntity, name: Component, stack: PoseStack, source: MultiBufferSource, light: Int, ptick: Float) {
|
||||
val d = Minecraft.getInstance().cameraEntity!!.distanceToSqr(ent.blockPos.center)
|
||||
if (d > 4096.0) return
|
||||
|
||||
val vec = Vec3(0.5, 20 / 16.0, 0.5)
|
||||
|
||||
stack.pushPose()
|
||||
stack.translate(vec.x, vec.y, vec.z)
|
||||
// stack.mulPose(context.entityRenderer.cameraOrientation())
|
||||
stack.scale(0.025F, -0.025F, 0.025F)
|
||||
val opacity = Minecraft.getInstance().options.getBackgroundOpacity(0.25F)
|
||||
val alpha: Int = (opacity * 255.0f).toInt() shl 24
|
||||
// val alpha = 255
|
||||
val halfwidth = (-context.font.width(name)) / 2;
|
||||
RenderSystem.disableDepthTest()
|
||||
context.font.drawInBatch(name, halfwidth.toFloat(), 2f, 0xFFFFFF, false, stack.last().pose(), source, Font.DisplayMode.SEE_THROUGH, alpha, light)
|
||||
|
||||
RenderSystem.enableDepthTest()
|
||||
stack.popPose()
|
||||
}
|
||||
|
||||
}
|
||||
@@ -12,6 +12,7 @@ import org.neoflock.neocomputers.NeoComputers
|
||||
import org.neoflock.neocomputers.gui.menu.ScreenMenu
|
||||
import org.neoflock.neocomputers.gui.screen.CaseScreen
|
||||
import org.neoflock.neocomputers.gui.screen.CombustionGeneratorScreen
|
||||
import org.neoflock.neocomputers.gui.screen.RackScreen
|
||||
import org.neoflock.neocomputers.gui.screen.RelayScreen
|
||||
import org.neoflock.neocomputers.gui.screen.ScreenScreen
|
||||
|
||||
@@ -22,11 +23,14 @@ object Menus {
|
||||
val COMBUSTGEN_MENU: RegistrySupplier<MenuType<CombustionGeneratorMenu>> = MENUS.register("combustgen_menu") { MenuType(::CombustionGeneratorMenu, FeatureFlagSet.of() ) }
|
||||
val CASE_MENU: RegistrySupplier<MenuType<CaseMenu>> = MENUS.register("case_menu") { MenuType(::CaseMenu, FeatureFlagSet.of() )}
|
||||
val RELAY_MENU: RegistrySupplier<MenuType<RelayMenu>> = MENUS.register("relay_menu") { MenuType(::RelayMenu, FeatureFlagSet.of() )}
|
||||
val RACK_MENU: RegistrySupplier<MenuType<RackMenu>> = MENUS.register("rack_menu") { MenuRegistry.ofExtended(::RackMenu) }
|
||||
// val RACK_MENU: RegistrySupplier<MenuType<RackMenu>> = MENUS.register("rack_menu") { MenuType(::RackMenu, FeatureFlagSet.of() )}
|
||||
|
||||
fun registerScreens() {
|
||||
MenuScreens.register(Menus.COMBUSTGEN_MENU.get()) { m: CombustionGeneratorMenu, u, comp ->CombustionGeneratorScreen(m,u,comp)}
|
||||
MenuScreens.register(Menus.SCREEN_MENU.get(), ::ScreenScreen)
|
||||
MenuScreens.register(Menus.CASE_MENU.get(), ::CaseScreen)
|
||||
MenuScreens.register(Menus.RELAY_MENU.get(), ::RelayScreen)
|
||||
MenuScreens.register(Menus.RACK_MENU.get(), ::RackScreen)
|
||||
}
|
||||
}
|
||||
192
src/main/kotlin/org/neoflock/neocomputers/gui/menu/RackMenu.kt
Normal file
@@ -0,0 +1,192 @@
|
||||
package org.neoflock.neocomputers.gui.menu
|
||||
|
||||
import com.mojang.blaze3d.systems.RenderSystem
|
||||
import com.mojang.blaze3d.vertex.BufferUploader
|
||||
import com.mojang.blaze3d.vertex.DefaultVertexFormat
|
||||
import com.mojang.blaze3d.vertex.Tesselator
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer
|
||||
import com.mojang.blaze3d.vertex.VertexFormat
|
||||
import io.netty.buffer.Unpooled
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.client.gui.components.events.GuiEventListener
|
||||
import net.minecraft.client.renderer.GameRenderer
|
||||
import net.minecraft.client.renderer.MultiBufferSource
|
||||
import net.minecraft.client.renderer.RenderStateShard
|
||||
import net.minecraft.client.renderer.RenderType
|
||||
import net.minecraft.client.resources.sounds.SimpleSoundInstance
|
||||
import net.minecraft.network.FriendlyByteBuf
|
||||
import net.minecraft.sounds.SoundEvents
|
||||
import net.minecraft.world.Container
|
||||
import net.minecraft.world.SimpleContainer
|
||||
import net.minecraft.world.entity.player.Inventory
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import org.neoflock.neocomputers.NeoComputers
|
||||
import org.neoflock.neocomputers.entity.RackEntity
|
||||
import org.neoflock.neocomputers.gui.widget.ComponentRoles
|
||||
import org.neoflock.neocomputers.gui.widget.DynamicSlot
|
||||
import org.neoflock.neocomputers.item.ComponentItem
|
||||
import org.neoflock.neocomputers.utils.GenericContainerMenu
|
||||
|
||||
class RackSlot(container: Container, slot: Int, x: Int, y: Int) : DynamicSlot(container, slot, x, y), GuiEventListener {
|
||||
// i hate that i made this, my regret is immeasurable
|
||||
val MAIN_COLOURS = listOf(0xff8382d8.toInt(), 0xff75bdc1.toInt(), 0xffc8ca5f.toInt(), 0xffdb7d75.toInt(), 0xff7ec95f.toInt())
|
||||
val DARK_COLOURS = listOf(0xff6a6ab0.toInt(), 0xff60999d.toInt(), 0xffa2a44e.toInt(), 0xffb36660.toInt(), 0xff67a34e.toInt())
|
||||
val LIGHT_COLOURS = listOf(0xffdcdcf0.toInt(), 0xffdcdcf0.toInt(), 0xffececd4.toInt(), 0xfff0dbd9.toInt(), 0xffdbecd4.toInt())
|
||||
|
||||
val secondaries = 2 // TODO: make this actually change depending on how many network cards
|
||||
|
||||
// todo: kotlin getters and setters
|
||||
fun getSelected(i: Int): Int = (container as RackEntity).conns[containerSlot*4+i]
|
||||
fun setSelected(i: Int, v: Int) { (container as RackEntity).conns[containerSlot*4+i] = v }
|
||||
|
||||
override fun draw(graphics: GuiGraphics, mouseX: Int, mouseY: Int) {
|
||||
super.draw(graphics, mouseX, mouseY)
|
||||
if (!hasItem()) { drawQuad(graphics, ComponentRoles.getTextureFor("rack"), x, y, 16, 16, 0f, 0f, 15f, 15f); return; }
|
||||
for (i in 0..secondaries) {
|
||||
if (getSelected(i) > -1) drawConnection(graphics, getSelected(i), i-1)
|
||||
}
|
||||
|
||||
drawEndpoints(graphics, mouseX, mouseY, secondaries)
|
||||
}
|
||||
|
||||
override fun mayPlace(stack: ItemStack): Boolean {
|
||||
if (stack.item !is ComponentItem) return false
|
||||
return (stack.item as ComponentItem).getComponentRoles(stack).contains(ComponentRoles.RACK_MOUNTABLE)
|
||||
}
|
||||
|
||||
override fun onTake(player: Player, stack: ItemStack) {
|
||||
super.onTake(player, stack)
|
||||
setSelected(0, -1)
|
||||
setSelected(1, -1)
|
||||
setSelected(2, -1)
|
||||
setSelected(3, -1)
|
||||
(container as RackEntity).setChanged()
|
||||
|
||||
}
|
||||
|
||||
fun drawConnection(guiGraphics: GuiGraphics, side: Int, sec: Int = -1) {
|
||||
val bufferSource = guiGraphics.bufferSource()
|
||||
val buffer = bufferSource.getBuffer(RenderType.gui())
|
||||
|
||||
if (sec == -1) {
|
||||
drawColor(guiGraphics, buffer, 18, 1, DARK_COLOURS[side], 6 + (11 * side))
|
||||
drawColor(guiGraphics, buffer, 18, 2, MAIN_COLOURS[side], 6 + (11 * side))
|
||||
drawColor(guiGraphics, buffer, 18, 3, LIGHT_COLOURS[side], 6 + (11 * side))
|
||||
} else {
|
||||
drawColor(guiGraphics, buffer, 18, 6+(4*sec), MAIN_COLOURS[side], 6+(11*side))
|
||||
drawColor(guiGraphics, buffer, 18, 7+(4*sec), 0xff8f8f90.toInt(), 6+(11*side))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun drawEndpoints(guiGraphics: GuiGraphics, mx: Int, my: Int, sec: Int =0) {
|
||||
val bufferSource = guiGraphics.bufferSource()
|
||||
val buffer = bufferSource.getBuffer(RenderType.gui())
|
||||
|
||||
// main slot endpoint
|
||||
drawColor(guiGraphics, buffer, 17, 1, 0xff888888.toInt())
|
||||
drawColor(guiGraphics, buffer, 17, 3, 0xffffffff.toInt())
|
||||
|
||||
// main cable endpoints
|
||||
for (i in 0..4) {
|
||||
drawColor(guiGraphics, buffer, 24+(11*i), 1, 0xff333333.toInt(), 1, 3)
|
||||
drawColor(guiGraphics, buffer, 25+(11*i), 1, MAIN_COLOURS[i], 3, 3)
|
||||
drawColor(guiGraphics, buffer, 28+(11*i), 1, 0xffffffff.toInt(), 1, 3)
|
||||
|
||||
// highlight
|
||||
if (mx >= x+25+(11*i) && mx <= x+27+(11*i) && my >= y+1 && my <= y+3) {
|
||||
drawColor(guiGraphics, buffer, 25+(11*i), 1, 0x80FFFFFF.toInt(), 3, 3)
|
||||
}
|
||||
}
|
||||
|
||||
// secondary endpoints
|
||||
for (i in 0..<sec) {
|
||||
// slot
|
||||
drawColor(guiGraphics, buffer, 17, 6+(4*i), 0xffffffff.toInt())
|
||||
drawColor(guiGraphics, buffer, 17, 7+(4*i), 0xff888888.toInt())
|
||||
|
||||
// cable
|
||||
for (j in 0..4) {
|
||||
drawColor(guiGraphics, buffer, 24+(11*j), 6+(4*i), 0xff333333.toInt(), 1, 2)
|
||||
drawColor(guiGraphics, buffer, 25+(11*j), 6+(4*i), MAIN_COLOURS[j], 3, 2)
|
||||
drawColor(guiGraphics, buffer, 28+(11*j), 6+(4*i), 0xffffffff.toInt(), 1, 2)
|
||||
|
||||
// highlight
|
||||
if (mx >= x+25+(11*j) && mx <= x+27+(11*j) && my >= y+6+(4*i) && my <= y+8+(4*i)) {
|
||||
drawColor(guiGraphics, buffer, 25+(11*j), 6+(4*i), 0x80FFFFFF.toInt(), 3, 2)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun encode(buf: FriendlyByteBuf) { // client -> server
|
||||
buf.writeInt(containerSlot)
|
||||
buf.writeInt(getSelected(0))
|
||||
buf.writeInt(getSelected(1))
|
||||
buf.writeInt(getSelected(2))
|
||||
buf.writeInt(getSelected(3))
|
||||
|
||||
}
|
||||
|
||||
// TODO: replace with graphics.fill (cant be assed atm)
|
||||
fun drawColor(guiGraphics: GuiGraphics, buffer: VertexConsumer, _x:Int, _y: Int, col: Int, width: Int=1, height: Int=1) {
|
||||
val pose = guiGraphics.pose().last()
|
||||
|
||||
// x+_x+1 is one im not proud of
|
||||
buffer.addVertex(pose, x+_x+width.toFloat(), y+_y+height.toFloat(), 2f).setColor(col)
|
||||
buffer.addVertex(pose, x+_x+width.toFloat(), y+_y.toFloat(), 2f).setColor(col)
|
||||
buffer.addVertex(pose, x+_x.toFloat(), y+_y.toFloat(), 2f).setColor(col)
|
||||
buffer.addVertex(pose, x+_x.toFloat(), y+_y+height.toFloat(), 2f).setColor(col)
|
||||
}
|
||||
|
||||
fun clickynoise() {
|
||||
val handler = Minecraft.getInstance().soundManager
|
||||
handler.play(SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK, 1.0F));
|
||||
}
|
||||
|
||||
override fun mouseClicked(mouseX: Double, mouseY: Double, button: Int): Boolean {
|
||||
for (i in 0..4) { // main line
|
||||
if (mouseX >= x+25+(11*i) && mouseX <= x+28+(11*i) && mouseY >= y+1 && mouseY <= y+4 && button == 0) {
|
||||
setSelected(0, if (getSelected(0) != i) i else -1)
|
||||
(container as RackEntity).setChanged()
|
||||
clickynoise()
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
for (i in 0..<secondaries) { // secondary lines
|
||||
for (j in 0..4) {
|
||||
if (mouseX >= x+25+(11*j) && mouseX <= x+28+(11*j) && mouseY >= y+6+(4*i) && mouseY <= y+8+(4*i) && button == 0) {
|
||||
setSelected(i+1, if (getSelected(i+1) != j) j else -1)
|
||||
(container as RackEntity).setChanged()
|
||||
clickynoise()
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.mouseClicked(mouseX, mouseY, button)
|
||||
}
|
||||
|
||||
override fun setFocused(focused: Boolean) {
|
||||
}
|
||||
|
||||
override fun isFocused(): Boolean {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
class RackMenu : GenericContainerMenu {
|
||||
|
||||
constructor(i: Int, inv: Inventory, buf: FriendlyByteBuf) : this(i, inv, (inv.player.level().getBlockEntity(buf.readBlockPos()) as RackEntity))
|
||||
|
||||
constructor(i: Int, inv: Inventory, container: Container) : super(Menus.RACK_MENU.get(), i, container) {
|
||||
for(i in 0..3) {
|
||||
val slot = RackSlot(container, i, 20, 23+i*20)
|
||||
this.addSlot(slot)
|
||||
}
|
||||
this.addInventorySlots(inv, 8, 128)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -55,14 +55,10 @@ class RelaySlot(container: Container, slot: Int, x: Int, y: Int, val role: Strin
|
||||
override fun getMaxStackSize() = 1
|
||||
override fun getMaxStackSize(stack: ItemStack) = 1
|
||||
|
||||
override fun draw(graphics: GuiGraphics, relX: Int, relY: Int, mouseX: Int, mouseY: Int) {
|
||||
super.draw(graphics, relX, relY, mouseX, mouseY)
|
||||
override fun draw(graphics: GuiGraphics, mouseX: Int, mouseY: Int) {
|
||||
super.draw(graphics, mouseX, mouseY)
|
||||
if(!hasItem()) {
|
||||
RenderSystem.enableBlend()
|
||||
RenderSystem.setShaderTexture(0, ComponentRoles.getTextureFor(role))
|
||||
RenderSystem.setShader { GameRenderer.getPositionTexShader() }
|
||||
drawQuad(relX + x - 1, relY + y - 1, 18, 18, 0F, 0F, 15F, 15F)
|
||||
RenderSystem.disableBlend()
|
||||
drawQuad(graphics, ComponentRoles.getTextureFor(role), x-1, y-1, 18, 18, 0f, 0f, 15f, 15f)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ class CaseScreen : GenericContainerScreen<CaseMenu> {
|
||||
|
||||
private var btn: ImagerButton? = null
|
||||
override fun shouldCenterTitle(): Boolean = false
|
||||
// override fun findMenuTexture(): ResourceLocation = BG
|
||||
|
||||
var isOn = false
|
||||
var lastError: String? = null
|
||||
@@ -77,7 +78,7 @@ class CaseScreen : GenericContainerScreen<CaseMenu> {
|
||||
|
||||
constructor(abstractContainerMenu: CaseMenu, inventory: Inventory, component: Component) : super(abstractContainerMenu, inventory, component) {
|
||||
btn = ImagerButton(
|
||||
15, 15,
|
||||
71, 33,
|
||||
18, 18,
|
||||
ButtonSprites(BTN, 18, 18, 36, 36)
|
||||
) {
|
||||
@@ -85,17 +86,11 @@ class CaseScreen : GenericContainerScreen<CaseMenu> {
|
||||
buf.writeByte(if(isOn) 0x02 else 0x01)
|
||||
NodeSynchronizer.sendScreenInteraction(buf)
|
||||
}
|
||||
// addRenderableWidget(btn!!)
|
||||
}
|
||||
override fun renderBg(guiGraphics: GuiGraphics, f: Float, i: Int, j: Int) {
|
||||
super.renderBg(guiGraphics, f, i ,j)
|
||||
val relX = (this.width - this.imageWidth) / 2
|
||||
val relY = (this.height - this.imageHeight) / 2
|
||||
|
||||
btn!!.x = relX+70
|
||||
btn!!.y = relY+33
|
||||
btn!!.render(guiGraphics, i, j, f) // minecraft SUCKSSS
|
||||
guiGraphics.blit(PCB, relX, relY, 0, 0, this.imageWidth, this.imageHeight)
|
||||
addWidget(btn!!)
|
||||
}
|
||||
override fun renderbg(guiGraphics: GuiGraphics, f: Float, i: Int, j: Int) {
|
||||
guiGraphics.blit(PCB, 0, 0, 0, 0, this.imageWidth, this.imageHeight) // WE'RE FREE
|
||||
}
|
||||
|
||||
override fun renderCustomOverlay(graphics: GuiGraphics, mouseX: Int, mouseY: Int, blend: Float) {
|
||||
@@ -105,13 +100,4 @@ class CaseScreen : GenericContainerScreen<CaseMenu> {
|
||||
}
|
||||
}
|
||||
|
||||
override fun mouseClicked(mouseX: Double, mouseY: Double, button: Int): Boolean { // todo: make a better widget system than mojang, practically not even using the fact it's a widget atp
|
||||
if (button == 0 && btn!!.isHovered) {
|
||||
btn!!.playDownSound(Minecraft.getInstance().soundManager)
|
||||
btn!!.onClick(mouseX, mouseY)
|
||||
return true
|
||||
}
|
||||
return super.mouseClicked(mouseX, mouseY, button)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
package org.neoflock.neocomputers.gui.screen
|
||||
|
||||
import io.netty.buffer.Unpooled
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.client.gui.components.Button
|
||||
import net.minecraft.client.gui.components.SpriteIconButton
|
||||
import net.minecraft.client.gui.components.events.GuiEventListener
|
||||
import net.minecraft.client.gui.narration.NarrationElementOutput
|
||||
import net.minecraft.network.FriendlyByteBuf
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.network.chat.MutableComponent
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.world.entity.player.Inventory
|
||||
import org.neoflock.neocomputers.NeoComputers
|
||||
import org.neoflock.neocomputers.entity.RackEntity
|
||||
import org.neoflock.neocomputers.gui.menu.RackMenu
|
||||
import org.neoflock.neocomputers.gui.menu.RackSlot
|
||||
import org.neoflock.neocomputers.gui.widget.IconTextButton
|
||||
import org.neoflock.neocomputers.network.NodeSynchronizer
|
||||
import org.neoflock.neocomputers.utils.GenericContainerScreen
|
||||
import java.util.function.Supplier
|
||||
|
||||
class RackScreen(menu: RackMenu, inventory: Inventory, component: Component) : GenericContainerScreen<RackMenu>(menu, inventory, component) {
|
||||
override fun findMenuTexture(): ResourceLocation = ResourceLocation.fromNamespaceAndPath(NeoComputers.MODID, "textures/gui/rack.png")
|
||||
val RELAY = ResourceLocation.fromNamespaceAndPath(NeoComputers.MODID, "textures/gui/relay.png")
|
||||
|
||||
var relay_mode = if (menu.container is RackEntity) (menu.container as RackEntity).relayMode else false
|
||||
|
||||
val relaybtn = IconTextButton(100, 96, if(relay_mode) "Enabled" else "Disabled", RELAY, width = 64) {
|
||||
if (relay_mode){
|
||||
it.message = Component.literal("Disabled")
|
||||
relay_mode = false
|
||||
} else {
|
||||
it.message = Component.literal("Enabled")
|
||||
relay_mode = true
|
||||
}
|
||||
|
||||
val buffer = FriendlyByteBuf(Unpooled.buffer())
|
||||
buffer.writeBoolean(relay_mode)
|
||||
(menu.slots[0] as RackSlot).encode(buffer)
|
||||
NodeSynchronizer.sendScreenInteraction(buffer)
|
||||
}
|
||||
init {
|
||||
this.imageWidth = 175
|
||||
this.imageHeight = 209
|
||||
this.inventoryLabelY = imageHeight - 93
|
||||
addWidget(relaybtn)
|
||||
}
|
||||
|
||||
override fun renderbg(guiGraphics: GuiGraphics, partialTick: Float, mouseX: Int, mouseY: Int) {
|
||||
renderSideLabels(guiGraphics)
|
||||
if(relay_mode) renderRelayConnections(guiGraphics)
|
||||
}
|
||||
|
||||
fun renderRelayConnections(graphics: GuiGraphics) {
|
||||
for(i in 0..3) {
|
||||
val x = 50+(i*11)
|
||||
graphics.fill(x, 104, x+4, 105, 0xffffffff.toInt())
|
||||
graphics.fill(x, 105, x+4, 106, 0xff888888.toInt())
|
||||
}
|
||||
}
|
||||
|
||||
fun renderSideLabels(graphics: GuiGraphics) {
|
||||
val x = 115+7
|
||||
val y = 20
|
||||
|
||||
graphics.drawString(font, "Bottom", x, y, 0x404040, false)
|
||||
graphics.drawString(font, "Top", x, y+11, 0x404040, false)
|
||||
graphics.drawString(font, "Back", x, y+22, 0x404040, false)
|
||||
graphics.drawString(font, "Right", x, y+33, 0x404040, false)
|
||||
graphics.drawString(font, "Left", x, y+44, 0x404040, false)
|
||||
}
|
||||
|
||||
// override fun processScreenStatePacket(buf: FriendlyByteBuf) {
|
||||
// super.processScreenStatePacket(buf)
|
||||
//// NeoComputers.LOGGER.info("porcessing screen state packet...")
|
||||
//// relay_mode = buf.readBoolean()
|
||||
//// if (relay_mode) relaybtn.message = Component.literal("Enabled")
|
||||
//// else relaybtn.message = Component.literal("Disabled")
|
||||
////
|
||||
//// for (slot in menu.slots) {
|
||||
//// if (slot is RackSlot) {
|
||||
//// slot.processStateScreenPacket(buf)
|
||||
//// }
|
||||
//// }
|
||||
//
|
||||
// }
|
||||
|
||||
override fun mouseClicked(mouseX: Double, mouseY: Double, button: Int): Boolean {
|
||||
if (super.mouseClicked(mouseX, mouseY, button)) return true
|
||||
for (slot in menu.slots) {
|
||||
if (slot is RackSlot) {
|
||||
if(slot.mouseClicked(mouseX-imageX, mouseY-imageY, button)) {
|
||||
val buf = FriendlyByteBuf(Unpooled.buffer())
|
||||
buf.writeBoolean(relay_mode)
|
||||
slot.encode(buf)
|
||||
|
||||
NodeSynchronizer.sendScreenInteraction(buf)
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -46,6 +46,8 @@ class ScreenScreen : GenericContainerScreen<ScreenMenu>{
|
||||
}
|
||||
}
|
||||
|
||||
override fun renderLabels(guiGraphics: GuiGraphics, mouseX: Int, mouseY: Int) { }
|
||||
|
||||
// override fun onClose() {
|
||||
// super.onClose()
|
||||
// renderer.
|
||||
|
||||
@@ -84,13 +84,13 @@ data class ComponentSlotRequirement(val tier: Int, val role: String) {
|
||||
// Tier 0 allows ALL tiers, making it completely untiered.
|
||||
// Role determines what the role is.
|
||||
class ComponentSlot(container: Container, slot: Int, x: Int, y: Int, val machine: ComponentUser?, val requirement: ComponentSlotRequirement): DynamicSlot(container, slot, x, y) {
|
||||
override fun draw(graphics: GuiGraphics, relX: Int, relY: Int, mouseX: Int, mouseY: Int) {
|
||||
super.draw(graphics, relX, relY, mouseX, mouseY)
|
||||
override fun draw(graphics: GuiGraphics, mouseX: Int, mouseY: Int) {
|
||||
super.draw(graphics, mouseX, mouseY)
|
||||
if(!hasItem()) {
|
||||
RenderSystem.enableBlend()
|
||||
RenderSystem.setShaderTexture(0, ComponentRoles.getTextureFor(requirement.role))
|
||||
RenderSystem.setShader { GameRenderer.getPositionTexShader() }
|
||||
drawQuad(relX + x - 1, relY + y - 1, 18, 18, 0F, 0F, 15F, 15F)
|
||||
// RenderSystem.enableBlend()
|
||||
// RenderSystem.setShaderTexture(0, ComponentRoles.getTextureFor(requirement.role))
|
||||
// RenderSystem.setShader { GameRenderer.getPositionTexShader() }
|
||||
drawQuad(graphics, ComponentRoles.getTextureFor(requirement.role), x - 1, y - 1, 18, 18, 0F, 0F, 15F, 15F)
|
||||
if (requirement.tier > 0) {
|
||||
RenderSystem.setShaderTexture(
|
||||
0,
|
||||
@@ -99,10 +99,11 @@ class ComponentSlot(container: Container, slot: Int, x: Int, y: Int, val machine
|
||||
"textures/gui/slots/tier${requirement.tier - 1}.png"
|
||||
)
|
||||
)
|
||||
RenderSystem.setShader { GameRenderer.getPositionTexShader() }
|
||||
drawQuad(relX + x - 1, relY + y - 1, 18, 18, 0F, 0F, 15F, 15F)
|
||||
val tex = ResourceLocation.fromNamespaceAndPath(NeoComputers.MODID, "textures/gui/slots/tier${requirement.tier - 1}.png")
|
||||
// RenderSystem.setShader { GameRenderer.getPositionTexShader() }
|
||||
drawQuad(graphics, tex, x - 1, y - 1, 18, 18, 0F, 0F, 15F, 15F)
|
||||
}
|
||||
RenderSystem.disableBlend()
|
||||
// RenderSystem.disableBlend()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,9 +5,12 @@ import com.mojang.blaze3d.vertex.BufferBuilder
|
||||
import com.mojang.blaze3d.vertex.BufferUploader
|
||||
import com.mojang.blaze3d.vertex.DefaultVertexFormat
|
||||
import com.mojang.blaze3d.vertex.Tesselator
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer
|
||||
import com.mojang.blaze3d.vertex.VertexFormat
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.client.renderer.GameRenderer
|
||||
import net.minecraft.client.renderer.RenderStateShard
|
||||
import net.minecraft.client.renderer.RenderStateShard.ShaderStateShard
|
||||
import net.minecraft.client.renderer.RenderType
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.world.Container
|
||||
@@ -17,29 +20,26 @@ import org.neoflock.neocomputers.NeoComputers
|
||||
open class DynamicSlot(container: Container, slot: Int, x: Int, y: Int) : Slot(container, slot, x, y) {
|
||||
|
||||
val BACKGROUND: ResourceLocation = ResourceLocation.fromNamespaceAndPath(NeoComputers.MODID, "textures/gui/slots/slot.png")
|
||||
|
||||
open fun draw(graphics: GuiGraphics, relX: Int, relY: Int, mouseX: Int, mouseY: Int) {
|
||||
RenderSystem.enableBlend() // background
|
||||
RenderSystem.setShaderTexture(0, BACKGROUND)
|
||||
RenderSystem.setShader { GameRenderer.getPositionTexShader() }
|
||||
drawQuad(relX+x-1, relY+y-1, 18, 18, 0F, 0F, 15F, 15F)
|
||||
RenderSystem.disableBlend()
|
||||
val RENDER_TYPE = { r: ResourceLocation ->
|
||||
RenderType.create("nc_gui_slot", DefaultVertexFormat.POSITION_TEX, VertexFormat.Mode.QUADS, RenderType.TRANSIENT_BUFFER_SIZE, RenderType.CompositeState.builder()
|
||||
.setShaderState(ShaderStateShard.POSITION_TEX_SHADER)
|
||||
.setTextureState(RenderStateShard.TextureStateShard(r, false, false))
|
||||
.setTransparencyState(RenderStateShard.TransparencyStateShard.TRANSLUCENT_TRANSPARENCY)
|
||||
.createCompositeState(false))
|
||||
}
|
||||
|
||||
fun drawQuad(x: Int, y: Int, width: Int, height: Int, u1: Float, v1: Float, u2: Float, v2: Float) {
|
||||
var t: Tesselator = Tesselator.getInstance()
|
||||
var builder: BufferBuilder = t.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX)
|
||||
|
||||
builder.addVertex(x.toFloat(), (y+height).toFloat(), 1f).setUv(u1/15F, v2/15F)
|
||||
builder.addVertex((x+width).toFloat(), (y+height).toFloat(), 1f).setUv(u2/15F, v2/15F)
|
||||
builder.addVertex((x+width).toFloat(), y.toFloat(), 1f).setUv(u2/15F, v1/15F)
|
||||
builder.addVertex(x.toFloat(), y.toFloat(), 1f).setUv(u1/15F,v1/15F)
|
||||
|
||||
BufferUploader.drawWithShader(builder.build()!!)
|
||||
open fun draw(graphics: GuiGraphics, mouseX: Int, mouseY: Int) {
|
||||
drawQuad(graphics, BACKGROUND, x-1, y-1, 18, 18, 0F, 0F, 15F, 15F)
|
||||
}
|
||||
|
||||
// private fun renderSlotHighlight(guiGraphics: GuiGraphics, x: Int, y: Int, k: Int) { // im not sure but i tihnk i copied this from mc source code
|
||||
// guiGraphics.fillGradient(RenderType.guiOverlay(), x, y, x + 16, y + 16, -2130706433, -2130706433, k);
|
||||
// }
|
||||
fun drawQuad(guiGraphics: GuiGraphics, tex: ResourceLocation, x: Int, y: Int, width: Int, height: Int, u1: Float, v1: Float, u2: Float, v2: Float) {
|
||||
val pose = guiGraphics.pose().last()
|
||||
val builder = guiGraphics.bufferSource().getBuffer(RENDER_TYPE(tex))
|
||||
|
||||
builder.addVertex(pose, x.toFloat(), (y+height).toFloat(), 1f).setUv(u1/15F, v2/15F)
|
||||
builder.addVertex(pose, (x+width).toFloat(), (y+height).toFloat(), 1f).setUv(u2/15F, v2/15F)
|
||||
builder.addVertex(pose, (x+width).toFloat(), y.toFloat(), 1f).setUv(u2/15F, v1/15F)
|
||||
builder.addVertex(pose, x.toFloat(), y.toFloat(), 1f).setUv(u1/15F,v1/15F)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package org.neoflock.neocomputers.gui.widget
|
||||
|
||||
import com.mojang.blaze3d.systems.RenderSystem
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.gui.Font
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.client.gui.components.Button
|
||||
import net.minecraft.client.renderer.texture.TextureAtlas
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.network.chat.MutableComponent
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.util.ResourceLocationPattern
|
||||
import org.neoflock.neocomputers.NeoComputers
|
||||
import java.util.function.Supplier
|
||||
|
||||
class press(val lambda: (IconTextButton) -> Unit) : Button.OnPress {
|
||||
override fun onPress(button: Button) {
|
||||
lambda(button as IconTextButton)
|
||||
}
|
||||
}
|
||||
|
||||
class narr : Button.CreateNarration {
|
||||
override fun createNarrationMessage(supplier: Supplier<MutableComponent?>): MutableComponent? {
|
||||
return supplier.get() // no narration for u
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class IconTextButton(x: Int, y: Int, text: String, val icon: ResourceLocation, val iconw: Int =16, val iconh: Int = 16, width: Int=150, height: Int=20, lambda: (IconTextButton) -> Unit) :
|
||||
Button(x, y, width, height, Component.literal(text),press(lambda), narr()) {
|
||||
|
||||
|
||||
var xOffset = 2
|
||||
override fun renderWidget(guiGraphics: GuiGraphics, mouseX: Int, mouseY: Int, partialTick: Float) {
|
||||
super.renderWidget(guiGraphics, mouseX, mouseY, partialTick)
|
||||
|
||||
RenderSystem.disableBlend() // i hate this
|
||||
val imx = x + xOffset
|
||||
val imy = y + (height/2) - (iconh/2)
|
||||
guiGraphics.blit(icon, imx, imy, 0f, 0f, iconw, iconh, iconw, iconh)
|
||||
RenderSystem.enableBlend()
|
||||
}
|
||||
|
||||
override fun renderString(guiGraphics: GuiGraphics, font: Font, color: Int) {
|
||||
val startx = x + iconw/2 // idk why /2, might be coincidence thing
|
||||
renderScrollingString(guiGraphics, font, message, startx, y, startx+width, y+height, color)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -10,7 +10,7 @@ import org.neoflock.neocomputers.gui.widget.ComponentRoles
|
||||
class InternetCard: Item(Item.Properties()), ComponentItem {
|
||||
override fun getComponentRoles(itemStack: ItemStack): Set<String> = setOf(ComponentRoles.CARD, ComponentRoles.INET)
|
||||
|
||||
override fun getComponentTier(itemStack: ItemStack): Int = 1
|
||||
override fun getComponentTier(itemStack: ItemStack): Int = 2
|
||||
|
||||
override fun whenComponentPlaced(itemStack: ItemStack, machine: ComponentUser?, newRole: String) {
|
||||
if(machine != null) ensureHasAddress(itemStack)
|
||||
|
||||
@@ -46,4 +46,6 @@ object Items {
|
||||
|
||||
val REDIO0 = ITEMS.register("redio0") { RedstoneCard0() }
|
||||
val REDIO1 = ITEMS.register("redio1") { RedstoneCard1() }
|
||||
|
||||
val SERVER0 = ITEMS.register("server0") { ServerItem() }
|
||||
}
|
||||
62
src/main/kotlin/org/neoflock/neocomputers/item/RackItem.kt
Normal file
@@ -0,0 +1,62 @@
|
||||
package org.neoflock.neocomputers.item
|
||||
|
||||
import com.mojang.blaze3d.shaders.Shader
|
||||
import com.mojang.blaze3d.vertex.DefaultVertexFormat
|
||||
import com.mojang.blaze3d.vertex.PoseStack
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer
|
||||
import com.mojang.blaze3d.vertex.VertexFormat
|
||||
import net.minecraft.client.renderer.MultiBufferSource
|
||||
import net.minecraft.client.renderer.RenderStateShard
|
||||
import net.minecraft.client.renderer.RenderType
|
||||
import net.minecraft.client.renderer.texture.OverlayTexture
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import org.neoflock.neocomputers.NeoComputers
|
||||
|
||||
interface RackItem {
|
||||
// companion object {
|
||||
// val RENDER_TYPE = {l: ResourceLocation ->
|
||||
// RenderType.create("nc_server", DefaultVertexFormat.POSITION_COLOR_TEX_LIGHTMAP, VertexFormat.Mode.QUADS, RenderType.SMALL_BUFFER_SIZE, RenderType.CompositeState.builder()
|
||||
// .setShaderState(RenderStateShard.ShaderStateShard.POSITION_COLOR_TEX_LIGHTMAP_SHADER)
|
||||
// .setLightmapState(RenderStateShard.LIGHTMAP)
|
||||
// .setTextureState(RenderStateShard.TextureStateShard(l, false, false))
|
||||
// .createCompositeState(false))
|
||||
// }
|
||||
// }
|
||||
val TOP_TEX: ResourceLocation
|
||||
get() = ResourceLocation.fromNamespaceAndPath(NeoComputers.MODID, "textures/block/generic_top.png")
|
||||
|
||||
val FRONT_TEX: ResourceLocation
|
||||
get() = ResourceLocation.fromNamespaceAndPath(NeoComputers.MODID, "textures/block/rack_server.png")
|
||||
|
||||
fun render_lights(source: MultiBufferSource, stack: PoseStack, light: Int)
|
||||
|
||||
fun render(source: MultiBufferSource, stack: PoseStack, light: Int, v_offset: Float = 2f) {
|
||||
val pose = stack.last()
|
||||
|
||||
|
||||
// var buffer = source.getBuffer(RenderType.gui()) // TODO: correct rendertype
|
||||
var buffer = source.getBuffer(RenderType.entitySolid(TOP_TEX))
|
||||
// val u1 = 1/16f
|
||||
buffer.addVertex(pose, 0f, 0f, 0f).setUv(1/16f, 15/16f).setColor(1f, 1f, 1f, 1f).setLight(light).setNormal(pose, 0f, -1f, 0f).setOverlay(OverlayTexture.NO_OVERLAY)
|
||||
buffer.addVertex(pose, 14/16f, 0f, 0f).setUv(1/16f, 1/16f).setColor(1f, 1f, 1f, 1f).setLight(light).setNormal(pose, 0f, -1f, 0f).setOverlay(OverlayTexture.NO_OVERLAY)
|
||||
buffer.addVertex(pose, 14/16f, 0f, 14/16f).setUv(15/16f, 1/16f).setColor(1f, 1f, 1f, 1f).setLight(light).setNormal(pose, 0f, -1f, 0f).setOverlay(OverlayTexture.NO_OVERLAY)
|
||||
buffer.addVertex(pose, 0f, 0f, 14/16f).setUv(15/16f, 1/16f).setColor(1f, 1f, 1f, 1f).setLight(light).setNormal(pose, 0f, -1f, 0f).setOverlay(OverlayTexture.NO_OVERLAY)
|
||||
|
||||
buffer.addVertex(pose, 0f, 3/16f, 14/16f).setUv(15/16f, 1/16f).setColor(1f, 1f, 1f, 1f).setLight(light).setNormal(pose, 0f, 1f, 0f).setOverlay(OverlayTexture.NO_OVERLAY)
|
||||
buffer.addVertex(pose, 14/16f, 3/16f, 14/16f).setUv(15/16f, 15/16f).setColor(1f, 1f, 1f, 1f).setLight(light).setNormal(pose, 0f, 1f, 0f).setOverlay(OverlayTexture.NO_OVERLAY)
|
||||
buffer.addVertex(pose, 14/16f, 3/16f, 0f).setUv(1/16f, 15/16f).setColor(1f, 1f, 1f, 1f).setLight(light).setNormal(pose, 0f, 1f, 0f).setOverlay(OverlayTexture.NO_OVERLAY)
|
||||
buffer.addVertex(pose, 0f, 3/16f, 0f).setUv(1/16f, 1/16f).setColor(1f, 1f, 1f, 1f).setLight(light).setNormal(pose, 0f, 1f, 0f).setOverlay(OverlayTexture.NO_OVERLAY)
|
||||
|
||||
buffer = source.getBuffer(RenderType.entitySolid(FRONT_TEX))
|
||||
buffer.addVertex(pose, 14/16f, 3/16f, 14/16f).setUv(1/16f, v_offset/16f).setColor(1f, 1f, 1f, 1f).setLight(light).setNormal(pose, 1f, 0f, 0f).setOverlay(OverlayTexture.NO_OVERLAY)
|
||||
buffer.addVertex(pose, 14/16f, 0f, 14/16f).setUv(1/16f, (v_offset+3)/16f).setColor(1f, 1f, 1f, 1f).setLight(light).setNormal(pose, 1f, 0f, 0f).setOverlay(OverlayTexture.NO_OVERLAY)
|
||||
buffer.addVertex(pose, 14/16f, 0/16f, 0/16f).setUv(15/16f, (v_offset+3)/16f).setColor(1f, 1f, 1f, 1f).setLight(light).setNormal(pose, 1f, 0f, 0f).setOverlay(OverlayTexture.NO_OVERLAY)
|
||||
buffer.addVertex(pose, 14/16f, 3/16f, 0/16f).setUv(15/16f, v_offset/16f).setColor(1f, 1f, 1f, 1f).setLight(light).setNormal(pose, 1f, 0f, 0f).setOverlay(OverlayTexture.NO_OVERLAY)
|
||||
|
||||
stack.pushPose()
|
||||
stack.translate((14/16f)+0.001F, 0f, 0f)
|
||||
render_lights(source, stack, light)
|
||||
stack.popPose()
|
||||
}
|
||||
|
||||
}
|
||||
26
src/main/kotlin/org/neoflock/neocomputers/item/ServerItem.kt
Normal file
@@ -0,0 +1,26 @@
|
||||
package org.neoflock.neocomputers.item
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack
|
||||
import net.minecraft.client.renderer.MultiBufferSource
|
||||
import net.minecraft.client.renderer.item.ItemProperties
|
||||
import net.minecraft.world.item.Item
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import org.neoflock.neocomputers.entity.ComponentUser
|
||||
import org.neoflock.neocomputers.gui.widget.ComponentRoles
|
||||
import org.neoflock.neocomputers.network.DeviceNode
|
||||
|
||||
class ServerItem() : Item(Properties()), ComponentItem, RackItem {
|
||||
override fun getComponentRoles(itemStack: ItemStack): Set<String> = setOf(ComponentRoles.RACK_MOUNTABLE)
|
||||
|
||||
override fun getComponentTier(itemStack: ItemStack): Int = 0
|
||||
|
||||
override fun toComponentNode(
|
||||
itemStack: ItemStack,
|
||||
machine: ComponentUser?
|
||||
): DeviceNode? {
|
||||
return null // TODO: atom machine item plz
|
||||
}
|
||||
|
||||
override fun render_lights(source: MultiBufferSource, stack: PoseStack, light: Int) {
|
||||
}
|
||||
}
|
||||
@@ -55,6 +55,7 @@ object Tabs {
|
||||
output.accept(ItemStack(Items.REDIO1.get()))
|
||||
|
||||
output.accept(ItemStack(Items.EE0.get()))
|
||||
output.accept(ItemStack(Items.SERVER0.get()))
|
||||
|
||||
// Criminal black magic to put LuaBIOS EEPROM in the tabs
|
||||
do {
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
package org.neoflock.neocomputers.network
|
||||
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.network.FriendlyByteBuf
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.world.level.Level
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import org.neoflock.neocomputers.NeoComputers
|
||||
import org.neoflock.neocomputers.network.Networking.Message
|
||||
import org.neoflock.neocomputers.network.Networking.Visibility
|
||||
@@ -10,6 +11,9 @@ import org.neoflock.neocomputers.network.Networking.maxHopCount
|
||||
import java.util.UUID
|
||||
import kotlin.math.min
|
||||
|
||||
// tmp class until JNI bindings work
|
||||
data class NNComponent(val type: String)
|
||||
|
||||
open class DeviceNode(_address: UUID? = null) {
|
||||
val connections = HashSet<DeviceNode>()
|
||||
private var reachableCache: Set<DeviceNode>? = null
|
||||
@@ -146,66 +150,72 @@ open class DeviceNode(_address: UUID? = null) {
|
||||
|
||||
fun getReachable(): Set<DeviceNode> {
|
||||
if(reachableCache == null) {
|
||||
reachableCache = computeReachable();
|
||||
reachableCache = computeReachable()
|
||||
}
|
||||
return reachableCache!!;
|
||||
return reachableCache!!
|
||||
}
|
||||
|
||||
open fun invalidateReachableCache() {
|
||||
reachableCache = null
|
||||
}
|
||||
|
||||
// Returns a subset of connections, for a subset of direct
|
||||
// meant for things like drives which dont want to accidentally fuse networks
|
||||
open fun getPreferredFew() = setOf<DeviceNode>()
|
||||
|
||||
fun computeReachable(): Set<DeviceNode> {
|
||||
if(reachability == Visibility.NONE) {
|
||||
return setOf();
|
||||
return setOf()
|
||||
}
|
||||
if(reachability == Visibility.DIRECT) {
|
||||
return connections.minus(this);
|
||||
if(reachability == Visibility.SOME) {
|
||||
return getPreferredFew()
|
||||
}
|
||||
if(reachability == Visibility.NETWORK) {
|
||||
// absolute cinema
|
||||
val working = HashSet<DeviceNode>();
|
||||
val pending = mutableListOf(this);
|
||||
var iterCount = 0;
|
||||
val working = HashSet<DeviceNode>()
|
||||
val pending = mutableListOf(this)
|
||||
var iterCount = 0
|
||||
while(iterCount < maxHopCount && pending.isNotEmpty()) {
|
||||
iterCount++;
|
||||
iterCount++
|
||||
val subnode = pending.removeFirst()
|
||||
if(subnode in working) continue
|
||||
working.add(subnode)
|
||||
if(subnode.reachability == Visibility.NETWORK) {
|
||||
pending.addAll(subnode.connections)
|
||||
} else if(subnode.reachability == Visibility.DIRECT) {
|
||||
working.addAll(subnode.connections)
|
||||
} else if(subnode.reachability == Visibility.SOME) {
|
||||
pending.addAll(subnode.getPreferredFew())
|
||||
}
|
||||
}
|
||||
// cannot send to itself!
|
||||
working.remove(this);
|
||||
return working;
|
||||
working.remove(this)
|
||||
return working
|
||||
}
|
||||
throw NotImplementedError("visibility not implemented");
|
||||
throw NotImplementedError("visibility not implemented")
|
||||
}
|
||||
|
||||
fun connectTo(other: DeviceNode) {
|
||||
this.directConnectTo(other);
|
||||
other.directConnectTo(this);
|
||||
this.directConnectTo(other)
|
||||
other.directConnectTo(this)
|
||||
}
|
||||
|
||||
fun disconnectFrom(other: DeviceNode) {
|
||||
this.directDisconnectFrom(other);
|
||||
other.directDisconnectFrom(this);
|
||||
this.directDisconnectFrom(other)
|
||||
other.directDisconnectFrom(this)
|
||||
}
|
||||
|
||||
fun directConnectTo(other: DeviceNode) {
|
||||
if(other == this) return;
|
||||
if(other in connections) return;
|
||||
connections.add(other);
|
||||
this.onConnect(other);
|
||||
if(other == this) return
|
||||
if(other in connections) return
|
||||
connections.add(other)
|
||||
this.onConnect(other)
|
||||
invalidateReachableCache()
|
||||
}
|
||||
|
||||
fun directDisconnectFrom(other: DeviceNode) {
|
||||
if(other !in connections) return;
|
||||
connections.remove(other);
|
||||
this.onDisconnect(other);
|
||||
if(other !in connections) return
|
||||
connections.remove(other)
|
||||
this.onDisconnect(other)
|
||||
invalidateReachableCache()
|
||||
}
|
||||
|
||||
// Network synchronization with the NodeSynchronizer
|
||||
@@ -225,6 +235,8 @@ open class DeviceNode(_address: UUID? = null) {
|
||||
|
||||
// client-side, meant to bring state forward
|
||||
open fun processCommit(buf: FriendlyByteBuf) {}
|
||||
|
||||
open fun getComponent(): NNComponent? = null
|
||||
}
|
||||
|
||||
// Used by the relay
|
||||
@@ -235,9 +247,10 @@ interface ConventionalNetworkDevice {
|
||||
|
||||
abstract class WirelessEndpoint(address: UUID?) : DeviceNode(address) {
|
||||
|
||||
abstract fun getRange(): Double
|
||||
abstract fun getDimension(): Int
|
||||
abstract fun getPosition(): BlockPos
|
||||
abstract fun getEndpointRange(): Double
|
||||
abstract fun getEndpointDimension(): Int
|
||||
abstract fun getEndpointLevel(): Level
|
||||
abstract fun getEndpointPosition(): Vec3
|
||||
// separate from process for simplicity
|
||||
abstract fun receiveWireless(message: Message, emitter: WirelessEndpoint)
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.neoflock.neocomputers.network
|
||||
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.world.level.Level
|
||||
import org.neoflock.neocomputers.entity.MachineEvent
|
||||
import java.util.UUID
|
||||
import kotlin.math.min
|
||||
@@ -27,8 +28,8 @@ object Networking {
|
||||
enum class Visibility {
|
||||
// only it can see itself
|
||||
NONE,
|
||||
// can only see its direct connections
|
||||
DIRECT,
|
||||
// some, as determined by getPreferredFew()
|
||||
SOME,
|
||||
// Can see everything network-wide
|
||||
NETWORK,
|
||||
}
|
||||
@@ -36,7 +37,8 @@ object Networking {
|
||||
|
||||
abstract class Message(val sender: DeviceNode)
|
||||
|
||||
class ClassicPacket(sender: DeviceNode, val src: String, val dst: String, val port: Int, val data: List<Any>, val hopCount: Int) : Message(sender) {
|
||||
// null dst means broadcast
|
||||
class ClassicPacket(sender: DeviceNode, val src: String, val dst: String?, val port: Int, val data: List<Any>, val hopCount: Int) : Message(sender) {
|
||||
fun hop(sender: DeviceNode) = ClassicPacket(sender, src, dst, port, data, hopCount + 1);
|
||||
}
|
||||
|
||||
@@ -50,30 +52,26 @@ object Networking {
|
||||
|
||||
// node may differ from message.sender in the case of relays,
|
||||
// as they might have DIRECT reachability but
|
||||
fun emitMessage(deviceNode: DeviceNode, message: Message) {
|
||||
deviceNode.getReachable().forEach { it.received(message) }
|
||||
fun emitMessage(deviceNode: DeviceNode, message: Message, exclude: Set<DeviceNode> = setOf()) {
|
||||
deviceNode.getReachable().forEach { if(it !in exclude) it.received(message) }
|
||||
}
|
||||
|
||||
fun computeRangeAllowedByHardness(src: BlockPos, dst: BlockPos): Double {
|
||||
fun computeRangeAllowedByHardness(level: Level, src: BlockPos, dst: BlockPos): Double {
|
||||
return Double.POSITIVE_INFINITY // TODO: math
|
||||
}
|
||||
|
||||
fun distanceBetween(a: BlockPos, b: BlockPos): Double {
|
||||
return sqrt((a.x - b.x + a.y - b.y + a.z - b.z).toDouble().pow(2.0));
|
||||
}
|
||||
|
||||
fun emitWirelessMessage(starter: WirelessEndpoint, range: Double, message: Message) {
|
||||
val startPos = starter.getPosition();
|
||||
val startDim = starter.getDimension();
|
||||
val range = starter.getRange();
|
||||
val startPos = starter.getEndpointPosition()
|
||||
val startDim = starter.getEndpointDimension()
|
||||
val level = starter.getEndpointLevel()
|
||||
wirelessNodes.get().forEach {
|
||||
if(it.getDimension() != startDim) return;
|
||||
val pos = it.getPosition();
|
||||
val d = distanceBetween(startPos, pos);
|
||||
var trueRange = min(it.getRange(), range);
|
||||
trueRange = min(trueRange, computeRangeAllowedByHardness(startPos, pos));
|
||||
if(d > trueRange) return;
|
||||
it.receiveWireless(message, starter);
|
||||
if(it.getEndpointDimension() != startDim) return
|
||||
val pos = it.getEndpointPosition()
|
||||
val d = startPos.distanceTo(pos)
|
||||
var trueRange = min(it.getEndpointRange(), range)
|
||||
trueRange = min(trueRange, computeRangeAllowedByHardness(level, BlockPos.containing(startPos), BlockPos.containing(pos)))
|
||||
if(d > trueRange) return
|
||||
it.receiveWireless(message, starter)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,16 @@
|
||||
package org.neoflock.neocomputers.utils
|
||||
|
||||
// based off the ImplementedContainer of https://docs.fabricmc.net/develop/blocks/block-containers
|
||||
import com.mojang.blaze3d.vertex.DefaultVertexFormat
|
||||
import com.mojang.blaze3d.vertex.VertexFormat
|
||||
import dev.architectury.registry.menu.MenuRegistry
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.client.gui.components.AbstractWidget
|
||||
import net.minecraft.client.gui.components.events.GuiEventListener
|
||||
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen
|
||||
import net.minecraft.client.renderer.RenderStateShard
|
||||
import net.minecraft.client.renderer.RenderStateShard.ShaderStateShard
|
||||
import net.minecraft.client.renderer.RenderType
|
||||
import net.minecraft.world.Container;
|
||||
import net.minecraft.core.NonNullList;
|
||||
import net.minecraft.network.FriendlyByteBuf
|
||||
@@ -68,7 +75,7 @@ abstract class GenericContainerMenu(menuType: MenuType<*>, id: Int, var containe
|
||||
// Based off the code in ChestMenu
|
||||
for (i in 0..2) {
|
||||
for (j in 0..8) {
|
||||
this.addSlot(Slot(inventory, j + i * 9 + 9, 8 + j * 18, 84 + i * 18))
|
||||
this.addSlot(Slot(inventory, j + i * 9 + 9, 8 + j * 18, y + i * 18))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,6 +135,15 @@ abstract class GenericContainerScreen<T: GenericContainerMenu>(menu: T, inventor
|
||||
val imageY: Int
|
||||
get() = (height - imageHeight) / 2
|
||||
|
||||
var widgets = mutableListOf<AbstractWidget>()
|
||||
|
||||
val RENDER_TYPE = { r: ResourceLocation ->
|
||||
RenderType.create("nc_gui_bg", DefaultVertexFormat.POSITION_TEX, VertexFormat.Mode.QUADS, RenderType.TRANSIENT_BUFFER_SIZE, RenderType.CompositeState.builder()
|
||||
.setShaderState(ShaderStateShard.POSITION_TEX_SHADER)
|
||||
.setTextureState(RenderStateShard.TextureStateShard(r, false, false))
|
||||
.createCompositeState(false))
|
||||
}
|
||||
|
||||
override fun init() {
|
||||
super.init()
|
||||
|
||||
@@ -138,24 +154,50 @@ abstract class GenericContainerScreen<T: GenericContainerMenu>(menu: T, inventor
|
||||
val menuTex = findMenuTexture()
|
||||
val cx = (width - imageWidth) / 2
|
||||
val cy = (height - imageHeight) / 2
|
||||
guiGraphics.pose().pushPose()
|
||||
guiGraphics.pose().translate(cx.toFloat(), cy.toFloat(), 0f)
|
||||
|
||||
guiGraphics.blit(menuTex, imageX, imageY, 0, 0, imageWidth, imageHeight)
|
||||
guiGraphics.blit(menuTex, 0, 0, 0, 0, imageWidth, imageHeight)
|
||||
renderbg(guiGraphics, f, i-cx, j-cy)
|
||||
|
||||
for (widget in widgets) {
|
||||
widget.render(guiGraphics, i-cx, j-cy, f)
|
||||
}
|
||||
|
||||
for (slot in menu.slots) {
|
||||
if (slot is DynamicSlot) {
|
||||
// NeoComputers.LOGGER.info("slot")
|
||||
slot.draw(guiGraphics, cx, cy, i, j)
|
||||
slot.draw(guiGraphics, i-cx, j-cy)
|
||||
}
|
||||
}
|
||||
|
||||
guiGraphics.pose().popPose()
|
||||
}
|
||||
|
||||
open fun renderCustomOverlay(graphics: GuiGraphics, mouseX: Int, mouseY: Int, blend: Float) {
|
||||
open fun renderbg(guiGraphics: GuiGraphics, partialTick: Float, mouseX: Int, mouseY: Int) {}
|
||||
|
||||
}
|
||||
open fun renderCustomOverlay(graphics: GuiGraphics, mouseX: Int, mouseY: Int, blend: Float) { }
|
||||
|
||||
override fun render(graphics: GuiGraphics, mouseX: Int, mouseY: Int, something: Float) {
|
||||
super.render(graphics, mouseX, mouseY, something)
|
||||
renderCustomOverlay(graphics, mouseX, mouseY, something)
|
||||
|
||||
graphics.pose().pushPose()
|
||||
graphics.pose().translate(imageX.toFloat(), imageY.toFloat(), 0f)
|
||||
renderCustomOverlay(graphics, mouseX-imageX, mouseY-imageY, something)
|
||||
graphics.pose().popPose() // not even doing this because it's better anymore, im just doing this because i dont want to change it back
|
||||
|
||||
if(shouldRenderTooltip()) super.renderTooltip(graphics, mouseX, mouseY)
|
||||
}
|
||||
|
||||
override fun mouseClicked(mouseX: Double, mouseY: Double, button: Int): Boolean {
|
||||
super.mouseClicked(mouseX, mouseY, button)
|
||||
for (widget in widgets) {
|
||||
if (widget.mouseClicked(mouseX-imageX, mouseY-imageY, button)) return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
fun addWidget(widget: AbstractWidget) {
|
||||
widgets.add(widget)
|
||||
}
|
||||
}
|
||||
8
src/main/resources/assets/neocomputers/atlases/gui.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"sources": [
|
||||
{
|
||||
"type": "single",
|
||||
"source": "neocomputers:block/relay_top"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"variants": {
|
||||
"": { "model": "neocomputers:block/rack"}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"variants": {
|
||||
"": {
|
||||
"model": "neocomputers:block/relay"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"variants": {
|
||||
"": {
|
||||
"model": "neocomputers:block/robot"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,7 @@
|
||||
"block.neocomputers.capacitor3": "Large Capacitor",
|
||||
"block.neocomputers.case": "Case (Untiered)",
|
||||
"block.neocomputers.cable": "Cable",
|
||||
"block.neocomputers.relay": "Relay",
|
||||
"item.neocomputers.eeprom0": "EEPROM (Tier 1)",
|
||||
"item.neocomputers.cpu0": "CPU (Tier 1)",
|
||||
"item.neocomputers.cpu1": "CPU (Tier 2)",
|
||||
|
||||
67
src/main/resources/assets/neocomputers/lang/fr_fr.json
Normal file
@@ -0,0 +1,67 @@
|
||||
{
|
||||
"neocomputers.confirm": "Confirmer",
|
||||
"neocomputers.cancel": "Annuler",
|
||||
"block.neocomputers.combustgen": "Générateur à combustion",
|
||||
"block.neocomputers.redio": "Controleur de redstone",
|
||||
"item.neocomputers.redio0": "Carte redstone (niveau 1)",
|
||||
"item.neocomputers.redio1": "Carte redstone (niveau 2)",
|
||||
"block.neocomputers.solargen": "Panneau solaire",
|
||||
"block.neocomputers.screen": "Écran (sans niveau)",
|
||||
"block.neocomputers.capacitor": "Petit condensateur",
|
||||
"block.neocomputers.capacitor2": "Condensateur moyen",
|
||||
"block.neocomputers.capacitor3": "Grand condensateur",
|
||||
"block.neocomputers.case": "Boîtier (sans niveau)",
|
||||
"block.neocomputers.cable": "Cable",
|
||||
"block.neocomputers.relay": "Relais",
|
||||
"item.neocomputers.eeprom0": "EEPROM (niveau 1)",
|
||||
"item.neocomputers.cpu0": "Processeur (niveau 1)",
|
||||
"item.neocomputers.cpu1": "Processeur (niveau 2)",
|
||||
"item.neocomputers.cpu2": "Processeur (niveau 3)",
|
||||
"item.neocomputers.cbus0": "Bus informatique (niveau 1)",
|
||||
"item.neocomputers.cbus1": "Bus informatique (niveau 2)",
|
||||
"item.neocomputers.cbus2": "Bus informatique (niveau 3)",
|
||||
"item.neocomputers.cbus_creative": "Bus informatique (créatif)",
|
||||
"item.neocomputers.memory0": "Mémoire (niveau 1)",
|
||||
"item.neocomputers.memory1": "Mémoire (niveau 1,5)",
|
||||
"item.neocomputers.memory2": "Mémoire (niveau 2)",
|
||||
"item.neocomputers.memory3": "Mémoire (niveau 2,5)",
|
||||
"item.neocomputers.memory4": "Mémoire (niveau 3)",
|
||||
"item.neocomputers.memory5": "Mémoire (niveau 3,5)",
|
||||
"item.neocomputers.inet": "Carte internet",
|
||||
"item.neocomputers.lan": "Carte réseau sans fil",
|
||||
"item.neocomputers.wlan0": "Carte réseau sans fil (niveau 1)",
|
||||
"item.neocomputers.wlan1": "Carte réseau sans fil (niveau 2)",
|
||||
"item.neocomputers.tunnel": "Carte liée",
|
||||
"item.neocomputers.data0": "Carte de données (niveau 1)",
|
||||
"item.neocomputers.data1": "Carte de données (niveau 2)",
|
||||
"item.neocomputers.data2": "Carte de données (niveau 3)",
|
||||
"item.neocomputers.gpu0": "Carte graphiques (niveau 1)",
|
||||
"item.neocomputers.gpu1": "Carte graphiques (niveau 2)",
|
||||
"item.neocomputers.gpu2": "Carte graphiques (niveau 3)",
|
||||
"item.neocomputers.hdd0": "Disque dur (niveau 1)",
|
||||
"item.neocomputers.hdd1": "Disque dur (niveau 2)",
|
||||
"item.neocomputers.hdd2": "Disque dur (niveau 3)",
|
||||
"neocomputers.errors.ENOCPU": "absence d'un processeur",
|
||||
"neocomputers.errors.E2BIG": "trop de composants",
|
||||
"neocomputers.errors.ENOENJ": "niveau d'énergie dangereusement bas",
|
||||
"neocomputers.errors.ENOMEM": "absence de mémoire",
|
||||
"neocomputers.wlan.range": "Portée: %1$s blocs",
|
||||
"neocomputers.data.limit": "Mémoire: %1$s",
|
||||
"neocomputers.gpu.vram": "Mémoire vidéo: %1$spx",
|
||||
"neocomputers.disk.spaceused": "Espace utilisé: %1$s / %2$s",
|
||||
"neocomputers.readonly": "Lecture seule",
|
||||
"neocomputers.readwrite": "Lecture-écriture",
|
||||
"neocomputers.noaddr": "Pas d'adresse attribué",
|
||||
"neocomputers.computer.on": "ALLUMÉ",
|
||||
"neocomputers.computer.off": "ÉTEINT",
|
||||
"neocomputers.computer.errorNoMsg": "Erreur: ",
|
||||
"neocomputers.computer.energy": "Énergie: %1$s / %2$s J",
|
||||
"neocomputers.computer.memory": "Mémoire: %1$s / %2$s",
|
||||
"neocomputers.computer.components": "Composants: %1$s / %2$s",
|
||||
"neocomputers.memory.capacity": "Capacité: %1$s",
|
||||
"neocomputers.arch": "Architecture: %1$s",
|
||||
"neocomputers.eeprom.codeused": "Code stocké: %1$s / %2$s",
|
||||
"neocomputers.eeprom.dataused": "Données stockées: %1$s / %2$s",
|
||||
"neocomputers.tunnel.channel": "Chaîne connectée: %1$s",
|
||||
"sounds.neocomputers.computer_running": "Ventilateurs d'ordinateur"
|
||||
}
|
||||
67
src/main/resources/assets/neocomputers/lang/nl_nl.json
Normal file
@@ -0,0 +1,67 @@
|
||||
{
|
||||
"neocomputers.confirm": "Bevestigen",
|
||||
"neocomputers.cancel": "Annuleren",
|
||||
"block.neocomputers.combustgen": "Verbrandingsgenerator",
|
||||
"block.neocomputers.redio": "Redstone I/O",
|
||||
"item.neocomputers.redio0": "Redstonekaart (niveau 1)",
|
||||
"item.neocomputers.redio1": "Redstonekaart (niveau 2)",
|
||||
"block.neocomputers.solargen": "Zonnegenerator",
|
||||
"block.neocomputers.screen": "Scherm (niveauloos)",
|
||||
"block.neocomputers.capacitor": "Kleine condensator",
|
||||
"block.neocomputers.capacitor2": "Middelgrote condensator",
|
||||
"block.neocomputers.capacitor3": "Grote condensator",
|
||||
"block.neocomputers.case": "Behuizing (niveauloos)",
|
||||
"block.neocomputers.cable": "Kabel",
|
||||
"block.neocomputers.relay": "Doorgever",
|
||||
"item.neocomputers.eeprom0": "EEPROM (niveau 1)",
|
||||
"item.neocomputers.cpu0": "Processor (niveau 1)",
|
||||
"item.neocomputers.cpu1": "Processor (niveau 2)",
|
||||
"item.neocomputers.cpu2": "Processor (niveau 3)",
|
||||
"item.neocomputers.cbus0": "Componentenbus (niveau 1)",
|
||||
"item.neocomputers.cbus1": "Componentenbus (niveau 2)",
|
||||
"item.neocomputers.cbus2": "Componentenbus (niveau 3)",
|
||||
"item.neocomputers.cbus_creative": "Componentenbus (creatief)",
|
||||
"item.neocomputers.memory0": "Geheugen (niveau 1)",
|
||||
"item.neocomputers.memory1": "Geheugen (niveau 1,5)",
|
||||
"item.neocomputers.memory2": "Geheugen (niveau 2)",
|
||||
"item.neocomputers.memory3": "Geheugen (niveau 2,5)",
|
||||
"item.neocomputers.memory4": "Geheugen (niveau 3)",
|
||||
"item.neocomputers.memory5": "Geheugen (niveau 3,5)",
|
||||
"item.neocomputers.inet": "Internetkaart",
|
||||
"item.neocomputers.lan": "Bedrade netwerkkaart",
|
||||
"item.neocomputers.wlan0": "Draadloze netwerkkaart (niveau 1)",
|
||||
"item.neocomputers.wlan1": "Draadloze netwerkkaart (niveau 2)",
|
||||
"item.neocomputers.tunnel": "Gekoppelde kaart",
|
||||
"item.neocomputers.data0": "Datakaart (niveau 1)",
|
||||
"item.neocomputers.data1": "Datakaart (niveau 2)",
|
||||
"item.neocomputers.data2": "Datakaart (niveau 3)",
|
||||
"item.neocomputers.gpu0": "Videokaart (niveau 1)",
|
||||
"item.neocomputers.gpu1": "Videokaart (niveau 2)",
|
||||
"item.neocomputers.gpu2": "Videokaart (niveau 3)",
|
||||
"item.neocomputers.hdd0": "Harde schijf (niveau 1)",
|
||||
"item.neocomputers.hdd1": "Harde schijf (niveau 2)",
|
||||
"item.neocomputers.hdd2": "Harde schijf (niveau 3)",
|
||||
"neocomputers.errors.ENOCPU": "geen processor",
|
||||
"neocomputers.errors.E2BIG": "te veel componenten",
|
||||
"neocomputers.errors.ENOENJ": "gevaarlijk weinig stroom",
|
||||
"neocomputers.errors.ENOMEM": "geen geheugen",
|
||||
"neocomputers.wlan.range": "Bereik: %1$s blokken",
|
||||
"neocomputers.data.limit": "Geheugen: %1$s",
|
||||
"neocomputers.gpu.vram": "Videogeheugen: %1$spx",
|
||||
"neocomputers.disk.spaceused": "Gebruikte ruimte: %1$s / %2$s",
|
||||
"neocomputers.readonly": "Alleen-lezen",
|
||||
"neocomputers.readwrite": "Lezen-schrijven",
|
||||
"neocomputers.noaddr": "Geen adres toegewezen",
|
||||
"neocomputers.computer.on": "AAN",
|
||||
"neocomputers.computer.off": "UIT",
|
||||
"neocomputers.computer.errorNoMsg": "Fout: ",
|
||||
"neocomputers.computer.energy": "Stroom: %1$s / %2$s J",
|
||||
"neocomputers.computer.memory": "Geheugen: %1$s / %2$s",
|
||||
"neocomputers.computer.components": "Componenten: %1$s / %2$s",
|
||||
"neocomputers.memory.capacity": "Capaciteit: %1$s",
|
||||
"neocomputers.arch": "Architectuur: %1$s",
|
||||
"neocomputers.eeprom.codeused": "Opgeslagen code: %1$s / %2$s",
|
||||
"neocomputers.eeprom.dataused": "Opgeslagen data: %1$s / %2$s",
|
||||
"neocomputers.tunnel.channel": "Gekoppeld kanaal: %1$s",
|
||||
"sounds.neocomputers.computer_running": "Computerventilatoren"
|
||||
}
|
||||
@@ -13,6 +13,7 @@
|
||||
"block.neocomputers.capacitor3": "Condensator Electric Mare",
|
||||
"block.neocomputers.case": "Carcasă (fără grad)",
|
||||
"block.neocomputers.cable": "Cabluri",
|
||||
"block.neocomputers.relay": "Releu",
|
||||
"item.neocomputers.eeprom0": "Memorie Programabilă Electronic (Grad 1)",
|
||||
"item.neocomputers.cpu0": "Procesor Central (Grad 1)",
|
||||
"item.neocomputers.cpu1": "Procesor Central (Grad 2)",
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
{
|
||||
"parent": "minecraft:block/block",
|
||||
"render_type": "minecraft:solid",
|
||||
"textures": {
|
||||
"side": "neocomputers:block/rack_side",
|
||||
"top": "neocomputers:block/generic_top"
|
||||
},
|
||||
"elements": [
|
||||
{
|
||||
"from": [0, 0, 0],
|
||||
"to": [1, 16, 16],
|
||||
"faces": {
|
||||
"west": { "uv": [0, 0, 16, 16], "texture": "side", "tint_index": 0 },
|
||||
"east": { "uv": [0, 0, 16, 16], "texture": "side", "tint_index": 0 },
|
||||
"north": { "uv": [0, 0, 16, 1], "texture": "side", "tint_index": 0 },
|
||||
"south": { "uv": [0, 0, 16, 1], "texture": "side", "tint_index": 0 },
|
||||
"up": { "uv": [0, 0, 16, 1], "texture": "side", "tint_index": 0 },
|
||||
"down": { "uv": [0, 0, 16, 1], "texture": "side", "tint_index": 0 }
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [1, 0, 0],
|
||||
"to": [16, 16, 1],
|
||||
"faces": {
|
||||
"north": { "uv": [0, 0, 15, 16], "texture": "side", "tint_index": 0 },
|
||||
"south": { "uv": [1, 0, 16, 16], "texture": "side", "tint_index": 0 },
|
||||
"west": { "uv": [0, 0, 1, 16], "texture": "side", "tint_index": 0 },
|
||||
"east": { "uv": [0, 0, 1, 16], "texture": "side", "tint_index": 0 },
|
||||
"up": { "uv": [0, 0, 16, 1], "texture": "side", "tint_index": 0 },
|
||||
"down": { "uv": [0, 0, 16, 1], "texture": "side", "tint_index": 0 }
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [1, 0, 15],
|
||||
"to": [16, 16, 16],
|
||||
"faces": {
|
||||
"north": { "uv": [0, 0, 15, 16], "texture": "side", "tint_index": 0 },
|
||||
"south": { "uv": [1, 0, 16, 16], "texture": "side", "tint_index": 0 },
|
||||
"west": { "uv": [0, 0, 1, 16], "texture": "side", "tint_index": 0 },
|
||||
"east": { "uv": [0, 0, 1, 16], "texture": "side", "tint_index": 0 },
|
||||
"up": { "uv": [0, 0, 16, 1], "texture": "side", "tint_index": 0 },
|
||||
"down": { "uv": [0, 0, 16, 1], "texture": "side", "tint_index": 0 }
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [1, 0, 1],
|
||||
"to": [16, 2, 15],
|
||||
"faces": {
|
||||
"north": { "uv": [0, 0, 1, 16], "texture": "top", "tint_index": 0 },
|
||||
"south": { "uv": [0, 0, 1, 16], "texture": "top", "tint_index": 0 },
|
||||
"west": { "uv": [0, 0, 1, 16], "texture": "top", "tint_index": 0 },
|
||||
"east": { "uv": [0, 0, 1, 16], "texture": "top", "tint_index": 0 },
|
||||
"up": { "uv": [2, 1, 16, 15], "texture": "top", "tint_index": 0 },
|
||||
"down": { "uv": [0, 0, 1, 1], "texture": "top", "tint_index": 0 }
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [1, 14, 1],
|
||||
"to": [16, 16, 15],
|
||||
"faces": {
|
||||
"north": { "uv": [0, 0, 1, 16], "texture": "top", "tint_index": 0 },
|
||||
"south": { "uv": [0, 0, 1, 16], "texture": "top", "tint_index": 0 },
|
||||
"west": { "uv": [0, 0, 1, 16], "texture": "top", "tint_index": 0 },
|
||||
"east": { "uv": [1, 0, 15, 2], "texture": "top", "tint_index": 0 },
|
||||
"up": { "uv": [1, 1, 16, 15], "texture": "top", "tint_index": 0 },
|
||||
"down": { "uv": [0, 0, 1, 1], "texture": "top", "tint_index": 0 }
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"parent": "minecraft:block/cube",
|
||||
"textures": {
|
||||
"up": "neocomputers:block/relay_top",
|
||||
"down": "neocomputers:block/screen_bottom",
|
||||
"north": "neocomputers:block/relay_side",
|
||||
"south": "neocomputers:block/relay_side",
|
||||
"east": "neocomputers:block/relay_side",
|
||||
"west": "neocomputers:block/relay_side",
|
||||
"particle": "neocomputers:block/case_top"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"parent": "neocomputers:block/rack"
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"parent": "neocomputers:block/relay"
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "minecraft:item/generated",
|
||||
"textures": {
|
||||
"layer0": "neocomputers:item/server0"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "minecraft:item/generated",
|
||||
"textures": {
|
||||
"layer0": "neocomputers:item/server1"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "minecraft:item/generated",
|
||||
"textures": {
|
||||
"layer0": "neocomputers:item/server2"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "minecraft:item/generated",
|
||||
"textures": {
|
||||
"layer0": "neocomputers:item/server_creative"
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 328 B |
|
After Width: | Height: | Size: 438 B |
|
After Width: | Height: | Size: 477 B |
|
After Width: | Height: | Size: 431 B |
BIN
src/main/resources/assets/neocomputers/textures/block/robot.png
Normal file
|
After Width: | Height: | Size: 934 B |
|
Before Width: | Height: | Size: 271 KiB After Width: | Height: | Size: 242 KiB |
|
Before Width: | Height: | Size: 342 B After Width: | Height: | Size: 718 B |
BIN
src/main/resources/assets/neocomputers/textures/gui/rack.png
Normal file
|
After Width: | Height: | Size: 5.1 KiB |
BIN
src/main/resources/assets/neocomputers/textures/gui/relay.png
Normal file
|
After Width: | Height: | Size: 547 B |
|
Before Width: | Height: | Size: 241 B After Width: | Height: | Size: 471 B |
|
Before Width: | Height: | Size: 618 B |
|
Before Width: | Height: | Size: 394 B After Width: | Height: | Size: 623 B |
|
Before Width: | Height: | Size: 417 B After Width: | Height: | Size: 618 B |
|
Before Width: | Height: | Size: 221 B After Width: | Height: | Size: 465 B |
|
Before Width: | Height: | Size: 473 B After Width: | Height: | Size: 579 B |
|
Before Width: | Height: | Size: 472 B After Width: | Height: | Size: 602 B |
@@ -1,4 +1,4 @@
|
||||
accessWidener v2 named
|
||||
|
||||
accessible method net/minecraft/world/level/block/entity/BlockEntityType <init> (Lnet/minecraft/world/level/block/entity/BlockEntityType$BlockEntitySupplier;Ljava/util/Set;)V
|
||||
# accessible method net/minecraft/world/level/block/entity/BlockEntityType <init> (Lnet/minecraft/world/level/block/entity/BlockEntityType$BlockEntitySupplier;Ljava/util/Set;)V
|
||||
accessible field net/minecraft/core/Direction$Plane faces [Lnet/minecraft/core/Direction;
|
||||