Compare commits
4 Commits
93b082ee55
...
f12965fc6c
Author | SHA1 | Date |
---|---|---|
Shadowfacts | f12965fc6c | |
Shadowfacts | 28e14ae8bf | |
Shadowfacts | e41c9e3ccb | |
Shadowfacts | b87a36caa4 |
|
@ -74,7 +74,7 @@ repositories {
|
||||||
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.
|
||||||
modImplementation "alexiil.mc.lib:libblockattributes-all:${project.libblockattributes_version}"
|
modCompile "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}"
|
||||||
|
|
||||||
|
@ -85,6 +85,8 @@ dependencies {
|
||||||
include project(":plugin:mousewheelie")
|
include project(":plugin:mousewheelie")
|
||||||
runtimeOnly project(":plugin:rei")
|
runtimeOnly project(":plugin:rei")
|
||||||
include project(":plugin:rei")
|
include project(":plugin:rei")
|
||||||
|
runtimeOnly project(":plugin:techreborn")
|
||||||
|
include project(":plugin:techreborn")
|
||||||
|
|
||||||
modRuntime("io.github.cottonmc:cotton-resources:${project.cotton_resources_version}") {
|
modRuntime("io.github.cottonmc:cotton-resources:${project.cotton_resources_version}") {
|
||||||
exclude group: "net.fabricmc.fabric-api"
|
exclude group: "net.fabricmc.fabric-api"
|
||||||
|
|
|
@ -5,7 +5,7 @@ minecraft_version=1.16.5
|
||||||
yarn_mappings=1.16.5+build.4
|
yarn_mappings=1.16.5+build.4
|
||||||
loader_version=0.11.1
|
loader_version=0.11.1
|
||||||
|
|
||||||
mod_version=0.1.0
|
mod_version=0.2.0
|
||||||
maven_group=net.shadowfacts
|
maven_group=net.shadowfacts
|
||||||
archives_base_name=PhysicalConnectivity
|
archives_base_name=PhysicalConnectivity
|
||||||
|
|
||||||
|
|
|
@ -34,8 +34,8 @@ object PhyConPlugin: ClientModInitializer, REIPluginV0 {
|
||||||
override fun registerBounds(helper: DisplayHelper) {
|
override fun registerBounds(helper: DisplayHelper) {
|
||||||
BaseBoundsHandler.getInstance().registerExclusionZones(TerminalScreen::class.java) {
|
BaseBoundsHandler.getInstance().registerExclusionZones(TerminalScreen::class.java) {
|
||||||
val screen = MinecraftClient.getInstance().currentScreen as TerminalScreen
|
val screen = MinecraftClient.getInstance().currentScreen as TerminalScreen
|
||||||
val button = screen.terminalVC.sortMode
|
val view = screen.terminalVC.settingsView
|
||||||
val rect = button.convert(button.bounds, to = null)
|
val rect = view.convert(view.bounds, to = null)
|
||||||
listOf(
|
listOf(
|
||||||
Rectangle(rect.left.toInt(), rect.top.toInt(), 20, 20)
|
Rectangle(rect.left.toInt(), rect.top.toInt(), 20, 20)
|
||||||
)
|
)
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
plugins {
|
||||||
|
id "fabric-loom"
|
||||||
|
id "org.jetbrains.kotlin.jvm"
|
||||||
|
}
|
||||||
|
|
||||||
|
archivesBaseName = project.archives_base_name
|
||||||
|
version = project.mod_version
|
||||||
|
group = project.maven_group
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
maven {
|
||||||
|
url = "https://maven.modmuss50.me/"
|
||||||
|
}
|
||||||
|
jcenter()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation project(":")
|
||||||
|
|
||||||
|
modImplementation("TechReborn:TechReborn-1.16:${project.techreborn_version}") {
|
||||||
|
exclude group: "net.fabricmc.fabric-api"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
archives_base_name=PhyCon-Plugin-TechReborn
|
||||||
|
|
||||||
|
techreborn_version=3.8.2+build.222
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
package net.shadowfacts.phycon.plugin.techreborn
|
||||||
|
|
||||||
|
import alexiil.mc.lib.attributes.AttributeList
|
||||||
|
import alexiil.mc.lib.attributes.AttributeSourceType
|
||||||
|
import alexiil.mc.lib.attributes.item.GroupedItemInv
|
||||||
|
import alexiil.mc.lib.attributes.item.ItemAttributes
|
||||||
|
import net.fabricmc.api.ModInitializer
|
||||||
|
import net.minecraft.block.BlockState
|
||||||
|
import net.minecraft.util.math.BlockPos
|
||||||
|
import net.minecraft.world.World
|
||||||
|
import techreborn.blockentity.storage.item.StorageUnitBaseBlockEntity
|
||||||
|
import techreborn.init.TRContent
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author shadowfacts
|
||||||
|
*/
|
||||||
|
object PhyConTR: ModInitializer {
|
||||||
|
|
||||||
|
override fun onInitialize() {
|
||||||
|
TRContent.StorageUnit.values().forEach {
|
||||||
|
ItemAttributes.GROUPED_INV.setBlockAdder(AttributeSourceType.COMPAT_WRAPPER, it.block, ::addStorageUnitGroupedInv)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun addStorageUnitGroupedInv(world: World, pos: BlockPos, state: BlockState, to: AttributeList<GroupedItemInv>) {
|
||||||
|
(world.getBlockEntity(pos) as? StorageUnitBaseBlockEntity)?.also { su ->
|
||||||
|
to.offer(StorageUnitWrapper(su))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,81 @@
|
||||||
|
package net.shadowfacts.phycon.plugin.techreborn
|
||||||
|
|
||||||
|
import alexiil.mc.lib.attributes.Simulation
|
||||||
|
import alexiil.mc.lib.attributes.item.GroupedItemInv
|
||||||
|
import alexiil.mc.lib.attributes.item.GroupedItemInvView
|
||||||
|
import alexiil.mc.lib.attributes.item.ItemStackCollections
|
||||||
|
import alexiil.mc.lib.attributes.item.ItemStackUtil
|
||||||
|
import alexiil.mc.lib.attributes.item.filter.ItemFilter
|
||||||
|
import net.minecraft.item.ItemStack
|
||||||
|
import net.shadowfacts.phycon.util.copyWithCount
|
||||||
|
import techreborn.blockentity.storage.item.StorageUnitBaseBlockEntity
|
||||||
|
import kotlin.math.min
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author shadowfacts
|
||||||
|
*/
|
||||||
|
class StorageUnitWrapper(
|
||||||
|
val be: StorageUnitBaseBlockEntity,
|
||||||
|
): GroupedItemInv {
|
||||||
|
|
||||||
|
override fun getStoredStacks(): Set<ItemStack> {
|
||||||
|
val set = ItemStackCollections.set()
|
||||||
|
if (!be.storedStack.isEmpty) {
|
||||||
|
set.add(be.storedStack)
|
||||||
|
}
|
||||||
|
return set
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getTotalCapacity(): Int {
|
||||||
|
return be.maxCapacity
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getStatistics(filter: ItemFilter): GroupedItemInvView.ItemInvStatistic {
|
||||||
|
// todo: should spaceAddable really be zero? that's what SimpleGroupedItemInv does
|
||||||
|
return if (be.storedStack.isEmpty) {
|
||||||
|
GroupedItemInvView.ItemInvStatistic(filter, 0, 0, totalCapacity)
|
||||||
|
} else if (filter.matches(be.storedStack)) {
|
||||||
|
// don't use the storedAmount field, it's only used on the client for rendering
|
||||||
|
val amount = be.getStoredAmount()
|
||||||
|
GroupedItemInvView.ItemInvStatistic(filter, amount, 0, totalCapacity - amount)
|
||||||
|
} else {
|
||||||
|
GroupedItemInvView.ItemInvStatistic(filter, 0, 0, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun attemptInsertion(filter: ItemStack, simulation: Simulation): ItemStack {
|
||||||
|
if (simulation.isAction) {
|
||||||
|
return be.processInput(filter)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (be.storedStack.isEmpty) {
|
||||||
|
return ItemStack.EMPTY
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ItemStackUtil.areEqualIgnoreAmounts(be.storedStack, filter)) {
|
||||||
|
return filter
|
||||||
|
}
|
||||||
|
|
||||||
|
val availableCapacity = totalCapacity - be.getStoredAmount()
|
||||||
|
return if (availableCapacity >= filter.count) {
|
||||||
|
ItemStack.EMPTY
|
||||||
|
} else {
|
||||||
|
filter.copyWithCount(filter.count - availableCapacity)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun attemptExtraction(filter: ItemFilter, maxAmount: Int, simulation: Simulation): ItemStack {
|
||||||
|
if (be.storedStack.isEmpty || !filter.matches(be.storedStack)) {
|
||||||
|
return ItemStack.EMPTY
|
||||||
|
}
|
||||||
|
|
||||||
|
val extracted = min(maxAmount, be.getStoredAmount())
|
||||||
|
|
||||||
|
if (simulation.isAction) {
|
||||||
|
be.storedStack.decrement(extracted)
|
||||||
|
}
|
||||||
|
|
||||||
|
return be.storedStack.copyWithCount(extracted)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
{
|
||||||
|
"schemaVersion": 1,
|
||||||
|
"id": "phycon_techreborn",
|
||||||
|
"version": "${version}",
|
||||||
|
|
||||||
|
"name": "PhyCon TechReborn Integration",
|
||||||
|
"description": "",
|
||||||
|
"authors": [
|
||||||
|
"Shadowfacts"
|
||||||
|
],
|
||||||
|
"contact": {
|
||||||
|
"homepage": "https://git.shadowfacts.net/minecraft/PhysicalConnectivity"
|
||||||
|
},
|
||||||
|
"license": "LGPL-3.0",
|
||||||
|
"environment": "client",
|
||||||
|
"entrypoints": {
|
||||||
|
"main": [
|
||||||
|
{
|
||||||
|
"adapter": "kotlin",
|
||||||
|
"value": "net.shadowfacts.phycon.plugin.techreborn.PhyConTR"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"mixins": [
|
||||||
|
],
|
||||||
|
"depends": {
|
||||||
|
"fabricloader": ">=0.4.0",
|
||||||
|
"fabric": "*",
|
||||||
|
"fabric-language-kotlin": ">=1.3.50",
|
||||||
|
"phycon": "*",
|
||||||
|
"techreborn": "*"
|
||||||
|
},
|
||||||
|
|
||||||
|
"custom": {
|
||||||
|
"modmenu:parent": "phycon"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -12,3 +12,4 @@ pluginManagement {
|
||||||
include("kiwi-java")
|
include("kiwi-java")
|
||||||
include("plugin:mousewheelie")
|
include("plugin:mousewheelie")
|
||||||
include("plugin:rei")
|
include("plugin:rei")
|
||||||
|
include("plugin:techreborn")
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
package net.shadowfacts.phycon.api;
|
||||||
|
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author shadowfacts
|
||||||
|
*/
|
||||||
|
public interface PhyConAPI {
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
<E extends Enum<E> & TerminalSetting> TerminalSettingKey<E> registerTerminalSetting(Identifier id, E defaultValue);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
package net.shadowfacts.phycon.api;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author shadowfacts
|
||||||
|
*/
|
||||||
|
public interface PhyConPlugin {
|
||||||
|
|
||||||
|
void initializePhyCon(PhyConAPI api);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package net.shadowfacts.phycon.api;
|
||||||
|
|
||||||
|
import net.minecraft.text.Text;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author shadowfacts
|
||||||
|
*/
|
||||||
|
public interface TerminalSetting {
|
||||||
|
|
||||||
|
Identifier getIconTexture();
|
||||||
|
|
||||||
|
int[] getUV();
|
||||||
|
|
||||||
|
@Nullable Text getTooltip();
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
package net.shadowfacts.phycon.api;
|
||||||
|
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author shadowfacts
|
||||||
|
*/
|
||||||
|
public interface TerminalSettingKey<E extends Enum<E> & TerminalSetting> {
|
||||||
|
|
||||||
|
Identifier getID();
|
||||||
|
|
||||||
|
E getValue();
|
||||||
|
|
||||||
|
}
|
|
@ -13,6 +13,7 @@ import net.shadowfacts.cacao.util.MouseButton
|
||||||
import net.shadowfacts.cacao.util.RenderHelper
|
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 java.util.*
|
import java.util.*
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -48,6 +49,9 @@ open class CacaoHandledScreen<Handler: ScreenHandler>(
|
||||||
|
|
||||||
override fun removeWindow(window: Window) {
|
override fun removeWindow(window: Window) {
|
||||||
_windows.remove(window)
|
_windows.remove(window)
|
||||||
|
if (windows.isEmpty()) {
|
||||||
|
onClose()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun init() {
|
override fun init() {
|
||||||
|
@ -151,12 +155,17 @@ open class CacaoHandledScreen<Handler: ScreenHandler>(
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun keyPressed(keyCode: Int, scanCode: Int, modifiers: Int): Boolean {
|
override fun keyPressed(keyCode: Int, scanCode: Int, modifiers: Int): Boolean {
|
||||||
|
if (keyCode == GLFW.GLFW_KEY_ESCAPE) {
|
||||||
|
windows.lastOrNull()?.removeFromScreen()
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
val modifiersSet by lazy { KeyModifiers(modifiers) }
|
val modifiersSet by lazy { KeyModifiers(modifiers) }
|
||||||
if (findResponder { it.keyPressed(keyCode, modifiersSet) }) {
|
if (findResponder { it.keyPressed(keyCode, modifiersSet) }) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return super.keyPressed(keyCode, scanCode, modifiers)
|
return super.keyPressed(keyCode, scanCode, modifiers)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun charTyped(char: Char, modifiers: Int): Boolean {
|
override fun charTyped(char: Char, modifiers: Int): Boolean {
|
||||||
val modifiersSet by lazy { KeyModifiers(modifiers) }
|
val modifiersSet by lazy { KeyModifiers(modifiers) }
|
||||||
|
@ -166,4 +175,8 @@ open class CacaoHandledScreen<Handler: ScreenHandler>(
|
||||||
return super.charTyped(char, modifiers)
|
return super.charTyped(char, modifiers)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun shouldCloseOnEsc(): Boolean {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ 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.util.RenderHelper
|
||||||
import net.shadowfacts.cacao.window.Window
|
import net.shadowfacts.cacao.window.Window
|
||||||
|
import org.lwjgl.glfw.GLFW
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -60,7 +61,9 @@ open class CacaoScreen(title: Text = LiteralText("CacaoScreen")): Screen(title),
|
||||||
*/
|
*/
|
||||||
override fun removeWindow(window: Window) {
|
override fun removeWindow(window: Window) {
|
||||||
_windows.remove(window)
|
_windows.remove(window)
|
||||||
// todo: VC callbacks
|
if (windows.isEmpty()) {
|
||||||
|
onClose()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun init() {
|
override fun init() {
|
||||||
|
@ -126,12 +129,17 @@ open class CacaoScreen(title: Text = LiteralText("CacaoScreen")): Screen(title),
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun keyPressed(keyCode: Int, scanCode: Int, modifiers: Int): Boolean {
|
override fun keyPressed(keyCode: Int, scanCode: Int, modifiers: Int): Boolean {
|
||||||
|
if (keyCode == GLFW.GLFW_KEY_ESCAPE) {
|
||||||
|
windows.lastOrNull()?.removeFromScreen()
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
val modifiersSet by lazy { KeyModifiers(modifiers) }
|
val modifiersSet by lazy { KeyModifiers(modifiers) }
|
||||||
if (findResponder { it.keyPressed(keyCode, modifiersSet) }) {
|
if (findResponder { it.keyPressed(keyCode, modifiersSet) }) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return super.keyPressed(keyCode, scanCode, modifiers)
|
return super.keyPressed(keyCode, scanCode, modifiers)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun keyReleased(i: Int, j: Int, k: Int): Boolean {
|
override fun keyReleased(i: Int, j: Int, k: Int): Boolean {
|
||||||
return super.keyReleased(i, j, k)
|
return super.keyReleased(i, j, k)
|
||||||
|
@ -145,6 +153,10 @@ open class CacaoScreen(title: Text = LiteralText("CacaoScreen")): Screen(title),
|
||||||
return super.charTyped(char, modifiers)
|
return super.charTyped(char, modifiers)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun shouldCloseOnEsc(): Boolean {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun AbstractCacaoScreen.findResponder(fn: (Responder) -> Boolean): Boolean {
|
fun AbstractCacaoScreen.findResponder(fn: (Responder) -> Boolean): Boolean {
|
||||||
|
|
|
@ -11,10 +11,12 @@ import net.shadowfacts.cacao.util.texture.Texture
|
||||||
*
|
*
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
*/
|
*/
|
||||||
class TextureView(var texture: Texture): View() {
|
class TextureView(var texture: Texture?): View() {
|
||||||
|
|
||||||
override fun drawContent(matrixStack: MatrixStack, mouse: Point, delta: Float) {
|
override fun drawContent(matrixStack: MatrixStack, mouse: Point, delta: Float) {
|
||||||
RenderHelper.draw(matrixStack, bounds, texture)
|
texture?.also {
|
||||||
|
RenderHelper.draw(matrixStack, bounds, it)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
package net.shadowfacts.phycon
|
||||||
|
|
||||||
|
import net.minecraft.util.Identifier
|
||||||
|
import net.shadowfacts.phycon.api.PhyConAPI
|
||||||
|
import net.shadowfacts.phycon.api.PhyConPlugin
|
||||||
|
import net.shadowfacts.phycon.api.TerminalSettingKey
|
||||||
|
import net.shadowfacts.phycon.util.SortMode
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author shadowfacts
|
||||||
|
*/
|
||||||
|
object DefaultPlugin: PhyConPlugin {
|
||||||
|
|
||||||
|
lateinit var SORT_MODE: TerminalSettingKey<SortMode>
|
||||||
|
private set
|
||||||
|
|
||||||
|
override fun initializePhyCon(api: PhyConAPI) {
|
||||||
|
SORT_MODE = api.registerTerminalSetting(Identifier(PhysicalConnectivity.MODID, "sort"), SortMode.COUNT_HIGH_FIRST)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package net.shadowfacts.phycon
|
||||||
|
|
||||||
|
import net.minecraft.util.Identifier
|
||||||
|
import net.shadowfacts.phycon.api.PhyConAPI
|
||||||
|
import net.shadowfacts.phycon.api.TerminalSetting
|
||||||
|
import net.shadowfacts.phycon.api.TerminalSettingKey
|
||||||
|
import net.shadowfacts.phycon.util.TerminalSettings
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author shadowfacts
|
||||||
|
*/
|
||||||
|
object PhyConAPIImpl: PhyConAPI {
|
||||||
|
|
||||||
|
override fun <E> registerTerminalSetting(id: Identifier, defaultValue: E): TerminalSettingKey<E> where E: Enum<E>, E: TerminalSetting? {
|
||||||
|
return TerminalSettings.register(id, defaultValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -2,6 +2,8 @@ package net.shadowfacts.phycon
|
||||||
|
|
||||||
import net.fabricmc.api.ModInitializer
|
import net.fabricmc.api.ModInitializer
|
||||||
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking
|
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking
|
||||||
|
import net.fabricmc.loader.api.FabricLoader
|
||||||
|
import net.shadowfacts.phycon.api.PhyConPlugin
|
||||||
import net.shadowfacts.phycon.init.PhyBlockEntities
|
import net.shadowfacts.phycon.init.PhyBlockEntities
|
||||||
import net.shadowfacts.phycon.init.PhyBlocks
|
import net.shadowfacts.phycon.init.PhyBlocks
|
||||||
import net.shadowfacts.phycon.init.PhyItems
|
import net.shadowfacts.phycon.init.PhyItems
|
||||||
|
@ -27,6 +29,10 @@ object PhysicalConnectivity: ModInitializer {
|
||||||
registerGlobalReceiver(C2STerminalRequestItem)
|
registerGlobalReceiver(C2STerminalRequestItem)
|
||||||
registerGlobalReceiver(C2STerminalUpdateDisplayedItems)
|
registerGlobalReceiver(C2STerminalUpdateDisplayedItems)
|
||||||
registerGlobalReceiver(C2SConfigureDevice)
|
registerGlobalReceiver(C2SConfigureDevice)
|
||||||
|
|
||||||
|
for (it in FabricLoader.getInstance().getEntrypoints("phycon", PhyConPlugin::class.java)) {
|
||||||
|
it.initializePhyCon(PhyConAPIImpl)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun registerGlobalReceiver(receiver: ServerReceiver) {
|
private fun registerGlobalReceiver(receiver: ServerReceiver) {
|
||||||
|
|
|
@ -14,12 +14,15 @@ import net.shadowfacts.phycon.client.PhyExtendedModelProvider
|
||||||
import net.shadowfacts.phycon.client.PhyModelProvider
|
import net.shadowfacts.phycon.client.PhyModelProvider
|
||||||
import net.shadowfacts.phycon.networking.ClientReceiver
|
import net.shadowfacts.phycon.networking.ClientReceiver
|
||||||
import net.shadowfacts.phycon.networking.S2CTerminalUpdateDisplayedItems
|
import net.shadowfacts.phycon.networking.S2CTerminalUpdateDisplayedItems
|
||||||
|
import net.shadowfacts.phycon.util.TerminalSettings
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
*/
|
*/
|
||||||
object PhysicalConnectivityClient: ClientModInitializer {
|
object PhysicalConnectivityClient: ClientModInitializer {
|
||||||
|
|
||||||
|
val terminalSettings = TerminalSettings()
|
||||||
|
|
||||||
var screenMaterial: RenderMaterial? = null
|
var screenMaterial: RenderMaterial? = null
|
||||||
private set
|
private set
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,72 @@
|
||||||
|
package net.shadowfacts.phycon.block.terminal
|
||||||
|
|
||||||
|
import net.minecraft.client.util.math.MatrixStack
|
||||||
|
import net.shadowfacts.cacao.geometry.Point
|
||||||
|
import net.shadowfacts.cacao.geometry.Size
|
||||||
|
import net.shadowfacts.cacao.util.EnumHelper
|
||||||
|
import net.shadowfacts.cacao.util.MouseButton
|
||||||
|
import net.shadowfacts.cacao.util.texture.Texture
|
||||||
|
import net.shadowfacts.cacao.view.TextureView
|
||||||
|
import net.shadowfacts.cacao.view.button.AbstractButton
|
||||||
|
import net.shadowfacts.phycon.PhysicalConnectivityClient
|
||||||
|
import net.shadowfacts.phycon.api.TerminalSetting
|
||||||
|
import net.shadowfacts.phycon.util.TerminalSettings
|
||||||
|
import java.util.EnumMap
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author shadowfacts
|
||||||
|
*/
|
||||||
|
class SettingButton<E>(
|
||||||
|
val key: TerminalSettings.SettingKey<E>,
|
||||||
|
): AbstractButton<SettingButton<E>>(
|
||||||
|
TextureView(null).apply {
|
||||||
|
intrinsicContentSize = Size(16.0, 16.0)
|
||||||
|
},
|
||||||
|
padding = 2.0
|
||||||
|
) where E: Enum<E>, E: TerminalSetting {
|
||||||
|
|
||||||
|
private val textureCache = EnumMap<E, Texture>(key.clazz)
|
||||||
|
|
||||||
|
private val textureView: TextureView
|
||||||
|
get() = content as TextureView
|
||||||
|
|
||||||
|
init {
|
||||||
|
updateTexture()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateTexture() {
|
||||||
|
textureView.texture = textureCache.getOrPut(key.value) {
|
||||||
|
val uv = key.value.uv
|
||||||
|
Texture(key.value.iconTexture, uv[0], uv[1])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun mouseClicked(point: Point, mouseButton: MouseButton): Boolean {
|
||||||
|
if (!disabled) {
|
||||||
|
val newValue = when (mouseButton) {
|
||||||
|
MouseButton.LEFT -> EnumHelper.next(key.value)
|
||||||
|
MouseButton.RIGHT -> EnumHelper.previous(key.value)
|
||||||
|
else -> {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PhysicalConnectivityClient.terminalSettings[key] = newValue
|
||||||
|
|
||||||
|
updateTexture()
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.mouseClicked(point, mouseButton)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun draw(matrixStack: MatrixStack, mouse: Point, delta: Float) {
|
||||||
|
super.draw(matrixStack, mouse, delta)
|
||||||
|
|
||||||
|
if (mouse in bounds) {
|
||||||
|
key.value.tooltip?.also {
|
||||||
|
window!!.drawTooltip(listOf(it))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,57 +0,0 @@
|
||||||
package net.shadowfacts.phycon.block.terminal
|
|
||||||
|
|
||||||
import net.minecraft.util.Identifier
|
|
||||||
import net.shadowfacts.cacao.geometry.Point
|
|
||||||
import net.shadowfacts.cacao.geometry.Size
|
|
||||||
import net.shadowfacts.cacao.util.EnumHelper
|
|
||||||
import net.shadowfacts.cacao.util.MouseButton
|
|
||||||
import net.shadowfacts.cacao.util.texture.Texture
|
|
||||||
import net.shadowfacts.cacao.view.TextureView
|
|
||||||
import net.shadowfacts.cacao.view.button.AbstractButton
|
|
||||||
import net.shadowfacts.phycon.PhysicalConnectivity
|
|
||||||
import net.shadowfacts.phycon.util.SortMode
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author shadowfacts
|
|
||||||
*/
|
|
||||||
class SortModeButton(
|
|
||||||
initialValue: SortMode,
|
|
||||||
): AbstractButton<SortModeButton>(
|
|
||||||
TextureView(TEXTURES[initialValue]!!).apply {
|
|
||||||
intrinsicContentSize = Size(16.0, 16.0)
|
|
||||||
}
|
|
||||||
) {
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
private val ID = Identifier(PhysicalConnectivity.MODID, "textures/gui/terminal.png")
|
|
||||||
private val TEXTURES = mapOf(
|
|
||||||
SortMode.COUNT_HIGH_FIRST to Texture(ID, 0, 230),
|
|
||||||
SortMode.COUNT_LOW_FIRST to Texture(ID, 16, 230),
|
|
||||||
SortMode.ALPHABETICAL to Texture(ID, 32, 230),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private val textureView: TextureView
|
|
||||||
get() = content as TextureView
|
|
||||||
|
|
||||||
var value: SortMode = initialValue
|
|
||||||
set(value) {
|
|
||||||
field = value
|
|
||||||
textureView.texture = TEXTURES[value]!!
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun mouseClicked(point: Point, mouseButton: MouseButton): Boolean {
|
|
||||||
if (!disabled) {
|
|
||||||
value = when (mouseButton) {
|
|
||||||
MouseButton.LEFT -> EnumHelper.next(value)
|
|
||||||
MouseButton.RIGHT -> EnumHelper.previous(value)
|
|
||||||
else -> {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return super.mouseClicked(point, mouseButton)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -57,6 +57,7 @@ class TerminalBlockEntity: DeviceBlockEntity(PhyBlockEntities.TERMINAL),
|
||||||
private var observers = 0
|
private var observers = 0
|
||||||
val cachedNetItems = ItemStackCollections.intMap()
|
val cachedNetItems = ItemStackCollections.intMap()
|
||||||
|
|
||||||
|
// todo: multiple players could have the terminal open simultaneously
|
||||||
var netItemObserver: WeakReference<NetItemObserver>? = null
|
var netItemObserver: WeakReference<NetItemObserver>? = null
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
@ -117,7 +118,9 @@ class TerminalBlockEntity: DeviceBlockEntity(PhyBlockEntities.TERMINAL),
|
||||||
|
|
||||||
private fun updateAndSync() {
|
private fun updateAndSync() {
|
||||||
updateNetItems()
|
updateNetItems()
|
||||||
|
// syncs the internal buffer to the client
|
||||||
sync()
|
sync()
|
||||||
|
// syncs the open container (if any) to the client
|
||||||
netItemObserver?.get()?.netItemsChanged()
|
netItemObserver?.get()?.netItemsChanged()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,14 +156,6 @@ class TerminalBlockEntity: DeviceBlockEntity(PhyBlockEntities.TERMINAL),
|
||||||
finishable.forEach(::stackLocateRequestCompleted)
|
finishable.forEach(::stackLocateRequestCompleted)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addObserver() {
|
|
||||||
observers++
|
|
||||||
}
|
|
||||||
|
|
||||||
fun removeObserver() {
|
|
||||||
observers--
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun tick() {
|
override fun tick() {
|
||||||
super.tick()
|
super.tick()
|
||||||
|
|
||||||
|
@ -171,10 +166,6 @@ class TerminalBlockEntity: DeviceBlockEntity(PhyBlockEntities.TERMINAL),
|
||||||
|
|
||||||
if (counter % 20 == 0L && !world!!.isClient) {
|
if (counter % 20 == 0L && !world!!.isClient) {
|
||||||
beginInsertions()
|
beginInsertions()
|
||||||
|
|
||||||
if (observers > 0) {
|
|
||||||
updateAndSync()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -197,7 +188,6 @@ class TerminalBlockEntity: DeviceBlockEntity(PhyBlockEntities.TERMINAL),
|
||||||
}
|
}
|
||||||
player.openHandledScreen(factory)
|
player.openHandledScreen(factory)
|
||||||
}
|
}
|
||||||
addObserver()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun requestItem(stack: ItemStack, amount: Int = stack.count) {
|
fun requestItem(stack: ItemStack, amount: Int = stack.count) {
|
||||||
|
|
|
@ -53,7 +53,6 @@ class TerminalScreen(handler: TerminalScreenHandler, playerInv: PlayerInventory,
|
||||||
|
|
||||||
var searchQuery = ""
|
var searchQuery = ""
|
||||||
var scrollPosition = 0.0
|
var scrollPosition = 0.0
|
||||||
var sortMode = SortMode.COUNT_HIGH_FIRST
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
backgroundWidth = 252
|
backgroundWidth = 252
|
||||||
|
@ -72,7 +71,7 @@ class TerminalScreen(handler: TerminalScreenHandler, playerInv: PlayerInventory,
|
||||||
|
|
||||||
fun requestUpdatedItems() {
|
fun requestUpdatedItems() {
|
||||||
val player = MinecraftClient.getInstance().player!!
|
val player = MinecraftClient.getInstance().player!!
|
||||||
player.networkHandler.sendPacket(C2STerminalUpdateDisplayedItems(handler.terminal, searchQuery, sortMode, scrollPosition.toFloat()))
|
player.networkHandler.sendPacket(C2STerminalUpdateDisplayedItems(handler.terminal, searchQuery, scrollPosition.toFloat()))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun showRequestAmountDialog(stack: ItemStack) {
|
private fun showRequestAmountDialog(stack: ItemStack) {
|
||||||
|
|
|
@ -10,11 +10,13 @@ import net.minecraft.screen.ScreenHandler
|
||||||
import net.minecraft.server.network.ServerPlayerEntity
|
import net.minecraft.server.network.ServerPlayerEntity
|
||||||
import net.minecraft.util.Identifier
|
import net.minecraft.util.Identifier
|
||||||
import net.minecraft.util.registry.Registry
|
import net.minecraft.util.registry.Registry
|
||||||
|
import net.shadowfacts.phycon.DefaultPlugin
|
||||||
import net.shadowfacts.phycon.PhysicalConnectivity
|
import net.shadowfacts.phycon.PhysicalConnectivity
|
||||||
import net.shadowfacts.phycon.init.PhyBlocks
|
import net.shadowfacts.phycon.init.PhyBlocks
|
||||||
import net.shadowfacts.phycon.init.PhyScreens
|
import net.shadowfacts.phycon.init.PhyScreens
|
||||||
import net.shadowfacts.phycon.networking.S2CTerminalUpdateDisplayedItems
|
import net.shadowfacts.phycon.networking.S2CTerminalUpdateDisplayedItems
|
||||||
import net.shadowfacts.phycon.util.SortMode
|
import net.shadowfacts.phycon.util.SortMode
|
||||||
|
import net.shadowfacts.phycon.util.TerminalSettings
|
||||||
import net.shadowfacts.phycon.util.copyWithCount
|
import net.shadowfacts.phycon.util.copyWithCount
|
||||||
import java.lang.ref.WeakReference
|
import java.lang.ref.WeakReference
|
||||||
import kotlin.math.ceil
|
import kotlin.math.ceil
|
||||||
|
@ -25,7 +27,11 @@ import kotlin.math.roundToInt
|
||||||
/**
|
/**
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
*/
|
*/
|
||||||
class TerminalScreenHandler(syncId: Int, val playerInv: PlayerInventory, val terminal: TerminalBlockEntity): ScreenHandler(PhyScreens.TERMINAL, syncId),
|
class TerminalScreenHandler(
|
||||||
|
syncId: Int,
|
||||||
|
val playerInv: PlayerInventory,
|
||||||
|
val terminal: TerminalBlockEntity,
|
||||||
|
): ScreenHandler(PhyScreens.TERMINAL, syncId),
|
||||||
TerminalBlockEntity.NetItemObserver {
|
TerminalBlockEntity.NetItemObserver {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
@ -36,8 +42,7 @@ class TerminalScreenHandler(syncId: Int, val playerInv: PlayerInventory, val ter
|
||||||
|
|
||||||
private val fakeInv = FakeInventory(this)
|
private val fakeInv = FakeInventory(this)
|
||||||
private var searchQuery: String = ""
|
private var searchQuery: String = ""
|
||||||
var sortMode = SortMode.COUNT_HIGH_FIRST
|
private var settings = TerminalSettings()
|
||||||
private set
|
|
||||||
var totalEntries = 0
|
var totalEntries = 0
|
||||||
private set
|
private set
|
||||||
var scrollPosition = 0f
|
var scrollPosition = 0f
|
||||||
|
@ -54,12 +59,17 @@ class TerminalScreenHandler(syncId: Int, val playerInv: PlayerInventory, val ter
|
||||||
private set
|
private set
|
||||||
|
|
||||||
constructor(syncId: Int, playerInv: PlayerInventory, buf: PacketByteBuf):
|
constructor(syncId: Int, playerInv: PlayerInventory, buf: PacketByteBuf):
|
||||||
this(syncId, playerInv, PhyBlocks.TERMINAL.getBlockEntity(playerInv.player.world, buf.readBlockPos())!!)
|
this(
|
||||||
|
syncId,
|
||||||
|
playerInv,
|
||||||
|
PhyBlocks.TERMINAL.getBlockEntity(playerInv.player.world, buf.readBlockPos())!!
|
||||||
|
)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
if (!terminal.world!!.isClient) {
|
if (!terminal.world!!.isClient) {
|
||||||
|
assert(terminal.netItemObserver?.get() === null)
|
||||||
terminal.netItemObserver = WeakReference(this)
|
terminal.netItemObserver = WeakReference(this)
|
||||||
netItemsChanged()
|
// intentionally don't call netItemsChanged immediately, we need to wait for the client to send us its settings
|
||||||
}
|
}
|
||||||
|
|
||||||
// network
|
// network
|
||||||
|
@ -107,7 +117,7 @@ class TerminalScreenHandler(syncId: Int, val playerInv: PlayerInventory, val ter
|
||||||
totalEntries = filtered.size
|
totalEntries = filtered.size
|
||||||
|
|
||||||
val sorted =
|
val sorted =
|
||||||
when (sortMode) {
|
when (settings[DefaultPlugin.SORT_MODE]) {
|
||||||
SortMode.COUNT_HIGH_FIRST -> filtered.sortedByDescending { it.intValue }
|
SortMode.COUNT_HIGH_FIRST -> filtered.sortedByDescending { it.intValue }
|
||||||
SortMode.COUNT_LOW_FIRST -> filtered.sortedBy { it.intValue }
|
SortMode.COUNT_LOW_FIRST -> filtered.sortedBy { it.intValue }
|
||||||
SortMode.ALPHABETICAL -> filtered.sortedBy { it.key.name.string }
|
SortMode.ALPHABETICAL -> filtered.sortedBy { it.key.name.string }
|
||||||
|
@ -120,7 +130,7 @@ class TerminalScreenHandler(syncId: Int, val playerInv: PlayerInventory, val ter
|
||||||
|
|
||||||
// itemEntries = sorted.map { Entry(it.key, it.intValue) }
|
// itemEntries = sorted.map { Entry(it.key, it.intValue) }
|
||||||
|
|
||||||
(player as ServerPlayerEntity).networkHandler.sendPacket(S2CTerminalUpdateDisplayedItems(terminal, itemEntries, searchQuery, sortMode, scrollPosition, totalEntries))
|
(player as ServerPlayerEntity).networkHandler.sendPacket(S2CTerminalUpdateDisplayedItems(terminal, itemEntries, searchQuery, settings, scrollPosition, totalEntries))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun totalRows(): Int {
|
fun totalRows(): Int {
|
||||||
|
@ -139,18 +149,17 @@ class TerminalScreenHandler(syncId: Int, val playerInv: PlayerInventory, val ter
|
||||||
return currentScrollOffsetInRows() * 9
|
return currentScrollOffsetInRows() * 9
|
||||||
}
|
}
|
||||||
|
|
||||||
fun sendUpdatedItemsToClient(player: ServerPlayerEntity, query: String, sortMode: SortMode, scrollPosition: Float) {
|
fun sendUpdatedItemsToClient(player: ServerPlayerEntity, query: String, settings: TerminalSettings, scrollPosition: Float) {
|
||||||
this.searchQuery = query
|
this.searchQuery = query
|
||||||
this.sortMode = sortMode
|
this.settings = settings
|
||||||
this.scrollPosition = scrollPosition
|
this.scrollPosition = scrollPosition
|
||||||
netItemsChanged()
|
netItemsChanged()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun receivedUpdatedItemsFromServer(entries: List<Entry>, query: String, sortMode: SortMode, scrollPosition: Float, totalEntries: Int) {
|
fun receivedUpdatedItemsFromServer(entries: List<Entry>, query: String, scrollPosition: Float, totalEntries: Int) {
|
||||||
assert(playerInv.player.world.isClient)
|
assert(playerInv.player.world.isClient)
|
||||||
|
|
||||||
this.searchQuery = query
|
this.searchQuery = query
|
||||||
this.sortMode = sortMode
|
|
||||||
this.scrollPosition = scrollPosition
|
this.scrollPosition = scrollPosition
|
||||||
this.totalEntries = totalEntries
|
this.totalEntries = totalEntries
|
||||||
itemEntries = entries
|
itemEntries = entries
|
||||||
|
@ -163,7 +172,7 @@ class TerminalScreenHandler(syncId: Int, val playerInv: PlayerInventory, val ter
|
||||||
override fun close(player: PlayerEntity) {
|
override fun close(player: PlayerEntity) {
|
||||||
super.close(player)
|
super.close(player)
|
||||||
|
|
||||||
terminal.removeObserver()
|
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): ItemStack {
|
||||||
|
|
|
@ -2,15 +2,18 @@ package net.shadowfacts.phycon.block.terminal
|
||||||
|
|
||||||
import net.minecraft.text.TranslatableText
|
import net.minecraft.text.TranslatableText
|
||||||
import net.minecraft.util.math.MathHelper
|
import net.minecraft.util.math.MathHelper
|
||||||
|
import net.shadowfacts.cacao.geometry.Axis
|
||||||
import net.shadowfacts.cacao.geometry.Point
|
import net.shadowfacts.cacao.geometry.Point
|
||||||
import net.shadowfacts.cacao.util.Color
|
import net.shadowfacts.cacao.util.Color
|
||||||
import net.shadowfacts.cacao.util.MouseButton
|
import net.shadowfacts.cacao.util.MouseButton
|
||||||
import net.shadowfacts.cacao.view.Label
|
import net.shadowfacts.cacao.view.Label
|
||||||
|
import net.shadowfacts.cacao.view.StackView
|
||||||
import net.shadowfacts.cacao.view.View
|
import net.shadowfacts.cacao.view.View
|
||||||
import net.shadowfacts.cacao.view.textfield.TextField
|
import net.shadowfacts.cacao.view.textfield.TextField
|
||||||
import net.shadowfacts.cacao.viewcontroller.ViewController
|
import net.shadowfacts.cacao.viewcontroller.ViewController
|
||||||
import net.shadowfacts.kiwidsl.dsl
|
import net.shadowfacts.kiwidsl.dsl
|
||||||
import net.shadowfacts.phycon.util.SortMode
|
import net.shadowfacts.phycon.util.SortMode
|
||||||
|
import net.shadowfacts.phycon.util.TerminalSettings
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
|
@ -22,7 +25,7 @@ class TerminalViewController(
|
||||||
): ViewController() {
|
): ViewController() {
|
||||||
|
|
||||||
private lateinit var scrollTrack: ScrollTrackView
|
private lateinit var scrollTrack: ScrollTrackView
|
||||||
lateinit var sortMode: SortModeButton
|
lateinit var settingsView: View
|
||||||
private set
|
private set
|
||||||
lateinit var searchField: TextField
|
lateinit var searchField: TextField
|
||||||
private set
|
private set
|
||||||
|
@ -84,8 +87,12 @@ class TerminalViewController(
|
||||||
|
|
||||||
scrollTrack = view.addSubview(ScrollTrackView(::scrollPositionChanged))
|
scrollTrack = view.addSubview(ScrollTrackView(::scrollPositionChanged))
|
||||||
|
|
||||||
sortMode = view.addSubview(SortModeButton(SortMode.COUNT_HIGH_FIRST)).apply {
|
val settingsStack = view.addSubview(StackView(Axis.VERTICAL, spacing = 2.0))
|
||||||
handler = ::sortModeChanged
|
settingsView = settingsStack
|
||||||
|
TerminalSettings.allKeys.forEach { key ->
|
||||||
|
val button = SettingButton(key)
|
||||||
|
button.handler = { settingsChanged() }
|
||||||
|
settingsStack.addArrangedSubview(button)
|
||||||
}
|
}
|
||||||
|
|
||||||
view.solver.dsl {
|
view.solver.dsl {
|
||||||
|
@ -108,10 +115,8 @@ class TerminalViewController(
|
||||||
scrollTrack.bottomAnchor equalTo (network.bottomAnchor - 1)
|
scrollTrack.bottomAnchor equalTo (network.bottomAnchor - 1)
|
||||||
scrollTrack.widthAnchor equalTo 12
|
scrollTrack.widthAnchor equalTo 12
|
||||||
|
|
||||||
sortMode.leftAnchor equalTo pane.rightAnchor + 4
|
settingsStack.leftAnchor equalTo (pane.rightAnchor + 4)
|
||||||
sortMode.topAnchor equalTo pane.topAnchor
|
settingsStack.topAnchor equalTo pane.topAnchor
|
||||||
sortMode.widthAnchor equalTo 20
|
|
||||||
sortMode.heightAnchor equalTo 20
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,8 +136,7 @@ class TerminalViewController(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun sortModeChanged(button: SortModeButton) {
|
private fun settingsChanged() {
|
||||||
screen.sortMode = button.value
|
|
||||||
screen.requestUpdatedItems()
|
screen.requestUpdatedItems()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,8 @@ import net.minecraft.util.registry.RegistryKey
|
||||||
import net.shadowfacts.phycon.PhysicalConnectivity
|
import net.shadowfacts.phycon.PhysicalConnectivity
|
||||||
import net.shadowfacts.phycon.block.terminal.TerminalBlockEntity
|
import net.shadowfacts.phycon.block.terminal.TerminalBlockEntity
|
||||||
import net.shadowfacts.phycon.util.copyWithCount
|
import net.shadowfacts.phycon.util.copyWithCount
|
||||||
|
import net.shadowfacts.phycon.util.readItemStackWithoutCount
|
||||||
|
import net.shadowfacts.phycon.util.writeItemStackWithoutCount
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
|
@ -28,10 +30,10 @@ object C2STerminalRequestItem: ServerReceiver {
|
||||||
buf.writeIdentifier(terminal.world!!.registryKey.value)
|
buf.writeIdentifier(terminal.world!!.registryKey.value)
|
||||||
buf.writeBlockPos(terminal.pos)
|
buf.writeBlockPos(terminal.pos)
|
||||||
|
|
||||||
// Force the count of the stack to be 1 before serializing for the network because
|
// Don't send the count of the fake stack when sending over the network because
|
||||||
// PacketByteBuf serializes the stack count as a byte. Otherwise counts > 127 will result in
|
// PacketByteBuf serializes the stack count as a byte. Otherwise counts > 127 will result in
|
||||||
// an overflow and be negative on the receiving side.
|
// an overflow and be negative on the receiving side.
|
||||||
buf.writeItemStack(stack.copyWithCount(1))
|
buf.writeItemStackWithoutCount(stack)
|
||||||
|
|
||||||
buf.writeVarInt(amount)
|
buf.writeVarInt(amount)
|
||||||
return ClientPlayNetworking.createC2SPacket(CHANNEL, buf)
|
return ClientPlayNetworking.createC2SPacket(CHANNEL, buf)
|
||||||
|
@ -40,7 +42,7 @@ object C2STerminalRequestItem: 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 stack = buf.readItemStack()
|
val stack = buf.readItemStackWithoutCount()
|
||||||
val amount = buf.readVarInt()
|
val amount = buf.readVarInt()
|
||||||
|
|
||||||
server.execute {
|
server.execute {
|
||||||
|
|
|
@ -10,9 +10,11 @@ import net.minecraft.server.network.ServerPlayNetworkHandler
|
||||||
import net.minecraft.server.network.ServerPlayerEntity
|
import net.minecraft.server.network.ServerPlayerEntity
|
||||||
import net.minecraft.util.Identifier
|
import net.minecraft.util.Identifier
|
||||||
import net.shadowfacts.phycon.PhysicalConnectivity
|
import net.shadowfacts.phycon.PhysicalConnectivity
|
||||||
|
import net.shadowfacts.phycon.PhysicalConnectivityClient
|
||||||
import net.shadowfacts.phycon.block.terminal.TerminalBlockEntity
|
import net.shadowfacts.phycon.block.terminal.TerminalBlockEntity
|
||||||
import net.shadowfacts.phycon.block.terminal.TerminalScreenHandler
|
import net.shadowfacts.phycon.block.terminal.TerminalScreenHandler
|
||||||
import net.shadowfacts.phycon.util.SortMode
|
import net.shadowfacts.phycon.util.SortMode
|
||||||
|
import net.shadowfacts.phycon.util.TerminalSettings
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
|
@ -21,14 +23,14 @@ object C2STerminalUpdateDisplayedItems: ServerReceiver {
|
||||||
|
|
||||||
override val CHANNEL = Identifier(PhysicalConnectivity.MODID, "terminal_update_displayed")
|
override val CHANNEL = Identifier(PhysicalConnectivity.MODID, "terminal_update_displayed")
|
||||||
|
|
||||||
operator fun invoke(terminal: TerminalBlockEntity, query: String, sortMode: SortMode, scrollPosition: Float): Packet<*> {
|
operator fun invoke(terminal: TerminalBlockEntity, query: String, scrollPosition: Float): Packet<*> {
|
||||||
val buf = PacketByteBufs.create()
|
val buf = PacketByteBufs.create()
|
||||||
|
|
||||||
buf.writeIdentifier(terminal.world!!.registryKey.value)
|
buf.writeIdentifier(terminal.world!!.registryKey.value)
|
||||||
buf.writeBlockPos(terminal.pos)
|
buf.writeBlockPos(terminal.pos)
|
||||||
|
|
||||||
buf.writeString(query)
|
buf.writeString(query)
|
||||||
buf.writeVarInt(sortMode.ordinal)
|
buf.writeCompoundTag(PhysicalConnectivityClient.terminalSettings.toTag())
|
||||||
buf.writeFloat(scrollPosition)
|
buf.writeFloat(scrollPosition)
|
||||||
|
|
||||||
return ClientPlayNetworking.createC2SPacket(CHANNEL, buf)
|
return ClientPlayNetworking.createC2SPacket(CHANNEL, buf)
|
||||||
|
@ -38,7 +40,8 @@ object C2STerminalUpdateDisplayedItems: ServerReceiver {
|
||||||
val dimID = buf.readIdentifier()
|
val dimID = buf.readIdentifier()
|
||||||
val pos = buf.readBlockPos()
|
val pos = buf.readBlockPos()
|
||||||
val query = buf.readString()
|
val query = buf.readString()
|
||||||
val sortMode = SortMode.values()[buf.readVarInt()]
|
val settings = TerminalSettings()
|
||||||
|
settings.fromTag(buf.readCompoundTag()!!)
|
||||||
val scrollPosition = buf.readFloat()
|
val scrollPosition = buf.readFloat()
|
||||||
|
|
||||||
server.execute {
|
server.execute {
|
||||||
|
@ -46,7 +49,7 @@ object C2STerminalUpdateDisplayedItems: ServerReceiver {
|
||||||
val screenHandler = player.currentScreenHandler
|
val screenHandler = player.currentScreenHandler
|
||||||
if (screenHandler !is TerminalScreenHandler) return@execute
|
if (screenHandler !is TerminalScreenHandler) return@execute
|
||||||
if (screenHandler.terminal.pos != pos) return@execute
|
if (screenHandler.terminal.pos != pos) return@execute
|
||||||
screenHandler.sendUpdatedItemsToClient(player, query, sortMode, scrollPosition)
|
screenHandler.sendUpdatedItemsToClient(player, query, settings, scrollPosition)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,9 +7,13 @@ import net.minecraft.client.MinecraftClient
|
||||||
import net.minecraft.client.network.ClientPlayNetworkHandler
|
import net.minecraft.client.network.ClientPlayNetworkHandler
|
||||||
import net.minecraft.network.Packet
|
import net.minecraft.network.Packet
|
||||||
import net.minecraft.network.PacketByteBuf
|
import net.minecraft.network.PacketByteBuf
|
||||||
|
import net.shadowfacts.phycon.PhysicalConnectivityClient
|
||||||
import net.shadowfacts.phycon.block.terminal.TerminalBlockEntity
|
import net.shadowfacts.phycon.block.terminal.TerminalBlockEntity
|
||||||
import net.shadowfacts.phycon.block.terminal.TerminalScreenHandler
|
import net.shadowfacts.phycon.block.terminal.TerminalScreenHandler
|
||||||
import net.shadowfacts.phycon.util.SortMode
|
import net.shadowfacts.phycon.util.SortMode
|
||||||
|
import net.shadowfacts.phycon.util.TerminalSettings
|
||||||
|
import net.shadowfacts.phycon.util.readItemStackWithoutCount
|
||||||
|
import net.shadowfacts.phycon.util.writeItemStackWithoutCount
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
|
@ -17,7 +21,7 @@ import net.shadowfacts.phycon.util.SortMode
|
||||||
object S2CTerminalUpdateDisplayedItems: ClientReceiver {
|
object S2CTerminalUpdateDisplayedItems: ClientReceiver {
|
||||||
override val CHANNEL = C2STerminalUpdateDisplayedItems.CHANNEL
|
override val CHANNEL = C2STerminalUpdateDisplayedItems.CHANNEL
|
||||||
|
|
||||||
operator fun invoke(terminal: TerminalBlockEntity, entries: List<TerminalScreenHandler.Entry>, query: String, sortMode: SortMode, scrollPosition: Float, totalEntries: Int): Packet<*> {
|
operator fun invoke(terminal: TerminalBlockEntity, entries: List<TerminalScreenHandler.Entry>, query: String, settings: TerminalSettings, scrollPosition: Float, totalEntries: Int): Packet<*> {
|
||||||
val buf = PacketByteBufs.create()
|
val buf = PacketByteBufs.create()
|
||||||
|
|
||||||
buf.writeIdentifier(terminal.world!!.registryKey.value)
|
buf.writeIdentifier(terminal.world!!.registryKey.value)
|
||||||
|
@ -25,12 +29,12 @@ object S2CTerminalUpdateDisplayedItems: ClientReceiver {
|
||||||
|
|
||||||
buf.writeVarInt(entries.size)
|
buf.writeVarInt(entries.size)
|
||||||
for (e in entries) {
|
for (e in entries) {
|
||||||
buf.writeItemStack(e.stack)
|
buf.writeItemStackWithoutCount(e.stack)
|
||||||
buf.writeVarInt(e.amount)
|
buf.writeVarInt(e.amount)
|
||||||
}
|
}
|
||||||
|
|
||||||
buf.writeString(query)
|
buf.writeString(query)
|
||||||
buf.writeVarInt(sortMode.ordinal)
|
buf.writeCompoundTag(settings.toTag())
|
||||||
buf.writeFloat(scrollPosition)
|
buf.writeFloat(scrollPosition)
|
||||||
buf.writeInt(totalEntries)
|
buf.writeInt(totalEntries)
|
||||||
|
|
||||||
|
@ -43,10 +47,10 @@ object S2CTerminalUpdateDisplayedItems: ClientReceiver {
|
||||||
val entryCount = buf.readVarInt()
|
val entryCount = buf.readVarInt()
|
||||||
val entries = ArrayList<TerminalScreenHandler.Entry>(entryCount)
|
val entries = ArrayList<TerminalScreenHandler.Entry>(entryCount)
|
||||||
for (i in 0 until entryCount) {
|
for (i in 0 until entryCount) {
|
||||||
entries.add(TerminalScreenHandler.Entry(buf.readItemStack(), buf.readVarInt()))
|
entries.add(TerminalScreenHandler.Entry(buf.readItemStackWithoutCount(), buf.readVarInt()))
|
||||||
}
|
}
|
||||||
val query = buf.readString()
|
val query = buf.readString()
|
||||||
val sortMode = SortMode.values()[buf.readVarInt()]
|
PhysicalConnectivityClient.terminalSettings.fromTag(buf.readCompoundTag()!!)
|
||||||
val scrollPosition = buf.readFloat()
|
val scrollPosition = buf.readFloat()
|
||||||
val totalEntries = buf.readInt()
|
val totalEntries = buf.readInt()
|
||||||
|
|
||||||
|
@ -55,7 +59,7 @@ object S2CTerminalUpdateDisplayedItems: ClientReceiver {
|
||||||
val screenHandler = client.player!!.currentScreenHandler
|
val screenHandler = client.player!!.currentScreenHandler
|
||||||
if (screenHandler !is TerminalScreenHandler) return@execute
|
if (screenHandler !is TerminalScreenHandler) return@execute
|
||||||
if (screenHandler.terminal.pos != pos) return@execute
|
if (screenHandler.terminal.pos != pos) return@execute
|
||||||
screenHandler.receivedUpdatedItemsFromServer(entries, query, sortMode, scrollPosition, totalEntries)
|
screenHandler.receivedUpdatedItemsFromServer(entries, query, scrollPosition, totalEntries)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
package net.shadowfacts.phycon.util
|
||||||
|
|
||||||
|
import net.minecraft.item.Item
|
||||||
|
import net.minecraft.item.ItemStack
|
||||||
|
import net.minecraft.nbt.CompoundTag
|
||||||
|
import net.minecraft.network.PacketByteBuf
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author shadowfacts
|
||||||
|
*/
|
||||||
|
fun PacketByteBuf.writeItemStackWithoutCount(stack: ItemStack) {
|
||||||
|
if (stack.isEmpty) {
|
||||||
|
writeBoolean(false)
|
||||||
|
} else {
|
||||||
|
writeBoolean(true)
|
||||||
|
writeVarInt(Item.getRawId(stack.item))
|
||||||
|
val tag: CompoundTag? =
|
||||||
|
if (stack.item.isDamageable || stack.item.shouldSyncTagToClient()) {
|
||||||
|
stack.tag
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
writeCompoundTag(tag)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun PacketByteBuf.readItemStackWithoutCount(): ItemStack {
|
||||||
|
return if (!readBoolean()) {
|
||||||
|
ItemStack.EMPTY
|
||||||
|
} else {
|
||||||
|
val id = readVarInt()
|
||||||
|
val count = 1
|
||||||
|
val stack = ItemStack(Item.byRawId(id), count)
|
||||||
|
stack.tag = readCompoundTag()
|
||||||
|
stack
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,17 +2,27 @@ package net.shadowfacts.phycon.util
|
||||||
|
|
||||||
import net.minecraft.text.LiteralText
|
import net.minecraft.text.LiteralText
|
||||||
import net.minecraft.text.Text
|
import net.minecraft.text.Text
|
||||||
|
import net.minecraft.util.Identifier
|
||||||
|
import net.shadowfacts.phycon.PhysicalConnectivity
|
||||||
|
import net.shadowfacts.phycon.api.TerminalSetting
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
*/
|
*/
|
||||||
enum class SortMode: RotatableEnum {
|
enum class SortMode: TerminalSetting {
|
||||||
COUNT_HIGH_FIRST,
|
COUNT_HIGH_FIRST,
|
||||||
COUNT_LOW_FIRST,
|
COUNT_LOW_FIRST,
|
||||||
ALPHABETICAL;
|
ALPHABETICAL;
|
||||||
|
|
||||||
val tooltip: Text
|
override fun getIconTexture() = Identifier(PhysicalConnectivity.MODID, "textures/gui/terminal.png")
|
||||||
get() = when (this) {
|
|
||||||
|
override fun getUV() = when (this) {
|
||||||
|
COUNT_HIGH_FIRST -> intArrayOf(0, 230)
|
||||||
|
COUNT_LOW_FIRST -> intArrayOf(16, 230)
|
||||||
|
ALPHABETICAL -> intArrayOf(32, 230)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getTooltip() = when (this) {
|
||||||
COUNT_HIGH_FIRST -> LiteralText("Count, highest first")
|
COUNT_HIGH_FIRST -> LiteralText("Count, highest first")
|
||||||
COUNT_LOW_FIRST -> LiteralText("Count, lowest first")
|
COUNT_LOW_FIRST -> LiteralText("Count, lowest first")
|
||||||
ALPHABETICAL -> LiteralText("Name")
|
ALPHABETICAL -> LiteralText("Name")
|
||||||
|
|
|
@ -0,0 +1,83 @@
|
||||||
|
package net.shadowfacts.phycon.util
|
||||||
|
|
||||||
|
import net.minecraft.nbt.CompoundTag
|
||||||
|
import net.minecraft.util.Identifier
|
||||||
|
import net.shadowfacts.phycon.PhysicalConnectivityClient
|
||||||
|
import net.shadowfacts.phycon.api.TerminalSettingKey
|
||||||
|
import net.shadowfacts.phycon.api.TerminalSetting
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author shadowfacts
|
||||||
|
*/
|
||||||
|
class TerminalSettings {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val SETTINGS = mutableMapOf<Identifier, SettingKey<*>>()
|
||||||
|
private val DEFAULTS = mutableMapOf<TerminalSettingKey<*>, Enum<*>>()
|
||||||
|
|
||||||
|
val allKeys: Collection<SettingKey<*>>
|
||||||
|
get() = SETTINGS.values
|
||||||
|
|
||||||
|
fun <E> register(id: Identifier, defaultValue: E): SettingKey<E> where E: Enum<E>, E: TerminalSetting {
|
||||||
|
val setting = SettingKey(id, defaultValue.javaClass)
|
||||||
|
SETTINGS[id] = setting
|
||||||
|
DEFAULTS[setting] = defaultValue
|
||||||
|
return setting
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <E> getDefault(setting: TerminalSettingKey<E>): E where E: Enum<E>, E: TerminalSetting {
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
return DEFAULTS[setting] as E
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class SettingKey<E>(
|
||||||
|
val id: Identifier,
|
||||||
|
val clazz: Class<E>,
|
||||||
|
): TerminalSettingKey<E> where E: Enum<E>, E: TerminalSetting {
|
||||||
|
fun value(ordinal: Int): E? {
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
return if (clazz.enumConstants.size <= ordinal) null
|
||||||
|
else clazz.enumConstants[ordinal] as E
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getID() = id
|
||||||
|
override fun getValue() = PhysicalConnectivityClient.terminalSettings[this]
|
||||||
|
}
|
||||||
|
|
||||||
|
private val settings = mutableMapOf<TerminalSettingKey<*>, Enum<*>>()
|
||||||
|
|
||||||
|
operator fun <E> get(key: TerminalSettingKey<E>): E where E: Enum<E>, E: TerminalSetting {
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
return settings[key] as? E ?: getDefault(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
operator fun <E> set(key: SettingKey<E>, value: E) where E: Enum<E>, E: TerminalSetting {
|
||||||
|
settings[key] = value
|
||||||
|
}
|
||||||
|
|
||||||
|
fun toTag(): CompoundTag {
|
||||||
|
return CompoundTag().also {
|
||||||
|
settings.forEach { (s, v) ->
|
||||||
|
it.putInt(s.id.toString(), v.ordinal)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun fromTag(tag: CompoundTag) {
|
||||||
|
settings.clear()
|
||||||
|
tag.keys.forEach { k ->
|
||||||
|
val id = Identifier.tryParse(k) ?: return@forEach
|
||||||
|
val setting = SETTINGS[id] ?: return@forEach
|
||||||
|
setValueFromOrdinal(setting, tag.getInt(k))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun <E> setValueFromOrdinal(setting: SettingKey<E>, ordinal: Int) where E: Enum<E>, E: TerminalSetting {
|
||||||
|
val value = setting.value(ordinal)
|
||||||
|
if (value != null) {
|
||||||
|
this[setting] = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -35,6 +35,12 @@
|
||||||
"adapter": "kotlin",
|
"adapter": "kotlin",
|
||||||
"value": "net.shadowfacts.phycon.PhysicalConnectivityClient"
|
"value": "net.shadowfacts.phycon.PhysicalConnectivityClient"
|
||||||
}
|
}
|
||||||
|
],
|
||||||
|
"phycon": [
|
||||||
|
{
|
||||||
|
"adapter": "kotlin",
|
||||||
|
"value": "net.shadowfacts.phycon.DefaultPlugin"
|
||||||
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"mixins": [
|
"mixins": [
|
||||||
|
|
Loading…
Reference in New Issue