Initial update to 1.18.1

This commit is contained in:
Shadowfacts 2021-12-22 18:59:51 -05:00
parent 172536cdb8
commit 5488cc295a
80 changed files with 476 additions and 539 deletions

View File

@ -1,7 +1,7 @@
plugins { plugins {
id "fabric-loom" version "0.6.49" id "fabric-loom" version "0.10-SNAPSHOT"
id "maven-publish" id "maven-publish"
id "org.jetbrains.kotlin.jvm" version "1.4.30" id "org.jetbrains.kotlin.jvm" version "1.6.10"
} }
archivesBaseName = project.archives_base_name archivesBaseName = project.archives_base_name
@ -10,8 +10,8 @@ group = project.maven_group
allprojects { allprojects {
pluginManager.withPlugin("java") { pluginManager.withPlugin("java") {
sourceCompatibility = JavaVersion.VERSION_1_8 sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_17
} }
} }
@ -43,6 +43,8 @@ configure(allprojects.findAll { it.name != "kiwi-java" }) {
// see http://yodaconditions.net/blog/fix-for-java-file-encoding-problems-with-gradle.html // see http://yodaconditions.net/blog/fix-for-java-file-encoding-problems-with-gradle.html
tasks.withType(JavaCompile) { tasks.withType(JavaCompile) {
options.encoding = "UTF-8" options.encoding = "UTF-8"
// Minecraft 1.18 (1.18-pre2) upwards uses Java 17.
options.release = 17
} }
java { java {
@ -55,43 +57,54 @@ configure(allprojects.findAll { it.name != "kiwi-java" }) {
pluginManager.withPlugin("org.jetbrains.kotlin.jvm") { pluginManager.withPlugin("org.jetbrains.kotlin.jvm") {
compileKotlin { compileKotlin {
kotlinOptions.jvmTarget = JavaVersion.VERSION_1_8 kotlinOptions.jvmTarget = JavaVersion.VERSION_17
} }
} }
} }
minecraft { loom {
log4jConfigs.from "PhyConDebugLogging.xml" log4jConfigs.from "PhyConDebugLogging.xml"
} }
repositories { repositories {
maven { url "https://mod-buildcraft.com/maven" } maven { url "https://mod-buildcraft.com/maven" }
maven { url "http://server.bbkr.space:8081/artifactory/libs-release/" } // maven { url "https://server.bbkr.space:8081/artifactory/libs-release/" }
maven { url "https://maven.terraformersmc.com/releases" } maven { url "https://maven.terraformersmc.com/releases" }
jcenter() maven { url "https://maven.shedaniel.me/" }
maven { url "https://maven.siphalor.de/" }
maven { url "https://jitpack.io" }
mavenCentral()
} }
dependencies { dependencies {
// PSA: Some older mods, compiled on Loom 0.2.1, might have outdated Maven POMs. // PSA: Some older mods, compiled on Loom 0.2.1, might have outdated Maven POMs.
// You may need to force-disable transitiveness on them. // You may need to force-disable transitiveness on them.
modCompile "alexiil.mc.lib:libblockattributes-all:${project.libblockattributes_version}" modImplementation "alexiil.mc.lib:libblockattributes-all:${project.libblockattributes_version}"
include "alexiil.mc.lib:libblockattributes-core:${project.libblockattributes_version}" include "alexiil.mc.lib:libblockattributes-core:${project.libblockattributes_version}"
include "alexiil.mc.lib:libblockattributes-items:${project.libblockattributes_version}" include "alexiil.mc.lib:libblockattributes-items:${project.libblockattributes_version}"
compile project(":kiwi-java") implementation project(":kiwi-java")
include project(":kiwi-java") include project(":kiwi-java")
runtimeOnly project(":plugin:mousewheelie") modRuntimeOnly "de.siphalor:mousewheelie-1.18:${project.mousewheelie_version}"
include project(":plugin:mousewheelie") runtimeOnly(project(":plugin:mousewheelie")) {
runtimeOnly project(":plugin:rei") transitive = false
include project(":plugin:rei")
runtimeOnly project(":plugin:techreborn")
include project(":plugin:techreborn")
modRuntime("io.github.cottonmc:cotton-resources:${project.cotton_resources_version}") {
exclude group: "net.fabricmc.fabric-api"
} }
modRuntime("com.terraformersmc:modmenu:${project.modmenu_version}") { include project(":plugin:mousewheelie")
modRuntimeOnly "me.shedaniel:RoughlyEnoughItems-fabric:${project.rei_version}"
runtimeOnly(project(":plugin:rei")) {
transitive = false
}
include project(":plugin:rei")
// runtimeOnly project(":plugin:techreborn")
// include project(":plugin:techreborn")
// modRuntime("io.github.cottonmc:cotton-resources:${project.cotton_resources_version}") {
// exclude group: "net.fabricmc.fabric-api"
// }
modRuntimeOnly("com.terraformersmc:modmenu:${project.modmenu_version}") {
exclude group: "net.fabricmc.fabric-api" exclude group: "net.fabricmc.fabric-api"
} }
@ -105,22 +118,22 @@ jar {
} }
// configure the maven publication // configure the maven publication
publishing { // publishing {
publications { // publications {
mavenJava(MavenPublication) { // mavenJava(MavenPublication) {
// add all the jars that should be included when publishing to maven // // add all the jars that should be included when publishing to maven
artifact(remapJar) { // artifact(remapJar) {
builtBy remapJar // builtBy remapJar
} // }
artifact(sourcesJar) { // artifact(sourcesJar) {
builtBy remapSourcesJar // builtBy remapSourcesJar
} // }
} // }
} // }
// select the repositories you want to publish to // // select the repositories you want to publish to
repositories { // repositories {
// uncomment to publish to the local maven // // uncomment to publish to the local maven
// mavenLocal() // // mavenLocal()
} // }
} // }

View File

@ -1,19 +1,21 @@
org.gradle.jvmargs=-Xmx1G org.gradle.jvmargs=-Xmx1G
org.gradle.daemon=false org.gradle.daemon=false
minecraft_version=1.16.5 minecraft_version=1.18.1
yarn_mappings=1.16.5+build.4 yarn_mappings=1.18.1+build.7
loader_version=0.11.1 loader_version=0.12.12
mod_version=0.2.0 mod_version=0.2.0
maven_group=net.shadowfacts maven_group=net.shadowfacts
archives_base_name=PhysicalConnectivity archives_base_name=PhysicalConnectivity
fabric_version=0.30.0+1.16 fabric_version=0.44.0+1.18
fabric_kotlin_version=1.4.30+build.2 fabric_kotlin_version=1.7.1+kotlin.1.6.10
libblockattributes_version=0.8.5 libblockattributes_version=0.10.0
cotton_resources_version=1.7.4 # cotton_resources_version=1.7.4
modmenu_version=1.16.8 modmenu_version=3.0.1
rei_version=7.1.356
mousewheelie_version=1.8.0+mc1.18-pre5
junit_version = 5.4.0 junit_version = 5.4.0

View File

@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.8-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists

@ -1 +1 @@
Subproject commit 1cbaea53d207f1e16c6e5ee2e6bf6e3c1440ac44 Subproject commit abe783ae7ce45ccf296ed7b7e5c1b194e7c560fa

View File

@ -3,7 +3,7 @@ plugins {
id "org.jetbrains.kotlin.jvm" id "org.jetbrains.kotlin.jvm"
} }
archivesBaseName = project.archives_base_name archivesBaseName = "PhyCon-Plugin-MouseWheelie"
version = project.mod_version version = project.mod_version
group = project.maven_group group = project.maven_group
@ -11,13 +11,18 @@ repositories {
maven { maven {
url = "https://maven.siphalor.de/" url = "https://maven.siphalor.de/"
} }
jcenter() maven {
url = "https://jitpack.io"
}
mavenCentral()
} }
dependencies { dependencies {
implementation project(":") implementation(project(":")) {
transitive = false
}
modImplementation("de.siphalor:mousewheelie-1.16:${project.mousewheelie_version}") { modImplementation("de.siphalor:mousewheelie-1.18:${project.mousewheelie_version}") {
exclude group: "net.fabricmc" exclude group: "net.fabricmc"
exclude group: "net.fabricmc.fabric-api" exclude group: "net.fabricmc.fabric-api"
exclude module: "modmenu" exclude module: "modmenu"

View File

@ -1,4 +0,0 @@
archives_base_name=PhyCon-Plugin-MouseWheelie
mousewheelie_version=1.6.4+mc1.16.4

View File

@ -3,7 +3,7 @@ plugins {
id "org.jetbrains.kotlin.jvm" id "org.jetbrains.kotlin.jvm"
} }
archivesBaseName = project.archives_base_name archivesBaseName = "PhyCon-Plugin-REI"
version = project.mod_version version = project.mod_version
group = project.maven_group group = project.maven_group
@ -11,16 +11,15 @@ repositories {
maven { maven {
url = "https://maven.shedaniel.me/" url = "https://maven.shedaniel.me/"
} }
jcenter() mavenCentral()
} }
dependencies { dependencies {
implementation project(":") implementation(project(":")) {
transitive = false
modCompileOnly("me.shedaniel:RoughlyEnoughItems-api:${project.rei_version}") {
exclude group: "net.fabricmc.fabric-api"
} }
modRuntime("me.shedaniel:RoughlyEnoughItems:${project.rei_version}") {
modCompileOnly("me.shedaniel:RoughlyEnoughItems-api-fabric:${project.rei_version}") {
exclude group: "net.fabricmc.fabric-api" exclude group: "net.fabricmc.fabric-api"
} }
} }

View File

@ -1,3 +0,0 @@
archives_base_name=PhyCon-Plugin-REI
rei_version=5.10.184

View File

@ -1,25 +1,23 @@
package net.shadowfacts.phycon.plugin.rei package net.shadowfacts.phycon.plugin.rei
import me.shedaniel.math.Rectangle import me.shedaniel.math.Rectangle
import me.shedaniel.rei.api.BaseBoundsHandler import me.shedaniel.rei.api.client.REIRuntime
import me.shedaniel.rei.api.DisplayHelper import me.shedaniel.rei.api.client.plugins.REIClientPlugin
import me.shedaniel.rei.api.REIHelper import me.shedaniel.rei.api.client.registry.screen.ScreenRegistry
import me.shedaniel.rei.api.plugins.REIPluginV0
import net.fabricmc.api.ClientModInitializer import net.fabricmc.api.ClientModInitializer
import net.minecraft.client.MinecraftClient import net.minecraft.client.MinecraftClient
import net.minecraft.util.Identifier
import net.shadowfacts.phycon.block.terminal.AbstractTerminalScreen import net.shadowfacts.phycon.block.terminal.AbstractTerminalScreen
/** /**
* @author shadowfacts * @author shadowfacts
*/ */
object PhyConPlugin: ClientModInitializer, REIPluginV0 { object PhyConPlugin: ClientModInitializer, REIClientPlugin {
const val MODID = "phycon_rei" const val MODID = "phycon_rei"
override fun onInitializeClient() { override fun onInitializeClient() {
AbstractTerminalScreen.registerClickHandler { mouseX, mouseY, button -> AbstractTerminalScreen.registerClickHandler { mouseX, mouseY, button ->
REIHelper.getInstance().searchTextField?.also { REIRuntime.getInstance().searchTextField?.also {
if (it.bounds.contains(mouseX, mouseY)) { if (it.isFocused) {
this.terminalVC.searchField.resignFirstResponder() this.terminalVC.searchField.resignFirstResponder()
} else { } else {
this.terminalVC.searchField.becomeFirstResponder() this.terminalVC.searchField.becomeFirstResponder()
@ -29,10 +27,8 @@ object PhyConPlugin: ClientModInitializer, REIPluginV0 {
} }
} }
override fun getPluginIdentifier() = Identifier(MODID, "rei_plugin") override fun registerScreens(registry: ScreenRegistry) {
registry.exclusionZones().register(AbstractTerminalScreen::class.java) {
override fun registerBounds(helper: DisplayHelper) {
BaseBoundsHandler.getInstance().registerExclusionZones(AbstractTerminalScreen::class.java) {
val screen = MinecraftClient.getInstance().currentScreen as AbstractTerminalScreen<*, *> val screen = MinecraftClient.getInstance().currentScreen as AbstractTerminalScreen<*, *>
val view = screen.terminalVC.settingsView val view = screen.terminalVC.settingsView
val rect = view.convert(view.bounds, to = null) val rect = view.convert(view.bounds, to = null)

View File

@ -1,9 +1,7 @@
package net.shadowfacts.phycon.plugin.rei package net.shadowfacts.phycon.plugin.rei
import me.shedaniel.rei.server.ContainerContext import me.shedaniel.rei.api.common.display.Display
import me.shedaniel.rei.server.ContainerInfo import me.shedaniel.rei.api.common.transfer.info.MenuInfo
import me.shedaniel.rei.server.ContainerInfoHandler
import me.shedaniel.rei.server.StackAccessor
import net.fabricmc.api.ModInitializer import net.fabricmc.api.ModInitializer
import net.minecraft.util.Identifier import net.minecraft.util.Identifier
import net.shadowfacts.phycon.block.terminal.CraftingTerminalScreenHandler import net.shadowfacts.phycon.block.terminal.CraftingTerminalScreenHandler
@ -14,34 +12,34 @@ import net.shadowfacts.phycon.block.terminal.CraftingTerminalScreenHandler
object PhyConPluginCommon: ModInitializer { object PhyConPluginCommon: ModInitializer {
override fun onInitialize() { override fun onInitialize() {
ContainerInfoHandler.registerContainerInfo(Identifier("minecraft", "plugins/crafting"), TerminalInfo) // ContainerInfoHandler.registerContainerInfo(Identifier("minecraft", "plugins/crafting"), TerminalInfo)
} }
object TerminalInfo: ContainerInfo<CraftingTerminalScreenHandler> { // object TerminalInfo: ContainerInfo<CraftingTerminalScreenHandler> {
override fun getContainerClass() = CraftingTerminalScreenHandler::class.java // override fun getContainerClass() = CraftingTerminalScreenHandler::class.java
//
override fun getCraftingResultSlotIndex(container: CraftingTerminalScreenHandler): Int { // override fun getCraftingResultSlotIndex(container: CraftingTerminalScreenHandler): Int {
return container.resultSlot.id // return container.resultSlot.id
} // }
//
override fun getCraftingWidth(container: CraftingTerminalScreenHandler): Int { // override fun getCraftingWidth(container: CraftingTerminalScreenHandler): Int {
return 3 // return 3
} // }
//
override fun getCraftingHeight(container: CraftingTerminalScreenHandler): Int { // override fun getCraftingHeight(container: CraftingTerminalScreenHandler): Int {
return 3 // return 3
} // }
//
override fun getGridStacks(context: ContainerContext<CraftingTerminalScreenHandler>): List<StackAccessor> { // override fun getGridStacks(context: ContainerContext<CraftingTerminalScreenHandler>): List<StackAccessor> {
val handler = context.container // val handler = context.container
return (handler.craftingSlotsStart until handler.craftingSlotsEnd).map(context::getStack) // return (handler.craftingSlotsStart until handler.craftingSlotsEnd).map(context::getStack)
} // }
//
override fun getInventoryStacks(context: ContainerContext<CraftingTerminalScreenHandler>): List<StackAccessor> { // override fun getInventoryStacks(context: ContainerContext<CraftingTerminalScreenHandler>): List<StackAccessor> {
val handler = context.container // val handler = context.container
val slots = (handler.playerSlotsStart until handler.playerSlotsEnd) + (handler.bufferSlotsStart until handler.bufferSlotsEnd) // val slots = (handler.playerSlotsStart until handler.playerSlotsEnd) + (handler.bufferSlotsStart until handler.bufferSlotsEnd)
return slots.map(context::getStack) // return slots.map(context::getStack)
} // }
} // }
} }

View File

@ -25,7 +25,7 @@
"value": "net.shadowfacts.phycon.plugin.rei.PhyConPlugin" "value": "net.shadowfacts.phycon.plugin.rei.PhyConPlugin"
} }
], ],
"rei_plugins": [ "rei": [
{ {
"adapter": "kotlin", "adapter": "kotlin",
"value": "net.shadowfacts.phycon.plugin.rei.PhyConPlugin" "value": "net.shadowfacts.phycon.plugin.rei.PhyConPlugin"
@ -39,7 +39,7 @@
"fabric": "*", "fabric": "*",
"fabric-language-kotlin": ">=1.3.50", "fabric-language-kotlin": ">=1.3.50",
"phycon": "*", "phycon": "*",
"roughlyenoughitems": "^5.0.0" "roughlyenoughitems": "^7.0.0"
}, },
"custom": { "custom": {

View File

@ -11,11 +11,13 @@ repositories {
maven { maven {
url = "https://maven.modmuss50.me/" url = "https://maven.modmuss50.me/"
} }
jcenter() mavenCentral()
} }
dependencies { dependencies {
implementation project(":") implementation(project(":")) {
transitive = false
}
modImplementation("TechReborn:TechReborn-1.16:${project.techreborn_version}") { modImplementation("TechReborn:TechReborn-1.16:${project.techreborn_version}") {
exclude group: "net.fabricmc.fabric-api" exclude group: "net.fabricmc.fabric-api"

View File

@ -1,6 +1,6 @@
pluginManagement { pluginManagement {
repositories { repositories {
jcenter() mavenCentral()
maven { maven {
name = 'Fabric' name = 'Fabric'
url = 'https://maven.fabricmc.net/' url = 'https://maven.fabricmc.net/'
@ -12,4 +12,4 @@ pluginManagement {
include("kiwi-java") include("kiwi-java")
include("plugin:mousewheelie") include("plugin:mousewheelie")
include("plugin:rei") include("plugin:rei")
include("plugin:techreborn") // include("plugin:techreborn")

View File

@ -41,7 +41,7 @@ public class MixinHandledScreen {
AbstractTerminalScreen<?, ?> self = (AbstractTerminalScreen<?, ?>)(Object)this; AbstractTerminalScreen<?, ?> self = (AbstractTerminalScreen<?, ?>)(Object)this;
AbstractTerminalScreenHandler<?> handler = self.getScreenHandler(); AbstractTerminalScreenHandler<?> handler = self.getScreenHandler();
if (slot.id < handler.getNetworkSlotsEnd() && stack.getCount() > 1) { if (slot.id < handler.getNetworkSlotsEnd() && stack.getCount() > 1) {
self.drawNetworkSlotAmount(stack, x, y, slot, matrixStack); self.drawNetworkSlotAmount(stack, x, y);
return; return;
} }
} }

View File

@ -1,6 +1,5 @@
package net.shadowfacts.cacao package net.shadowfacts.cacao
import com.mojang.blaze3d.systems.RenderSystem
import net.minecraft.client.gui.screen.ingame.HandledScreen import net.minecraft.client.gui.screen.ingame.HandledScreen
import net.minecraft.client.util.math.MatrixStack import net.minecraft.client.util.math.MatrixStack
import net.minecraft.entity.player.PlayerInventory import net.minecraft.entity.player.PlayerInventory
@ -14,6 +13,7 @@ import net.shadowfacts.cacao.util.RenderHelper
import net.shadowfacts.cacao.window.ScreenHandlerWindow import net.shadowfacts.cacao.window.ScreenHandlerWindow
import net.shadowfacts.cacao.window.Window import net.shadowfacts.cacao.window.Window
import org.lwjgl.glfw.GLFW import org.lwjgl.glfw.GLFW
import org.lwjgl.opengl.GL11
import java.util.* import java.util.*
/** /**
@ -82,8 +82,8 @@ open class CacaoHandledScreen<Handler: ScreenHandler>(
override fun render(matrixStack: MatrixStack, mouseX: Int, mouseY: Int, delta: Float) { override fun render(matrixStack: MatrixStack, mouseX: Int, mouseY: Int, delta: Float) {
val mouse = Point(mouseX, mouseY) val mouse = Point(mouseX, mouseY)
RenderSystem.pushMatrix() matrixStack.push()
RenderSystem.translatef(0f, 0f, -350f) matrixStack.translate(0.0, 0.0, -350.0)
for (i in windows.indices) { for (i in windows.indices) {
val it = windows[i] val it = windows[i]
@ -100,7 +100,7 @@ open class CacaoHandledScreen<Handler: ScreenHandler>(
super.render(matrixStack, -1, -1, delta) super.render(matrixStack, -1, -1, delta)
} }
RenderSystem.popMatrix() matrixStack.pop()
} }
it.draw(matrixStack, mouse, delta) it.draw(matrixStack, mouse, delta)

View File

@ -1,20 +1,21 @@
package net.shadowfacts.cacao.util package net.shadowfacts.cacao.util
import com.mojang.blaze3d.platform.GlStateManager
import com.mojang.blaze3d.systems.RenderSystem import com.mojang.blaze3d.systems.RenderSystem
import net.minecraft.client.MinecraftClient import net.minecraft.client.MinecraftClient
import net.minecraft.client.gui.DrawableHelper import net.minecraft.client.gui.DrawableHelper
import net.minecraft.client.gui.screen.Screen
import net.minecraft.client.render.* import net.minecraft.client.render.*
import net.minecraft.client.sound.PositionedSoundInstance import net.minecraft.client.sound.PositionedSoundInstance
import net.minecraft.client.util.math.MatrixStack import net.minecraft.client.util.math.MatrixStack
import net.minecraft.sound.SoundEvent import net.minecraft.sound.SoundEvent
import net.minecraft.text.LiteralText
import net.minecraft.text.OrderedText import net.minecraft.text.OrderedText
import net.minecraft.text.Text import net.minecraft.text.Text
import net.minecraft.util.math.Matrix4f import net.minecraft.util.math.Matrix4f
import net.shadowfacts.cacao.geometry.Point import net.shadowfacts.cacao.geometry.Point
import net.shadowfacts.cacao.geometry.Rect import net.shadowfacts.cacao.geometry.Rect
import net.shadowfacts.cacao.util.texture.Texture import net.shadowfacts.cacao.util.texture.Texture
import org.lwjgl.opengl.GL11 import kotlin.math.roundToInt
/** /**
* Helper methods for rendering using Minecraft's utilities from Cacao views. * Helper methods for rendering using Minecraft's utilities from Cacao views.
@ -45,18 +46,18 @@ object RenderHelper: DrawableHelper() {
*/ */
fun draw(matrixStack: MatrixStack, rect: Rect, texture: Texture) { fun draw(matrixStack: MatrixStack, rect: Rect, texture: Texture) {
if (disabled) return if (disabled) return
color(1f, 1f, 1f, 1f) RenderSystem.setShader(GameRenderer::getPositionTexShader)
MinecraftClient.getInstance().textureManager.bindTexture(texture.location) RenderSystem.setShaderTexture(0, texture.location)
draw(matrixStack, rect.left, rect.top, texture.u, texture.v, rect.width, rect.height, texture.width, texture.height) draw(matrixStack, rect.left, rect.top, texture.u, texture.v, rect.width, rect.height, texture.width, texture.height)
} }
fun drawLine(start: Point, end: Point, z: Double, width: Float, color: Color) { fun drawLine(start: Point, end: Point, z: Double, width: Float, color: Color) {
if (disabled) return if (disabled) return
GlStateManager.lineWidth(width) RenderSystem.lineWidth(width)
val tessellator = Tessellator.getInstance() val tessellator = Tessellator.getInstance()
val buffer = tessellator.buffer val buffer = tessellator.buffer
buffer.begin(GL11.GL_LINES, VertexFormats.POSITION_COLOR) buffer.begin(VertexFormat.DrawMode.LINES, VertexFormats.POSITION_COLOR)
buffer.vertex(start.x, start.y, z).color(color).next() buffer.vertex(start.x, start.y, z).color(color).next()
buffer.vertex(end.x, end.y, z).color(color).next() buffer.vertex(end.x, end.y, z).color(color).next()
tessellator.draw() tessellator.draw()
@ -71,19 +72,19 @@ object RenderHelper: DrawableHelper() {
val uEnd = (u + width).toFloat() / textureWidth val uEnd = (u + width).toFloat() / textureWidth
val vStart = v.toFloat() / textureHeight val vStart = v.toFloat() / textureHeight
val vEnd = (v + height).toFloat() / textureHeight val vEnd = (v + height).toFloat() / textureHeight
drawTexturedQuad(matrixStack.peek().model, x, x + width, y, y + height, 0.0, uStart, uEnd, vStart, vEnd) drawTexturedQuad(matrixStack.peek().positionMatrix, x, x + width, y, y + height, 0.0, uStart, uEnd, vStart, vEnd)
} }
// Copied from net.minecraft.client.gui.DrawableHelper // Copied from net.minecraft.client.gui.DrawableHelper
// TODO: use an access transformer to just call minecraft's impl
private fun drawTexturedQuad(matrix: Matrix4f, x0: Double, x1: Double, y0: Double, y1: Double, z: Double, u0: Float, u1: Float, v0: Float, v1: Float) { private fun drawTexturedQuad(matrix: Matrix4f, x0: Double, x1: Double, y0: Double, y1: Double, z: Double, u0: Float, u1: Float, v0: Float, v1: Float) {
val bufferBuilder = Tessellator.getInstance().buffer val bufferBuilder = Tessellator.getInstance().buffer
bufferBuilder.begin(GL11.GL_QUADS, VertexFormats.POSITION_TEXTURE) bufferBuilder.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_TEXTURE)
bufferBuilder.vertex(matrix, x0.toFloat(), y1.toFloat(), z.toFloat()).texture(u0, v1).next() bufferBuilder.vertex(matrix, x0.toFloat(), y1.toFloat(), z.toFloat()).texture(u0, v1).next()
bufferBuilder.vertex(matrix, x1.toFloat(), y1.toFloat(), z.toFloat()).texture(u1, v1).next() bufferBuilder.vertex(matrix, x1.toFloat(), y1.toFloat(), z.toFloat()).texture(u1, v1).next()
bufferBuilder.vertex(matrix, x1.toFloat(), y0.toFloat(), z.toFloat()).texture(u1, v0).next() bufferBuilder.vertex(matrix, x1.toFloat(), y0.toFloat(), z.toFloat()).texture(u1, v0).next()
bufferBuilder.vertex(matrix, x0.toFloat(), y0.toFloat(), z.toFloat()).texture(u0, v0).next() bufferBuilder.vertex(matrix, x0.toFloat(), y0.toFloat(), z.toFloat()).texture(u0, v0).next()
bufferBuilder.end() bufferBuilder.end()
RenderSystem.enableAlphaTest()
BufferRenderer.draw(bufferBuilder) BufferRenderer.draw(bufferBuilder)
} }
@ -95,110 +96,22 @@ object RenderHelper: DrawableHelper() {
drawTooltip(matrixStack, texts.map(Text::asOrderedText), mouse) drawTooltip(matrixStack, texts.map(Text::asOrderedText), mouse)
} }
// Based on Screen.renderOrderedTooltip private val dummyScreen = object: Screen(LiteralText("")) {
init {
textRenderer = MinecraftClient.getInstance().textRenderer
itemRenderer = MinecraftClient.getInstance().itemRenderer
}
}
@JvmName("drawOrderedTooltip") @JvmName("drawOrderedTooltip")
fun drawTooltip(matrixStack: MatrixStack, texts: List<OrderedText>, mouse: Point) { fun drawTooltip(matrixStack: MatrixStack, texts: List<OrderedText>, mouse: Point) {
if (disabled) return if (disabled) return
if (texts.isEmpty()) return if (texts.isEmpty()) return
val client = MinecraftClient.getInstance() val client = MinecraftClient.getInstance()
val textRenderer = client.textRenderer dummyScreen.width = client.window.scaledWidth
dummyScreen.height = client.window.scaledHeight
val maxWidth = texts.maxOf(textRenderer::getWidth) dummyScreen.renderOrderedTooltip(matrixStack, texts, mouse.x.roundToInt(), mouse.y.roundToInt())
var x = mouse.x.toInt() + 12
var y = mouse.y.toInt() - 12
var p = 8
if (texts.size > 1) {
p += 2 + (texts.size - 1) * 8
}
if (x + maxWidth > client.window.scaledWidth) {
x -= 28 + maxWidth
}
if (y + p + 6 > client.window.scaledHeight) {
y = client.window.scaledHeight - p - 6
}
matrixStack.push()
val q = -267386864
val r = 1347420415
val s = 1344798847
val t = 1
val tessellator = Tessellator.getInstance()
val buffer = tessellator.buffer
buffer.begin(GL11.GL_QUADS, VertexFormats.POSITION_COLOR)
val matrix = matrixStack.peek().model
val z = 400
fillGradient(matrix, buffer, x - 3, y - 4, x + maxWidth + 3, y - 3, z, q, q)
fillGradient(matrix, buffer, x - 3, y + p + 3, x + maxWidth + 3, y + p + 4, z, q, q)
fillGradient(matrix, buffer, x - 3, y - 3, x + maxWidth + 3, y + p + 3, z, q, q)
fillGradient(matrix, buffer, x - 4, y - 3, x - 3, y + p + 3, z, q, q)
fillGradient(matrix, buffer, x + maxWidth + 3, y - 3, x + maxWidth + 4, y + p + 3, z, q, q)
fillGradient(matrix, buffer, x - 3, y - 3 + 1, x - 3 + 1, y + p + 3 - 1, z, r, s)
fillGradient(matrix, buffer, x + maxWidth + 2, y - 3 + 1, x + maxWidth + 3, y + p + 3 - 1, z, r, s)
fillGradient(matrix, buffer, x - 3, y - 3, x + maxWidth + 3, y - 3 + 1, z, r, r)
fillGradient(matrix, buffer, x - 3, y + p + 2, x + maxWidth + 3, y + p + 3, z, s, s)
RenderSystem.enableDepthTest()
RenderSystem.disableTexture()
RenderSystem.enableBlend()
RenderSystem.defaultBlendFunc()
RenderSystem.shadeModel(7425)
buffer.end()
BufferRenderer.draw(buffer)
RenderSystem.shadeModel(7424)
RenderSystem.disableBlend()
RenderSystem.enableTexture()
val immediate = VertexConsumerProvider.immediate(buffer)
matrixStack.translate(0.0, 0.0, 400.0)
for (i in texts.indices) {
val text = texts[i]
textRenderer.draw(text, x.toFloat(), y.toFloat(), -1, true, matrix, immediate, false, 0, 15728880)
if (i == 0) {
y += 2
}
y += 10
}
immediate.draw()
matrixStack.pop()
}
/**
* @see org.lwjgl.opengl.GL11.glPushMatrix
*/
fun pushMatrix() {
if (disabled) return
RenderSystem.pushMatrix()
}
/**
* @see org.lwjgl.opengl.GL11.glPopMatrix
*/
fun popMatrix() {
if (disabled) return
RenderSystem.popMatrix()
}
/**
* @see org.lwjgl.opengl.GL11.glTranslated
*/
fun translate(x: Double, y: Double, z: Double = 0.0) {
if (disabled) return
RenderSystem.translated(x, y, z)
}
/**
* @see org.lwjgl.opengl.GL11.glScaled
*/
fun scale(x: Double, y: Double, z: Double = 1.0) {
if (disabled) return
RenderSystem.scaled(x, y, z)
} }
/** /**
@ -206,7 +119,7 @@ object RenderHelper: DrawableHelper() {
*/ */
fun color(r: Float, g: Float, b: Float, alpha: Float) { fun color(r: Float, g: Float, b: Float, alpha: Float) {
if (disabled) return if (disabled) return
RenderSystem.color4f(r, g, b, alpha) RenderSystem.setShaderColor(r, g, b, alpha)
} }
private fun VertexConsumer.color(color: Color): VertexConsumer { private fun VertexConsumer.color(color: Color): VertexConsumer {

View File

@ -26,11 +26,13 @@ class BezierCurveView(val curve: BezierCurve): View() {
var lineColor = Color.BLACK var lineColor = Color.BLACK
override fun drawContent(matrixStack: MatrixStack, mouse: Point, delta: Float) { override fun drawContent(matrixStack: MatrixStack, mouse: Point, delta: Float) {
RenderHelper.scale(bounds.width, bounds.height) matrixStack.push()
matrixStack.scale(bounds.width.toFloat(), bounds.height.toFloat(), 1f)
for ((index, point) in points.withIndex()) { for ((index, point) in points.withIndex()) {
val next = points.getOrNull(index + 1) ?: break val next = points.getOrNull(index + 1) ?: break
RenderHelper.drawLine(point, next, zIndex, lineWidth, lineColor) RenderHelper.drawLine(point, next, zIndex, lineWidth, lineColor)
} }
matrixStack.pop()
} }
} }

View File

@ -29,7 +29,7 @@ class DialogView(
CANCEL, CONFIRM, OK, CLOSE; CANCEL, CONFIRM, OK, CLOSE;
override val localizedName: Text override val localizedName: Text
get() = LiteralText(name.toLowerCase().capitalize()) // todo: actually localize me get() = LiteralText(name.lowercase().replaceFirstChar(Char::titlecase)) // todo: actually localize me
} }
private lateinit var background: NinePatchView private lateinit var background: NinePatchView

View File

@ -12,7 +12,6 @@ import no.birkett.kiwi.Constraint
import no.birkett.kiwi.Solver import no.birkett.kiwi.Solver
import java.lang.RuntimeException import java.lang.RuntimeException
import java.util.* import java.util.*
import kotlin.collections.HashSet
import kotlin.math.floor import kotlin.math.floor
/** /**
@ -368,8 +367,8 @@ open class View(): Responder {
* @param delta The time since the last frame. * @param delta The time since the last frame.
*/ */
open fun draw(matrixStack: MatrixStack, mouse: Point, delta: Float) { open fun draw(matrixStack: MatrixStack, mouse: Point, delta: Float) {
RenderHelper.pushMatrix() matrixStack.push()
RenderHelper.translate(floor(frame.left), floor(frame.top)) matrixStack.translate(frame.left, frame.top, 0.0)
RenderHelper.fill(matrixStack, bounds, backgroundColor) RenderHelper.fill(matrixStack, bounds, backgroundColor)
@ -380,7 +379,7 @@ open class View(): Responder {
it.draw(matrixStack, mouseInView, delta) it.draw(matrixStack, mouseInView, delta)
} }
RenderHelper.popMatrix() matrixStack.pop()
} }
/** /**

View File

@ -109,8 +109,8 @@ abstract class AbstractButton<Impl: AbstractButton<Impl>>(val content: View, val
} }
override fun draw(matrixStack: MatrixStack, mouse: Point, delta: Float) { override fun draw(matrixStack: MatrixStack, mouse: Point, delta: Float) {
RenderHelper.pushMatrix() matrixStack.push()
RenderHelper.translate(floor(frame.left), floor(frame.top)) matrixStack.translate(frame.left, frame.top, 0.0)
RenderHelper.fill(matrixStack, bounds, backgroundColor) RenderHelper.fill(matrixStack, bounds, backgroundColor)
@ -123,7 +123,7 @@ abstract class AbstractButton<Impl: AbstractButton<Impl>>(val content: View, val
// don't draw subviews, otherwise all background views + content will get drawn // don't draw subviews, otherwise all background views + content will get drawn
RenderHelper.popMatrix() matrixStack.pop()
if (tooltip != null && mouse in bounds) { if (tooltip != null && mouse in bounds) {
window!!.drawTooltip(listOf(tooltip!!)) window!!.drawTooltip(listOf(tooltip!!))

View File

@ -1,15 +1,12 @@
package net.shadowfacts.cacao.view.textfield package net.shadowfacts.cacao.view.textfield
import net.minecraft.client.MinecraftClient import net.minecraft.client.MinecraftClient
import net.minecraft.client.gui.screen.TickableElement
import net.minecraft.client.gui.widget.TextFieldWidget import net.minecraft.client.gui.widget.TextFieldWidget
import net.minecraft.client.util.math.MatrixStack import net.minecraft.client.util.math.MatrixStack
import net.minecraft.text.LiteralText import net.minecraft.text.LiteralText
import net.shadowfacts.cacao.geometry.Point import net.shadowfacts.cacao.geometry.Point
import net.shadowfacts.cacao.util.Color
import net.shadowfacts.cacao.util.KeyModifiers import net.shadowfacts.cacao.util.KeyModifiers
import net.shadowfacts.cacao.util.MouseButton import net.shadowfacts.cacao.util.MouseButton
import net.shadowfacts.cacao.util.RenderHelper
import net.shadowfacts.cacao.view.View import net.shadowfacts.cacao.view.View
import net.shadowfacts.phycon.mixin.client.TextFieldWidgetAccessor import net.shadowfacts.phycon.mixin.client.TextFieldWidgetAccessor
import org.lwjgl.glfw.GLFW import org.lwjgl.glfw.GLFW
@ -25,7 +22,7 @@ import org.lwjgl.glfw.GLFW
*/ */
abstract class AbstractTextField<Impl: AbstractTextField<Impl>>( abstract class AbstractTextField<Impl: AbstractTextField<Impl>>(
initialText: String initialText: String
): View(), TickableElement { ): View() {
/** /**
* A function that is invoked when the text in this text field changes. * A function that is invoked when the text in this text field changes.
@ -70,7 +67,7 @@ abstract class AbstractTextField<Impl: AbstractTextField<Impl>>(
var drawBackground = true var drawBackground = true
set(value) { set(value) {
field = value field = value
minecraftWidget.setHasBorder(value) minecraftWidget.setDrawsBackground(value)
} }
private lateinit var originInWindow: Point private lateinit var originInWindow: Point
@ -79,7 +76,7 @@ abstract class AbstractTextField<Impl: AbstractTextField<Impl>>(
init { init {
minecraftWidget.text = initialText minecraftWidget.text = initialText
minecraftWidget.setTextPredicate { this.validate(it) } minecraftWidget.setTextPredicate { this.validate(it) }
minecraftWidget.setHasBorder(drawBackground) minecraftWidget.setDrawsBackground(drawBackground)
} }
/** /**
@ -103,14 +100,14 @@ abstract class AbstractTextField<Impl: AbstractTextField<Impl>>(
} }
override fun drawContent(matrixStack: MatrixStack, mouse: Point, delta: Float) { override fun drawContent(matrixStack: MatrixStack, mouse: Point, delta: Float) {
RenderHelper.pushMatrix() matrixStack.push()
RenderHelper.translate(-originInWindow.x, -originInWindow.y) matrixStack.translate(-originInWindow.x, -originInWindow.y, 0.0)
val mouseXInWindow = (mouse.x + originInWindow.x).toInt() val mouseXInWindow = (mouse.x + originInWindow.x).toInt()
val mouseYInWindow = (mouse.y + originInWindow.y).toInt() val mouseYInWindow = (mouse.y + originInWindow.y).toInt()
minecraftWidget.render(matrixStack, mouseXInWindow, mouseYInWindow, delta) minecraftWidget.render(matrixStack, mouseXInWindow, mouseYInWindow, delta)
RenderHelper.popMatrix() matrixStack.pop()
} }
override fun mouseClicked(point: Point, mouseButton: MouseButton): Boolean { override fun mouseClicked(point: Point, mouseButton: MouseButton): Boolean {
@ -135,12 +132,12 @@ abstract class AbstractTextField<Impl: AbstractTextField<Impl>>(
override fun didBecomeFirstResponder() { override fun didBecomeFirstResponder() {
super.didBecomeFirstResponder() super.didBecomeFirstResponder()
minecraftWidget.setSelected(true) minecraftWidget.setTextFieldFocused(true)
} }
override fun didResignFirstResponder() { override fun didResignFirstResponder() {
super.didResignFirstResponder() super.didResignFirstResponder()
minecraftWidget.setSelected(false) minecraftWidget.setTextFieldFocused(false)
} }
override fun charTyped(char: Char, modifiers: KeyModifiers): Boolean { override fun charTyped(char: Char, modifiers: KeyModifiers): Boolean {
@ -164,7 +161,7 @@ abstract class AbstractTextField<Impl: AbstractTextField<Impl>>(
return result || (isFirstResponder && keyCode != GLFW.GLFW_KEY_ESCAPE) return result || (isFirstResponder && keyCode != GLFW.GLFW_KEY_ESCAPE)
} }
override fun tick() { fun tick() {
minecraftWidget.tick() minecraftWidget.tick()
} }

View File

@ -100,4 +100,4 @@ class KiwiContext(val solver: Solver) {
fun Solver.dsl(init: KiwiContext.() -> Unit): Solver { fun Solver.dsl(init: KiwiContext.() -> Unit): Solver {
KiwiContext(this).init() KiwiContext(this).init()
return this return this
} }

View File

@ -2,15 +2,20 @@ package net.shadowfacts.phycon.block
import net.minecraft.block.Block import net.minecraft.block.Block
import net.minecraft.block.BlockEntityProvider import net.minecraft.block.BlockEntityProvider
import net.minecraft.block.BlockState
import net.minecraft.block.entity.BlockEntity import net.minecraft.block.entity.BlockEntity
import net.minecraft.block.entity.BlockEntityTicker
import net.minecraft.block.entity.BlockEntityType
import net.minecraft.util.math.BlockPos import net.minecraft.util.math.BlockPos
import net.minecraft.world.BlockView import net.minecraft.world.BlockView
import net.minecraft.world.World
/** /**
* @author shadowfacts * @author shadowfacts
*/ */
abstract class BlockWithEntity<T: BlockEntity>(settings: Settings): Block(settings), BlockEntityProvider { abstract class BlockWithEntity<T: BlockEntity>(settings: Settings): Block(settings), BlockEntityProvider {
abstract override fun createBlockEntity(world: BlockView): T? abstract override fun createBlockEntity(pos: BlockPos, state: BlockState): T?
fun getBlockEntity(world: BlockView, pos: BlockPos): T? { fun getBlockEntity(world: BlockView, pos: BlockPos): T? {
val entity = world.getBlockEntity(pos) val entity = world.getBlockEntity(pos)
return if (entity != null) { return if (entity != null) {
@ -19,4 +24,4 @@ abstract class BlockWithEntity<T: BlockEntity>(settings: Settings): Block(settin
null null
} }
} }
} }

View File

@ -1,6 +1,9 @@
package net.shadowfacts.phycon.block package net.shadowfacts.phycon.block
import net.minecraft.block.BlockState import net.minecraft.block.BlockState
import net.minecraft.block.entity.BlockEntity
import net.minecraft.block.entity.BlockEntityTicker
import net.minecraft.block.entity.BlockEntityType
import net.minecraft.entity.player.PlayerEntity import net.minecraft.entity.player.PlayerEntity
import net.minecraft.util.math.BlockPos import net.minecraft.util.math.BlockPos
import net.minecraft.util.math.Direction import net.minecraft.util.math.Direction
@ -25,4 +28,14 @@ abstract class DeviceBlock<T: DeviceBlockEntity>(settings: Settings): BlockWithE
getBlockEntity(world, pos)!!.onBreak() getBlockEntity(world, pos)!!.onBreak()
} }
override fun <T: BlockEntity> getTicker(world: World, state: BlockState, type: BlockEntityType<T>): BlockEntityTicker<T>? {
return if (world.isClient) {
null
} else {
BlockEntityTicker { world, blockPos, blockState, blockEntity ->
(blockEntity as DeviceBlockEntity).tick()
}
}
}
} }

View File

@ -1,34 +1,32 @@
package net.shadowfacts.phycon.block package net.shadowfacts.phycon.block
import net.fabricmc.fabric.api.block.entity.BlockEntityClientSerializable
import net.minecraft.block.BlockState import net.minecraft.block.BlockState
import net.minecraft.block.entity.BlockEntity import net.minecraft.block.entity.BlockEntity
import net.minecraft.block.entity.BlockEntityType import net.minecraft.block.entity.BlockEntityType
import net.minecraft.nbt.CompoundTag import net.minecraft.nbt.NbtCompound
import net.minecraft.util.Tickable import net.minecraft.network.packet.s2c.play.BlockEntityUpdateS2CPacket
import net.minecraft.util.math.BlockPos
import net.shadowfacts.phycon.PhysicalConnectivity import net.shadowfacts.phycon.PhysicalConnectivity
import net.shadowfacts.phycon.api.PacketSink
import net.shadowfacts.phycon.api.PacketSource
import net.shadowfacts.phycon.api.Interface import net.shadowfacts.phycon.api.Interface
import net.shadowfacts.phycon.api.NetworkComponentBlock import net.shadowfacts.phycon.api.NetworkComponentBlock
import net.shadowfacts.phycon.api.PacketSink
import net.shadowfacts.phycon.api.PacketSource
import net.shadowfacts.phycon.api.frame.EthernetFrame import net.shadowfacts.phycon.api.frame.EthernetFrame
import net.shadowfacts.phycon.api.frame.PacketFrame import net.shadowfacts.phycon.api.frame.PacketFrame
import net.shadowfacts.phycon.api.packet.Packet import net.shadowfacts.phycon.api.packet.Packet
import net.shadowfacts.phycon.api.util.IPAddress import net.shadowfacts.phycon.api.util.IPAddress
import net.shadowfacts.phycon.api.util.MACAddress import net.shadowfacts.phycon.api.util.MACAddress
import net.shadowfacts.phycon.util.NetworkUtil
import net.shadowfacts.phycon.frame.ARPQueryFrame import net.shadowfacts.phycon.frame.ARPQueryFrame
import net.shadowfacts.phycon.frame.ARPResponseFrame import net.shadowfacts.phycon.frame.ARPResponseFrame
import net.shadowfacts.phycon.frame.BasePacketFrame import net.shadowfacts.phycon.frame.BasePacketFrame
import net.shadowfacts.phycon.packet.* import net.shadowfacts.phycon.packet.*
import net.shadowfacts.phycon.util.NetworkUtil
import java.util.* import java.util.*
/** /**
* @author shadowfacts * @author shadowfacts
*/ */
abstract class DeviceBlockEntity(type: BlockEntityType<*>): BlockEntity(type), abstract class DeviceBlockEntity(type: BlockEntityType<*>, pos: BlockPos, state: BlockState): BlockEntity(type, pos, state),
BlockEntityClientSerializable,
Tickable,
PacketSink, PacketSink,
PacketSource, PacketSource,
Interface { Interface {
@ -126,7 +124,7 @@ abstract class DeviceBlockEntity(type: BlockEntityType<*>): BlockEntity(type),
} }
} }
override fun tick() { open fun tick() {
counter++ counter++
if (!world!!.isClient) { if (!world!!.isClient) {
@ -148,33 +146,50 @@ abstract class DeviceBlockEntity(type: BlockEntityType<*>): BlockEntity(type),
} }
} }
protected open fun toCommonTag(tag: CompoundTag) { protected open fun toCommonTag(tag: NbtCompound) {
tag.putInt("IPAddress", ipAddress.address) tag.putInt("IPAddress", ipAddress.address)
tag.putLong("MACAddress", macAddress.address) tag.putLong("MACAddress", macAddress.address)
} }
protected open fun fromCommonTag(tag: CompoundTag) { protected open fun fromCommonTag(tag: NbtCompound) {
ipAddress = IPAddress(tag.getInt("IPAddress")) ipAddress = IPAddress(tag.getInt("IPAddress"))
macAddress = MACAddress(tag.getLong("MACAddress")) macAddress = MACAddress(tag.getLong("MACAddress"))
} }
override fun toTag(tag: CompoundTag): CompoundTag { override fun writeNbt(tag: NbtCompound) {
super.writeNbt(tag)
toCommonTag(tag) toCommonTag(tag)
return super.toTag(tag)
} }
override fun fromTag(state: BlockState, tag: CompoundTag) { override fun readNbt(tag: NbtCompound) {
super.fromTag(state, tag) super.readNbt(tag)
fromCommonTag(tag) fromCommonTag(tag)
if (tag.getBoolean("_SyncPacket")) {
fromClientTag(tag)
}
} }
override fun toClientTag(tag: CompoundTag): CompoundTag { override fun toUpdatePacket(): BlockEntityUpdateS2CPacket {
return BlockEntityUpdateS2CPacket.create(this)
}
override fun toInitialChunkDataNbt(): NbtCompound {
val tag = NbtCompound()
tag.putBoolean("_SyncPacket", true)
return toClientTag(tag)
}
open fun toClientTag(tag: NbtCompound): NbtCompound {
toCommonTag(tag) toCommonTag(tag)
return tag return tag
} }
override fun fromClientTag(tag: CompoundTag) { open fun fromClientTag(tag: NbtCompound) {
fromCommonTag(tag) }
fun markUpdate() {
markDirty()
world!!.updateListeners(pos, cachedState, cachedState, 3)
} }
fun onBreak() { fun onBreak() {

View File

@ -42,7 +42,7 @@ class CableBlock(
), NetworkCableBlock { ), NetworkCableBlock {
companion object { companion object {
val ID = Identifier(PhysicalConnectivity.MODID, "cable") val ID = Identifier(PhysicalConnectivity.MODID, "cable")
val CABLE_MATERIAL = Material.Builder(MaterialColor.BLUE).build() val CABLE_MATERIAL = Material.Builder(MapColor.BLUE).build()
val CENTER_SHAPE = createCuboidShape(6.0, 6.0, 6.0, 10.0, 10.0, 10.0) val CENTER_SHAPE = createCuboidShape(6.0, 6.0, 6.0, 10.0, 10.0, 10.0)
val SIDE_SHAPES = mapOf<Direction, VoxelShape>( val SIDE_SHAPES = mapOf<Direction, VoxelShape>(
Direction.DOWN to createCuboidShape(6.0, 0.0, 6.0, 10.0, 6.0, 10.0), Direction.DOWN to createCuboidShape(6.0, 0.0, 6.0, 10.0, 6.0, 10.0),

View File

@ -15,6 +15,8 @@ import net.minecraft.world.BlockView
import net.minecraft.world.World import net.minecraft.world.World
import net.shadowfacts.phycon.PhysicalConnectivity import net.shadowfacts.phycon.PhysicalConnectivity
import net.shadowfacts.phycon.block.FaceDeviceBlock import net.shadowfacts.phycon.block.FaceDeviceBlock
import kotlin.math.max
import kotlin.math.min
/** /**
* @author shadowfacts * @author shadowfacts
@ -57,7 +59,7 @@ class ExtractorBlock: FaceDeviceBlock<ExtractorBlockEntity>(
arr[i] = 16.0 - arr[i] arr[i] = 16.0 - arr[i]
} }
} }
createCuboidShape(arr[0], arr[1], arr[2], arr[3], arr[4], arr[5]) createCuboidShape(min(arr[0], arr[3]), min(arr[1], arr[4]), min(arr[2], arr[5]), max(arr[0], arr[3]), max(arr[1], arr[4]), max(arr[2], arr[5]))
} }
EXTRACTOR_SHAPES[dir] = shapes.reduce { a, b -> VoxelShapes.union(a, b) } EXTRACTOR_SHAPES[dir] = shapes.reduce { a, b -> VoxelShapes.union(a, b) }
} }
@ -67,7 +69,7 @@ class ExtractorBlock: FaceDeviceBlock<ExtractorBlockEntity>(
override val faceThickness = 6.0 override val faceThickness = 6.0
override val faceShapes: Map<Direction, VoxelShape> = EXTRACTOR_SHAPES override val faceShapes: Map<Direction, VoxelShape> = EXTRACTOR_SHAPES
override fun createBlockEntity(world: BlockView) = ExtractorBlockEntity() override fun createBlockEntity(pos: BlockPos, state: BlockState) = ExtractorBlockEntity(pos, state)
override fun onPlaced(world: World, pos: BlockPos, state: BlockState, entity: LivingEntity?, stack: ItemStack) { override fun onPlaced(world: World, pos: BlockPos, state: BlockState, entity: LivingEntity?, stack: ItemStack) {
if (!world.isClient) { if (!world.isClient) {

View File

@ -5,8 +5,10 @@ import alexiil.mc.lib.attributes.Simulation
import alexiil.mc.lib.attributes.item.FixedItemInv import alexiil.mc.lib.attributes.item.FixedItemInv
import alexiil.mc.lib.attributes.item.ItemAttributes import alexiil.mc.lib.attributes.item.ItemAttributes
import alexiil.mc.lib.attributes.item.filter.ExactItemStackFilter import alexiil.mc.lib.attributes.item.filter.ExactItemStackFilter
import net.minecraft.block.BlockState
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
import net.minecraft.nbt.CompoundTag import net.minecraft.nbt.NbtCompound
import net.minecraft.util.math.BlockPos
import net.minecraft.util.math.Direction import net.minecraft.util.math.Direction
import net.shadowfacts.phycon.api.packet.Packet import net.shadowfacts.phycon.api.packet.Packet
import net.shadowfacts.phycon.init.PhyBlockEntities import net.shadowfacts.phycon.init.PhyBlockEntities
@ -26,7 +28,7 @@ import kotlin.properties.Delegates
/** /**
* @author shadowfacts * @author shadowfacts
*/ */
class ExtractorBlockEntity: DeviceBlockEntity(PhyBlockEntities.EXTRACTOR), class ExtractorBlockEntity(pos: BlockPos, state: BlockState): DeviceBlockEntity(PhyBlockEntities.EXTRACTOR, pos, state),
NetworkStackDispatcher<ExtractorBlockEntity.PendingInsertion>, NetworkStackDispatcher<ExtractorBlockEntity.PendingInsertion>,
ActivationController.ActivatableDevice, ActivationController.ActivatableDevice,
ClientConfigurableDevice { ClientConfigurableDevice {
@ -106,21 +108,21 @@ class ExtractorBlockEntity: DeviceBlockEntity(PhyBlockEntities.EXTRACTOR),
return false return false
} }
override fun toCommonTag(tag: CompoundTag) { override fun toCommonTag(tag: NbtCompound) {
super.toCommonTag(tag) super.toCommonTag(tag)
writeDeviceConfiguration(tag) writeDeviceConfiguration(tag)
} }
override fun fromCommonTag(tag: CompoundTag) { override fun fromCommonTag(tag: NbtCompound) {
super.fromCommonTag(tag) super.fromCommonTag(tag)
loadDeviceConfiguration(tag) loadDeviceConfiguration(tag)
} }
override fun writeDeviceConfiguration(tag: CompoundTag) { override fun writeDeviceConfiguration(tag: NbtCompound) {
tag.putString("ActivationMode", controller.activationMode.name) tag.putString("ActivationMode", controller.activationMode.name)
} }
override fun loadDeviceConfiguration(tag: CompoundTag) { override fun loadDeviceConfiguration(tag: NbtCompound) {
controller.activationMode = ActivationMode.valueOf(tag.getString("ActivationMode")) controller.activationMode = ActivationMode.valueOf(tag.getString("ActivationMode"))
} }

View File

@ -25,6 +25,8 @@ import net.minecraft.world.World
import net.shadowfacts.phycon.PhysicalConnectivity import net.shadowfacts.phycon.PhysicalConnectivity
import net.shadowfacts.phycon.block.FaceDeviceBlock import net.shadowfacts.phycon.block.FaceDeviceBlock
import java.util.* import java.util.*
import kotlin.math.max
import kotlin.math.min
/** /**
* @author shadowfacts * @author shadowfacts
@ -66,7 +68,7 @@ class InserterBlock: FaceDeviceBlock<InserterBlockEntity>(
arr[i] = 16.0 - arr[i] arr[i] = 16.0 - arr[i]
} }
} }
createCuboidShape(arr[0], arr[1], arr[2], arr[3], arr[4], arr[5]) createCuboidShape(min(arr[0], arr[3]), min(arr[1], arr[4]), min(arr[2], arr[5]), max(arr[0], arr[3]), max(arr[1], arr[4]), max(arr[2], arr[5]))
} }
INSERTER_SHAPES[dir] = shapes.reduce { a, b -> VoxelShapes.union(a, b) } INSERTER_SHAPES[dir] = shapes.reduce { a, b -> VoxelShapes.union(a, b) }
} }
@ -76,7 +78,7 @@ class InserterBlock: FaceDeviceBlock<InserterBlockEntity>(
override val faceThickness = 6.0 override val faceThickness = 6.0
override val faceShapes: Map<Direction, VoxelShape> = INSERTER_SHAPES override val faceShapes: Map<Direction, VoxelShape> = INSERTER_SHAPES
override fun createBlockEntity(world: BlockView) = InserterBlockEntity() override fun createBlockEntity(pos: BlockPos, state: BlockState) = InserterBlockEntity(pos, state)
override fun onPlaced(world: World, pos: BlockPos, state: BlockState, entity: LivingEntity?, stack: ItemStack) { override fun onPlaced(world: World, pos: BlockPos, state: BlockState, entity: LivingEntity?, stack: ItemStack) {
if (!world.isClient) { if (!world.isClient) {
@ -94,7 +96,7 @@ class InserterBlock: FaceDeviceBlock<InserterBlockEntity>(
if (!world.isClient) { if (!world.isClient) {
val be = getBlockEntity(world, pos)!! val be = getBlockEntity(world, pos)!!
be.sync() be.markUpdate()
val factory = object: ExtendedScreenHandlerFactory { val factory = object: ExtendedScreenHandlerFactory {
override fun createMenu(syncId: Int, playerInv: PlayerInventory, player: PlayerEntity): ScreenHandler { override fun createMenu(syncId: Int, playerInv: PlayerInventory, player: PlayerEntity): ScreenHandler {

View File

@ -5,8 +5,10 @@ import alexiil.mc.lib.attributes.Simulation
import alexiil.mc.lib.attributes.item.ItemAttributes import alexiil.mc.lib.attributes.item.ItemAttributes
import alexiil.mc.lib.attributes.item.ItemInsertable import alexiil.mc.lib.attributes.item.ItemInsertable
import alexiil.mc.lib.attributes.item.ItemStackUtil import alexiil.mc.lib.attributes.item.ItemStackUtil
import net.minecraft.block.BlockState
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
import net.minecraft.nbt.CompoundTag import net.minecraft.nbt.NbtCompound
import net.minecraft.util.math.BlockPos
import net.minecraft.util.math.Direction import net.minecraft.util.math.Direction
import net.shadowfacts.phycon.api.packet.Packet import net.shadowfacts.phycon.api.packet.Packet
import net.shadowfacts.phycon.block.DeviceBlockEntity import net.shadowfacts.phycon.block.DeviceBlockEntity
@ -25,7 +27,7 @@ import kotlin.math.min
/** /**
* @author shadowfacts * @author shadowfacts
*/ */
class InserterBlockEntity: DeviceBlockEntity(PhyBlockEntities.INSERTER), class InserterBlockEntity(pos: BlockPos, state: BlockState): DeviceBlockEntity(PhyBlockEntities.INSERTER, pos, state),
ItemStackPacketHandler, ItemStackPacketHandler,
ActivationController.ActivatableDevice, ActivationController.ActivatableDevice,
ClientConfigurableDevice, ClientConfigurableDevice,
@ -132,24 +134,24 @@ class InserterBlockEntity: DeviceBlockEntity(PhyBlockEntities.INSERTER),
currentRequest = null currentRequest = null
} }
override fun toCommonTag(tag: CompoundTag) { override fun toCommonTag(tag: NbtCompound) {
super.toCommonTag(tag) super.toCommonTag(tag)
writeDeviceConfiguration(tag) writeDeviceConfiguration(tag)
tag.put("StackToExtract", stackToExtract.toTag(CompoundTag())) tag.put("StackToExtract", stackToExtract.writeNbt(NbtCompound()))
} }
override fun fromCommonTag(tag: CompoundTag) { override fun fromCommonTag(tag: NbtCompound) {
super.fromCommonTag(tag) super.fromCommonTag(tag)
loadDeviceConfiguration(tag) loadDeviceConfiguration(tag)
stackToExtract = ItemStack.fromTag(tag.getCompound("StackToExtract")) stackToExtract = ItemStack.fromNbt(tag.getCompound("StackToExtract"))
} }
override fun writeDeviceConfiguration(tag: CompoundTag) { override fun writeDeviceConfiguration(tag: NbtCompound) {
tag.putString("ActivationMode", controller.activationMode.name) tag.putString("ActivationMode", controller.activationMode.name)
tag.putInt("AmountToExtract", amountToExtract) tag.putInt("AmountToExtract", amountToExtract)
} }
override fun loadDeviceConfiguration(tag: CompoundTag) { override fun loadDeviceConfiguration(tag: NbtCompound) {
controller.activationMode = ActivationMode.valueOf(tag.getString("ActivationMode")) controller.activationMode = ActivationMode.valueOf(tag.getString("ActivationMode"))
amountToExtract = tag.getInt("AmountToExtract") amountToExtract = tag.getInt("AmountToExtract")
} }

View File

@ -3,6 +3,7 @@ package net.shadowfacts.phycon.block.inserter
import com.mojang.blaze3d.systems.RenderSystem import com.mojang.blaze3d.systems.RenderSystem
import net.minecraft.client.gui.screen.ingame.HandledScreen import net.minecraft.client.gui.screen.ingame.HandledScreen
import net.minecraft.client.gui.widget.TextFieldWidget import net.minecraft.client.gui.widget.TextFieldWidget
import net.minecraft.client.render.GameRenderer
import net.minecraft.client.util.math.MatrixStack import net.minecraft.client.util.math.MatrixStack
import net.minecraft.entity.player.PlayerInventory import net.minecraft.entity.player.PlayerInventory
import net.minecraft.screen.slot.Slot import net.minecraft.screen.slot.Slot
@ -44,9 +45,9 @@ class InserterScreen(
amountField = TextFieldWidget(textRenderer, x + 57, y + 24, 80, 9, LiteralText("Amount")) amountField = TextFieldWidget(textRenderer, x + 57, y + 24, 80, 9, LiteralText("Amount"))
amountField.text = handler.inserter.amountToExtract.toString() amountField.text = handler.inserter.amountToExtract.toString()
amountField.setHasBorder(false) amountField.setDrawsBackground(false)
amountField.isVisible = true amountField.isVisible = true
amountField.setSelected(true) amountField.setTextFieldFocused(true)
amountField.setEditableColor(0xffffff) amountField.setEditableColor(0xffffff)
amountField.setTextPredicate { amountField.setTextPredicate {
if (it.isEmpty()) { if (it.isEmpty()) {
@ -60,7 +61,7 @@ class InserterScreen(
} }
} }
} }
addChild(amountField) addDrawableChild(amountField)
} }
fun amountUpdated() { fun amountUpdated() {
@ -70,16 +71,16 @@ class InserterScreen(
} }
} }
override fun tick() { override fun handledScreenTick() {
super.tick() super.handledScreenTick()
amountField.tick() amountField.tick()
} }
override fun drawBackground(matrixStack: MatrixStack, delta: Float, mouseX: Int, mouseY: Int) { override fun drawBackground(matrixStack: MatrixStack, delta: Float, mouseX: Int, mouseY: Int) {
renderBackground(matrixStack) renderBackground(matrixStack)
RenderSystem.color4f(1f, 1f, 1f, 1f) RenderSystem.setShader(GameRenderer::getPositionTexShader)
client!!.textureManager.bindTexture(BACKGROUND) RenderSystem.setShaderTexture(0, BACKGROUND)
val x = (width - backgroundWidth) / 2 val x = (width - backgroundWidth) / 2
val y = (height - backgroundHeight) / 2 val y = (height - backgroundHeight) / 2
drawTexture(matrixStack, x, y, 0, 0, backgroundWidth, backgroundHeight) drawTexture(matrixStack, x, y, 0, 0, backgroundWidth, backgroundHeight)
@ -96,7 +97,7 @@ class InserterScreen(
override fun onMouseClick(slot: Slot?, invSlot: Int, clickData: Int, slotActionType: SlotActionType?) { override fun onMouseClick(slot: Slot?, invSlot: Int, clickData: Int, slotActionType: SlotActionType?) {
super.onMouseClick(slot, invSlot, clickData, slotActionType) super.onMouseClick(slot, invSlot, clickData, slotActionType)
amountField.setSelected(true) amountField.setTextFieldFocused(true)
} }
override fun charTyped(c: Char, i: Int): Boolean { override fun charTyped(c: Char, i: Int): Boolean {

View File

@ -60,17 +60,17 @@ class InserterScreenHandler(
return true return true
} }
override fun onSlotClick(slotId: Int, clickData: Int, actionType: SlotActionType, player: PlayerEntity): ItemStack { override fun onSlotClick(slotId: Int, clickData: Int, actionType: SlotActionType, player: PlayerEntity) {
// fake slot // fake slot
if (slotId == 0) { if (slotId == 0) {
if (player.inventory.cursorStack.isEmpty) { if (cursorStack.isEmpty) {
inserter.stackToExtract = ItemStack.EMPTY inserter.stackToExtract = ItemStack.EMPTY
} else { } else {
inserter.stackToExtract = player.inventory.cursorStack.copyWithCount(1) inserter.stackToExtract = cursorStack.copyWithCount(1)
} }
stackToExtractChanged() stackToExtractChanged()
} }
return super.onSlotClick(slotId, clickData, actionType, player) super.onSlotClick(slotId, clickData, actionType, player)
} }
override fun transferSlot(player: PlayerEntity, slotId: Int): ItemStack { override fun transferSlot(player: PlayerEntity, slotId: Int): ItemStack {

View File

@ -51,7 +51,7 @@ class MinerBlock: DeviceBlock<MinerBlockEntity>(
builder.add(FACING) builder.add(FACING)
} }
override fun createBlockEntity(world: BlockView) = MinerBlockEntity() override fun createBlockEntity(pos: BlockPos, state: BlockState) = MinerBlockEntity(pos, state)
override fun getPlacementState(context: ItemPlacementContext): BlockState? { override fun getPlacementState(context: ItemPlacementContext): BlockState? {
val facing = if (context.player?.isSneaking == true) context.side.opposite else context.playerFacing.opposite val facing = if (context.player?.isSneaking == true) context.side.opposite else context.playerFacing.opposite

View File

@ -7,7 +7,7 @@ import net.minecraft.block.Block
import net.minecraft.block.BlockState import net.minecraft.block.BlockState
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
import net.minecraft.item.Items import net.minecraft.item.Items
import net.minecraft.nbt.CompoundTag import net.minecraft.nbt.NbtCompound
import net.minecraft.server.world.ServerWorld import net.minecraft.server.world.ServerWorld
import net.minecraft.text.TranslatableText import net.minecraft.text.TranslatableText
import net.minecraft.util.math.BlockPos import net.minecraft.util.math.BlockPos
@ -27,7 +27,7 @@ import kotlin.math.min
/** /**
* @author shadowfacts * @author shadowfacts
*/ */
class MinerBlockEntity: DeviceBlockEntity(PhyBlockEntities.MINER), class MinerBlockEntity(pos: BlockPos, state: BlockState): DeviceBlockEntity(PhyBlockEntities.MINER, pos, state),
NetworkStackProvider, NetworkStackProvider,
NetworkStackDispatcher<MinerBlockEntity.PendingInsertion>, NetworkStackDispatcher<MinerBlockEntity.PendingInsertion>,
ActivationController.ActivatableDevice, ActivationController.ActivatableDevice,
@ -156,23 +156,23 @@ class MinerBlockEntity: DeviceBlockEntity(PhyBlockEntities.MINER),
return minerMode == MinerMode.ON_DEMAND return minerMode == MinerMode.ON_DEMAND
} }
override fun toCommonTag(tag: CompoundTag) { override fun toCommonTag(tag: NbtCompound) {
super.toCommonTag(tag) super.toCommonTag(tag)
writeDeviceConfiguration(tag) writeDeviceConfiguration(tag)
} }
override fun fromCommonTag(tag: CompoundTag) { override fun fromCommonTag(tag: NbtCompound) {
super.fromCommonTag(tag) super.fromCommonTag(tag)
loadDeviceConfiguration(tag) loadDeviceConfiguration(tag)
} }
override fun writeDeviceConfiguration(tag: CompoundTag) { override fun writeDeviceConfiguration(tag: NbtCompound) {
tag.putString("MinerMode", minerMode.name) tag.putString("MinerMode", minerMode.name)
tag.putString("ActivationMode", controller.activationMode.name) tag.putString("ActivationMode", controller.activationMode.name)
tag.putInt("ProviderPriority", providerPriority) tag.putInt("ProviderPriority", providerPriority)
} }
override fun loadDeviceConfiguration(tag: CompoundTag) { override fun loadDeviceConfiguration(tag: NbtCompound) {
minerMode = MinerMode.valueOf(tag.getString("MinerMode")) minerMode = MinerMode.valueOf(tag.getString("MinerMode"))
controller.activationMode = ActivationMode.valueOf(tag.getString("ActivationMode")) controller.activationMode = ActivationMode.valueOf(tag.getString("ActivationMode"))
providerPriority = tag.getInt("ProviderPriority") providerPriority = tag.getInt("ProviderPriority")
@ -181,7 +181,7 @@ class MinerBlockEntity: DeviceBlockEntity(PhyBlockEntities.MINER),
enum class MinerMode { enum class MinerMode {
ON_DEMAND, AUTOMATIC; ON_DEMAND, AUTOMATIC;
val friendlyName = TranslatableText("gui.phycon.miner_mode.${name.toLowerCase()}") val friendlyName = TranslatableText("gui.phycon.miner_mode.${name.lowercase()}")
} }
class MinerInvProxy(val miner: MinerBlockEntity): GroupedItemInvView { class MinerInvProxy(val miner: MinerBlockEntity): GroupedItemInvView {
@ -205,7 +205,8 @@ class MinerBlockEntity: DeviceBlockEntity(PhyBlockEntities.MINER),
// todo: does BlockState.equals actually work or is reference equality fine for BlockStates? // todo: does BlockState.equals actually work or is reference equality fine for BlockStates?
if (cachedDrops == null || realState != cachedState || recalculate) { if (cachedDrops == null || realState != cachedState || recalculate) {
cachedState = realState cachedState = realState
val be = if (realState.block.hasBlockEntity()) world.getBlockEntity(targetPos) else null
val be = if (realState.hasBlockEntity()) world.getBlockEntity(targetPos) else null
cachedDrops = Block.getDroppedStacks(realState, world as ServerWorld, targetPos, be, null, TOOL) cachedDrops = Block.getDroppedStacks(realState, world as ServerWorld, targetPos, be, null, TOOL)
} }
return cachedDrops!! return cachedDrops!!

View File

@ -40,7 +40,7 @@ class InterfaceBlock: FaceDeviceBlock<InterfaceBlockEntity>(
Direction.EAST to createCuboidShape(14.0, 2.0, 2.0, 16.0, 14.0, 14.0) Direction.EAST to createCuboidShape(14.0, 2.0, 2.0, 16.0, 14.0, 14.0)
) )
override fun createBlockEntity(world: BlockView) = InterfaceBlockEntity() override fun createBlockEntity(pos: BlockPos, state: BlockState) = InterfaceBlockEntity(pos, state)
override fun onPlaced(world: World, pos: BlockPos, state: BlockState, placer: LivingEntity?, stack: ItemStack) { override fun onPlaced(world: World, pos: BlockPos, state: BlockState, placer: LivingEntity?, stack: ItemStack) {
if (!world.isClient) { if (!world.isClient) {

View File

@ -6,7 +6,8 @@ import alexiil.mc.lib.attributes.item.GroupedItemInv
import alexiil.mc.lib.attributes.item.ItemAttributes import alexiil.mc.lib.attributes.item.ItemAttributes
import net.minecraft.block.BlockState import net.minecraft.block.BlockState
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
import net.minecraft.nbt.CompoundTag import net.minecraft.nbt.NbtCompound
import net.minecraft.util.math.BlockPos
import net.minecraft.util.math.Direction import net.minecraft.util.math.Direction
import net.shadowfacts.phycon.api.packet.Packet import net.shadowfacts.phycon.api.packet.Packet
import net.shadowfacts.phycon.init.PhyBlockEntities import net.shadowfacts.phycon.init.PhyBlockEntities
@ -23,7 +24,7 @@ import kotlin.math.min
/** /**
* @author shadowfacts * @author shadowfacts
*/ */
class InterfaceBlockEntity: DeviceBlockEntity(PhyBlockEntities.INTERFACE), class InterfaceBlockEntity(pos: BlockPos, state: BlockState): DeviceBlockEntity(PhyBlockEntities.INTERFACE, pos, state),
ItemStackPacketHandler, ItemStackPacketHandler,
NetworkStackProvider, NetworkStackProvider,
NetworkStackReceiver, NetworkStackReceiver,
@ -109,23 +110,23 @@ class InterfaceBlockEntity: DeviceBlockEntity(PhyBlockEntities.INTERFACE),
} }
} }
override fun toCommonTag(tag: CompoundTag) { override fun toCommonTag(tag: NbtCompound) {
super.toCommonTag(tag) super.toCommonTag(tag)
writeDeviceConfiguration(tag) writeDeviceConfiguration(tag)
} }
override fun fromCommonTag(tag: CompoundTag) { override fun fromCommonTag(tag: NbtCompound) {
super.fromCommonTag(tag) super.fromCommonTag(tag)
loadDeviceConfiguration(tag) loadDeviceConfiguration(tag)
} }
override fun writeDeviceConfiguration(tag: CompoundTag) { override fun writeDeviceConfiguration(tag: NbtCompound) {
tag.putInt("ProviderPriority", providerPriority) tag.putInt("ProviderPriority", providerPriority)
tag.putInt("ReceiverPriority", receiverPriority) tag.putInt("ReceiverPriority", receiverPriority)
tag.putBoolean("SyncPriorities", syncPriorities) tag.putBoolean("SyncPriorities", syncPriorities)
} }
override fun loadDeviceConfiguration(tag: CompoundTag) { override fun loadDeviceConfiguration(tag: NbtCompound) {
providerPriority = tag.getInt("ProviderPriority") providerPriority = tag.getInt("ProviderPriority")
receiverPriority = tag.getInt("ReceiverPriority") receiverPriority = tag.getInt("ReceiverPriority")
syncPriorities = tag.getBoolean("SyncPriorities") syncPriorities = tag.getBoolean("SyncPriorities")

View File

@ -4,6 +4,9 @@ import alexiil.mc.lib.attributes.AttributeList
import alexiil.mc.lib.attributes.AttributeProvider import alexiil.mc.lib.attributes.AttributeProvider
import net.minecraft.block.BlockState import net.minecraft.block.BlockState
import net.minecraft.block.Material import net.minecraft.block.Material
import net.minecraft.block.entity.BlockEntity
import net.minecraft.block.entity.BlockEntityTicker
import net.minecraft.block.entity.BlockEntityType
import net.minecraft.sound.BlockSoundGroup import net.minecraft.sound.BlockSoundGroup
import net.minecraft.util.Identifier import net.minecraft.util.Identifier
import net.minecraft.util.math.BlockPos import net.minecraft.util.math.BlockPos
@ -40,7 +43,17 @@ class SwitchBlock: BlockWithEntity<SwitchBlockEntity>(
return getBlockEntity(world, pos)?.interfaces?.find { it.side == side } return getBlockEntity(world, pos)?.interfaces?.find { it.side == side }
} }
override fun createBlockEntity(world: BlockView) = SwitchBlockEntity() override fun createBlockEntity(pos: BlockPos, state: BlockState) = SwitchBlockEntity(pos, state)
override fun <T: BlockEntity> getTicker(world: World, state: BlockState, type: BlockEntityType<T>): BlockEntityTicker<T>? {
return if (world.isClient) {
null
} else {
BlockEntityTicker { world, blockPos, blockState, blockEntity ->
(blockEntity as SwitchBlockEntity).tick()
}
}
}
override fun addAllAttributes(world: World, pos: BlockPos, state: BlockState, to: AttributeList<*>) { override fun addAllAttributes(world: World, pos: BlockPos, state: BlockState, to: AttributeList<*>) {
to.offer(getBlockEntity(world, pos)) to.offer(getBlockEntity(world, pos))

View File

@ -1,12 +1,14 @@
package net.shadowfacts.phycon.block.netswitch package net.shadowfacts.phycon.block.netswitch
import net.fabricmc.fabric.api.block.entity.BlockEntityClientSerializable
import net.minecraft.block.BlockState import net.minecraft.block.BlockState
import net.minecraft.block.entity.BlockEntity import net.minecraft.block.entity.BlockEntity
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
import net.minecraft.nbt.CompoundTag import net.minecraft.nbt.NbtCompound
import net.minecraft.nbt.ListTag import net.minecraft.nbt.NbtList
import net.minecraft.util.Tickable import net.minecraft.network.Packet
import net.minecraft.network.listener.ClientPlayPacketListener
import net.minecraft.network.packet.s2c.play.BlockEntityUpdateS2CPacket
import net.minecraft.util.math.BlockPos
import net.minecraft.util.math.Direction import net.minecraft.util.math.Direction
import net.shadowfacts.phycon.PhysicalConnectivity import net.shadowfacts.phycon.PhysicalConnectivity
import net.shadowfacts.phycon.api.Interface import net.shadowfacts.phycon.api.Interface
@ -25,9 +27,7 @@ import java.util.LinkedList
/** /**
* @author shadowfacts * @author shadowfacts
*/ */
class SwitchBlockEntity: BlockEntity(PhyBlockEntities.SWITCH), class SwitchBlockEntity(pos: BlockPos, state: BlockState): BlockEntity(PhyBlockEntities.SWITCH, pos, state) {
BlockEntityClientSerializable,
Tickable {
companion object { companion object {
var SWITCHING_CAPACITY = 256 // 256 packets/tick var SWITCHING_CAPACITY = 256 // 256 packets/tick
@ -82,7 +82,7 @@ class SwitchBlockEntity: BlockEntity(PhyBlockEntities.SWITCH),
return NetworkUtil.findConnectedInterface(world!!, pos, side) return NetworkUtil.findConnectedInterface(world!!, pos, side)
} }
override fun tick() { fun tick() {
packetsHandledThisTick = 0 packetsHandledThisTick = 0
while (delayedPackets.isNotEmpty() && packetsHandledThisTick <= SWITCHING_CAPACITY) { while (delayedPackets.isNotEmpty() && packetsHandledThisTick <= SWITCHING_CAPACITY) {
@ -91,39 +91,41 @@ class SwitchBlockEntity: BlockEntity(PhyBlockEntities.SWITCH),
} }
} }
override fun toTag(tag: CompoundTag): CompoundTag { override fun writeNbt(tag: NbtCompound) {
super.writeNbt(tag)
tag.putLongArray("InterfaceAddresses", interfaces.map { it.macAddress.address }) tag.putLongArray("InterfaceAddresses", interfaces.map { it.macAddress.address })
val list = ListTag() val list = NbtList()
for ((frame, fromItf) in delayedPackets) { for ((frame, fromItf) in delayedPackets) {
val packet = frame.packet val packet = frame.packet
if (packet !is ItemStackPacket) continue if (packet !is ItemStackPacket) continue
val compound = CompoundTag() val compound = NbtCompound()
compound.putInt("FromItfSide", fromItf.side.ordinal) compound.putInt("FromItfSide", fromItf.side.ordinal)
compound.putInt("SourceIP", packet.source.address) compound.putInt("SourceIP", packet.source.address)
compound.putInt("DestinationIP", packet.destination.address) compound.putInt("DestinationIP", packet.destination.address)
compound.putLong("SourceMAC", frame.source.address) compound.putLong("SourceMAC", frame.source.address)
compound.putLong("DestinationMAC", frame.destination.address) compound.putLong("DestinationMAC", frame.destination.address)
compound.put("Stack", packet.stack.toTag(CompoundTag())) compound.put("Stack", packet.stack.writeNbt(NbtCompound()))
list.add(compound) list.add(compound)
} }
tag.put("DelayedStackPackets", list) tag.put("DelayedStackPackets", list)
return super.toTag(tag)
} }
override fun fromTag(state: BlockState, tag: CompoundTag) { override fun readNbt(tag: NbtCompound) {
super.fromTag(state, tag) super.readNbt(tag)
tag.getLongArray("InterfaceAddresses")?.forEachIndexed { i, l -> tag.getLongArray("InterfaceAddresses")?.forEachIndexed { i, l ->
interfaces[i].macAddress = MACAddress(l) interfaces[i].macAddress = MACAddress(l)
} }
tag.getList("DelayedStackPackets", 10).forEach { it -> tag.getList("DelayedStackPackets", 10).forEach { it ->
val compound = it as CompoundTag val compound = it as NbtCompound
val fromItfSide = Direction.values()[compound.getInt("FromItfSide")] val fromItfSide = Direction.values()[compound.getInt("FromItfSide")]
val fromItf = interfaces.find { it.side == fromItfSide }!! val fromItf = interfaces.find { it.side == fromItfSide }!!
val sourceIP = IPAddress(compound.getInt("SourceIP")) val sourceIP = IPAddress(compound.getInt("SourceIP"))
val destinationIP = IPAddress(compound.getInt("DestinationIP")) val destinationIP = IPAddress(compound.getInt("DestinationIP"))
val sourceMAC = MACAddress(compound.getLong("SourceMAC")) val sourceMAC = MACAddress(compound.getLong("SourceMAC"))
val destinationMAC = MACAddress(compound.getLong("DestinationMAC")) val destinationMAC = MACAddress(compound.getLong("DestinationMAC"))
val stack = ItemStack.fromTag(compound.getCompound("Stack")) val stack = ItemStack.fromNbt(compound.getCompound("Stack"))
if (!stack.isEmpty) { if (!stack.isEmpty) {
val packet = ItemStackPacket(stack, sourceIP, destinationIP) val packet = ItemStackPacket(stack, sourceIP, destinationIP)
val frame = BasePacketFrame(packet, sourceMAC, destinationMAC) val frame = BasePacketFrame(packet, sourceMAC, destinationMAC)
@ -132,15 +134,14 @@ class SwitchBlockEntity: BlockEntity(PhyBlockEntities.SWITCH),
} }
} }
override fun toClientTag(tag: CompoundTag): CompoundTag { override fun toUpdatePacket(): Packet<ClientPlayPacketListener>? {
tag.putLongArray("InterfaceAddresses", interfaces.map { it.macAddress.address }) return BlockEntityUpdateS2CPacket.create(this)
return tag
} }
override fun fromClientTag(tag: CompoundTag) { override fun toInitialChunkDataNbt(): NbtCompound {
tag.getLongArray("InterfaceAddresses")?.forEachIndexed { i, l -> val tag = NbtCompound()
interfaces[i].macAddress = MACAddress(l) tag.putLongArray("InterfaceAddresses", interfaces.map { it.macAddress.address })
} return tag
} }
class SwitchInterface( class SwitchInterface(

View File

@ -44,7 +44,7 @@ class RedstoneControllerBlock: FaceDeviceBlock<RedstoneControllerBlockEntity>(
builder.add(POWERED) builder.add(POWERED)
} }
override fun createBlockEntity(world: BlockView) = RedstoneControllerBlockEntity() override fun createBlockEntity(pos: BlockPos, state: BlockState) = RedstoneControllerBlockEntity(pos, state)
override fun getPlacementState(context: ItemPlacementContext): BlockState { override fun getPlacementState(context: ItemPlacementContext): BlockState {
val state = super.getPlacementState(context) val state = super.getPlacementState(context)

View File

@ -1,6 +1,8 @@
package net.shadowfacts.phycon.block.redstone_controller package net.shadowfacts.phycon.block.redstone_controller
import net.minecraft.nbt.CompoundTag import net.minecraft.block.BlockState
import net.minecraft.nbt.NbtCompound
import net.minecraft.util.math.BlockPos
import net.shadowfacts.phycon.api.packet.Packet import net.shadowfacts.phycon.api.packet.Packet
import net.shadowfacts.phycon.api.util.IPAddress import net.shadowfacts.phycon.api.util.IPAddress
import net.shadowfacts.phycon.init.PhyBlockEntities import net.shadowfacts.phycon.init.PhyBlockEntities
@ -12,7 +14,7 @@ import net.shadowfacts.phycon.util.RedstoneMode
/** /**
* @author shadowfacts * @author shadowfacts
*/ */
class RedstoneControllerBlockEntity: DeviceBlockEntity(PhyBlockEntities.REDSTONE_CONTROLLER), class RedstoneControllerBlockEntity(pos: BlockPos, state: BlockState): DeviceBlockEntity(PhyBlockEntities.REDSTONE_CONTROLLER, pos, state),
ClientConfigurableDevice { ClientConfigurableDevice {
var managedDevices = Array<IPAddress?>(5) { null } var managedDevices = Array<IPAddress?>(5) { null }
@ -53,22 +55,22 @@ class RedstoneControllerBlockEntity: DeviceBlockEntity(PhyBlockEntities.REDSTONE
} }
} }
override fun toCommonTag(tag: CompoundTag) { override fun toCommonTag(tag: NbtCompound) {
super.toCommonTag(tag) super.toCommonTag(tag)
writeDeviceConfiguration(tag) writeDeviceConfiguration(tag)
} }
override fun fromCommonTag(tag: CompoundTag) { override fun fromCommonTag(tag: NbtCompound) {
super.fromCommonTag(tag) super.fromCommonTag(tag)
loadDeviceConfiguration(tag) loadDeviceConfiguration(tag)
} }
override fun writeDeviceConfiguration(tag: CompoundTag) { override fun writeDeviceConfiguration(tag: NbtCompound) {
tag.putIntArray("ManagedDevices", managedDevices.mapNotNull { it?.address }) tag.putIntArray("ManagedDevices", managedDevices.mapNotNull { it?.address })
tag.putString("RedstoneMode", redstoneMode.name) tag.putString("RedstoneMode", redstoneMode.name)
} }
override fun loadDeviceConfiguration(tag: CompoundTag) { override fun loadDeviceConfiguration(tag: NbtCompound) {
val addresses = tag.getIntArray("ManagedDevices") val addresses = tag.getIntArray("ManagedDevices")
managedDevices = (0..4).map { if (it >= addresses.size) null else IPAddress(addresses[it]) }.toTypedArray() managedDevices = (0..4).map { if (it >= addresses.size) null else IPAddress(addresses[it]) }.toTypedArray()
redstoneMode = RedstoneMode.valueOf(tag.getString("RedstoneMode")) redstoneMode = RedstoneMode.valueOf(tag.getString("RedstoneMode"))

View File

@ -45,7 +45,7 @@ class RedstoneEmitterBlock: FaceDeviceBlock<RedstoneEmitterBlockEntity>(
Direction.EAST to createCuboidShape(13.0, 0.0, 0.0, 16.0, 16.0, 16.0) Direction.EAST to createCuboidShape(13.0, 0.0, 0.0, 16.0, 16.0, 16.0)
) )
override fun createBlockEntity(world: BlockView) = RedstoneEmitterBlockEntity() override fun createBlockEntity(pos: BlockPos, state: BlockState) = RedstoneEmitterBlockEntity(pos, state)
override fun emitsRedstonePower(state: BlockState): Boolean { override fun emitsRedstonePower(state: BlockState): Boolean {
return true return true
@ -67,7 +67,7 @@ class RedstoneEmitterBlock: FaceDeviceBlock<RedstoneEmitterBlockEntity>(
if (!world.isClient) { if (!world.isClient) {
val be = getBlockEntity(world, pos)!! val be = getBlockEntity(world, pos)!!
be.sync() be.markUpdate()
val factory = object: ExtendedScreenHandlerFactory { val factory = object: ExtendedScreenHandlerFactory {
override fun createMenu(syncId: Int, playerInv: PlayerInventory, player: PlayerEntity): ScreenHandler { override fun createMenu(syncId: Int, playerInv: PlayerInventory, player: PlayerEntity): ScreenHandler {

View File

@ -1,9 +1,11 @@
package net.shadowfacts.phycon.block.redstone_emitter package net.shadowfacts.phycon.block.redstone_emitter
import alexiil.mc.lib.attributes.item.GroupedItemInvView import alexiil.mc.lib.attributes.item.GroupedItemInvView
import net.minecraft.block.BlockState
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
import net.minecraft.nbt.CompoundTag import net.minecraft.nbt.NbtCompound
import net.minecraft.text.TranslatableText import net.minecraft.text.TranslatableText
import net.minecraft.util.math.BlockPos
import net.shadowfacts.phycon.api.packet.Packet import net.shadowfacts.phycon.api.packet.Packet
import net.shadowfacts.phycon.api.util.IPAddress import net.shadowfacts.phycon.api.util.IPAddress
import net.shadowfacts.phycon.block.DeviceBlockEntity import net.shadowfacts.phycon.block.DeviceBlockEntity
@ -19,7 +21,7 @@ import kotlin.math.round
/** /**
* @author shadowfacts * @author shadowfacts
*/ */
class RedstoneEmitterBlockEntity: DeviceBlockEntity(PhyBlockEntities.REDSTONE_EMITTER), class RedstoneEmitterBlockEntity(pos: BlockPos, state: BlockState): DeviceBlockEntity(PhyBlockEntities.REDSTONE_EMITTER, pos, state),
ClientConfigurableDevice, ClientConfigurableDevice,
GhostInv { GhostInv {
@ -100,26 +102,26 @@ class RedstoneEmitterBlockEntity: DeviceBlockEntity(PhyBlockEntities.REDSTONE_EM
world!!.updateNeighborsAlways(pos.offset(cachedState[FaceDeviceBlock.FACING]), cachedState.block) world!!.updateNeighborsAlways(pos.offset(cachedState[FaceDeviceBlock.FACING]), cachedState.block)
} }
override fun toCommonTag(tag: CompoundTag) { override fun toCommonTag(tag: NbtCompound) {
super.toCommonTag(tag) super.toCommonTag(tag)
tag.putInt("CachedEmittedPower", cachedEmittedPower) tag.putInt("CachedEmittedPower", cachedEmittedPower)
tag.put("StackToMonitor", stackToMonitor.toTag(CompoundTag())) tag.put("StackToMonitor", stackToMonitor.writeNbt(NbtCompound()))
writeDeviceConfiguration(tag) writeDeviceConfiguration(tag)
} }
override fun fromCommonTag(tag: CompoundTag) { override fun fromCommonTag(tag: NbtCompound) {
super.fromCommonTag(tag) super.fromCommonTag(tag)
cachedEmittedPower = tag.getInt("CachedEmittedPower") cachedEmittedPower = tag.getInt("CachedEmittedPower")
stackToMonitor = ItemStack.fromTag(tag.getCompound("StackToMonitor")) stackToMonitor = ItemStack.fromNbt(tag.getCompound("StackToMonitor"))
loadDeviceConfiguration(tag) loadDeviceConfiguration(tag)
} }
override fun writeDeviceConfiguration(tag: CompoundTag) { override fun writeDeviceConfiguration(tag: NbtCompound) {
tag.putInt("MaxAmount", maxAmount) tag.putInt("MaxAmount", maxAmount)
tag.putString("Mode", mode.name) tag.putString("Mode", mode.name)
} }
override fun loadDeviceConfiguration(tag: CompoundTag) { override fun loadDeviceConfiguration(tag: NbtCompound) {
maxAmount = tag.getInt("MaxAmount") maxAmount = tag.getInt("MaxAmount")
mode = Mode.valueOf(tag.getString("Mode")) mode = Mode.valueOf(tag.getString("Mode"))
} }
@ -127,7 +129,7 @@ class RedstoneEmitterBlockEntity: DeviceBlockEntity(PhyBlockEntities.REDSTONE_EM
enum class Mode { enum class Mode {
ANALOG, DIGITAL; ANALOG, DIGITAL;
val friendlyName = TranslatableText("gui.phycon.redstone_emitter_mode.${name.toLowerCase()}") val friendlyName = TranslatableText("gui.phycon.redstone_emitter_mode.${name.lowercase()}")
} }
} }

View File

@ -2,6 +2,7 @@ package net.shadowfacts.phycon.block.redstone_emitter
import com.mojang.blaze3d.systems.RenderSystem import com.mojang.blaze3d.systems.RenderSystem
import net.minecraft.client.MinecraftClient import net.minecraft.client.MinecraftClient
import net.minecraft.client.render.GameRenderer
import net.minecraft.client.util.math.MatrixStack import net.minecraft.client.util.math.MatrixStack
import net.minecraft.entity.player.PlayerInventory import net.minecraft.entity.player.PlayerInventory
import net.minecraft.text.Text import net.minecraft.text.Text
@ -49,8 +50,8 @@ class RedstoneEmitterScreen(
override fun drawBackground(matrixStack: MatrixStack, delta: Float, mouseX: Int, mouseY: Int) { override fun drawBackground(matrixStack: MatrixStack, delta: Float, mouseX: Int, mouseY: Int) {
super.drawBackground(matrixStack, delta, mouseX, mouseY) super.drawBackground(matrixStack, delta, mouseX, mouseY)
RenderSystem.color4f(1f, 1f, 1f, 1f) RenderSystem.setShader(GameRenderer::getPositionTexShader)
client!!.textureManager.bindTexture(BACKGROUND) RenderSystem.setShaderTexture(0, BACKGROUND)
val x = (width - backgroundWidth) / 2 val x = (width - backgroundWidth) / 2
val y = (height - backgroundHeight) / 2 val y = (height - backgroundHeight) / 2
drawTexture(matrixStack, x, y, 0, 0, backgroundWidth, backgroundHeight) drawTexture(matrixStack, x, y, 0, 0, backgroundWidth, backgroundHeight)

View File

@ -55,16 +55,16 @@ class RedstoneEmitterScreenHandler(
return true return true
} }
override fun onSlotClick(slotId: Int, clickData: Int, slotActionType: SlotActionType, player: PlayerEntity): ItemStack { override fun onSlotClick(slotId: Int, clickData: Int, slotActionType: SlotActionType, player: PlayerEntity) {
// fake slot // fake slot
if (slotId == 0) { if (slotId == 0) {
if (player.inventory.cursorStack.isEmpty) { if (cursorStack.isEmpty) {
emitter.stackToMonitor = ItemStack.EMPTY emitter.stackToMonitor = ItemStack.EMPTY
} else { } else {
emitter.stackToMonitor = player.inventory.cursorStack.copyWithCount(1) emitter.stackToMonitor = cursorStack.copyWithCount(1)
} }
} }
return super.onSlotClick(slotId, clickData, slotActionType, player) super.onSlotClick(slotId, clickData, slotActionType, player)
} }
override fun transferSlot(player: PlayerEntity, slotId: Int): ItemStack { override fun transferSlot(player: PlayerEntity, slotId: Int): ItemStack {

View File

@ -3,42 +3,34 @@ package net.shadowfacts.phycon.block.terminal
import alexiil.mc.lib.attributes.item.GroupedItemInvView import alexiil.mc.lib.attributes.item.GroupedItemInvView
import alexiil.mc.lib.attributes.item.ItemStackCollections import alexiil.mc.lib.attributes.item.ItemStackCollections
import alexiil.mc.lib.attributes.item.ItemStackUtil import alexiil.mc.lib.attributes.item.ItemStackUtil
import net.fabricmc.fabric.api.block.entity.BlockEntityClientSerializable import net.minecraft.block.BlockState
import net.fabricmc.fabric.api.screenhandler.v1.ExtendedScreenHandlerFactory
import net.minecraft.block.entity.BlockEntityType import net.minecraft.block.entity.BlockEntityType
import net.minecraft.entity.player.PlayerEntity import net.minecraft.entity.player.PlayerEntity
import net.minecraft.entity.player.PlayerInventory
import net.minecraft.inventory.Inventory import net.minecraft.inventory.Inventory
import net.minecraft.inventory.InventoryChangedListener import net.minecraft.inventory.InventoryChangedListener
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
import net.minecraft.nbt.CompoundTag import net.minecraft.nbt.NbtCompound
import net.minecraft.network.PacketByteBuf
import net.minecraft.screen.ScreenHandler
import net.minecraft.server.network.ServerPlayerEntity
import net.minecraft.text.TranslatableText
import net.minecraft.util.ItemScatterer import net.minecraft.util.ItemScatterer
import net.minecraft.util.Tickable import net.minecraft.util.math.BlockPos
import net.minecraft.util.math.Direction import net.minecraft.util.math.Direction
import net.shadowfacts.phycon.api.Interface import net.shadowfacts.phycon.api.Interface
import net.shadowfacts.phycon.api.packet.Packet import net.shadowfacts.phycon.api.packet.Packet
import net.shadowfacts.phycon.api.util.IPAddress import net.shadowfacts.phycon.api.util.IPAddress
import net.shadowfacts.phycon.init.PhyBlockEntities
import net.shadowfacts.phycon.block.DeviceBlockEntity import net.shadowfacts.phycon.block.DeviceBlockEntity
import net.shadowfacts.phycon.util.NetworkUtil
import net.shadowfacts.phycon.component.* import net.shadowfacts.phycon.component.*
import net.shadowfacts.phycon.packet.* import net.shadowfacts.phycon.packet.*
import net.shadowfacts.phycon.util.NetworkUtil
import java.lang.ref.WeakReference import java.lang.ref.WeakReference
import java.util.* import java.util.*
import java.util.function.IntBinaryOperator
import kotlin.math.min import kotlin.math.min
import kotlin.properties.Delegates import kotlin.properties.Delegates
/** /**
* @author shadowfacts * @author shadowfacts
*/ */
abstract class AbstractTerminalBlockEntity(type: BlockEntityType<*>): DeviceBlockEntity(type), abstract class AbstractTerminalBlockEntity(type: BlockEntityType<*>, pos: BlockPos, state: BlockState): DeviceBlockEntity(type, pos, state),
InventoryChangedListener, InventoryChangedListener,
BlockEntityClientSerializable,
Tickable,
ItemStackPacketHandler, ItemStackPacketHandler,
NetworkStackDispatcher<AbstractTerminalBlockEntity.PendingInsertion> { NetworkStackDispatcher<AbstractTerminalBlockEntity.PendingInsertion> {
@ -129,7 +121,7 @@ abstract class AbstractTerminalBlockEntity(type: BlockEntityType<*>): DeviceBloc
protected fun updateAndSync() { protected fun updateAndSync() {
updateNetItems() updateNetItems()
// syncs the internal buffer to the client // syncs the internal buffer to the client
sync() markUpdate()
// syncs the open container (if any) to the client // syncs the open container (if any) to the client
netItemObserver?.get()?.netItemsChanged() netItemObserver?.get()?.netItemsChanged()
} }
@ -139,7 +131,7 @@ abstract class AbstractTerminalBlockEntity(type: BlockEntityType<*>): DeviceBloc
for (inventory in inventoryCache.values) { for (inventory in inventoryCache.values) {
for (stack in inventory.storedStacks) { for (stack in inventory.storedStacks) {
val amount = inventory.getAmount(stack) val amount = inventory.getAmount(stack)
cachedNetItems.mergeInt(stack, amount) { a, b -> a + b } cachedNetItems.mergeInt(stack, amount, IntBinaryOperator { a, b -> a + b })
} }
} }
} }
@ -225,8 +217,7 @@ abstract class AbstractTerminalBlockEntity(type: BlockEntityType<*>): DeviceBloc
override fun onInventoryChanged(inv: Inventory) { override fun onInventoryChanged(inv: Inventory) {
if (inv == internalBuffer && world != null && !world!!.isClient) { if (inv == internalBuffer && world != null && !world!!.isClient) {
markDirty() markUpdate()
sync()
} }
} }
@ -234,12 +225,12 @@ abstract class AbstractTerminalBlockEntity(type: BlockEntityType<*>): DeviceBloc
ItemScatterer.spawn(world, pos, internalBuffer) ItemScatterer.spawn(world, pos, internalBuffer)
} }
override fun toCommonTag(tag: CompoundTag) { override fun toCommonTag(tag: NbtCompound) {
super.toCommonTag(tag) super.toCommonTag(tag)
tag.put("InternalBuffer", internalBuffer.toTag()) tag.put("InternalBuffer", internalBuffer.toTag())
} }
override fun fromCommonTag(tag: CompoundTag) { override fun fromCommonTag(tag: NbtCompound) {
super.fromCommonTag(tag) super.fromCommonTag(tag)
internalBuffer.fromTag(tag.getCompound("InternalBuffer")) internalBuffer.fromTag(tag.getCompound("InternalBuffer"))
} }

View File

@ -5,6 +5,7 @@ import net.minecraft.client.MinecraftClient
import net.minecraft.client.gui.DrawableHelper import net.minecraft.client.gui.DrawableHelper
import net.minecraft.client.gui.Element import net.minecraft.client.gui.Element
import net.minecraft.client.gui.widget.TextFieldWidget import net.minecraft.client.gui.widget.TextFieldWidget
import net.minecraft.client.render.GameRenderer
import net.minecraft.client.render.Tessellator import net.minecraft.client.render.Tessellator
import net.minecraft.client.render.VertexConsumerProvider import net.minecraft.client.render.VertexConsumerProvider
import net.minecraft.client.util.math.MatrixStack import net.minecraft.client.util.math.MatrixStack
@ -100,7 +101,7 @@ abstract class AbstractTerminalScreen<BE: AbstractTerminalBlockEntity, T: Abstra
private val DECIMAL_FORMAT = DecimalFormat("#.#").apply { roundingMode = RoundingMode.HALF_UP } private val DECIMAL_FORMAT = DecimalFormat("#.#").apply { roundingMode = RoundingMode.HALF_UP }
private val FORMAT = DecimalFormat("##").apply { roundingMode = RoundingMode.HALF_UP } private val FORMAT = DecimalFormat("##").apply { roundingMode = RoundingMode.HALF_UP }
fun drawNetworkSlotAmount(stack: ItemStack, x: Int, y: Int, slot: Slot, matrixStack: MatrixStack) { fun drawNetworkSlotAmount(stack: ItemStack, x: Int, y: Int) {
val amount = stack.count val amount = stack.count
val s = when { val s = when {
amount < 1_000 -> amount.toString() amount < 1_000 -> amount.toString()
@ -121,16 +122,17 @@ abstract class AbstractTerminalScreen<BE: AbstractTerminalBlockEntity, T: Abstra
// empty string for label because vanilla renders the count behind the damage bar // empty string for label because vanilla renders the count behind the damage bar
itemRenderer.renderGuiItemOverlay(textRenderer, stack, x, y, "") itemRenderer.renderGuiItemOverlay(textRenderer, stack, x, y, "")
matrixStack.push() // ItemRenderer.renderGuiItemOverlay creates a new MatrixStack specifically for drawing the overlay
val matrixStack = MatrixStack()
matrixStack.translate(x.toDouble(), y.toDouble(), itemRenderer.zOffset + 200.0) matrixStack.translate(x.toDouble(), y.toDouble(), itemRenderer.zOffset + 200.0)
val scale = 2 / 3f val scale = 2 / 3f
matrixStack.scale(scale, scale, 1.0f) matrixStack.scale(scale, scale, 1.0f)
val immediate = VertexConsumerProvider.immediate(Tessellator.getInstance().buffer) val immediate = VertexConsumerProvider.immediate(Tessellator.getInstance().buffer)
val textX = (1 / scale * 18) - textRenderer.getWidth(s).toFloat() - 3 val textX = (1 / scale * 18) - textRenderer.getWidth(s).toFloat() - 3
val textY = (1 / scale * 18) - 11 val textY = (1 / scale * 18) - 11
textRenderer.draw(s, textX, textY, 0xffffff, true, matrixStack.peek().model, immediate, false, 0, 0xF000F0) textRenderer.draw(s, textX, textY, 0xffffff, true, matrixStack.peek().positionMatrix, immediate, false, 0, 0xF000F0)
RenderSystem.enableDepthTest()
immediate.draw() immediate.draw()
matrixStack.pop()
} }
override fun drawBackground(matrixStack: MatrixStack, delta: Float, mouseX: Int, mouseY: Int) { override fun drawBackground(matrixStack: MatrixStack, delta: Float, mouseX: Int, mouseY: Int) {
@ -140,15 +142,16 @@ abstract class AbstractTerminalScreen<BE: AbstractTerminalBlockEntity, T: Abstra
} }
open fun drawBackgroundTexture(matrixStack: MatrixStack) { open fun drawBackgroundTexture(matrixStack: MatrixStack) {
RenderSystem.color4f(1f, 1f, 1f, 1f) RenderSystem.setShader(GameRenderer::getPositionTexColorShader)
client!!.textureManager.bindTexture(backgroundTexture) RenderSystem.setShaderTexture(0, backgroundTexture)
RenderSystem.setShaderColor(1f, 1f, 1f, 1f)
val x = (width - backgroundWidth) / 2 val x = (width - backgroundWidth) / 2
val y = (height - backgroundHeight) / 2 val y = (height - backgroundHeight) / 2
drawTexture(matrixStack, x, y, 0, 0, backgroundWidth, backgroundHeight) drawTexture(matrixStack, x, y, 0, 0, backgroundWidth, backgroundHeight)
} }
override fun tick() { override fun handledScreenTick() {
super.tick() super.handledScreenTick()
if (amountVC != null) { if (amountVC != null) {
amountVC!!.field.tick() amountVC!!.field.tick()
@ -171,7 +174,7 @@ abstract class AbstractTerminalScreen<BE: AbstractTerminalBlockEntity, T: Abstra
override fun onMouseClick(slot: Slot?, invSlot: Int, clickData: Int, type: SlotActionType?) { override fun onMouseClick(slot: Slot?, invSlot: Int, clickData: Int, type: SlotActionType?) {
super.onMouseClick(slot, invSlot, clickData, type) super.onMouseClick(slot, invSlot, clickData, type)
if (slot != null && !slot.stack.isEmpty && handler.isNetworkSlot(slot.id) && playerInventory.cursorStack.isEmpty) { if (slot != null && !slot.stack.isEmpty && handler.isNetworkSlot(slot.id) && handler.cursorStack.isEmpty) {
val stack = slot.stack val stack = slot.stack
if (type == SlotActionType.QUICK_MOVE) { if (type == SlotActionType.QUICK_MOVE) {

View File

@ -170,16 +170,16 @@ abstract class AbstractTerminalScreenHandler<T: AbstractTerminalBlockEntity>(
terminal.netItemObserver = null terminal.netItemObserver = null
} }
override fun onSlotClick(slotId: Int, clickData: Int, actionType: SlotActionType, player: PlayerEntity): ItemStack { override fun onSlotClick(slotId: Int, clickData: Int, actionType: SlotActionType, player: PlayerEntity) {
if (isBufferSlot(slotId)) { if (isBufferSlot(slotId)) {
// todo: why does this think it's quick_craft sometimes? // todo: why does this think it's quick_craft sometimes?
if ((actionType == SlotActionType.PICKUP || actionType == SlotActionType.QUICK_CRAFT) && !player.inventory.cursorStack.isEmpty) { if ((actionType == SlotActionType.PICKUP || actionType == SlotActionType.QUICK_CRAFT) && !cursorStack.isEmpty) {
// placing cursor stack into buffer // placing cursor stack into buffer
val bufferSlot = slotId - bufferSlotsStart // subtract 54 to convert the handler slot ID to a valid buffer index val bufferSlot = slotId - bufferSlotsStart // subtract 54 to convert the handler slot ID to a valid buffer index
terminal.internalBuffer.markSlot(bufferSlot, TerminalBufferInventory.Mode.TO_NETWORK) terminal.internalBuffer.markSlot(bufferSlot, TerminalBufferInventory.Mode.TO_NETWORK)
} }
} }
return super.onSlotClick(slotId, clickData, actionType, player) super.onSlotClick(slotId, clickData, actionType, player)
} }
override fun transferSlot(player: PlayerEntity, slotId: Int): ItemStack { override fun transferSlot(player: PlayerEntity, slotId: Int): ItemStack {
@ -227,7 +227,7 @@ abstract class AbstractTerminalScreenHandler<T: AbstractTerminalBlockEntity>(
slot.markDirty() slot.markDirty()
slotsInsertedInto.add(index) slotsInsertedInto.add(index)
} else if (canStacksCombine(slotStack, stack) && slotStack.count < slotStack.maxCount) { } else if (ItemStack.canCombine(slotStack, stack) && slotStack.count < slotStack.maxCount) {
val maxToMove = slotStack.maxCount - slotStack.count val maxToMove = slotStack.maxCount - slotStack.count
val toMove = min(maxToMove, stack.count) val toMove = min(maxToMove, stack.count)
slotStack.increment(toMove) slotStack.increment(toMove)

View File

@ -1,6 +1,8 @@
package net.shadowfacts.phycon.block.terminal package net.shadowfacts.phycon.block.terminal
import net.minecraft.block.BlockState
import net.minecraft.util.Identifier import net.minecraft.util.Identifier
import net.minecraft.util.math.BlockPos
import net.minecraft.world.BlockView import net.minecraft.world.BlockView
import net.shadowfacts.phycon.PhysicalConnectivity import net.shadowfacts.phycon.PhysicalConnectivity
@ -13,6 +15,6 @@ class CraftingTerminalBlock: AbstractTerminalBlock<CraftingTerminalBlockEntity>(
val ID = Identifier(PhysicalConnectivity.MODID, "crafting_terminal") val ID = Identifier(PhysicalConnectivity.MODID, "crafting_terminal")
} }
override fun createBlockEntity(world: BlockView) = CraftingTerminalBlockEntity() override fun createBlockEntity(pos: BlockPos, state: BlockState) = CraftingTerminalBlockEntity(pos, state)
} }

View File

@ -2,19 +2,18 @@ package net.shadowfacts.phycon.block.terminal
import alexiil.mc.lib.attributes.item.ItemStackCollections import alexiil.mc.lib.attributes.item.ItemStackCollections
import alexiil.mc.lib.attributes.item.ItemStackUtil import alexiil.mc.lib.attributes.item.ItemStackUtil
import it.unimi.dsi.fastutil.objects.Object2IntMap
import net.fabricmc.fabric.api.screenhandler.v1.ExtendedScreenHandlerFactory import net.fabricmc.fabric.api.screenhandler.v1.ExtendedScreenHandlerFactory
import net.minecraft.block.BlockState
import net.minecraft.entity.player.PlayerEntity import net.minecraft.entity.player.PlayerEntity
import net.minecraft.entity.player.PlayerInventory import net.minecraft.entity.player.PlayerInventory
import net.minecraft.inventory.CraftingInventory
import net.minecraft.inventory.SimpleInventory import net.minecraft.inventory.SimpleInventory
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
import net.minecraft.nbt.CompoundTag import net.minecraft.nbt.NbtCompound
import net.minecraft.network.PacketByteBuf import net.minecraft.network.PacketByteBuf
import net.minecraft.screen.ScreenHandler import net.minecraft.screen.ScreenHandler
import net.minecraft.server.network.ServerPlayerEntity import net.minecraft.server.network.ServerPlayerEntity
import net.minecraft.text.Text
import net.minecraft.text.TranslatableText import net.minecraft.text.TranslatableText
import net.minecraft.util.math.BlockPos
import net.shadowfacts.phycon.init.PhyBlockEntities import net.shadowfacts.phycon.init.PhyBlockEntities
import net.shadowfacts.phycon.packet.ItemStackPacket import net.shadowfacts.phycon.packet.ItemStackPacket
import net.shadowfacts.phycon.packet.LocateStackPacket import net.shadowfacts.phycon.packet.LocateStackPacket
@ -27,7 +26,7 @@ import kotlin.math.min
/** /**
* @author shadowfacts * @author shadowfacts
*/ */
class CraftingTerminalBlockEntity: AbstractTerminalBlockEntity(PhyBlockEntities.CRAFTING_TERMINAL) { class CraftingTerminalBlockEntity(pos: BlockPos, state: BlockState): AbstractTerminalBlockEntity(PhyBlockEntities.CRAFTING_TERMINAL, pos, state) {
val craftingInv = SimpleInventory(9) val craftingInv = SimpleInventory(9)
@ -119,12 +118,12 @@ class CraftingTerminalBlockEntity: AbstractTerminalBlockEntity(PhyBlockEntities.
} }
} }
override fun toCommonTag(tag: CompoundTag) { override fun toCommonTag(tag: NbtCompound) {
super.toCommonTag(tag) super.toCommonTag(tag)
tag.put("CraftingInv", craftingInv.toTag()) tag.put("CraftingInv", craftingInv.toTag())
} }
override fun fromCommonTag(tag: CompoundTag) { override fun fromCommonTag(tag: NbtCompound) {
super.fromCommonTag(tag) super.fromCommonTag(tag)
craftingInv.fromTag(tag.getList("CraftingInv", 10)) craftingInv.fromTag(tag.getList("CraftingInv", 10))
} }

View File

@ -1,6 +1,7 @@
package net.shadowfacts.phycon.block.terminal package net.shadowfacts.phycon.block.terminal
import com.mojang.blaze3d.systems.RenderSystem import com.mojang.blaze3d.systems.RenderSystem
import net.minecraft.client.render.GameRenderer
import net.minecraft.client.util.math.MatrixStack import net.minecraft.client.util.math.MatrixStack
import net.minecraft.entity.player.PlayerInventory import net.minecraft.entity.player.PlayerInventory
import net.minecraft.text.Text import net.minecraft.text.Text
@ -34,13 +35,13 @@ class CraftingTerminalScreen(
} }
override fun drawBackgroundTexture(matrixStack: MatrixStack) { override fun drawBackgroundTexture(matrixStack: MatrixStack) {
RenderSystem.color4f(1f, 1f, 1f, 1f) RenderSystem.setShader(GameRenderer::getPositionTexShader)
client!!.textureManager.bindTexture(BACKGROUND_1) RenderSystem.setShaderTexture(0, BACKGROUND_1)
val x = (width - backgroundWidth) / 2 val x = (width - backgroundWidth) / 2
val y = (height - backgroundHeight) / 2 val y = (height - backgroundHeight) / 2
drawTexture(matrixStack, x, y, 0, 0, 256, 252) drawTexture(matrixStack, x, y, 0, 0, 256, 252)
client!!.textureManager.bindTexture(BACKGROUND_2) RenderSystem.setShaderTexture(0, BACKGROUND_2)
drawTexture(matrixStack, x + 256, y, 0, 0, 3, 252) drawTexture(matrixStack, x + 256, y, 0, 0, 3, 252)
} }

View File

@ -8,7 +8,7 @@ import net.minecraft.inventory.Inventory
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
import net.minecraft.network.PacketByteBuf import net.minecraft.network.PacketByteBuf
import net.minecraft.network.packet.s2c.play.ScreenHandlerSlotUpdateS2CPacket import net.minecraft.network.packet.s2c.play.ScreenHandlerSlotUpdateS2CPacket
import net.minecraft.recipe.RecipeFinder import net.minecraft.recipe.RecipeMatcher
import net.minecraft.recipe.RecipeType import net.minecraft.recipe.RecipeType
import net.minecraft.screen.slot.CraftingResultSlot import net.minecraft.screen.slot.CraftingResultSlot
import net.minecraft.screen.slot.Slot import net.minecraft.screen.slot.Slot
@ -73,7 +73,7 @@ class CraftingTerminalScreenHandler(
ItemStack.EMPTY ItemStack.EMPTY
} }
result.setStack(0, resultStack) result.setStack(0, resultStack)
player.networkHandler.sendPacket(ScreenHandlerSlotUpdateS2CPacket(syncId, resultSlot.id, resultStack)) player.networkHandler.sendPacket(ScreenHandlerSlotUpdateS2CPacket(syncId, nextRevision(), resultSlot.id, resultStack))
} }
} }
@ -105,7 +105,7 @@ class CraftingTerminalScreenHandler(
if (!insertItem(craftingResult, playerSlotsStart, playerSlotsEnd, true)) { if (!insertItem(craftingResult, playerSlotsStart, playerSlotsEnd, true)) {
return ItemStack.EMPTY return ItemStack.EMPTY
} }
resultSlot.onStackChanged(craftingResult, originalResult) resultSlot.onQuickTransfer(craftingResult, originalResult)
if (craftingResult.isEmpty) { if (craftingResult.isEmpty) {
resultSlot.stack = ItemStack.EMPTY resultSlot.stack = ItemStack.EMPTY
@ -115,8 +115,8 @@ class CraftingTerminalScreenHandler(
return ItemStack.EMPTY return ItemStack.EMPTY
} }
val taken = resultSlot.onTakeItem(player, craftingResult) resultSlot.onTakeItem(player, craftingResult)
player.dropItem(taken, false) player.dropItem(craftingResult, false)
return originalResult return originalResult
} else { } else {
@ -157,7 +157,7 @@ class CraftingTerminalScreenHandler(
backing.clear() backing.clear()
} }
override fun provideRecipeInputs(finder: RecipeFinder) { override fun provideRecipeInputs(finder: RecipeMatcher) {
TODO() TODO()
} }
} }

View File

@ -1,7 +1,8 @@
package net.shadowfacts.phycon.block.terminal package net.shadowfacts.phycon.block.terminal
import net.minecraft.block.BlockState
import net.minecraft.util.Identifier import net.minecraft.util.Identifier
import net.minecraft.world.BlockView import net.minecraft.util.math.BlockPos
import net.shadowfacts.phycon.PhysicalConnectivity import net.shadowfacts.phycon.PhysicalConnectivity
/** /**
@ -13,6 +14,6 @@ class TerminalBlock: AbstractTerminalBlock<TerminalBlockEntity>() {
val ID = Identifier(PhysicalConnectivity.MODID, "terminal") val ID = Identifier(PhysicalConnectivity.MODID, "terminal")
} }
override fun createBlockEntity(world: BlockView) = TerminalBlockEntity() override fun createBlockEntity(pos: BlockPos, state: BlockState) = TerminalBlockEntity(pos, state)
} }

View File

@ -1,19 +1,21 @@
package net.shadowfacts.phycon.block.terminal package net.shadowfacts.phycon.block.terminal
import net.fabricmc.fabric.api.screenhandler.v1.ExtendedScreenHandlerFactory import net.fabricmc.fabric.api.screenhandler.v1.ExtendedScreenHandlerFactory
import net.minecraft.block.BlockState
import net.minecraft.entity.player.PlayerEntity import net.minecraft.entity.player.PlayerEntity
import net.minecraft.entity.player.PlayerInventory import net.minecraft.entity.player.PlayerInventory
import net.minecraft.network.PacketByteBuf import net.minecraft.network.PacketByteBuf
import net.minecraft.screen.ScreenHandler import net.minecraft.screen.ScreenHandler
import net.minecraft.server.network.ServerPlayerEntity import net.minecraft.server.network.ServerPlayerEntity
import net.minecraft.text.TranslatableText import net.minecraft.text.TranslatableText
import net.minecraft.util.math.BlockPos
import net.shadowfacts.phycon.init.PhyBlockEntities import net.shadowfacts.phycon.init.PhyBlockEntities
import net.shadowfacts.phycon.packet.RequestInventoryPacket import net.shadowfacts.phycon.packet.RequestInventoryPacket
/** /**
* @author shadowfacts * @author shadowfacts
*/ */
class TerminalBlockEntity: AbstractTerminalBlockEntity(PhyBlockEntities.TERMINAL) { class TerminalBlockEntity(pos: BlockPos, state: BlockState): AbstractTerminalBlockEntity(PhyBlockEntities.TERMINAL, pos, state) {
override fun onActivate(player: PlayerEntity) { override fun onActivate(player: PlayerEntity) {
if (!world!!.isClient) { if (!world!!.isClient) {

View File

@ -3,8 +3,8 @@ package net.shadowfacts.phycon.block.terminal
import alexiil.mc.lib.attributes.item.ItemStackUtil import alexiil.mc.lib.attributes.item.ItemStackUtil
import net.minecraft.inventory.SimpleInventory import net.minecraft.inventory.SimpleInventory
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
import net.minecraft.nbt.CompoundTag import net.minecraft.nbt.NbtCompound
import net.minecraft.nbt.IntArrayTag import net.minecraft.nbt.NbtIntArray
import net.shadowfacts.phycon.util.fromTag import net.shadowfacts.phycon.util.fromTag
import net.shadowfacts.phycon.util.toTag import net.shadowfacts.phycon.util.toTag
import kotlin.math.min import kotlin.math.min
@ -21,14 +21,14 @@ class TerminalBufferInventory(size: Int): SimpleInventory(size) {
var modes = Array(size) { Mode.UNASSIGNED } var modes = Array(size) { Mode.UNASSIGNED }
private set private set
fun toTag(): CompoundTag { fun toTag(): NbtCompound {
val compound = CompoundTag() val compound = NbtCompound()
compound.put("Inventory", (this as SimpleInventory).toTag()) compound.put("Inventory", (this as SimpleInventory).toTag())
compound.put("Modes", IntArrayTag(modes.map(Mode::ordinal))) compound.put("Modes", NbtIntArray(modes.map(Mode::ordinal)))
return compound return compound
} }
fun fromTag(tag: CompoundTag) { fun fromTag(tag: NbtCompound) {
val inventory = tag.getList("Inventory", 10) val inventory = tag.getList("Inventory", 10)
(this as SimpleInventory).fromTag(inventory) (this as SimpleInventory).fromTag(inventory)
tag.getIntArray("Modes").forEachIndexed { i, it -> modes[i] = Mode.values()[it] } tag.getIntArray("Modes").forEachIndexed { i, it -> modes[i] = Mode.values()[it] }

View File

@ -6,6 +6,7 @@ import net.minecraft.client.render.model.*
import net.minecraft.client.texture.Sprite import net.minecraft.client.texture.Sprite
import net.minecraft.client.texture.SpriteAtlasTexture import net.minecraft.client.texture.SpriteAtlasTexture
import net.minecraft.client.util.SpriteIdentifier import net.minecraft.client.util.SpriteIdentifier
import net.minecraft.screen.PlayerScreenHandler
import net.minecraft.util.DyeColor import net.minecraft.util.DyeColor
import net.minecraft.util.Identifier import net.minecraft.util.Identifier
import net.minecraft.util.math.Direction import net.minecraft.util.math.Direction
@ -85,7 +86,7 @@ class ColoredCableModel(
rotationContainer: ModelBakeSettings, rotationContainer: ModelBakeSettings,
modelId: Identifier modelId: Identifier
): BakedModel { ): BakedModel {
centerSprite = textureGetter.apply(SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE, Identifier(PhysicalConnectivity.MODID, "block/cable/${color.getName()}/straight"))) centerSprite = textureGetter.apply(SpriteIdentifier(PlayerScreenHandler.BLOCK_ATLAS_TEXTURE, Identifier(PhysicalConnectivity.MODID, "block/cable/${color.getName()}/straight")))
sideRotations.forEach { (side, rot) -> sideRotations.forEach { (side, rot) ->
this.side[side.ordinal] = loader.bakeRecoloredCable(SIDE, rot, textureGetter, color) this.side[side.ordinal] = loader.bakeRecoloredCable(SIDE, rot, textureGetter, color)
@ -260,7 +261,7 @@ class ColoredCableModel(
override fun isBuiltin() = false override fun isBuiltin() = false
override fun getSprite() = centerSprite override fun getParticleSprite() = centerSprite
override fun getTransformation() = null override fun getTransformation() = null

View File

@ -120,9 +120,9 @@ abstract class FaceDeviceModel: UnbakedModel, BakedModel {
val sideQuads = getSideModel(state)?.getQuads(state, face, random) ?: listOf() val sideQuads = getSideModel(state)?.getQuads(state, face, random) ?: listOf()
val cableQuads = if (connection.direction == facing.opposite) { val cableQuads = if (connection.direction == facing.opposite) {
interfaceCableStraight[color]!![facing.ordinal]?.getQuads(state, face, random) ?: listOf() interfaceCableStraight[color]!![facing.ordinal].getQuads(state, face, random) ?: listOf()
} else if (connection == FaceCableConnection.NONE) { } else if (connection == FaceCableConnection.NONE) {
interfaceCableCap[color]!![facing.ordinal]?.getQuads(state, face, random) ?: listOf() interfaceCableCap[color]!![facing.ordinal].getQuads(state, face, random) ?: listOf()
} else { } else {
val model = when (facing) { val model = when (facing) {
Direction.DOWN -> when (connection) { Direction.DOWN -> when (connection) {
@ -183,7 +183,7 @@ abstract class FaceDeviceModel: UnbakedModel, BakedModel {
override fun isBuiltin() = false override fun isBuiltin() = false
abstract override fun getSprite(): Sprite abstract override fun getParticleSprite(): Sprite
override fun getTransformation() = null override fun getTransformation() = null

View File

@ -40,8 +40,8 @@ object RedstoneControllerModel: FaceDeviceModel() {
} }
} }
override fun getSprite(): Sprite { override fun getParticleSprite(): Sprite {
return offModels.first()!!.sprite return offModels.first()!!.particleSprite
} }
} }

View File

@ -13,6 +13,7 @@ import net.minecraft.client.texture.Sprite
import net.minecraft.client.texture.SpriteAtlasTexture import net.minecraft.client.texture.SpriteAtlasTexture
import net.minecraft.client.util.SpriteIdentifier import net.minecraft.client.util.SpriteIdentifier
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
import net.minecraft.screen.PlayerScreenHandler
import net.minecraft.util.Identifier import net.minecraft.util.Identifier
import net.minecraft.util.math.BlockPos import net.minecraft.util.math.BlockPos
import net.minecraft.util.math.Direction import net.minecraft.util.math.Direction
@ -32,10 +33,10 @@ class ScreenDeviceModel(
): UnbakedModel, BakedModel, FabricBakedModel { ): UnbakedModel, BakedModel, FabricBakedModel {
companion object { companion object {
private val CASING = SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE, Identifier(PhysicalConnectivity.MODID, "block/casing")) private val CASING = SpriteIdentifier(PlayerScreenHandler.BLOCK_ATLAS_TEXTURE, Identifier(PhysicalConnectivity.MODID, "block/casing"))
} }
private val screenTexture = SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE, screenTexture) private val screenTexture = SpriteIdentifier(PlayerScreenHandler.BLOCK_ATLAS_TEXTURE, screenTexture)
private lateinit var meshes: Array<Mesh> private lateinit var meshes: Array<Mesh>
private lateinit var screenSprite: Sprite private lateinit var screenSprite: Sprite
@ -171,7 +172,7 @@ class ScreenDeviceModel(
override fun isBuiltin() = false override fun isBuiltin() = false
override fun getSprite() = screenSprite override fun getParticleSprite() = screenSprite
override fun getTransformation() = null override fun getTransformation() = null

View File

@ -35,7 +35,7 @@ class SimpleFaceDeviceModel(
return sideModels[state[FaceDeviceBlock.COLOR]]!![state[FaceDeviceBlock.FACING].ordinal] return sideModels[state[FaceDeviceBlock.COLOR]]!![state[FaceDeviceBlock.FACING].ordinal]
} }
override fun getSprite(): Sprite { override fun getParticleSprite(): Sprite {
return sideModels[DyeColor.BLACK]!!.first().sprite return sideModels[DyeColor.BLACK]!!.first().particleSprite
} }
} }

View File

@ -1,48 +0,0 @@
package net.shadowfacts.phycon.client.screen
import net.minecraft.client.gui.widget.AbstractPressableButtonWidget
import net.shadowfacts.phycon.util.FriendlyNameable
import net.shadowfacts.phycon.util.RotatableEnum
import net.shadowfacts.phycon.util.next
import net.shadowfacts.phycon.util.prev
import kotlin.reflect.KMutableProperty
/**
* @author shadowfacts
*/
class EnumButton<E>(
val prop: KMutableProperty<E>,
x: Int,
y: Int,
width: Int,
height: Int,
val onChange: () -> Unit
): AbstractPressableButtonWidget(
x,
y,
width,
height,
prop.getter.call().friendlyName
) where E: Enum<E>, E: RotatableEnum, E: FriendlyNameable {
private var currentButton: Int? = null
override fun mouseClicked(d: Double, e: Double, button: Int): Boolean {
currentButton = button
val res = super.mouseClicked(d, e, button)
currentButton = null
return res
}
override fun isValidClickButton(i: Int): Boolean {
return i == 0 || i == 1
}
override fun onPress() {
val newVal = if ((currentButton ?: 0) == 0) prop.getter.call().next else prop.getter.call().prev
prop.setter.call(newVal)
message = newVal.friendlyName
onChange()
}
}

View File

@ -50,16 +50,16 @@ class ScrollTrackView(
}) })
} }
override fun mouseDragged(point: Point, delta: Point, mouseButton: MouseButton): Boolean { override fun mouseDragged(startPoint: Point, delta: Point, mouseButton: MouseButton): Boolean {
if (grabbedY == null && point !in thumbView.frame) { if (grabbedY == null && startPoint !in thumbView.frame) {
val newCenter = MathHelper.clamp(point.y, THUMB_HEIGHT / 2, frame.height - THUMB_HEIGHT / 2) val newCenter = MathHelper.clamp(startPoint.y, THUMB_HEIGHT / 2, frame.height - THUMB_HEIGHT / 2)
thumbView.frame = Rect(0.0, newCenter - THUMB_HEIGHT / 2, THUMB_WIDTH, THUMB_HEIGHT) thumbView.frame = Rect(0.0, newCenter - THUMB_HEIGHT / 2, THUMB_WIDTH, THUMB_HEIGHT)
} }
if (grabbedY == null) { if (grabbedY == null) {
grabbedY = point.y - thumbView.frame.top grabbedY = startPoint.y - thumbView.frame.top
} }
val newTop = MathHelper.clamp(point.y - grabbedY!!, 0.0, frame.height - THUMB_HEIGHT) val newTop = MathHelper.clamp(startPoint.y - grabbedY!!, 0.0, frame.height - THUMB_HEIGHT)
thumbView.frame = Rect(0.0, newTop, THUMB_WIDTH, THUMB_HEIGHT) thumbView.frame = Rect(0.0, newTop, THUMB_WIDTH, THUMB_HEIGHT)
scrollPositionChanged(this) scrollPositionChanged(this)

View File

@ -7,8 +7,8 @@ import net.shadowfacts.phycon.api.util.MACAddress
* @author shadowfacts * @author shadowfacts
*/ */
open class BaseFrame( open class BaseFrame(
@JvmField private val source: MACAddress, private val source: MACAddress,
@JvmField private val destination: MACAddress private val destination: MACAddress
): EthernetFrame { ): EthernetFrame {
override fun getSource() = source override fun getSource() = source
override fun getDestination() = destination override fun getDestination() = destination

View File

@ -8,7 +8,7 @@ import net.shadowfacts.phycon.api.util.MACAddress
* @author shadowfacts * @author shadowfacts
*/ */
class BasePacketFrame( class BasePacketFrame(
@JvmField private val packet: Packet, private val packet: Packet,
source: MACAddress, source: MACAddress,
destination: MACAddress, destination: MACAddress,
): BaseFrame(source, destination), PacketFrame { ): BaseFrame(source, destination), PacketFrame {

View File

@ -1,9 +1,11 @@
package net.shadowfacts.phycon.init package net.shadowfacts.phycon.init
import net.minecraft.block.Block import net.minecraft.block.Block
import net.minecraft.block.BlockState
import net.minecraft.block.entity.BlockEntity import net.minecraft.block.entity.BlockEntity
import net.minecraft.block.entity.BlockEntityType import net.minecraft.block.entity.BlockEntityType
import net.minecraft.util.Identifier import net.minecraft.util.Identifier
import net.minecraft.util.math.BlockPos
import net.minecraft.util.registry.Registry import net.minecraft.util.registry.Registry
import net.shadowfacts.phycon.block.extractor.ExtractorBlock import net.shadowfacts.phycon.block.extractor.ExtractorBlock
import net.shadowfacts.phycon.block.extractor.ExtractorBlockEntity import net.shadowfacts.phycon.block.extractor.ExtractorBlockEntity
@ -39,7 +41,7 @@ object PhyBlockEntities {
val REDSTONE_CONTROLLER = create(::RedstoneControllerBlockEntity, PhyBlocks.REDSTONE_CONTROLLER) val REDSTONE_CONTROLLER = create(::RedstoneControllerBlockEntity, PhyBlocks.REDSTONE_CONTROLLER)
val REDSTONE_EMITTER = create(::RedstoneEmitterBlockEntity, PhyBlocks.REDSTONE_EMITTER) val REDSTONE_EMITTER = create(::RedstoneEmitterBlockEntity, PhyBlocks.REDSTONE_EMITTER)
private fun <T: BlockEntity> create(builder: () -> T, block: Block): BlockEntityType<T> { private fun <T: BlockEntity> create(builder: (BlockPos, BlockState) -> T, block: Block): BlockEntityType<T> {
return BlockEntityType.Builder.create(builder, block).build(null) return BlockEntityType.Builder.create(builder, block).build(null)
} }

View File

@ -27,7 +27,7 @@ class ConsoleItem: Item(Settings().maxCount(1)) {
if (context.world.isClient) { if (context.world.isClient) {
this.openScreen(be) this.openScreen(be)
} else { } else {
be.sync() be.markUpdate()
} }
return ActionResult.SUCCESS return ActionResult.SUCCESS
} }
@ -38,7 +38,7 @@ class ConsoleItem: Item(Settings().maxCount(1)) {
private fun openScreen(be: DeviceBlockEntity) { private fun openScreen(be: DeviceBlockEntity) {
// val screen = TestCacaoScreen() // val screen = TestCacaoScreen()
val screen = DeviceConsoleScreen(be) val screen = DeviceConsoleScreen(be)
MinecraftClient.getInstance().openScreen(screen) MinecraftClient.getInstance().setScreen(screen)
} }
} }

View File

@ -15,7 +15,7 @@ import net.shadowfacts.phycon.util.text
open class DeviceBlockItem(block: DeviceBlock<*>, settings: Settings = Settings()): BlockItem(block, settings) { open class DeviceBlockItem(block: DeviceBlock<*>, settings: Settings = Settings()): BlockItem(block, settings) {
override fun appendTooltip(stack: ItemStack, world: World?, list: MutableList<Text>, context: TooltipContext) { override fun appendTooltip(stack: ItemStack, world: World?, list: MutableList<Text>, context: TooltipContext) {
val beTag = stack.getSubTag("BlockEntityTag") val beTag = stack.getSubNbt("BlockEntityTag")
if (beTag != null) { if (beTag != null) {
val ip = IPAddress(beTag.getInt("IPAddress")) val ip = IPAddress(beTag.getInt("IPAddress"))
list.add(text { list.add(text {

View File

@ -54,12 +54,12 @@ class ScrewdriverItem: Item(Settings().maxCount(1)) {
val be = block.getBlockEntity(context.world, context.blockPos)!! val be = block.getBlockEntity(context.world, context.blockPos)!!
val stack = ItemStack(block) val stack = ItemStack(block)
val beTag = stack.getOrCreateSubTag("BlockEntityTag") val beTag = be.createNbt()
be.toTag(beTag)
// remove x, y, z entries for stacking purposes // remove x, y, z entries for stacking purposes
beTag.remove("x") beTag.remove("x")
beTag.remove("y") beTag.remove("y")
beTag.remove("z") beTag.remove("z")
stack.setSubNbt("BlockEntityTag", beTag)
if (block === PhyBlocks.TERMINAL) { if (block === PhyBlocks.TERMINAL) {
// remove the terminal's internal buffer since it drops its items // remove the terminal's internal buffer since it drops its items

View File

@ -3,7 +3,7 @@ package net.shadowfacts.phycon.networking
import net.fabricmc.fabric.api.networking.v1.PacketByteBufs import net.fabricmc.fabric.api.networking.v1.PacketByteBufs
import net.fabricmc.fabric.api.networking.v1.PacketSender import net.fabricmc.fabric.api.networking.v1.PacketSender
import net.minecraft.block.entity.BlockEntity import net.minecraft.block.entity.BlockEntity
import net.minecraft.nbt.CompoundTag import net.minecraft.nbt.NbtCompound
import net.minecraft.network.Packet import net.minecraft.network.Packet
import net.minecraft.network.PacketByteBuf import net.minecraft.network.PacketByteBuf
import net.minecraft.server.MinecraftServer import net.minecraft.server.MinecraftServer
@ -24,9 +24,9 @@ object C2SConfigureDevice: ServerReceiver {
buf.writeIdentifier(be.world!!.registryKey.value) buf.writeIdentifier(be.world!!.registryKey.value)
buf.writeBlockPos(be.pos) buf.writeBlockPos(be.pos)
val tag = CompoundTag() val tag = NbtCompound()
be.writeDeviceConfiguration(tag) be.writeDeviceConfiguration(tag)
buf.writeCompoundTag(tag) buf.writeNbt(tag)
return createPacket(buf) return createPacket(buf)
} }
@ -34,7 +34,7 @@ object C2SConfigureDevice: ServerReceiver {
override fun receive(server: MinecraftServer, player: ServerPlayerEntity, handler: ServerPlayNetworkHandler, buf: PacketByteBuf, responseSender: PacketSender) { override fun receive(server: MinecraftServer, player: ServerPlayerEntity, handler: ServerPlayNetworkHandler, buf: PacketByteBuf, responseSender: PacketSender) {
val dimID = buf.readIdentifier() val dimID = buf.readIdentifier()
val pos = buf.readBlockPos() val pos = buf.readBlockPos()
val tag = buf.readCompoundTag() ?: return val tag = buf.readNbt() ?: return
server.execute { server.execute {
// todo: check if the player is close enough // todo: check if the player is close enough

View File

@ -42,7 +42,7 @@ object C2STerminalCraftingButton: ServerReceiver {
val action = Action.values()[buf.readByte().toInt()] val action = Action.values()[buf.readByte().toInt()]
server.execute { server.execute {
val key = RegistryKey.of(Registry.DIMENSION, dimID) val key = RegistryKey.of(Registry.WORLD_KEY, dimID)
val screenHandler = player.currentScreenHandler as? CraftingTerminalScreenHandler ?: return@execute val screenHandler = player.currentScreenHandler as? CraftingTerminalScreenHandler ?: return@execute
if (screenHandler.terminal.pos != pos || screenHandler.terminal.world!!.registryKey != key) return@execute if (screenHandler.terminal.pos != pos || screenHandler.terminal.world!!.registryKey != key) return@execute

View File

@ -45,7 +45,7 @@ object C2STerminalRequestItem: ServerReceiver {
val amount = buf.readVarInt() val amount = buf.readVarInt()
server.execute { server.execute {
val key = RegistryKey.of(Registry.DIMENSION, dimID) val key = RegistryKey.of(Registry.WORLD_KEY, dimID)
val world = server.getWorld(key) ?: return@execute val world = server.getWorld(key) ?: return@execute
val terminal = world.getBlockEntity(pos) as? AbstractTerminalBlockEntity ?: return@execute val terminal = world.getBlockEntity(pos) as? AbstractTerminalBlockEntity ?: return@execute
terminal.requestItem(stack, amount) terminal.requestItem(stack, amount)

View File

@ -29,7 +29,7 @@ object C2STerminalUpdateDisplayedItems: ServerReceiver {
buf.writeBlockPos(terminal.pos) buf.writeBlockPos(terminal.pos)
buf.writeString(query) buf.writeString(query)
buf.writeCompoundTag(PhysicalConnectivityClient.terminalSettings.toTag()) buf.writeNbt(PhysicalConnectivityClient.terminalSettings.toTag())
buf.writeFloat(scrollPosition) buf.writeFloat(scrollPosition)
return ClientPlayNetworking.createC2SPacket(CHANNEL, buf) return ClientPlayNetworking.createC2SPacket(CHANNEL, buf)
@ -40,7 +40,7 @@ object C2STerminalUpdateDisplayedItems: ServerReceiver {
val pos = buf.readBlockPos() val pos = buf.readBlockPos()
val query = buf.readString() val query = buf.readString()
val settings = TerminalSettings() val settings = TerminalSettings()
settings.fromTag(buf.readCompoundTag()!!) settings.fromTag(buf.readNbt()!!)
val scrollPosition = buf.readFloat() val scrollPosition = buf.readFloat()
server.execute { server.execute {

View File

@ -33,7 +33,7 @@ object S2CTerminalUpdateDisplayedItems: ClientReceiver {
} }
buf.writeString(query) buf.writeString(query)
buf.writeCompoundTag(settings.toTag()) buf.writeNbt(settings.toTag())
buf.writeFloat(scrollPosition) buf.writeFloat(scrollPosition)
buf.writeInt(totalEntries) buf.writeInt(totalEntries)
@ -49,7 +49,7 @@ object S2CTerminalUpdateDisplayedItems: ClientReceiver {
entries.add(AbstractTerminalScreenHandler.Entry(buf.readItemStackWithoutCount(), buf.readVarInt())) entries.add(AbstractTerminalScreenHandler.Entry(buf.readItemStackWithoutCount(), buf.readVarInt()))
} }
val query = buf.readString() val query = buf.readString()
PhysicalConnectivityClient.terminalSettings.fromTag(buf.readCompoundTag()!!) PhysicalConnectivityClient.terminalSettings.fromTag(buf.readNbt()!!)
val scrollPosition = buf.readFloat() val scrollPosition = buf.readFloat()
val totalEntries = buf.readInt() val totalEntries = buf.readInt()

View File

@ -7,8 +7,8 @@ import net.shadowfacts.phycon.api.util.IPAddress
* @author shadowfacts * @author shadowfacts
*/ */
abstract class BasePacket( abstract class BasePacket(
@JvmField private val source: IPAddress, private val source: IPAddress,
@JvmField private val destination: IPAddress private val destination: IPAddress
): Packet { ): Packet {
override fun getSource() = source override fun getSource() = source

View File

@ -11,5 +11,5 @@ enum class ActivationMode: RotatableEnum, FriendlyNameable {
MANAGED; MANAGED;
override val friendlyName: Text override val friendlyName: Text
get() = TranslatableText("gui.phycon.activation_mode.${name.toLowerCase()}") get() = TranslatableText("gui.phycon.activation_mode.${name.lowercase()}")
} }

View File

@ -3,20 +3,20 @@ package net.shadowfacts.phycon.util
import alexiil.mc.lib.attributes.item.ItemStackUtil import alexiil.mc.lib.attributes.item.ItemStackUtil
import net.minecraft.inventory.SimpleInventory import net.minecraft.inventory.SimpleInventory
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
import net.minecraft.nbt.CompoundTag import net.minecraft.nbt.NbtCompound
import net.minecraft.nbt.ListTag import net.minecraft.nbt.NbtList
import java.lang.RuntimeException import java.lang.RuntimeException
import kotlin.math.min import kotlin.math.min
/** /**
* @author shadowfacts * @author shadowfacts
*/ */
fun SimpleInventory.toTag(): ListTag { fun SimpleInventory.toTag(): NbtList {
val list = ListTag() val list = NbtList()
for (slot in 0 until size()) { for (slot in 0 until size()) {
val stack = getStack(slot) val stack = getStack(slot)
if (!stack.isEmpty) { if (!stack.isEmpty) {
val stackTag = stack.toTag(CompoundTag()) val stackTag = stack.writeNbt(NbtCompound())
stackTag.putInt("Slot", slot) stackTag.putInt("Slot", slot)
list.add(stackTag) list.add(stackTag)
} }
@ -24,16 +24,16 @@ fun SimpleInventory.toTag(): ListTag {
return list return list
} }
fun SimpleInventory.fromTag(list: ListTag) { fun SimpleInventory.fromTag(list: NbtList) {
if (list.isEmpty()) { if (list.isEmpty()) {
this.clear() this.clear()
return return
} }
if (list.elementType != 10.toByte()) throw RuntimeException("Can't decode BasicInventory from list tag that does not contain compound tags") if (list.heldType != 10.toByte()) throw RuntimeException("Can't decode BasicInventory from list tag that does not contain compound tags")
this.clear() this.clear()
for (tag in list) { for (tag in list) {
val compound = tag as CompoundTag val compound = tag as NbtCompound
val stack = ItemStack.fromTag(compound) val stack = ItemStack.fromNbt(compound)
val slot = compound.getInt("Slot") val slot = compound.getInt("Slot")
setStack(slot, stack) setStack(slot, stack)
} }

View File

@ -10,5 +10,5 @@ enum class CableConnection: StringIdentifiable {
OFF, OFF,
DISABLED; DISABLED;
override fun asString() = name.toLowerCase() override fun asString() = name.lowercase()
} }

View File

@ -1,14 +1,14 @@
package net.shadowfacts.phycon.util package net.shadowfacts.phycon.util
import net.minecraft.nbt.CompoundTag import net.minecraft.nbt.NbtCompound
/** /**
* @author shadowfacts * @author shadowfacts
*/ */
interface ClientConfigurableDevice { interface ClientConfigurableDevice {
fun writeDeviceConfiguration(tag: CompoundTag) fun writeDeviceConfiguration(tag: NbtCompound)
fun loadDeviceConfiguration(tag: CompoundTag) fun loadDeviceConfiguration(tag: NbtCompound)
} }

View File

@ -2,7 +2,7 @@ package net.shadowfacts.phycon.util
import net.minecraft.item.Item import net.minecraft.item.Item
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
import net.minecraft.nbt.CompoundTag import net.minecraft.nbt.NbtCompound
import net.minecraft.network.PacketByteBuf import net.minecraft.network.PacketByteBuf
/** /**
@ -14,13 +14,13 @@ fun PacketByteBuf.writeItemStackWithoutCount(stack: ItemStack) {
} else { } else {
writeBoolean(true) writeBoolean(true)
writeVarInt(Item.getRawId(stack.item)) writeVarInt(Item.getRawId(stack.item))
val tag: CompoundTag? = val tag: NbtCompound? =
if (stack.item.isDamageable || stack.item.shouldSyncTagToClient()) { if (stack.item.isDamageable || stack.item.isNbtSynced()) {
stack.tag stack.nbt
} else { } else {
null null
} }
writeCompoundTag(tag) writeNbt(tag)
} }
} }
@ -31,7 +31,7 @@ fun PacketByteBuf.readItemStackWithoutCount(): ItemStack {
val id = readVarInt() val id = readVarInt()
val count = 1 val count = 1
val stack = ItemStack(Item.byRawId(id), count) val stack = ItemStack(Item.byRawId(id), count)
stack.tag = readCompoundTag() stack.nbt = readNbt()
stack stack
} }
} }

View File

@ -26,5 +26,5 @@ enum class RedstoneMode: RotatableEnum, FriendlyNameable {
} }
override val friendlyName: Text override val friendlyName: Text
get() = TranslatableText("gui.phycon.redstone_mode.${name.toLowerCase()}") get() = TranslatableText("gui.phycon.redstone_mode.${name.lowercase()}")
} }

View File

@ -1,6 +1,6 @@
package net.shadowfacts.phycon.util package net.shadowfacts.phycon.util
import net.minecraft.nbt.CompoundTag import net.minecraft.nbt.NbtCompound
import net.minecraft.util.Identifier import net.minecraft.util.Identifier
import net.shadowfacts.phycon.PhysicalConnectivityClient import net.shadowfacts.phycon.PhysicalConnectivityClient
import net.shadowfacts.phycon.api.TerminalSettingKey import net.shadowfacts.phycon.api.TerminalSettingKey
@ -56,15 +56,15 @@ class TerminalSettings {
settings[key] = value settings[key] = value
} }
fun toTag(): CompoundTag { fun toTag(): NbtCompound {
return CompoundTag().also { return NbtCompound().also {
settings.forEach { (s, v) -> settings.forEach { (s, v) ->
it.putInt(s.id.toString(), v.ordinal) it.putInt(s.id.toString(), v.ordinal)
} }
} }
} }
fun fromTag(tag: CompoundTag) { fun fromTag(tag: NbtCompound) {
settings.clear() settings.clear()
tag.keys.forEach { k -> tag.keys.forEach { k ->
val id = Identifier.tryParse(k) ?: return@forEach val id = Identifier.tryParse(k) ?: return@forEach