Blanket reformat
This commit is contained in:
parent
4effe2f1b4
commit
f6f4c12d03
|
@ -17,7 +17,7 @@ import java.lang.invoke.MethodHandles
|
||||||
/**
|
/**
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
*/
|
*/
|
||||||
object PhyConPluginClient: ClientModInitializer, REIClientPlugin, AbstractTerminalScreen.SearchQueryListener {
|
object PhyConPluginClient : ClientModInitializer, REIClientPlugin, AbstractTerminalScreen.SearchQueryListener {
|
||||||
|
|
||||||
private val logger = LogManager.getLogger()
|
private val logger = LogManager.getLogger()
|
||||||
private var isHighlightingHandle: MethodHandle? = null
|
private var isHighlightingHandle: MethodHandle? = null
|
||||||
|
@ -39,7 +39,8 @@ object PhyConPluginClient: ClientModInitializer, REIClientPlugin, AbstractTermin
|
||||||
AbstractTerminalScreen.searchQueryListener = this
|
AbstractTerminalScreen.searchQueryListener = this
|
||||||
try {
|
try {
|
||||||
val clazz = Class.forName("me.shedaniel.rei.impl.client.gui.widget.search.OverlaySearchField")
|
val clazz = Class.forName("me.shedaniel.rei.impl.client.gui.widget.search.OverlaySearchField")
|
||||||
isHighlightingHandle = MethodHandles.publicLookup().findStaticGetter(clazz, "isHighlighting", Boolean::class.java)
|
isHighlightingHandle =
|
||||||
|
MethodHandles.publicLookup().findStaticGetter(clazz, "isHighlighting", Boolean::class.java)
|
||||||
} catch (e: ReflectiveOperationException) {
|
} catch (e: ReflectiveOperationException) {
|
||||||
logger.warn("Unable to find OverlaySearchField.isHighlighting, highlight sync will be disabled", e)
|
logger.warn("Unable to find OverlaySearchField.isHighlighting, highlight sync will be disabled", e)
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,23 +18,27 @@ import java.util.stream.IntStream
|
||||||
/**
|
/**
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
*/
|
*/
|
||||||
object PhyConPluginCommon: REIServerPlugin, PhyConPlugin {
|
object PhyConPluginCommon : REIServerPlugin, PhyConPlugin {
|
||||||
const val MODID = "phycon_rei"
|
const val MODID = "phycon_rei"
|
||||||
|
|
||||||
lateinit var REI_SYNC_KEY: TerminalSettingKey<REISyncMode>
|
lateinit var REI_SYNC_KEY: TerminalSettingKey<REISyncMode>
|
||||||
private set
|
private set
|
||||||
|
|
||||||
override fun registerMenuInfo(registry: MenuInfoRegistry) {
|
override fun registerMenuInfo(registry: MenuInfoRegistry) {
|
||||||
registry.register(CategoryIdentifier.of("minecraft", "plugins/crafting"), CraftingTerminalScreenHandler::class.java, SimpleMenuInfoProvider.of(::TerminalInfo))
|
registry.register(
|
||||||
|
CategoryIdentifier.of("minecraft", "plugins/crafting"),
|
||||||
|
CraftingTerminalScreenHandler::class.java,
|
||||||
|
SimpleMenuInfoProvider.of(::TerminalInfo)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun initializePhyCon(api: PhyConAPI) {
|
override fun initializePhyCon(api: PhyConAPI) {
|
||||||
REI_SYNC_KEY = api.registerTerminalSetting(Identifier(MODID, "rei_sync"), REISyncMode.OFF)
|
REI_SYNC_KEY = api.registerTerminalSetting(Identifier(MODID, "rei_sync"), REISyncMode.OFF)
|
||||||
}
|
}
|
||||||
|
|
||||||
class TerminalInfo<D: SimpleGridMenuDisplay>(
|
class TerminalInfo<D : SimpleGridMenuDisplay>(
|
||||||
private val display: D,
|
private val display: D,
|
||||||
): SimpleGridMenuInfo<CraftingTerminalScreenHandler, D> {
|
) : SimpleGridMenuInfo<CraftingTerminalScreenHandler, D> {
|
||||||
|
|
||||||
override fun getCraftingResultSlotIndex(menu: CraftingTerminalScreenHandler): Int {
|
override fun getCraftingResultSlotIndex(menu: CraftingTerminalScreenHandler): Int {
|
||||||
return menu.resultSlot.id
|
return menu.resultSlot.id
|
||||||
|
|
|
@ -8,7 +8,7 @@ import net.shadowfacts.phycon.api.TerminalSetting
|
||||||
/**
|
/**
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
*/
|
*/
|
||||||
enum class REISyncMode: TerminalSetting {
|
enum class REISyncMode : TerminalSetting {
|
||||||
OFF,
|
OFF,
|
||||||
ON,
|
ON,
|
||||||
HIGHLIGHT_ONLY;
|
HIGHLIGHT_ONLY;
|
||||||
|
|
|
@ -14,15 +14,24 @@ import techreborn.init.TRContent
|
||||||
/**
|
/**
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
*/
|
*/
|
||||||
object PhyConTR: ModInitializer {
|
object PhyConTR : ModInitializer {
|
||||||
|
|
||||||
override fun onInitialize() {
|
override fun onInitialize() {
|
||||||
TRContent.StorageUnit.values().forEach {
|
TRContent.StorageUnit.values().forEach {
|
||||||
ItemAttributes.GROUPED_INV.setBlockAdder(AttributeSourceType.COMPAT_WRAPPER, it.block, ::addStorageUnitGroupedInv)
|
ItemAttributes.GROUPED_INV.setBlockAdder(
|
||||||
|
AttributeSourceType.COMPAT_WRAPPER,
|
||||||
|
it.block,
|
||||||
|
::addStorageUnitGroupedInv
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addStorageUnitGroupedInv(world: World, pos: BlockPos, state: BlockState, to: AttributeList<GroupedItemInv>) {
|
private fun addStorageUnitGroupedInv(
|
||||||
|
world: World,
|
||||||
|
pos: BlockPos,
|
||||||
|
state: BlockState,
|
||||||
|
to: AttributeList<GroupedItemInv>
|
||||||
|
) {
|
||||||
(world.getBlockEntity(pos) as? StorageUnitBaseBlockEntity)?.also { su ->
|
(world.getBlockEntity(pos) as? StorageUnitBaseBlockEntity)?.also { su ->
|
||||||
to.offer(StorageUnitWrapper(su))
|
to.offer(StorageUnitWrapper(su))
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ import kotlin.math.min
|
||||||
*/
|
*/
|
||||||
class StorageUnitWrapper(
|
class StorageUnitWrapper(
|
||||||
val be: StorageUnitBaseBlockEntity,
|
val be: StorageUnitBaseBlockEntity,
|
||||||
): GroupedItemInv {
|
) : GroupedItemInv {
|
||||||
|
|
||||||
override fun getStoredStacks(): Set<ItemStack> {
|
override fun getStoredStacks(): Set<ItemStack> {
|
||||||
val set = ItemStackCollections.set()
|
val set = ItemStackCollections.set()
|
||||||
|
|
|
@ -16,6 +16,7 @@ public interface Interface {
|
||||||
|
|
||||||
void send(@NotNull EthernetFrame frame);
|
void send(@NotNull EthernetFrame frame);
|
||||||
|
|
||||||
default void cableDisconnected() {}
|
default void cableDisconnected() {
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,9 +10,9 @@ public interface NetworkDevice {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The IP address of this device.
|
* The IP address of this device.
|
||||||
*
|
* <p>
|
||||||
* If a device has not been assigned an address by a DHCP server, it may self-assign a randomly generated one.
|
* If a device has not been assigned an address by a DHCP server, it may self-assign a randomly generated one.
|
||||||
*
|
* <p>
|
||||||
* The address of a network device should never be the broadcast address.
|
* The address of a network device should never be the broadcast address.
|
||||||
*
|
*
|
||||||
* @return The IP address of this device.
|
* @return The IP address of this device.
|
||||||
|
|
|
@ -13,6 +13,7 @@ public interface TerminalSetting {
|
||||||
|
|
||||||
int[] getUV();
|
int[] getUV();
|
||||||
|
|
||||||
@Nullable Text getTooltip();
|
@Nullable
|
||||||
|
Text getTooltip();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,12 +23,14 @@ public final class IPAddress {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final Random ipAddressRandom = new Random();
|
private static final Random ipAddressRandom = new Random();
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static IPAddress random() {
|
public static IPAddress random() {
|
||||||
return random(ipAddressRandom);
|
return random(ipAddressRandom);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final Pattern IP_PATTERN = Pattern.compile("^(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})$");
|
private static final Pattern IP_PATTERN = Pattern.compile("^(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})$");
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public static IPAddress parse(String s) {
|
public static IPAddress parse(String s) {
|
||||||
Matcher matcher = IP_PATTERN.matcher(s);
|
Matcher matcher = IP_PATTERN.matcher(s);
|
||||||
|
|
|
@ -22,6 +22,7 @@ public final class MACAddress {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final Random macAddressRandom = new Random();
|
private static final Random macAddressRandom = new Random();
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static MACAddress random() {
|
public static MACAddress random() {
|
||||||
return random(macAddressRandom);
|
return random(macAddressRandom);
|
||||||
|
@ -61,7 +62,7 @@ public final class MACAddress {
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
MACAddress that = (MACAddress)o;
|
MACAddress that = (MACAddress) o;
|
||||||
return address == that.address;
|
return address == that.address;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ public class MixinHandledScreen {
|
||||||
at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/systems/RenderSystem;enableDepthTest()V")
|
at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/systems/RenderSystem;enableDepthTest()V")
|
||||||
)
|
)
|
||||||
private void drawSlotUnderlay(MatrixStack matrixStack, Slot slot, CallbackInfo ci) {
|
private void drawSlotUnderlay(MatrixStack matrixStack, Slot slot, CallbackInfo ci) {
|
||||||
if ((Object)this instanceof AbstractTerminalScreen<?, ?> self) {
|
if ((Object) this instanceof AbstractTerminalScreen<?, ?> self) {
|
||||||
self.drawSlotUnderlay(matrixStack, slot);
|
self.drawSlotUnderlay(matrixStack, slot);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@ public class MixinHandledScreen {
|
||||||
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/item/ItemRenderer;renderGuiItemOverlay(Lnet/minecraft/client/font/TextRenderer;Lnet/minecraft/item/ItemStack;IILjava/lang/String;)V")
|
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/item/ItemRenderer;renderGuiItemOverlay(Lnet/minecraft/client/font/TextRenderer;Lnet/minecraft/item/ItemStack;IILjava/lang/String;)V")
|
||||||
)
|
)
|
||||||
private void drawSlotAmount(ItemRenderer itemRenderer, TextRenderer textRenderer, ItemStack stack, int x, int y, @Nullable String countLabel, MatrixStack matrixStack, Slot slot) {
|
private void drawSlotAmount(ItemRenderer itemRenderer, TextRenderer textRenderer, ItemStack stack, int x, int y, @Nullable String countLabel, MatrixStack matrixStack, Slot slot) {
|
||||||
if ((Object)this instanceof AbstractTerminalScreen<?, ?> self) {
|
if ((Object) this instanceof AbstractTerminalScreen<?, ?> self) {
|
||||||
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);
|
self.drawNetworkSlotAmount(stack, x, y);
|
||||||
|
|
|
@ -9,8 +9,8 @@ interface AbstractCacaoScreen {
|
||||||
|
|
||||||
val windows: List<Window>
|
val windows: List<Window>
|
||||||
|
|
||||||
fun <T: Window> addWindow(window: T, index: Int): T
|
fun <T : Window> addWindow(window: T, index: Int): T
|
||||||
fun <T: Window> addWindow(window: T): T
|
fun <T : Window> addWindow(window: T): T
|
||||||
|
|
||||||
fun removeWindow(window: Window)
|
fun removeWindow(window: Window)
|
||||||
|
|
||||||
|
|
|
@ -20,11 +20,11 @@ import java.util.*
|
||||||
/**
|
/**
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
*/
|
*/
|
||||||
open class CacaoHandledScreen<Handler: ScreenHandler>(
|
open class CacaoHandledScreen<Handler : ScreenHandler>(
|
||||||
handler: Handler,
|
handler: Handler,
|
||||||
playerInv: PlayerInventory,
|
playerInv: PlayerInventory,
|
||||||
title: Text,
|
title: Text,
|
||||||
): HandledScreen<Handler>(handler, playerInv, title), AbstractCacaoScreen {
|
) : HandledScreen<Handler>(handler, playerInv, title), AbstractCacaoScreen {
|
||||||
|
|
||||||
private val _windows = LinkedList<Window>()
|
private val _windows = LinkedList<Window>()
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ open class CacaoHandledScreen<Handler: ScreenHandler>(
|
||||||
private var hasAppeared = false
|
private var hasAppeared = false
|
||||||
|
|
||||||
|
|
||||||
override fun <T: Window> addWindow(window: T, index: Int): T {
|
override fun <T : Window> addWindow(window: T, index: Int): T {
|
||||||
if (window is ScreenHandlerWindow && window.screenHandler != handler) {
|
if (window is ScreenHandlerWindow && window.screenHandler != handler) {
|
||||||
throw RuntimeException("Adding ScreenHandlerWindow to CacaoHandledScreen with different screen handler is not supported")
|
throw RuntimeException("Adding ScreenHandlerWindow to CacaoHandledScreen with different screen handler is not supported")
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,10 +20,11 @@ import java.util.*
|
||||||
*
|
*
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
*/
|
*/
|
||||||
open class CacaoScreen(title: Text = LiteralText("CacaoScreen")): Screen(title), AbstractCacaoScreen {
|
open class CacaoScreen(title: Text = LiteralText("CacaoScreen")) : Screen(title), AbstractCacaoScreen {
|
||||||
|
|
||||||
// _windows is the internal, mutable object, since we only want it to by mutated by the add/removeWindow methods.
|
// _windows is the internal, mutable object, since we only want it to by mutated by the add/removeWindow methods.
|
||||||
private val _windows = LinkedList<Window>()
|
private val _windows = LinkedList<Window>()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The list of windows that belong to this screen.
|
* The list of windows that belong to this screen.
|
||||||
*
|
*
|
||||||
|
@ -42,7 +43,7 @@ open class CacaoScreen(title: Text = LiteralText("CacaoScreen")): Screen(title),
|
||||||
* @param index The index to insert the window into the window list at.
|
* @param index The index to insert the window into the window list at.
|
||||||
* @return The window that was added, as a convenience.
|
* @return The window that was added, as a convenience.
|
||||||
*/
|
*/
|
||||||
override fun <T: Window> addWindow(window: T, index: Int): T {
|
override fun <T : Window> addWindow(window: T, index: Int): T {
|
||||||
if (hasAppeared) {
|
if (hasAppeared) {
|
||||||
window.viewController.viewWillAppear()
|
window.viewController.viewWillAppear()
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,10 +14,10 @@ class LayoutVariable(
|
||||||
val view: View?,
|
val view: View?,
|
||||||
val layoutGuide: LayoutGuide?,
|
val layoutGuide: LayoutGuide?,
|
||||||
val property: String,
|
val property: String,
|
||||||
): Variable("LayoutVariable") {
|
) : Variable("LayoutVariable") {
|
||||||
|
|
||||||
constructor(view: View, property: String): this(view, null, property)
|
constructor(view: View, property: String) : this(view, null, property)
|
||||||
constructor(layoutGuide: LayoutGuide, property: String): this(null, layoutGuide, property)
|
constructor(layoutGuide: LayoutGuide, property: String) : this(null, layoutGuide, property)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
if ((view == null) == (layoutGuide == null)) {
|
if ((view == null) == (layoutGuide == null)) {
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
# Cacao
|
# Cacao
|
||||||
|
|
||||||
Cacao is a UI framework for Fabric/Minecraft mods based on Apple's [Cocoa](https://en.wikipedia.org/wiki/Cocoa_(API)
|
Cacao is a UI framework for Fabric/Minecraft mods based on Apple's [Cocoa](https://en.wikipedia.org/wiki/Cocoa_(API)
|
||||||
UI toolkit.
|
UI toolkit.
|
||||||
|
|
||||||
## Architecture
|
## Architecture
|
||||||
|
|
||||||
### Screen
|
### Screen
|
||||||
|
|
||||||
A [CacaoScreen][] is the object that acts as the interface between Minecraft GUI code and the Cacao framework.
|
A [CacaoScreen][] is the object that acts as the interface between Minecraft GUI code and the Cacao framework.
|
||||||
|
|
||||||
The CacaoScreen draws Cacao views on screen and passes Minecraft input events to the appropriate Views. The CacaoScreen
|
The CacaoScreen draws Cacao views on screen and passes Minecraft input events to the appropriate Views. The CacaoScreen
|
||||||
|
@ -12,6 +15,7 @@ owns a group of [Window](#window) objects which are displayed on screen, one on
|
||||||
[CacaoScreen]: https://git.shadowfacts.net/minecraft/ASMR/src/branch/master/src/main/kotlin/net/shadowfacts/cacao/CacaoScreen.kt
|
[CacaoScreen]: https://git.shadowfacts.net/minecraft/ASMR/src/branch/master/src/main/kotlin/net/shadowfacts/cacao/CacaoScreen.kt
|
||||||
|
|
||||||
### Window
|
### Window
|
||||||
|
|
||||||
A [Window][] object has a root [View Controller](#view-controller) that it displays on screen.
|
A [Window][] object has a root [View Controller](#view-controller) that it displays on screen.
|
||||||
|
|
||||||
The Window occupies the entire screen space and translates events from the screen to the root View Controller's View.
|
The Window occupies the entire screen space and translates events from the screen to the root View Controller's View.
|
||||||
|
@ -21,6 +25,7 @@ view hierarchy.
|
||||||
[Window]: https://git.shadowfacts.net/minecraft/ASMR/src/branch/master/src/main/kotlin/net/shadowfacts/cacao/Window.kt
|
[Window]: https://git.shadowfacts.net/minecraft/ASMR/src/branch/master/src/main/kotlin/net/shadowfacts/cacao/Window.kt
|
||||||
|
|
||||||
### View Controller
|
### View Controller
|
||||||
|
|
||||||
A [ViewController][] object owns a view, receives lifecycle events for it, and is generally used to control the view.
|
A [ViewController][] object owns a view, receives lifecycle events for it, and is generally used to control the view.
|
||||||
|
|
||||||
Each View Controller has a single root [View](#view) which in turn may have subviews.
|
Each View Controller has a single root [View](#view) which in turn may have subviews.
|
||||||
|
@ -28,6 +33,7 @@ Each View Controller has a single root [View](#view) which in turn may have subv
|
||||||
[ViewController]: https://git.shadowfacts.net/minecraft/ASMR/src/branch/master/src/main/kotlin/net/shadowfacts/cacao/viewcontroller/ViewController.kt
|
[ViewController]: https://git.shadowfacts.net/minecraft/ASMR/src/branch/master/src/main/kotlin/net/shadowfacts/cacao/viewcontroller/ViewController.kt
|
||||||
|
|
||||||
### View
|
### View
|
||||||
|
|
||||||
A [View][] object represents a single view on screen. It handles drawing, positioning, and directly handles input.
|
A [View][] object represents a single view on screen. It handles drawing, positioning, and directly handles input.
|
||||||
|
|
||||||
[View]: https://git.shadowfacts.net/minecraft/ASMR/src/branch/master/src/main/kotlin/net/shadowfacts/cacao/view/View.kt
|
[View]: https://git.shadowfacts.net/minecraft/ASMR/src/branch/master/src/main/kotlin/net/shadowfacts/cacao/view/View.kt
|
||||||
|
|
|
@ -10,10 +10,12 @@ enum class AxisPosition {
|
||||||
* Top for vertical, left for horizontal.
|
* Top for vertical, left for horizontal.
|
||||||
*/
|
*/
|
||||||
LEADING,
|
LEADING,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Center X/Y.
|
* Center X/Y.
|
||||||
*/
|
*/
|
||||||
CENTER,
|
CENTER,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bottom for vertical, right for horizontal.
|
* Bottom for vertical, right for horizontal.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -7,7 +7,7 @@ package net.shadowfacts.cacao.geometry
|
||||||
*/
|
*/
|
||||||
data class Point(val x: Double, val y: Double) {
|
data class Point(val x: Double, val y: Double) {
|
||||||
|
|
||||||
constructor(x: Int, y: Int): this(x.toDouble(), y.toDouble())
|
constructor(x: Int, y: Int) : this(x.toDouble(), y.toDouble())
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val ORIGIN = Point(0.0, 0.0)
|
val ORIGIN = Point(0.0, 0.0)
|
||||||
|
|
|
@ -7,7 +7,7 @@ package net.shadowfacts.cacao.geometry
|
||||||
*/
|
*/
|
||||||
data class Rect(val left: Double, val top: Double, val width: Double, val height: Double) {
|
data class Rect(val left: Double, val top: Double, val width: Double, val height: Double) {
|
||||||
|
|
||||||
constructor(origin: Point, size: Size): this(origin.x, origin.y, size.width, size.height)
|
constructor(origin: Point, size: Size) : this(origin.x, origin.y, size.width, size.height)
|
||||||
|
|
||||||
val right: Double by lazy {
|
val right: Double by lazy {
|
||||||
left + width
|
left + width
|
||||||
|
|
|
@ -14,7 +14,7 @@ data class Color(val red: Int, val green: Int, val blue: Int, val alpha: Int = 2
|
||||||
/**
|
/**
|
||||||
* Constructs a color from the packed RGB color.
|
* Constructs a color from the packed RGB color.
|
||||||
*/
|
*/
|
||||||
constructor(rgb: Int, alpha: Int = 255): this(rgb shr 16, (rgb shr 8) and 255, rgb and 255, alpha)
|
constructor(rgb: Int, alpha: Int = 255) : this(rgb shr 16, (rgb shr 8) and 255, rgb and 255, alpha)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The ARGB packed representation of this color.
|
* The ARGB packed representation of this color.
|
||||||
|
|
|
@ -5,13 +5,13 @@ package net.shadowfacts.cacao.util
|
||||||
*/
|
*/
|
||||||
object EnumHelper {
|
object EnumHelper {
|
||||||
|
|
||||||
fun <E: Enum<E>> next(value: E): E {
|
fun <E : Enum<E>> next(value: E): E {
|
||||||
val constants = value.declaringClass.enumConstants
|
val constants = value.declaringClass.enumConstants
|
||||||
val index = constants.indexOf(value) + 1
|
val index = constants.indexOf(value) + 1
|
||||||
return if (index < constants.size) constants[index] else constants.first()
|
return if (index < constants.size) constants[index] else constants.first()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <E: Enum<E>> previous(value: E): E {
|
fun <E : Enum<E>> previous(value: E): E {
|
||||||
val constants = value.declaringClass.enumConstants
|
val constants = value.declaringClass.enumConstants
|
||||||
val index = constants.indexOf(value) - 1
|
val index = constants.indexOf(value) - 1
|
||||||
return if (index >= 0) constants[index] else constants.last()
|
return if (index >= 0) constants[index] else constants.last()
|
||||||
|
|
|
@ -28,6 +28,11 @@ class LayoutGuide(
|
||||||
val centerYAnchor: LayoutVariable = LayoutVariable(this, "centerY")
|
val centerYAnchor: LayoutVariable = LayoutVariable(this, "centerY")
|
||||||
|
|
||||||
val frame: Rect
|
val frame: Rect
|
||||||
get() = Rect(leftAnchor.value - owningView.leftAnchor.value, topAnchor.value - owningView.topAnchor.value, widthAnchor.value, heightAnchor.value)
|
get() = Rect(
|
||||||
|
leftAnchor.value - owningView.leftAnchor.value,
|
||||||
|
topAnchor.value - owningView.topAnchor.value,
|
||||||
|
widthAnchor.value,
|
||||||
|
heightAnchor.value
|
||||||
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ import kotlin.math.roundToInt
|
||||||
*
|
*
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
*/
|
*/
|
||||||
object RenderHelper: DrawableHelper() {
|
object RenderHelper : DrawableHelper() {
|
||||||
|
|
||||||
val disabled = (System.getProperty("cacao.drawing.disabled") ?: "false").toBoolean()
|
val disabled = (System.getProperty("cacao.drawing.disabled") ?: "false").toBoolean()
|
||||||
|
|
||||||
|
@ -48,7 +48,17 @@ object RenderHelper: DrawableHelper() {
|
||||||
if (disabled) return
|
if (disabled) return
|
||||||
RenderSystem.setShader(GameRenderer::getPositionTexShader)
|
RenderSystem.setShader(GameRenderer::getPositionTexShader)
|
||||||
RenderSystem.setShaderTexture(0, 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) {
|
||||||
|
@ -70,18 +80,50 @@ object RenderHelper: DrawableHelper() {
|
||||||
/**
|
/**
|
||||||
* Draws the bound texture with the given screen and texture position and size.
|
* Draws the bound texture with the given screen and texture position and size.
|
||||||
*/
|
*/
|
||||||
fun draw(matrixStack: MatrixStack, x: Double, y: Double, u: Int, v: Int, width: Double, height: Double, textureWidth: Int, textureHeight: Int) {
|
fun draw(
|
||||||
|
matrixStack: MatrixStack,
|
||||||
|
x: Double,
|
||||||
|
y: Double,
|
||||||
|
u: Int,
|
||||||
|
v: Int,
|
||||||
|
width: Double,
|
||||||
|
height: Double,
|
||||||
|
textureWidth: Int,
|
||||||
|
textureHeight: Int
|
||||||
|
) {
|
||||||
if (disabled) return
|
if (disabled) return
|
||||||
val uStart = u.toFloat() / textureWidth
|
val uStart = u.toFloat() / textureWidth
|
||||||
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().positionMatrix, 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
|
// 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(VertexFormat.DrawMode.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()
|
||||||
|
@ -100,7 +142,7 @@ object RenderHelper: DrawableHelper() {
|
||||||
drawTooltip(matrixStack, texts.map(Text::asOrderedText), mouse)
|
drawTooltip(matrixStack, texts.map(Text::asOrderedText), mouse)
|
||||||
}
|
}
|
||||||
|
|
||||||
private val dummyScreen = object: Screen(LiteralText("")) {
|
private val dummyScreen = object : Screen(LiteralText("")) {
|
||||||
init {
|
init {
|
||||||
textRenderer = MinecraftClient.getInstance().textRenderer
|
textRenderer = MinecraftClient.getInstance().textRenderer
|
||||||
itemRenderer = MinecraftClient.getInstance().itemRenderer
|
itemRenderer = MinecraftClient.getInstance().itemRenderer
|
||||||
|
|
|
@ -5,7 +5,7 @@ import kotlin.reflect.KProperty
|
||||||
/**
|
/**
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
*/
|
*/
|
||||||
class ObservableLateInitProperty<T: Any>(val observer: (T) -> Unit) {
|
class ObservableLateInitProperty<T : Any>(val observer: (T) -> Unit) {
|
||||||
|
|
||||||
lateinit var storage: T
|
lateinit var storage: T
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,13 @@ import net.minecraft.util.Identifier
|
||||||
* @param centerWidth The width of the center patch.
|
* @param centerWidth The width of the center patch.
|
||||||
* @param centerHeight The height of the center patch.
|
* @param centerHeight The height of the center patch.
|
||||||
*/
|
*/
|
||||||
data class NinePatchTexture(val texture: Texture, val cornerWidth: Int, val cornerHeight: Int, val centerWidth: Int, val centerHeight: Int) {
|
data class NinePatchTexture(
|
||||||
|
val texture: Texture,
|
||||||
|
val cornerWidth: Int,
|
||||||
|
val cornerHeight: Int,
|
||||||
|
val centerWidth: Int,
|
||||||
|
val centerHeight: Int
|
||||||
|
) {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val PANEL_BG = NinePatchTexture(Texture(Identifier("textures/gui/demo_background.png"), 0, 0), 5, 5, 238, 156)
|
val PANEL_BG = NinePatchTexture(Texture(Identifier("textures/gui/demo_background.png"), 0, 0), 5, 5, 238, 156)
|
||||||
|
|
|
@ -9,7 +9,7 @@ import net.shadowfacts.cacao.util.RenderHelper
|
||||||
/**
|
/**
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
*/
|
*/
|
||||||
class BezierCurveView(val curve: BezierCurve): View() {
|
class BezierCurveView(val curve: BezierCurve) : View() {
|
||||||
|
|
||||||
private val points by lazy {
|
private val points by lazy {
|
||||||
val step = 0.05
|
val step = 0.05
|
||||||
|
|
|
@ -19,13 +19,13 @@ class DialogView(
|
||||||
val buttonTypes: Array<ButtonType>,
|
val buttonTypes: Array<ButtonType>,
|
||||||
val iconTexture: Texture?,
|
val iconTexture: Texture?,
|
||||||
val buttonCallback: (ButtonType, Window) -> Unit
|
val buttonCallback: (ButtonType, Window) -> Unit
|
||||||
): View() {
|
) : View() {
|
||||||
|
|
||||||
interface ButtonType {
|
interface ButtonType {
|
||||||
val localizedName: Text
|
val localizedName: Text
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class DefaultButtonType: ButtonType {
|
enum class DefaultButtonType : ButtonType {
|
||||||
CANCEL, CONFIRM, OK, CLOSE;
|
CANCEL, CONFIRM, OK, CLOSE;
|
||||||
|
|
||||||
override val localizedName: Text
|
override val localizedName: Text
|
||||||
|
|
|
@ -31,7 +31,7 @@ class Label(
|
||||||
val maxLines: Int = 0,
|
val maxLines: Int = 0,
|
||||||
val wrappingMode: WrappingMode = WrappingMode.WRAP,
|
val wrappingMode: WrappingMode = WrappingMode.WRAP,
|
||||||
var textAlignment: TextAlignment = TextAlignment.LEFT
|
var textAlignment: TextAlignment = TextAlignment.LEFT
|
||||||
): View() {
|
) : View() {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val textRenderer: TextRenderer
|
private val textRenderer: TextRenderer
|
||||||
|
@ -52,7 +52,7 @@ class Label(
|
||||||
maxLines: Int = 0,
|
maxLines: Int = 0,
|
||||||
wrappingMode: WrappingMode = WrappingMode.WRAP,
|
wrappingMode: WrappingMode = WrappingMode.WRAP,
|
||||||
textAlignment: TextAlignment = TextAlignment.LEFT,
|
textAlignment: TextAlignment = TextAlignment.LEFT,
|
||||||
): this(LiteralText(text), shadow, maxLines, wrappingMode, textAlignment)
|
) : this(LiteralText(text), shadow, maxLines, wrappingMode, textAlignment)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The text of this label. Mutating this field will update the intrinsic content size and trigger a layout.
|
* The text of this label. Mutating this field will update the intrinsic content size and trigger a layout.
|
||||||
|
|
|
@ -17,7 +17,7 @@ import kotlin.math.roundToInt
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
* @param ninePatch The nine patch texture that this view will draw.
|
* @param ninePatch The nine patch texture that this view will draw.
|
||||||
*/
|
*/
|
||||||
open class NinePatchView(val ninePatch: NinePatchTexture): View() {
|
open class NinePatchView(val ninePatch: NinePatchTexture) : View() {
|
||||||
|
|
||||||
// Corners
|
// Corners
|
||||||
private val topLeftDelegate = ResettableLazyProperty {
|
private val topLeftDelegate = ResettableLazyProperty {
|
||||||
|
@ -26,24 +26,44 @@ open class NinePatchView(val ninePatch: NinePatchTexture): View() {
|
||||||
protected open val topLeft by topLeftDelegate
|
protected open val topLeft by topLeftDelegate
|
||||||
|
|
||||||
private val topRightDelegate = ResettableLazyProperty {
|
private val topRightDelegate = ResettableLazyProperty {
|
||||||
Rect(bounds.width - ninePatch.cornerWidth, 0.0, ninePatch.cornerWidth.toDouble(), ninePatch.cornerHeight.toDouble())
|
Rect(
|
||||||
|
bounds.width - ninePatch.cornerWidth,
|
||||||
|
0.0,
|
||||||
|
ninePatch.cornerWidth.toDouble(),
|
||||||
|
ninePatch.cornerHeight.toDouble()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
protected open val topRight by topRightDelegate
|
protected open val topRight by topRightDelegate
|
||||||
|
|
||||||
private val bottomLeftDelegate = ResettableLazyProperty {
|
private val bottomLeftDelegate = ResettableLazyProperty {
|
||||||
Rect(0.0, bounds.height - ninePatch.cornerHeight, ninePatch.cornerWidth.toDouble(), ninePatch.cornerHeight.toDouble())
|
Rect(
|
||||||
|
0.0,
|
||||||
|
bounds.height - ninePatch.cornerHeight,
|
||||||
|
ninePatch.cornerWidth.toDouble(),
|
||||||
|
ninePatch.cornerHeight.toDouble()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
protected open val bottomLeft by bottomLeftDelegate
|
protected open val bottomLeft by bottomLeftDelegate
|
||||||
|
|
||||||
private val bottomRightDelegate = ResettableLazyProperty {
|
private val bottomRightDelegate = ResettableLazyProperty {
|
||||||
Rect(bounds.width - ninePatch.cornerWidth, bounds.height - ninePatch.cornerHeight, ninePatch.cornerWidth.toDouble(), ninePatch.cornerHeight.toDouble())
|
Rect(
|
||||||
|
bounds.width - ninePatch.cornerWidth,
|
||||||
|
bounds.height - ninePatch.cornerHeight,
|
||||||
|
ninePatch.cornerWidth.toDouble(),
|
||||||
|
ninePatch.cornerHeight.toDouble()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
protected open val bottomRight by bottomRightDelegate
|
protected open val bottomRight by bottomRightDelegate
|
||||||
|
|
||||||
|
|
||||||
// Edges
|
// Edges
|
||||||
private val topMiddleDelegate = ResettableLazyProperty {
|
private val topMiddleDelegate = ResettableLazyProperty {
|
||||||
Rect(ninePatch.cornerWidth.toDouble(), topLeft.top, bounds.width - 2 * ninePatch.cornerWidth, ninePatch.cornerHeight.toDouble())
|
Rect(
|
||||||
|
ninePatch.cornerWidth.toDouble(),
|
||||||
|
topLeft.top,
|
||||||
|
bounds.width - 2 * ninePatch.cornerWidth,
|
||||||
|
ninePatch.cornerHeight.toDouble()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
protected open val topMiddle by topMiddleDelegate
|
protected open val topMiddle by topMiddleDelegate
|
||||||
|
|
||||||
|
@ -53,7 +73,12 @@ open class NinePatchView(val ninePatch: NinePatchTexture): View() {
|
||||||
protected open val bottomMiddle by bottomMiddleDelegate
|
protected open val bottomMiddle by bottomMiddleDelegate
|
||||||
|
|
||||||
private val leftMiddleDelegate = ResettableLazyProperty {
|
private val leftMiddleDelegate = ResettableLazyProperty {
|
||||||
Rect(topLeft.left, ninePatch.cornerHeight.toDouble(), ninePatch.cornerWidth.toDouble(), bounds.height - 2 * ninePatch.cornerHeight)
|
Rect(
|
||||||
|
topLeft.left,
|
||||||
|
ninePatch.cornerHeight.toDouble(),
|
||||||
|
ninePatch.cornerWidth.toDouble(),
|
||||||
|
bounds.height - 2 * ninePatch.cornerHeight
|
||||||
|
)
|
||||||
}
|
}
|
||||||
protected open val leftMiddle by leftMiddleDelegate
|
protected open val leftMiddle by leftMiddleDelegate
|
||||||
|
|
||||||
|
@ -69,7 +94,17 @@ open class NinePatchView(val ninePatch: NinePatchTexture): View() {
|
||||||
}
|
}
|
||||||
protected open val center by centerDelegate
|
protected open val center by centerDelegate
|
||||||
|
|
||||||
private val delegates = listOf(topLeftDelegate, topRightDelegate, bottomLeftDelegate, bottomRightDelegate, topMiddleDelegate, bottomMiddleDelegate, leftMiddleDelegate, rightMiddleDelegate, centerDelegate)
|
private val delegates = listOf(
|
||||||
|
topLeftDelegate,
|
||||||
|
topRightDelegate,
|
||||||
|
bottomLeftDelegate,
|
||||||
|
bottomRightDelegate,
|
||||||
|
topMiddleDelegate,
|
||||||
|
bottomMiddleDelegate,
|
||||||
|
leftMiddleDelegate,
|
||||||
|
rightMiddleDelegate,
|
||||||
|
centerDelegate
|
||||||
|
)
|
||||||
|
|
||||||
override fun didLayout() {
|
override fun didLayout() {
|
||||||
super.didLayout()
|
super.didLayout()
|
||||||
|
@ -93,30 +128,114 @@ open class NinePatchView(val ninePatch: NinePatchTexture): View() {
|
||||||
private fun drawEdges(matrixStack: MatrixStack) {
|
private fun drawEdges(matrixStack: MatrixStack) {
|
||||||
// Horizontal
|
// Horizontal
|
||||||
for (i in 0 until (topMiddle.width.roundToInt() / ninePatch.centerWidth)) {
|
for (i in 0 until (topMiddle.width.roundToInt() / ninePatch.centerWidth)) {
|
||||||
RenderHelper.draw(matrixStack, topMiddle.left + i * ninePatch.centerWidth, topMiddle.top, ninePatch.topMiddle.u, ninePatch.topMiddle.v, ninePatch.centerWidth.toDouble(), topMiddle.height, ninePatch.texture.width, ninePatch.texture.height)
|
RenderHelper.draw(
|
||||||
RenderHelper.draw(matrixStack, bottomMiddle.left + i * ninePatch.centerWidth, bottomMiddle.top, ninePatch.bottomMiddle.u, ninePatch.bottomMiddle.v, ninePatch.centerWidth.toDouble(), bottomMiddle.height, ninePatch.texture.width, ninePatch.texture.height)
|
matrixStack,
|
||||||
|
topMiddle.left + i * ninePatch.centerWidth,
|
||||||
|
topMiddle.top,
|
||||||
|
ninePatch.topMiddle.u,
|
||||||
|
ninePatch.topMiddle.v,
|
||||||
|
ninePatch.centerWidth.toDouble(),
|
||||||
|
topMiddle.height,
|
||||||
|
ninePatch.texture.width,
|
||||||
|
ninePatch.texture.height
|
||||||
|
)
|
||||||
|
RenderHelper.draw(
|
||||||
|
matrixStack,
|
||||||
|
bottomMiddle.left + i * ninePatch.centerWidth,
|
||||||
|
bottomMiddle.top,
|
||||||
|
ninePatch.bottomMiddle.u,
|
||||||
|
ninePatch.bottomMiddle.v,
|
||||||
|
ninePatch.centerWidth.toDouble(),
|
||||||
|
bottomMiddle.height,
|
||||||
|
ninePatch.texture.width,
|
||||||
|
ninePatch.texture.height
|
||||||
|
)
|
||||||
}
|
}
|
||||||
val remWidth = topMiddle.width.roundToInt() % ninePatch.centerWidth
|
val remWidth = topMiddle.width.roundToInt() % ninePatch.centerWidth
|
||||||
if (remWidth > 0) {
|
if (remWidth > 0) {
|
||||||
RenderHelper.draw(matrixStack, topMiddle.right - remWidth, topMiddle.top, ninePatch.topMiddle.u, ninePatch.topMiddle.v, remWidth.toDouble(), ninePatch.cornerHeight.toDouble(), ninePatch.texture.width, ninePatch.texture.height)
|
RenderHelper.draw(
|
||||||
RenderHelper.draw(matrixStack, bottomMiddle.right - remWidth, bottomMiddle.top, ninePatch.bottomMiddle.u, ninePatch.bottomMiddle.v, remWidth.toDouble(), ninePatch.cornerHeight.toDouble(), ninePatch.texture.width, ninePatch.texture.height)
|
matrixStack,
|
||||||
|
topMiddle.right - remWidth,
|
||||||
|
topMiddle.top,
|
||||||
|
ninePatch.topMiddle.u,
|
||||||
|
ninePatch.topMiddle.v,
|
||||||
|
remWidth.toDouble(),
|
||||||
|
ninePatch.cornerHeight.toDouble(),
|
||||||
|
ninePatch.texture.width,
|
||||||
|
ninePatch.texture.height
|
||||||
|
)
|
||||||
|
RenderHelper.draw(
|
||||||
|
matrixStack,
|
||||||
|
bottomMiddle.right - remWidth,
|
||||||
|
bottomMiddle.top,
|
||||||
|
ninePatch.bottomMiddle.u,
|
||||||
|
ninePatch.bottomMiddle.v,
|
||||||
|
remWidth.toDouble(),
|
||||||
|
ninePatch.cornerHeight.toDouble(),
|
||||||
|
ninePatch.texture.width,
|
||||||
|
ninePatch.texture.height
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Vertical
|
// Vertical
|
||||||
for (i in 0 until (leftMiddle.height.roundToInt() / ninePatch.centerHeight)) {
|
for (i in 0 until (leftMiddle.height.roundToInt() / ninePatch.centerHeight)) {
|
||||||
RenderHelper.draw(matrixStack, leftMiddle.left, leftMiddle.top + i * ninePatch.centerHeight, ninePatch.leftMiddle.u, ninePatch.leftMiddle.v, ninePatch.cornerWidth.toDouble(), ninePatch.centerHeight.toDouble(), ninePatch.texture.width, ninePatch.texture.height)
|
RenderHelper.draw(
|
||||||
RenderHelper.draw(matrixStack, rightMiddle.left, rightMiddle.top + i * ninePatch.centerHeight, ninePatch.rightMiddle.u, ninePatch.rightMiddle.v, ninePatch.cornerWidth.toDouble(), ninePatch.centerHeight.toDouble(), ninePatch.texture.width, ninePatch.texture.height)
|
matrixStack,
|
||||||
|
leftMiddle.left,
|
||||||
|
leftMiddle.top + i * ninePatch.centerHeight,
|
||||||
|
ninePatch.leftMiddle.u,
|
||||||
|
ninePatch.leftMiddle.v,
|
||||||
|
ninePatch.cornerWidth.toDouble(),
|
||||||
|
ninePatch.centerHeight.toDouble(),
|
||||||
|
ninePatch.texture.width,
|
||||||
|
ninePatch.texture.height
|
||||||
|
)
|
||||||
|
RenderHelper.draw(
|
||||||
|
matrixStack,
|
||||||
|
rightMiddle.left,
|
||||||
|
rightMiddle.top + i * ninePatch.centerHeight,
|
||||||
|
ninePatch.rightMiddle.u,
|
||||||
|
ninePatch.rightMiddle.v,
|
||||||
|
ninePatch.cornerWidth.toDouble(),
|
||||||
|
ninePatch.centerHeight.toDouble(),
|
||||||
|
ninePatch.texture.width,
|
||||||
|
ninePatch.texture.height
|
||||||
|
)
|
||||||
}
|
}
|
||||||
val remHeight = leftMiddle.height.roundToInt() % ninePatch.centerHeight
|
val remHeight = leftMiddle.height.roundToInt() % ninePatch.centerHeight
|
||||||
if (remHeight > 0) {
|
if (remHeight > 0) {
|
||||||
RenderHelper.draw(matrixStack, leftMiddle.left, leftMiddle.bottom - remHeight, ninePatch.leftMiddle.u, ninePatch.leftMiddle.v, ninePatch.cornerWidth.toDouble(), remHeight.toDouble(), ninePatch.texture.width, ninePatch.texture.height)
|
RenderHelper.draw(
|
||||||
RenderHelper.draw(matrixStack, rightMiddle.left, rightMiddle.bottom - remHeight, ninePatch.rightMiddle.u, ninePatch.rightMiddle.v, ninePatch.cornerWidth.toDouble(), remHeight.toDouble(), ninePatch.texture.width, ninePatch.texture.height)
|
matrixStack,
|
||||||
|
leftMiddle.left,
|
||||||
|
leftMiddle.bottom - remHeight,
|
||||||
|
ninePatch.leftMiddle.u,
|
||||||
|
ninePatch.leftMiddle.v,
|
||||||
|
ninePatch.cornerWidth.toDouble(),
|
||||||
|
remHeight.toDouble(),
|
||||||
|
ninePatch.texture.width,
|
||||||
|
ninePatch.texture.height
|
||||||
|
)
|
||||||
|
RenderHelper.draw(
|
||||||
|
matrixStack,
|
||||||
|
rightMiddle.left,
|
||||||
|
rightMiddle.bottom - remHeight,
|
||||||
|
ninePatch.rightMiddle.u,
|
||||||
|
ninePatch.rightMiddle.v,
|
||||||
|
ninePatch.cornerWidth.toDouble(),
|
||||||
|
remHeight.toDouble(),
|
||||||
|
ninePatch.texture.width,
|
||||||
|
ninePatch.texture.height
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun drawCenter(matrixStack: MatrixStack) {
|
private fun drawCenter(matrixStack: MatrixStack) {
|
||||||
for (i in 0 until (center.height.roundToInt() / ninePatch.centerHeight)) {
|
for (i in 0 until (center.height.roundToInt() / ninePatch.centerHeight)) {
|
||||||
drawCenterRow(matrixStack, center.top + i * ninePatch.centerHeight.toDouble(), ninePatch.centerHeight.toDouble())
|
drawCenterRow(
|
||||||
|
matrixStack,
|
||||||
|
center.top + i * ninePatch.centerHeight.toDouble(),
|
||||||
|
ninePatch.centerHeight.toDouble()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
val remHeight = center.height.roundToInt() % ninePatch.centerHeight
|
val remHeight = center.height.roundToInt() % ninePatch.centerHeight
|
||||||
if (remHeight > 0) {
|
if (remHeight > 0) {
|
||||||
|
@ -126,11 +245,31 @@ open class NinePatchView(val ninePatch: NinePatchTexture): View() {
|
||||||
|
|
||||||
private fun drawCenterRow(matrixStack: MatrixStack, y: Double, height: Double) {
|
private fun drawCenterRow(matrixStack: MatrixStack, y: Double, height: Double) {
|
||||||
for (i in 0 until (center.width.roundToInt() / ninePatch.centerWidth)) {
|
for (i in 0 until (center.width.roundToInt() / ninePatch.centerWidth)) {
|
||||||
RenderHelper.draw(matrixStack, center.left + i * ninePatch.centerWidth, y, ninePatch.center.u, ninePatch.center.v, ninePatch.centerWidth.toDouble(), height, ninePatch.texture.width, ninePatch.texture.height)
|
RenderHelper.draw(
|
||||||
|
matrixStack,
|
||||||
|
center.left + i * ninePatch.centerWidth,
|
||||||
|
y,
|
||||||
|
ninePatch.center.u,
|
||||||
|
ninePatch.center.v,
|
||||||
|
ninePatch.centerWidth.toDouble(),
|
||||||
|
height,
|
||||||
|
ninePatch.texture.width,
|
||||||
|
ninePatch.texture.height
|
||||||
|
)
|
||||||
}
|
}
|
||||||
val remWidth = center.width.roundToInt() % ninePatch.centerWidth
|
val remWidth = center.width.roundToInt() % ninePatch.centerWidth
|
||||||
if (remWidth > 0) {
|
if (remWidth > 0) {
|
||||||
RenderHelper.draw(matrixStack, center.right - remWidth, y, ninePatch.center.u, ninePatch.center.v, remWidth.toDouble(), height, ninePatch.texture.width, ninePatch.texture.height)
|
RenderHelper.draw(
|
||||||
|
matrixStack,
|
||||||
|
center.right - remWidth,
|
||||||
|
y,
|
||||||
|
ninePatch.center.u,
|
||||||
|
ninePatch.center.v,
|
||||||
|
remWidth.toDouble(),
|
||||||
|
height,
|
||||||
|
ninePatch.texture.width,
|
||||||
|
ninePatch.texture.height
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,10 +25,11 @@ open class StackView(
|
||||||
val axis: Axis,
|
val axis: Axis,
|
||||||
val distribution: Distribution = Distribution.FILL,
|
val distribution: Distribution = Distribution.FILL,
|
||||||
val spacing: Double = 0.0
|
val spacing: Double = 0.0
|
||||||
): View() {
|
) : View() {
|
||||||
|
|
||||||
// the internal, mutable list of arranged subviews
|
// the internal, mutable list of arranged subviews
|
||||||
private val _arrangedSubviews = LinkedList<View>()
|
private val _arrangedSubviews = LinkedList<View>()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The list of arranged subviews belonging to this stack view.
|
* The list of arranged subviews belonging to this stack view.
|
||||||
* This list should never be mutated directly, only be calling the [addArrangedSubview]/[removeArrangedSubview]
|
* This list should never be mutated directly, only be calling the [addArrangedSubview]/[removeArrangedSubview]
|
||||||
|
@ -50,7 +51,7 @@ open class StackView(
|
||||||
* By default, adds the view to the end of the stack.
|
* By default, adds the view to the end of the stack.
|
||||||
* @return The view that was added, as a convenience.
|
* @return The view that was added, as a convenience.
|
||||||
*/
|
*/
|
||||||
fun <T: View> addArrangedSubview(view: T, index: Int = arrangedSubviews.size): T {
|
fun <T : View> addArrangedSubview(view: T, index: Int = arrangedSubviews.size): T {
|
||||||
addSubview(view)
|
addSubview(view)
|
||||||
_arrangedSubviews.add(index, view)
|
_arrangedSubviews.add(index, view)
|
||||||
|
|
||||||
|
@ -139,10 +140,16 @@ open class StackView(
|
||||||
val previous = arrangedSubviews.getOrNull(index - 1)
|
val previous = arrangedSubviews.getOrNull(index - 1)
|
||||||
val next = arrangedSubviews.getOrNull(index + 1)
|
val next = arrangedSubviews.getOrNull(index + 1)
|
||||||
if (next != null) {
|
if (next != null) {
|
||||||
arrangedSubviewConnections.add(index, anchor(TRAILING, view) equalTo (anchor(LEADING, next) + spacing))
|
arrangedSubviewConnections.add(
|
||||||
|
index,
|
||||||
|
anchor(TRAILING, view) equalTo (anchor(LEADING, next) + spacing)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
if (previous != null) {
|
if (previous != null) {
|
||||||
arrangedSubviewConnections.add(index - 1, anchor(TRAILING, previous) equalTo (anchor(LEADING, view) - spacing))
|
arrangedSubviewConnections.add(
|
||||||
|
index - 1,
|
||||||
|
anchor(TRAILING, previous) equalTo (anchor(LEADING, view) - spacing)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -150,12 +157,15 @@ open class StackView(
|
||||||
when (distribution) {
|
when (distribution) {
|
||||||
Distribution.LEADING ->
|
Distribution.LEADING ->
|
||||||
perpAnchor(LEADING) equalTo perpAnchor(LEADING, view)
|
perpAnchor(LEADING) equalTo perpAnchor(LEADING, view)
|
||||||
|
|
||||||
Distribution.TRAILING ->
|
Distribution.TRAILING ->
|
||||||
perpAnchor(TRAILING) equalTo perpAnchor(TRAILING, view)
|
perpAnchor(TRAILING) equalTo perpAnchor(TRAILING, view)
|
||||||
|
|
||||||
Distribution.FILL -> {
|
Distribution.FILL -> {
|
||||||
perpAnchor(LEADING) equalTo perpAnchor(LEADING, view)
|
perpAnchor(LEADING) equalTo perpAnchor(LEADING, view)
|
||||||
perpAnchor(TRAILING) equalTo perpAnchor(TRAILING, view)
|
perpAnchor(TRAILING) equalTo perpAnchor(TRAILING, view)
|
||||||
}
|
}
|
||||||
|
|
||||||
Distribution.CENTER ->
|
Distribution.CENTER ->
|
||||||
perpAnchor(CENTER) equalTo perpAnchor(CENTER, view)
|
perpAnchor(CENTER) equalTo perpAnchor(CENTER, view)
|
||||||
}
|
}
|
||||||
|
@ -165,6 +175,7 @@ open class StackView(
|
||||||
private fun anchor(position: AxisPosition, view: View = this): LayoutVariable {
|
private fun anchor(position: AxisPosition, view: View = this): LayoutVariable {
|
||||||
return view.getAnchor(axis, position)
|
return view.getAnchor(axis, position)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun perpAnchor(position: AxisPosition, view: View = this): LayoutVariable {
|
private fun perpAnchor(position: AxisPosition, view: View = this): LayoutVariable {
|
||||||
return view.getAnchor(axis.perpendicular, position)
|
return view.getAnchor(axis.perpendicular, position)
|
||||||
}
|
}
|
||||||
|
@ -199,6 +210,7 @@ open class StackView(
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
LEADING,
|
LEADING,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The centers of the arranged subviews are pinned to the center of the stack view.
|
* The centers of the arranged subviews are pinned to the center of the stack view.
|
||||||
* ```
|
* ```
|
||||||
|
@ -222,6 +234,7 @@ open class StackView(
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
CENTER,
|
CENTER,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The trailing edges of arranged subviews are pinned to the leading edge of the stack view.
|
* The trailing edges of arranged subviews are pinned to the leading edge of the stack view.
|
||||||
* ```
|
* ```
|
||||||
|
@ -245,6 +258,7 @@ open class StackView(
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
TRAILING,
|
TRAILING,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The arranged subviews fill the perpendicular axis of the stack view.
|
* The arranged subviews fill the perpendicular axis of the stack view.
|
||||||
* ```
|
* ```
|
||||||
|
|
|
@ -11,7 +11,7 @@ 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) {
|
||||||
texture?.also {
|
texture?.also {
|
||||||
|
|
|
@ -20,7 +20,7 @@ import kotlin.math.floor
|
||||||
*
|
*
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
*/
|
*/
|
||||||
open class View(): Responder {
|
open class View() : Responder {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The window whose view hierarchy this view belongs to.
|
* The window whose view hierarchy this view belongs to.
|
||||||
|
@ -42,6 +42,7 @@ open class View(): Responder {
|
||||||
v.solver = it
|
v.solver = it
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The constraint solver used by the [Window] this view belongs to.
|
* The constraint solver used by the [Window] this view belongs to.
|
||||||
* Not initialized until [wasAdded] called, using it before that will throw a runtime exception.
|
* Not initialized until [wasAdded] called, using it before that will throw a runtime exception.
|
||||||
|
@ -55,30 +56,37 @@ open class View(): Responder {
|
||||||
* Layout anchor for the left edge of this view in the window's coordinate system.
|
* Layout anchor for the left edge of this view in the window's coordinate system.
|
||||||
*/
|
*/
|
||||||
val leftAnchor = LayoutVariable(this, "left")
|
val leftAnchor = LayoutVariable(this, "left")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Layout anchor for the right edge of this view in the window's coordinate system.
|
* Layout anchor for the right edge of this view in the window's coordinate system.
|
||||||
*/
|
*/
|
||||||
val rightAnchor = LayoutVariable(this, "right")
|
val rightAnchor = LayoutVariable(this, "right")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Layout anchor for the top edge of this view in the window's coordinate system.
|
* Layout anchor for the top edge of this view in the window's coordinate system.
|
||||||
*/
|
*/
|
||||||
val topAnchor = LayoutVariable(this, "top")
|
val topAnchor = LayoutVariable(this, "top")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Layout anchor for the bottom edge of this view in the window's coordinate system.
|
* Layout anchor for the bottom edge of this view in the window's coordinate system.
|
||||||
*/
|
*/
|
||||||
val bottomAnchor = LayoutVariable(this, "bottom")
|
val bottomAnchor = LayoutVariable(this, "bottom")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Layout anchor for the width of this view in the window's coordinate system.
|
* Layout anchor for the width of this view in the window's coordinate system.
|
||||||
*/
|
*/
|
||||||
val widthAnchor = LayoutVariable(this, "width")
|
val widthAnchor = LayoutVariable(this, "width")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Layout anchor for the height of this view in the window's coordinate system.
|
* Layout anchor for the height of this view in the window's coordinate system.
|
||||||
*/
|
*/
|
||||||
val heightAnchor = LayoutVariable(this, "height")
|
val heightAnchor = LayoutVariable(this, "height")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Layout anchor for the center X position of this view in the window's coordinate system.
|
* Layout anchor for the center X position of this view in the window's coordinate system.
|
||||||
*/
|
*/
|
||||||
val centerXAnchor = LayoutVariable(this, "centerX")
|
val centerXAnchor = LayoutVariable(this, "centerX")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Layout anchor for the center Y position of this view in the window's coordinate system.
|
* Layout anchor for the center Y position of this view in the window's coordinate system.
|
||||||
*/
|
*/
|
||||||
|
@ -155,6 +163,7 @@ open class View(): Responder {
|
||||||
* This view's parent view. If `null`, this view is a top-level view in the [Window].
|
* This view's parent view. If `null`, this view is a top-level view in the [Window].
|
||||||
*/
|
*/
|
||||||
var superview: View? = null
|
var superview: View? = null
|
||||||
|
|
||||||
// _subviews is the internal, mutable object since we only want it to be mutated by the add/removeSubview methods
|
// _subviews is the internal, mutable object since we only want it to be mutated by the add/removeSubview methods
|
||||||
private val _subviews = LinkedList<View>()
|
private val _subviews = LinkedList<View>()
|
||||||
private var subviewsSortedByZIndex: List<View> = listOf()
|
private var subviewsSortedByZIndex: List<View> = listOf()
|
||||||
|
@ -165,7 +174,7 @@ open class View(): Responder {
|
||||||
*/
|
*/
|
||||||
val subviews: List<View> = _subviews
|
val subviews: List<View> = _subviews
|
||||||
|
|
||||||
constructor(frame: Rect): this() {
|
constructor(frame: Rect) : this() {
|
||||||
this.usesConstraintBasedLayout = false
|
this.usesConstraintBasedLayout = false
|
||||||
this.frame = frame
|
this.frame = frame
|
||||||
}
|
}
|
||||||
|
@ -181,6 +190,7 @@ open class View(): Responder {
|
||||||
AxisPosition.CENTER -> centerXAnchor
|
AxisPosition.CENTER -> centerXAnchor
|
||||||
AxisPosition.TRAILING -> rightAnchor
|
AxisPosition.TRAILING -> rightAnchor
|
||||||
}
|
}
|
||||||
|
|
||||||
Axis.VERTICAL ->
|
Axis.VERTICAL ->
|
||||||
when (position) {
|
when (position) {
|
||||||
AxisPosition.LEADING -> topAnchor
|
AxisPosition.LEADING -> topAnchor
|
||||||
|
@ -196,7 +206,7 @@ open class View(): Responder {
|
||||||
* @param view The view to add.
|
* @param view The view to add.
|
||||||
* @return The view that was added, as a convenience.
|
* @return The view that was added, as a convenience.
|
||||||
*/
|
*/
|
||||||
fun <T: View> addSubview(view: T): T {
|
fun <T : View> addSubview(view: T): T {
|
||||||
_subviews.add(view)
|
_subviews.add(view)
|
||||||
subviewsSortedByZIndex = subviews.sortedBy(View::zIndex)
|
subviewsSortedByZIndex = subviews.sortedBy(View::zIndex)
|
||||||
|
|
||||||
|
@ -240,7 +250,11 @@ open class View(): Responder {
|
||||||
for (b in a + 1 until variables.size) {
|
for (b in a + 1 until variables.size) {
|
||||||
// if the variable views have no common ancestor after the removed view's superview is unset,
|
// if the variable views have no common ancestor after the removed view's superview is unset,
|
||||||
// the constraint crossed the this<->view boundary and should be removed
|
// the constraint crossed the this<->view boundary and should be removed
|
||||||
val ancestor = LowestCommonAncestor.find(variables[a].viewOrLayoutGuideView, variables[b].viewOrLayoutGuideView, View::superview)
|
val ancestor = LowestCommonAncestor.find(
|
||||||
|
variables[a].viewOrLayoutGuideView,
|
||||||
|
variables[b].viewOrLayoutGuideView,
|
||||||
|
View::superview
|
||||||
|
)
|
||||||
if (ancestor == null) {
|
if (ancestor == null) {
|
||||||
return@filter true
|
return@filter true
|
||||||
}
|
}
|
||||||
|
@ -350,7 +364,12 @@ open class View(): Responder {
|
||||||
if (usesConstraintBasedLayout) {
|
if (usesConstraintBasedLayout) {
|
||||||
val superviewLeft = superview?.leftAnchor?.value ?: 0.0
|
val superviewLeft = superview?.leftAnchor?.value ?: 0.0
|
||||||
val superviewTop = superview?.topAnchor?.value ?: 0.0
|
val superviewTop = superview?.topAnchor?.value ?: 0.0
|
||||||
frame = Rect(leftAnchor.value - superviewLeft, topAnchor.value - superviewTop, widthAnchor.value, heightAnchor.value)
|
frame = Rect(
|
||||||
|
leftAnchor.value - superviewLeft,
|
||||||
|
topAnchor.value - superviewTop,
|
||||||
|
widthAnchor.value,
|
||||||
|
heightAnchor.value
|
||||||
|
)
|
||||||
bounds = Rect(0.0, 0.0, widthAnchor.value, heightAnchor.value)
|
bounds = Rect(0.0, 0.0, widthAnchor.value, heightAnchor.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ import kotlin.math.floor
|
||||||
* Will be added as a subview of the button and laid out using constraints.
|
* Will be added as a subview of the button and laid out using constraints.
|
||||||
* @param padding The padding between the [content] and the edges of the button.
|
* @param padding The padding between the [content] and the edges of the button.
|
||||||
*/
|
*/
|
||||||
abstract class AbstractButton<Impl: AbstractButton<Impl>>(val content: View, val padding: Double = 4.0): View() {
|
abstract class AbstractButton<Impl : AbstractButton<Impl>>(val content: View, val padding: Double = 4.0) : View() {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The function that handles when this button is clicked.
|
* The function that handles when this button is clicked.
|
||||||
|
@ -51,6 +51,7 @@ abstract class AbstractButton<Impl: AbstractButton<Impl>>(val content: View, val
|
||||||
field = value
|
field = value
|
||||||
value?.also(::addBackground)
|
value?.also(::addBackground)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The background to draw when the button is hovered over by the mouse.
|
* The background to draw when the button is hovered over by the mouse.
|
||||||
* If `null`, the normal [background] will be used.
|
* If `null`, the normal [background] will be used.
|
||||||
|
@ -62,6 +63,7 @@ abstract class AbstractButton<Impl: AbstractButton<Impl>>(val content: View, val
|
||||||
field = value
|
field = value
|
||||||
value?.also(::addBackground)
|
value?.also(::addBackground)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The background to draw when the button is [disabled].
|
* The background to draw when the button is [disabled].
|
||||||
* If `null`, the normal [background] will be used.
|
* If `null`, the normal [background] will be used.
|
||||||
|
|
|
@ -14,7 +14,7 @@ class Button(
|
||||||
content: View,
|
content: View,
|
||||||
padding: Double = 4.0,
|
padding: Double = 4.0,
|
||||||
handler: ((Button) -> Unit)? = null
|
handler: ((Button) -> Unit)? = null
|
||||||
): AbstractButton<Button>(content, padding) {
|
) : AbstractButton<Button>(content, padding) {
|
||||||
init {
|
init {
|
||||||
this.handler = handler
|
this.handler = handler
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,13 +33,13 @@ import net.shadowfacts.kiwidsl.dsl
|
||||||
* Positioning of content views is handled by the dropdown.
|
* Positioning of content views is handled by the dropdown.
|
||||||
* @param updateView A function for updating the view used as the button's 'label' that's visible even when the dropdown isn't.
|
* @param updateView A function for updating the view used as the button's 'label' that's visible even when the dropdown isn't.
|
||||||
*/
|
*/
|
||||||
class DropdownButton<Value, ContentView: View>(
|
class DropdownButton<Value, ContentView : View>(
|
||||||
val initialValue: Value,
|
val initialValue: Value,
|
||||||
val allValues: Iterable<Value>,
|
val allValues: Iterable<Value>,
|
||||||
val createView: (Value) -> ContentView,
|
val createView: (Value) -> ContentView,
|
||||||
val updateView: (newValue: Value, view: ContentView) -> Unit,
|
val updateView: (newValue: Value, view: ContentView) -> Unit,
|
||||||
padding: Double = 4.0
|
padding: Double = 4.0
|
||||||
): AbstractButton<DropdownButton<Value, ContentView>>(
|
) : AbstractButton<DropdownButton<Value, ContentView>>(
|
||||||
StackView(Axis.HORIZONTAL),
|
StackView(Axis.HORIZONTAL),
|
||||||
padding
|
padding
|
||||||
) {
|
) {
|
||||||
|
@ -144,7 +144,7 @@ private class DropdownItemBackgroundView(
|
||||||
private val first: Boolean,
|
private val first: Boolean,
|
||||||
private val last: Boolean,
|
private val last: Boolean,
|
||||||
ninePatch: NinePatchTexture
|
ninePatch: NinePatchTexture
|
||||||
): NinePatchView(ninePatch) {
|
) : NinePatchView(ninePatch) {
|
||||||
|
|
||||||
// Corners
|
// Corners
|
||||||
private val topLeftDelegate = ResettableLazyProperty {
|
private val topLeftDelegate = ResettableLazyProperty {
|
||||||
|
@ -159,7 +159,12 @@ private class DropdownItemBackgroundView(
|
||||||
override val topRight by topRightDelegate
|
override val topRight by topRightDelegate
|
||||||
|
|
||||||
private val bottomLeftDelegate = ResettableLazyProperty {
|
private val bottomLeftDelegate = ResettableLazyProperty {
|
||||||
Rect(topLeft.left, bounds.height - ninePatch.cornerHeight, topLeft.width, if (last) ninePatch.cornerHeight.toDouble() else 0.0)
|
Rect(
|
||||||
|
topLeft.left,
|
||||||
|
bounds.height - ninePatch.cornerHeight,
|
||||||
|
topLeft.width,
|
||||||
|
if (last) ninePatch.cornerHeight.toDouble() else 0.0
|
||||||
|
)
|
||||||
}
|
}
|
||||||
override val bottomLeft by bottomLeftDelegate
|
override val bottomLeft by bottomLeftDelegate
|
||||||
|
|
||||||
|
@ -180,7 +185,12 @@ private class DropdownItemBackgroundView(
|
||||||
override val bottomMiddle by bottomMiddleDelegate
|
override val bottomMiddle by bottomMiddleDelegate
|
||||||
|
|
||||||
private val leftMiddleDelegate = ResettableLazyProperty {
|
private val leftMiddleDelegate = ResettableLazyProperty {
|
||||||
Rect(topLeft.left, topLeft.bottom, topLeft.width, bounds.height - (if (first && last) 2 else if (first || last) 1 else 0) * ninePatch.cornerHeight)
|
Rect(
|
||||||
|
topLeft.left,
|
||||||
|
topLeft.bottom,
|
||||||
|
topLeft.width,
|
||||||
|
bounds.height - (if (first && last) 2 else if (first || last) 1 else 0) * ninePatch.cornerHeight
|
||||||
|
)
|
||||||
}
|
}
|
||||||
override val leftMiddle by leftMiddleDelegate
|
override val leftMiddle by leftMiddleDelegate
|
||||||
|
|
||||||
|
@ -195,7 +205,17 @@ private class DropdownItemBackgroundView(
|
||||||
}
|
}
|
||||||
override val center by centerDelegate
|
override val center by centerDelegate
|
||||||
|
|
||||||
private val delegates = listOf(topLeftDelegate, topRightDelegate, bottomLeftDelegate, bottomRightDelegate, topMiddleDelegate, bottomMiddleDelegate, leftMiddleDelegate, rightMiddleDelegate, centerDelegate)
|
private val delegates = listOf(
|
||||||
|
topLeftDelegate,
|
||||||
|
topRightDelegate,
|
||||||
|
bottomLeftDelegate,
|
||||||
|
bottomRightDelegate,
|
||||||
|
topMiddleDelegate,
|
||||||
|
bottomMiddleDelegate,
|
||||||
|
leftMiddleDelegate,
|
||||||
|
rightMiddleDelegate,
|
||||||
|
centerDelegate
|
||||||
|
)
|
||||||
|
|
||||||
override fun didLayout() {
|
override fun didLayout() {
|
||||||
super.didLayout()
|
super.didLayout()
|
||||||
|
|
|
@ -16,10 +16,10 @@ import net.shadowfacts.cacao.view.Label
|
||||||
* @param initialValue The initial enum value for this button.
|
* @param initialValue The initial enum value for this button.
|
||||||
* @param localizer A function that takes an enum value and converts into a [Text] for the button's label.
|
* @param localizer A function that takes an enum value and converts into a [Text] for the button's label.
|
||||||
*/
|
*/
|
||||||
class EnumButton<E: Enum<E>>(
|
class EnumButton<E : Enum<E>>(
|
||||||
initialValue: E,
|
initialValue: E,
|
||||||
val localizer: (E) -> Text
|
val localizer: (E) -> Text
|
||||||
): AbstractButton<EnumButton<E>>(
|
) : AbstractButton<EnumButton<E>>(
|
||||||
Label(localizer(initialValue), shadow = true)
|
Label(localizer(initialValue), shadow = true)
|
||||||
) {
|
) {
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ import net.shadowfacts.cacao.view.View
|
||||||
class ToggleButton(
|
class ToggleButton(
|
||||||
initialState: Boolean,
|
initialState: Boolean,
|
||||||
handler: ((ToggleButton) -> Unit)? = null,
|
handler: ((ToggleButton) -> Unit)? = null,
|
||||||
): AbstractButton<ToggleButton>(TextureView(if (initialState) ON else OFF), padding = 0.0) {
|
) : AbstractButton<ToggleButton>(TextureView(if (initialState) ON else OFF), padding = 0.0) {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val OFF = Texture(Identifier("textures/gui/checkbox.png"), 0, 0, 64, 64)
|
val OFF = Texture(Identifier("textures/gui/checkbox.png"), 0, 0, 64, 64)
|
||||||
|
|
|
@ -20,9 +20,9 @@ import org.lwjgl.glfw.GLFW
|
||||||
* the exact type of text field.
|
* the exact type of text field.
|
||||||
* @param initialText The initial value of the text field.
|
* @param initialText The initial value of the text field.
|
||||||
*/
|
*/
|
||||||
abstract class AbstractTextField<Impl: AbstractTextField<Impl>>(
|
abstract class AbstractTextField<Impl : AbstractTextField<Impl>>(
|
||||||
initialText: String
|
initialText: String
|
||||||
): View() {
|
) : 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.
|
||||||
|
@ -166,7 +166,8 @@ abstract class AbstractTextField<Impl: AbstractTextField<Impl>>(
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo: label for the TextFieldWidget?
|
// todo: label for the TextFieldWidget?
|
||||||
private class ProxyWidget: TextFieldWidget(MinecraftClient.getInstance().textRenderer, 0, 0, 0, 0, LiteralText("")) {
|
private class ProxyWidget :
|
||||||
|
TextFieldWidget(MinecraftClient.getInstance().textRenderer, 0, 0, 0, 0, LiteralText("")) {
|
||||||
// AbstractButtonWidget.height is protected
|
// AbstractButtonWidget.height is protected
|
||||||
fun setHeight(height: Int) {
|
fun setHeight(height: Int) {
|
||||||
this.height = height
|
this.height = height
|
||||||
|
|
|
@ -6,7 +6,7 @@ package net.shadowfacts.cacao.view.textfield
|
||||||
open class NumberField(
|
open class NumberField(
|
||||||
initialValue: Int,
|
initialValue: Int,
|
||||||
handler: ((NumberField) -> Unit)? = null,
|
handler: ((NumberField) -> Unit)? = null,
|
||||||
): AbstractTextField<NumberField>(initialValue.toString()) {
|
) : AbstractTextField<NumberField>(initialValue.toString()) {
|
||||||
|
|
||||||
var number: Int?
|
var number: Int?
|
||||||
get() {
|
get() {
|
||||||
|
|
|
@ -10,7 +10,7 @@ package net.shadowfacts.cacao.view.textfield
|
||||||
open class TextField(
|
open class TextField(
|
||||||
initialText: String,
|
initialText: String,
|
||||||
handler: ((TextField) -> Unit)? = null
|
handler: ((TextField) -> Unit)? = null
|
||||||
): AbstractTextField<TextField>(initialText) {
|
) : AbstractTextField<TextField>(initialText) {
|
||||||
init {
|
init {
|
||||||
this.handler = handler
|
this.handler = handler
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,11 +34,11 @@ import java.lang.RuntimeException
|
||||||
* @param onTabChange A function invoked immediately after the active tab has changed (and the content view has been
|
* @param onTabChange A function invoked immediately after the active tab has changed (and the content view has been
|
||||||
* updated).
|
* updated).
|
||||||
*/
|
*/
|
||||||
class TabViewController<T: TabViewController.Tab>(
|
class TabViewController<T : TabViewController.Tab>(
|
||||||
val tabs: List<T>,
|
val tabs: List<T>,
|
||||||
initialTab: T = tabs.first(),
|
initialTab: T = tabs.first(),
|
||||||
val onTabChange: ((T) -> Unit)? = null
|
val onTabChange: ((T) -> Unit)? = null
|
||||||
): ViewController() {
|
) : ViewController() {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Tab interface defines the requirements for tab objects that can be used with this view controller.
|
* The Tab interface defines the requirements for tab objects that can be used with this view controller.
|
||||||
|
@ -83,7 +83,7 @@ class TabViewController<T: TabViewController.Tab>(
|
||||||
override val tooltip: Text? = null,
|
override val tooltip: Text? = null,
|
||||||
override val controller: ViewController,
|
override val controller: ViewController,
|
||||||
private val visible: (() -> Boolean)? = null
|
private val visible: (() -> Boolean)? = null
|
||||||
): Tab {
|
) : Tab {
|
||||||
override val isVisible: Boolean
|
override val isVisible: Boolean
|
||||||
get() = visible?.invoke() ?: true
|
get() = visible?.invoke() ?: true
|
||||||
}
|
}
|
||||||
|
@ -99,6 +99,7 @@ class TabViewController<T: TabViewController.Tab>(
|
||||||
private lateinit var outerStack: StackView
|
private lateinit var outerStack: StackView
|
||||||
private lateinit var tabStack: StackView
|
private lateinit var tabStack: StackView
|
||||||
private lateinit var currentTabController: ViewController
|
private lateinit var currentTabController: ViewController
|
||||||
|
|
||||||
// todo: this shouldn't be public, use layout guides
|
// todo: this shouldn't be public, use layout guides
|
||||||
lateinit var tabVCContainer: View
|
lateinit var tabVCContainer: View
|
||||||
private set
|
private set
|
||||||
|
@ -227,9 +228,9 @@ class TabViewController<T: TabViewController.Tab>(
|
||||||
window!!.layout()
|
window!!.layout()
|
||||||
}
|
}
|
||||||
|
|
||||||
private class TabButton<T: Tab>(
|
private class TabButton<T : Tab>(
|
||||||
val tab: T,
|
val tab: T,
|
||||||
): AbstractButton<TabButton<T>>(
|
) : AbstractButton<TabButton<T>>(
|
||||||
tab.tabView,
|
tab.tabView,
|
||||||
padding = 2.0
|
padding = 2.0
|
||||||
) {
|
) {
|
||||||
|
|
|
@ -58,6 +58,7 @@ abstract class ViewController {
|
||||||
|
|
||||||
// _children is the internal, mutable object since we only want it to be mutated by the embed/removeChild methods
|
// _children is the internal, mutable object since we only want it to be mutated by the embed/removeChild methods
|
||||||
private var _children = LinkedList<ViewController>()
|
private var _children = LinkedList<ViewController>()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The list of all the child VCs of this view controller.
|
* The list of all the child VCs of this view controller.
|
||||||
* This list should never be mutated directly, only by the [embedChild]/[removeChild] methods.
|
* This list should never be mutated directly, only by the [embedChild]/[removeChild] methods.
|
||||||
|
|
|
@ -9,6 +9,6 @@ import net.shadowfacts.cacao.viewcontroller.ViewController
|
||||||
class ScreenHandlerWindow(
|
class ScreenHandlerWindow(
|
||||||
val screenHandler: ScreenHandler,
|
val screenHandler: ScreenHandler,
|
||||||
viewController: ViewController
|
viewController: ViewController
|
||||||
): Window(viewController) {
|
) : Window(viewController) {
|
||||||
|
|
||||||
}
|
}
|
|
@ -48,30 +48,37 @@ open class Window(
|
||||||
* Layout anchor for the left edge of this view in the window's coordinate system.
|
* Layout anchor for the left edge of this view in the window's coordinate system.
|
||||||
*/
|
*/
|
||||||
val leftAnchor = Variable("left")
|
val leftAnchor = Variable("left")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Layout anchor for the right edge of this view in the window's coordinate system.
|
* Layout anchor for the right edge of this view in the window's coordinate system.
|
||||||
*/
|
*/
|
||||||
val rightAnchor = Variable("right")
|
val rightAnchor = Variable("right")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Layout anchor for the top edge of this view in the window's coordinate system.
|
* Layout anchor for the top edge of this view in the window's coordinate system.
|
||||||
*/
|
*/
|
||||||
val topAnchor = Variable("top")
|
val topAnchor = Variable("top")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Layout anchor for the bottom edge of this view in the window's coordinate system.
|
* Layout anchor for the bottom edge of this view in the window's coordinate system.
|
||||||
*/
|
*/
|
||||||
val bottomAnchor = Variable("bottom")
|
val bottomAnchor = Variable("bottom")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Layout anchor for the width of this view in the window's coordinate system.
|
* Layout anchor for the width of this view in the window's coordinate system.
|
||||||
*/
|
*/
|
||||||
val widthAnchor = Variable("width")
|
val widthAnchor = Variable("width")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Layout anchor for the height of this view in the window's coordinate system.
|
* Layout anchor for the height of this view in the window's coordinate system.
|
||||||
*/
|
*/
|
||||||
val heightAnchor = Variable("height")
|
val heightAnchor = Variable("height")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Layout anchor for the center X position of this view in the window's coordinate system.
|
* Layout anchor for the center X position of this view in the window's coordinate system.
|
||||||
*/
|
*/
|
||||||
val centerXAnchor = Variable("centerX")
|
val centerXAnchor = Variable("centerX")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Layout anchor for the center Y position of this view in the window's coordinate system.
|
* Layout anchor for the center Y position of this view in the window's coordinate system.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -17,7 +17,8 @@ class KiwiContext(val solver: Solver) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun ExpressionConvertible.equalTo(other: ExpressionConvertible, strength: Double): Constraint {
|
fun ExpressionConvertible.equalTo(other: ExpressionConvertible, strength: Double): Constraint {
|
||||||
return Symbolics.equals(this.toExpression(), other.toExpression()).setStrength(strength).apply(solver::addConstraint)
|
return Symbolics.equals(this.toExpression(), other.toExpression()).setStrength(strength)
|
||||||
|
.apply(solver::addConstraint)
|
||||||
}
|
}
|
||||||
|
|
||||||
infix fun ExpressionConvertible.equalTo(constant: Number): Constraint {
|
infix fun ExpressionConvertible.equalTo(constant: Number): Constraint {
|
||||||
|
@ -25,7 +26,8 @@ class KiwiContext(val solver: Solver) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun ExpressionConvertible.equalTo(constant: Number, strength: Double): Constraint {
|
fun ExpressionConvertible.equalTo(constant: Number, strength: Double): Constraint {
|
||||||
return Symbolics.equals(this.toExpression(), constant.toDouble()).setStrength(strength).apply(solver::addConstraint)
|
return Symbolics.equals(this.toExpression(), constant.toDouble()).setStrength(strength)
|
||||||
|
.apply(solver::addConstraint)
|
||||||
}
|
}
|
||||||
|
|
||||||
infix fun ExpressionConvertible.lessThanOrEqualTo(other: ExpressionConvertible): Constraint {
|
infix fun ExpressionConvertible.lessThanOrEqualTo(other: ExpressionConvertible): Constraint {
|
||||||
|
@ -33,7 +35,8 @@ class KiwiContext(val solver: Solver) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun ExpressionConvertible.lessThanOrEqualTo(other: ExpressionConvertible, strength: Double): Constraint {
|
fun ExpressionConvertible.lessThanOrEqualTo(other: ExpressionConvertible, strength: Double): Constraint {
|
||||||
return Symbolics.lessThanOrEqualTo(this.toExpression(), other.toExpression()).setStrength(strength).apply(solver::addConstraint)
|
return Symbolics.lessThanOrEqualTo(this.toExpression(), other.toExpression()).setStrength(strength)
|
||||||
|
.apply(solver::addConstraint)
|
||||||
}
|
}
|
||||||
|
|
||||||
infix fun ExpressionConvertible.lessThanOrEqualTo(constant: Number): Constraint {
|
infix fun ExpressionConvertible.lessThanOrEqualTo(constant: Number): Constraint {
|
||||||
|
@ -41,7 +44,8 @@ class KiwiContext(val solver: Solver) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun ExpressionConvertible.lessThanOrEqualTo(constant: Number, strength: Double): Constraint {
|
fun ExpressionConvertible.lessThanOrEqualTo(constant: Number, strength: Double): Constraint {
|
||||||
return Symbolics.lessThanOrEqualTo(this.toExpression(), constant.toDouble()).setStrength(strength).apply(solver::addConstraint)
|
return Symbolics.lessThanOrEqualTo(this.toExpression(), constant.toDouble()).setStrength(strength)
|
||||||
|
.apply(solver::addConstraint)
|
||||||
}
|
}
|
||||||
|
|
||||||
infix fun ExpressionConvertible.greaterThanOrEqualTo(other: ExpressionConvertible): Constraint {
|
infix fun ExpressionConvertible.greaterThanOrEqualTo(other: ExpressionConvertible): Constraint {
|
||||||
|
@ -49,7 +53,8 @@ class KiwiContext(val solver: Solver) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun ExpressionConvertible.greaterThanOrEqualTo(other: ExpressionConvertible, strength: Double): Constraint {
|
fun ExpressionConvertible.greaterThanOrEqualTo(other: ExpressionConvertible, strength: Double): Constraint {
|
||||||
return Symbolics.greaterThanOrEqualTo(this.toExpression(), other.toExpression()).setStrength(strength).apply(solver::addConstraint)
|
return Symbolics.greaterThanOrEqualTo(this.toExpression(), other.toExpression()).setStrength(strength)
|
||||||
|
.apply(solver::addConstraint)
|
||||||
}
|
}
|
||||||
|
|
||||||
infix fun ExpressionConvertible.greaterThanOrEqualTo(constant: Number): Constraint {
|
infix fun ExpressionConvertible.greaterThanOrEqualTo(constant: Number): Constraint {
|
||||||
|
@ -57,7 +62,8 @@ class KiwiContext(val solver: Solver) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun ExpressionConvertible.greaterThanOrEqualTo(constant: Number, strength: Double): Constraint {
|
fun ExpressionConvertible.greaterThanOrEqualTo(constant: Number, strength: Double): Constraint {
|
||||||
return Symbolics.greaterThanOrEqualTo(this.toExpression(), constant.toDouble()).setStrength(strength).apply(solver::addConstraint)
|
return Symbolics.greaterThanOrEqualTo(this.toExpression(), constant.toDouble()).setStrength(strength)
|
||||||
|
.apply(solver::addConstraint)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Addition
|
// Addition
|
||||||
|
|
|
@ -9,13 +9,14 @@ import net.shadowfacts.phycon.util.SortMode
|
||||||
/**
|
/**
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
*/
|
*/
|
||||||
object DefaultPlugin: PhyConPlugin {
|
object DefaultPlugin : PhyConPlugin {
|
||||||
|
|
||||||
lateinit var SORT_MODE: TerminalSettingKey<SortMode>
|
lateinit var SORT_MODE: TerminalSettingKey<SortMode>
|
||||||
private set
|
private set
|
||||||
|
|
||||||
override fun initializePhyCon(api: PhyConAPI) {
|
override fun initializePhyCon(api: PhyConAPI) {
|
||||||
SORT_MODE = api.registerTerminalSetting(Identifier(PhysicalConnectivity.MODID, "sort"), SortMode.COUNT_HIGH_FIRST)
|
SORT_MODE =
|
||||||
|
api.registerTerminalSetting(Identifier(PhysicalConnectivity.MODID, "sort"), SortMode.COUNT_HIGH_FIRST)
|
||||||
SORT_MODE.setPriority(Int.MAX_VALUE)
|
SORT_MODE.setPriority(Int.MAX_VALUE)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,9 +9,12 @@ import net.shadowfacts.phycon.util.TerminalSettings
|
||||||
/**
|
/**
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
*/
|
*/
|
||||||
object PhyConAPIImpl: PhyConAPI {
|
object PhyConAPIImpl : PhyConAPI {
|
||||||
|
|
||||||
override fun <E> registerTerminalSetting(id: Identifier, defaultValue: E): TerminalSettingKey<E> where E: Enum<E>, E: TerminalSetting? {
|
override fun <E> registerTerminalSetting(
|
||||||
|
id: Identifier,
|
||||||
|
defaultValue: E
|
||||||
|
): TerminalSettingKey<E> where E : Enum<E>, E : TerminalSetting? {
|
||||||
return TerminalSettings.register(id, defaultValue)
|
return TerminalSettings.register(id, defaultValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ import org.apache.logging.log4j.LogManager
|
||||||
/**
|
/**
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
*/
|
*/
|
||||||
object PhysicalConnectivity: ModInitializer {
|
object PhysicalConnectivity : ModInitializer {
|
||||||
|
|
||||||
val MODID = "phycon"
|
val MODID = "phycon"
|
||||||
|
|
||||||
|
@ -33,7 +33,10 @@ object PhysicalConnectivity: ModInitializer {
|
||||||
registerGlobalReceiver(C2STerminalRequestItem)
|
registerGlobalReceiver(C2STerminalRequestItem)
|
||||||
registerGlobalReceiver(C2STerminalUpdateDisplayedItems)
|
registerGlobalReceiver(C2STerminalUpdateDisplayedItems)
|
||||||
|
|
||||||
ItemStorage.SIDED.registerForBlockEntity(P2PReceiverBlockEntity::provideItemStorage, PhyBlockEntities.P2P_RECEIVER)
|
ItemStorage.SIDED.registerForBlockEntity(
|
||||||
|
P2PReceiverBlockEntity::provideItemStorage,
|
||||||
|
PhyBlockEntities.P2P_RECEIVER
|
||||||
|
)
|
||||||
|
|
||||||
for (it in FabricLoader.getInstance().getEntrypoints("phycon", PhyConPlugin::class.java)) {
|
for (it in FabricLoader.getInstance().getEntrypoints("phycon", PhyConPlugin::class.java)) {
|
||||||
it.initializePhyCon(PhyConAPIImpl)
|
it.initializePhyCon(PhyConAPIImpl)
|
||||||
|
|
|
@ -21,7 +21,7 @@ import net.shadowfacts.phycon.util.TerminalSettings
|
||||||
/**
|
/**
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
*/
|
*/
|
||||||
object PhysicalConnectivityClient: ClientModInitializer {
|
object PhysicalConnectivityClient : ClientModInitializer {
|
||||||
|
|
||||||
val terminalSettings = TerminalSettings()
|
val terminalSettings = TerminalSettings()
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ 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(pos: BlockPos, state: BlockState): T?
|
abstract override fun createBlockEntity(pos: BlockPos, state: BlockState): T?
|
||||||
|
|
||||||
fun getBlockEntity(world: BlockView, pos: BlockPos): T? {
|
fun getBlockEntity(world: BlockView, pos: BlockPos): T? {
|
||||||
|
|
|
@ -15,11 +15,21 @@ import net.shadowfacts.phycon.api.NetworkComponentBlock
|
||||||
/**
|
/**
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
*/
|
*/
|
||||||
abstract class DeviceBlock<T: DeviceBlockEntity>(settings: Settings): BlockWithEntity<T>(settings), NetworkComponentBlock {
|
abstract class DeviceBlock<T : DeviceBlockEntity>(settings: Settings) : BlockWithEntity<T>(settings),
|
||||||
|
NetworkComponentBlock {
|
||||||
|
|
||||||
abstract override fun getNetworkConnectedSides(state: BlockState, world: WorldAccess, pos: BlockPos): Collection<Direction>
|
abstract override fun getNetworkConnectedSides(
|
||||||
|
state: BlockState,
|
||||||
|
world: WorldAccess,
|
||||||
|
pos: BlockPos
|
||||||
|
): Collection<Direction>
|
||||||
|
|
||||||
override fun getNetworkInterfaceForSide(side: Direction, state: BlockState, world: WorldAccess, pos: BlockPos): Interface? {
|
override fun getNetworkInterfaceForSide(
|
||||||
|
side: Direction,
|
||||||
|
state: BlockState,
|
||||||
|
world: WorldAccess,
|
||||||
|
pos: BlockPos
|
||||||
|
): Interface? {
|
||||||
return getBlockEntity(world, pos)!!
|
return getBlockEntity(world, pos)!!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,7 +38,11 @@ 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>? {
|
override fun <T : BlockEntity> getTicker(
|
||||||
|
world: World,
|
||||||
|
state: BlockState,
|
||||||
|
type: BlockEntityType<T>
|
||||||
|
): BlockEntityTicker<T>? {
|
||||||
return if (world.isClient) {
|
return if (world.isClient) {
|
||||||
null
|
null
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -28,7 +28,8 @@ import java.util.*
|
||||||
/**
|
/**
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
*/
|
*/
|
||||||
abstract class DeviceBlockEntity(type: BlockEntityType<*>, pos: BlockPos, state: BlockState): BlockEntity(type, pos, state),
|
abstract class DeviceBlockEntity(type: BlockEntityType<*>, pos: BlockPos, state: BlockState) :
|
||||||
|
BlockEntity(type, pos, state),
|
||||||
PacketSink,
|
PacketSink,
|
||||||
PacketSource,
|
PacketSource,
|
||||||
Interface {
|
Interface {
|
||||||
|
@ -60,6 +61,7 @@ abstract class DeviceBlockEntity(type: BlockEntityType<*>, pos: BlockPos, state:
|
||||||
is DeviceRemovedPacket -> {
|
is DeviceRemovedPacket -> {
|
||||||
arpTable.remove(packet.source)
|
arpTable.remove(packet.source)
|
||||||
}
|
}
|
||||||
|
|
||||||
is PingPacket -> {
|
is PingPacket -> {
|
||||||
sendPacket(PongPacket(ipAddress, packet.source))
|
sendPacket(PongPacket(ipAddress, packet.source))
|
||||||
}
|
}
|
||||||
|
@ -72,7 +74,14 @@ abstract class DeviceBlockEntity(type: BlockEntityType<*>, pos: BlockPos, state:
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun receive(frame: EthernetFrame) {
|
override fun receive(frame: EthernetFrame) {
|
||||||
PhysicalConnectivity.NETWORK_LOGGER.debug("{} ({}, {}) received frame from {}: {}", this, ipAddress, macAddress, frame.source, frame)
|
PhysicalConnectivity.NETWORK_LOGGER.debug(
|
||||||
|
"{} ({}, {}) received frame from {}: {}",
|
||||||
|
this,
|
||||||
|
ipAddress,
|
||||||
|
macAddress,
|
||||||
|
frame.source,
|
||||||
|
frame
|
||||||
|
)
|
||||||
when (frame) {
|
when (frame) {
|
||||||
is ARPQueryFrame -> handleARPQuery(frame)
|
is ARPQueryFrame -> handleARPQuery(frame)
|
||||||
is ARPResponseFrame -> handleARPResponse(frame)
|
is ARPResponseFrame -> handleARPResponse(frame)
|
||||||
|
@ -89,14 +98,26 @@ abstract class DeviceBlockEntity(type: BlockEntityType<*>, pos: BlockPos, state:
|
||||||
PhysicalConnectivity.NETWORK_LOGGER.debug("{}, ({}), received ARP query for {}", this, ipAddress, frame.queryIP)
|
PhysicalConnectivity.NETWORK_LOGGER.debug("{}, ({}), received ARP query for {}", this, ipAddress, frame.queryIP)
|
||||||
arpTable[frame.sourceIP] = frame.source
|
arpTable[frame.sourceIP] = frame.source
|
||||||
if (frame.queryIP == ipAddress) {
|
if (frame.queryIP == ipAddress) {
|
||||||
PhysicalConnectivity.NETWORK_LOGGER.debug("{} ({}) sending ARP response to {} with {}", this, ipAddress, frame.sourceIP, macAddress)
|
PhysicalConnectivity.NETWORK_LOGGER.debug(
|
||||||
|
"{} ({}) sending ARP response to {} with {}",
|
||||||
|
this,
|
||||||
|
ipAddress,
|
||||||
|
frame.sourceIP,
|
||||||
|
macAddress
|
||||||
|
)
|
||||||
send(ARPResponseFrame(ipAddress, macAddress, frame.source))
|
send(ARPResponseFrame(ipAddress, macAddress, frame.source))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleARPResponse(frame: ARPResponseFrame) {
|
private fun handleARPResponse(frame: ARPResponseFrame) {
|
||||||
arpTable[frame.query] = frame.source
|
arpTable[frame.query] = frame.source
|
||||||
PhysicalConnectivity.NETWORK_LOGGER.debug("{}, ({}) received ARP response for {} with {}", this, ipAddress, frame.query, frame.source)
|
PhysicalConnectivity.NETWORK_LOGGER.debug(
|
||||||
|
"{}, ({}) received ARP response for {} with {}",
|
||||||
|
this,
|
||||||
|
ipAddress,
|
||||||
|
frame.query,
|
||||||
|
frame.source
|
||||||
|
)
|
||||||
|
|
||||||
val toRemove = packetQueue.filter { (packet, _) ->
|
val toRemove = packetQueue.filter { (packet, _) ->
|
||||||
if (packet.destination == frame.query) {
|
if (packet.destination == frame.query) {
|
||||||
|
@ -122,7 +143,12 @@ abstract class DeviceBlockEntity(type: BlockEntityType<*>, pos: BlockPos, state:
|
||||||
} else {
|
} else {
|
||||||
packetQueue.add(PendingPacket(packet, counter))
|
packetQueue.add(PendingPacket(packet, counter))
|
||||||
|
|
||||||
PhysicalConnectivity.NETWORK_LOGGER.debug("{} ({}) sending ARP query for {}", this, ipAddress, packet.destination)
|
PhysicalConnectivity.NETWORK_LOGGER.debug(
|
||||||
|
"{} ({}) sending ARP query for {}",
|
||||||
|
this,
|
||||||
|
ipAddress,
|
||||||
|
packet.destination
|
||||||
|
)
|
||||||
send(ARPQueryFrame(packet.destination, ipAddress, macAddress))
|
send(ARPQueryFrame(packet.destination, ipAddress, macAddress))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -141,6 +167,7 @@ abstract class DeviceBlockEntity(type: BlockEntityType<*>, pos: BlockPos, state:
|
||||||
this.cachedDestination = WeakReference(it)
|
this.cachedDestination = WeakReference(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> throw RuntimeException("DeviceBlockEntity.findDestination must be overridden by devices which have more than 1 network connected side")
|
else -> throw RuntimeException("DeviceBlockEntity.findDestination must be overridden by devices which have more than 1 network connected side")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@ import java.util.*
|
||||||
/**
|
/**
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
*/
|
*/
|
||||||
abstract class FaceDeviceBlock<T: DeviceBlockEntity>(settings: Settings): DeviceBlock<T>(settings) {
|
abstract class FaceDeviceBlock<T : DeviceBlockEntity>(settings: Settings) : DeviceBlock<T>(settings) {
|
||||||
companion object {
|
companion object {
|
||||||
val FACING = Properties.FACING
|
val FACING = Properties.FACING
|
||||||
val CABLE_CONNECTION = EnumProperty.of("cable_connection", FaceCableConnection::class.java)
|
val CABLE_CONNECTION = EnumProperty.of("cable_connection", FaceCableConnection::class.java)
|
||||||
|
@ -82,7 +82,11 @@ abstract class FaceDeviceBlock<T: DeviceBlockEntity>(settings: Settings): Device
|
||||||
if (cableConnection == FaceCableConnection.NONE) {
|
if (cableConnection == FaceCableConnection.NONE) {
|
||||||
VoxelShapes.union(faceShapes[facing], centerShapes[facing])
|
VoxelShapes.union(faceShapes[facing], centerShapes[facing])
|
||||||
} else {
|
} else {
|
||||||
VoxelShapes.union(faceShapes[facing], centerShapes[facing], CableBlock.SIDE_SHAPES[cableConnection.direction])
|
VoxelShapes.union(
|
||||||
|
faceShapes[facing],
|
||||||
|
centerShapes[facing],
|
||||||
|
CableBlock.SIDE_SHAPES[cableConnection.direction]
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -92,7 +96,12 @@ abstract class FaceDeviceBlock<T: DeviceBlockEntity>(settings: Settings): Device
|
||||||
return if (direction != null) EnumSet.of(direction) else setOf()
|
return if (direction != null) EnumSet.of(direction) else setOf()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getNetworkInterfaceForSide(side: Direction, state: BlockState, world: WorldAccess, pos: BlockPos): Interface? {
|
override fun getNetworkInterfaceForSide(
|
||||||
|
side: Direction,
|
||||||
|
state: BlockState,
|
||||||
|
world: WorldAccess,
|
||||||
|
pos: BlockPos
|
||||||
|
): Interface? {
|
||||||
return if (side == state[FACING]) {
|
return if (side == state[FACING]) {
|
||||||
null
|
null
|
||||||
} else {
|
} else {
|
||||||
|
@ -108,15 +117,22 @@ abstract class FaceDeviceBlock<T: DeviceBlockEntity>(settings: Settings): Device
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getPlacementState(context: ItemPlacementContext): BlockState {
|
override fun getPlacementState(context: ItemPlacementContext): BlockState {
|
||||||
val facing = if (context.player?.isSneaking == true) context.side.opposite else context.playerLookDirection.opposite
|
val facing =
|
||||||
|
if (context.player?.isSneaking == true) context.side.opposite else context.playerLookDirection.opposite
|
||||||
// todo: this should never be called
|
// todo: this should never be called
|
||||||
val cableConnection = FaceCableConnection.from(getCableConnectedSide(context.world, context.blockPos, facing, DyeColor.BLUE))
|
val cableConnection =
|
||||||
|
FaceCableConnection.from(getCableConnectedSide(context.world, context.blockPos, facing, DyeColor.BLUE))
|
||||||
return defaultState
|
return defaultState
|
||||||
.with(FACING, facing)
|
.with(FACING, facing)
|
||||||
.with(CABLE_CONNECTION, cableConnection)
|
.with(CABLE_CONNECTION, cableConnection)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getCableConnectedSide(world: WorldAccess, pos: BlockPos, facing: Direction, color: DyeColor): Direction? {
|
private fun getCableConnectedSide(
|
||||||
|
world: WorldAccess,
|
||||||
|
pos: BlockPos,
|
||||||
|
facing: Direction,
|
||||||
|
color: DyeColor
|
||||||
|
): Direction? {
|
||||||
for (side in Direction.values()) {
|
for (side in Direction.values()) {
|
||||||
if (side == facing) {
|
if (side == facing) {
|
||||||
continue
|
continue
|
||||||
|
@ -130,18 +146,32 @@ abstract class FaceDeviceBlock<T: DeviceBlockEntity>(settings: Settings): Device
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun canConnectTo(world: WorldAccess, side: Direction, candidateState: BlockState, candidatePos: BlockPos, myColor: DyeColor): Boolean {
|
private fun canConnectTo(
|
||||||
|
world: WorldAccess,
|
||||||
|
side: Direction,
|
||||||
|
candidateState: BlockState,
|
||||||
|
candidatePos: BlockPos,
|
||||||
|
myColor: DyeColor
|
||||||
|
): Boolean {
|
||||||
val block = candidateState.block
|
val block = candidateState.block
|
||||||
return if (block is FaceDeviceBlock<*> && candidateState[COLOR] == myColor) {
|
return if (block is FaceDeviceBlock<*> && candidateState[COLOR] == myColor) {
|
||||||
true
|
true
|
||||||
} else if (block is CableBlock && block.color == myColor) {
|
} else if (block is CableBlock && block.color == myColor) {
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
block is NetworkComponentBlock && block.getNetworkConnectedSides(candidateState, world, candidatePos).contains(side.opposite)
|
block is NetworkComponentBlock && block.getNetworkConnectedSides(candidateState, world, candidatePos)
|
||||||
|
.contains(side.opposite)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getStateForNeighborUpdate(state: BlockState, side: Direction, neighborState: BlockState, world: WorldAccess, pos: BlockPos, neighborPos: BlockPos): BlockState {
|
override fun getStateForNeighborUpdate(
|
||||||
|
state: BlockState,
|
||||||
|
side: Direction,
|
||||||
|
neighborState: BlockState,
|
||||||
|
world: WorldAccess,
|
||||||
|
pos: BlockPos,
|
||||||
|
neighborPos: BlockPos
|
||||||
|
): BlockState {
|
||||||
val current = state[CABLE_CONNECTION]
|
val current = state[CABLE_CONNECTION]
|
||||||
var newConnection = current
|
var newConnection = current
|
||||||
|
|
||||||
|
@ -159,7 +189,12 @@ abstract class FaceDeviceBlock<T: DeviceBlockEntity>(settings: Settings): Device
|
||||||
return state.with(CABLE_CONNECTION, newConnection)
|
return state.with(CABLE_CONNECTION, newConnection)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getOutlineShape(state: BlockState, world: BlockView, pos: BlockPos, context: ShapeContext): VoxelShape {
|
override fun getOutlineShape(
|
||||||
|
state: BlockState,
|
||||||
|
world: BlockView,
|
||||||
|
pos: BlockPos,
|
||||||
|
context: ShapeContext
|
||||||
|
): VoxelShape {
|
||||||
return getShape(state[FACING], state[CABLE_CONNECTION])
|
return getShape(state[FACING], state[CABLE_CONNECTION])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,7 @@ import java.util.*
|
||||||
*/
|
*/
|
||||||
class CableBlock(
|
class CableBlock(
|
||||||
val color: DyeColor,
|
val color: DyeColor,
|
||||||
): Block(
|
) : Block(
|
||||||
FabricBlockSettings.of(CABLE_MATERIAL)
|
FabricBlockSettings.of(CABLE_MATERIAL)
|
||||||
.strength(0.3f)
|
.strength(0.3f)
|
||||||
.nonOpaque()
|
.nonOpaque()
|
||||||
|
@ -63,7 +63,8 @@ class CableBlock(
|
||||||
VoxelShapes.union(acc, SIDE_SHAPES[side])
|
VoxelShapes.union(acc, SIDE_SHAPES[side])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val CONNECTIONS: Map<Direction, EnumProperty<CableConnection>> = Direction.values().associate { it to EnumProperty.of(it.name.toLowerCase(), CableConnection::class.java) }
|
val CONNECTIONS: Map<Direction, EnumProperty<CableConnection>> =
|
||||||
|
Direction.values().associate { it to EnumProperty.of(it.name.toLowerCase(), CableConnection::class.java) }
|
||||||
|
|
||||||
fun getShape(state: BlockState): VoxelShape {
|
fun getShape(state: BlockState): VoxelShape {
|
||||||
val key = Direction.values().foldIndexed(0) { i, acc, dir ->
|
val key = Direction.values().foldIndexed(0) { i, acc, dir ->
|
||||||
|
@ -110,7 +111,14 @@ class CableBlock(
|
||||||
return getInitialState(context.world, context.blockPos)
|
return getInitialState(context.world, context.blockPos)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getStateForNeighborUpdate(state: BlockState, side: Direction, neighborState: BlockState, world: WorldAccess, blockPos_1: BlockPos, blockPos_2: BlockPos): BlockState {
|
override fun getStateForNeighborUpdate(
|
||||||
|
state: BlockState,
|
||||||
|
side: Direction,
|
||||||
|
neighborState: BlockState,
|
||||||
|
world: WorldAccess,
|
||||||
|
blockPos_1: BlockPos,
|
||||||
|
blockPos_2: BlockPos
|
||||||
|
): BlockState {
|
||||||
val prop = CONNECTIONS[side]
|
val prop = CONNECTIONS[side]
|
||||||
val current = state[prop]
|
val current = state[prop]
|
||||||
return when (current) {
|
return when (current) {
|
||||||
|
@ -119,7 +127,11 @@ class CableBlock(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getConnectionStateInDirection(world: WorldAccess, pos: BlockPos, direction: Direction): CableConnection {
|
private fun getConnectionStateInDirection(
|
||||||
|
world: WorldAccess,
|
||||||
|
pos: BlockPos,
|
||||||
|
direction: Direction
|
||||||
|
): CableConnection {
|
||||||
val offsetPos = pos.offset(direction)
|
val offsetPos = pos.offset(direction)
|
||||||
val state = world.getBlockState(offsetPos)
|
val state = world.getBlockState(offsetPos)
|
||||||
val block = state.block
|
val block = state.block
|
||||||
|
@ -140,7 +152,12 @@ class CableBlock(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getNetworkInterfaceForSide(side: Direction, state: BlockState, world: WorldAccess, pos: BlockPos): Interface? {
|
override fun getNetworkInterfaceForSide(
|
||||||
|
side: Direction,
|
||||||
|
state: BlockState,
|
||||||
|
world: WorldAccess,
|
||||||
|
pos: BlockPos
|
||||||
|
): Interface? {
|
||||||
// cables don't have network interfaces
|
// cables don't have network interfaces
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
@ -169,11 +186,18 @@ class CableBlock(
|
||||||
val connectedToPos = pos.offset(side)
|
val connectedToPos = pos.offset(side)
|
||||||
val connectedTo = world.getBlockState(connectedToPos)
|
val connectedTo = world.getBlockState(connectedToPos)
|
||||||
if (connectedTo.block == this && connectedTo[CONNECTIONS[side.opposite]] == CableConnection.DISABLED) {
|
if (connectedTo.block == this && connectedTo[CONNECTIONS[side.opposite]] == CableConnection.DISABLED) {
|
||||||
world.setBlockState(connectedToPos, connectedTo.with(CONNECTIONS[side.opposite], CableConnection.ON))
|
world.setBlockState(
|
||||||
|
connectedToPos,
|
||||||
|
connectedTo.with(CONNECTIONS[side.opposite], CableConnection.ON)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
state.with(prop, if (connectedTo.block is NetworkComponentBlock) CableConnection.ON else CableConnection.OFF)
|
state.with(
|
||||||
|
prop,
|
||||||
|
if (connectedTo.block is NetworkComponentBlock) CableConnection.ON else CableConnection.OFF
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> state.with(prop, CableConnection.DISABLED)
|
else -> state.with(prop, CableConnection.DISABLED)
|
||||||
}
|
}
|
||||||
world.setBlockState(pos, newState)
|
world.setBlockState(pos, newState)
|
||||||
|
@ -195,7 +219,12 @@ class CableBlock(
|
||||||
// return false
|
// return false
|
||||||
// }
|
// }
|
||||||
|
|
||||||
override fun getOutlineShape(state: BlockState, world: BlockView, pos: BlockPos, context: ShapeContext): VoxelShape {
|
override fun getOutlineShape(
|
||||||
|
state: BlockState,
|
||||||
|
world: BlockView,
|
||||||
|
pos: BlockPos,
|
||||||
|
context: ShapeContext
|
||||||
|
): VoxelShape {
|
||||||
return getShape(state)
|
return getShape(state)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ import kotlin.math.min
|
||||||
/**
|
/**
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
*/
|
*/
|
||||||
class ExtractorBlock: FaceDeviceBlock<ExtractorBlockEntity>(
|
class ExtractorBlock : FaceDeviceBlock<ExtractorBlockEntity>(
|
||||||
Settings.of(Material.METAL)
|
Settings.of(Material.METAL)
|
||||||
.strength(1.5f)
|
.strength(1.5f)
|
||||||
.sounds(BlockSoundGroup.METAL)
|
.sounds(BlockSoundGroup.METAL)
|
||||||
|
@ -59,7 +59,14 @@ class ExtractorBlock: FaceDeviceBlock<ExtractorBlockEntity>(
|
||||||
arr[i] = 16.0 - arr[i]
|
arr[i] = 16.0 - arr[i]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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]))
|
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) }
|
||||||
}
|
}
|
||||||
|
@ -77,7 +84,14 @@ class ExtractorBlock: FaceDeviceBlock<ExtractorBlockEntity>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun neighborUpdate(state: BlockState, world: World, pos: BlockPos, neighbor: Block, neighborPos: BlockPos, bl: Boolean) {
|
override fun neighborUpdate(
|
||||||
|
state: BlockState,
|
||||||
|
world: World,
|
||||||
|
pos: BlockPos,
|
||||||
|
neighbor: Block,
|
||||||
|
neighborPos: BlockPos,
|
||||||
|
bl: Boolean
|
||||||
|
) {
|
||||||
if (!world.isClient) {
|
if (!world.isClient) {
|
||||||
getBlockEntity(world, pos)!!.updateInventory()
|
getBlockEntity(world, pos)!!.updateInventory()
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,8 @@ import kotlin.properties.Delegates
|
||||||
/**
|
/**
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
*/
|
*/
|
||||||
class ExtractorBlockEntity(pos: BlockPos, state: BlockState): DeviceBlockEntity(PhyBlockEntities.EXTRACTOR, pos, state),
|
class ExtractorBlockEntity(pos: BlockPos, state: BlockState) :
|
||||||
|
DeviceBlockEntity(PhyBlockEntities.EXTRACTOR, pos, state),
|
||||||
NetworkStackDispatcher<ExtractorBlockEntity.PendingInsertion>,
|
NetworkStackDispatcher<ExtractorBlockEntity.PendingInsertion>,
|
||||||
ActivationController.ActivatableDevice,
|
ActivationController.ActivatableDevice,
|
||||||
ClientConfigurableDevice {
|
ClientConfigurableDevice {
|
||||||
|
@ -75,7 +76,13 @@ class ExtractorBlockEntity(pos: BlockPos, state: BlockState): DeviceBlockEntity(
|
||||||
val inventory = getInventory() ?: return insertion.stack
|
val inventory = getInventory() ?: return insertion.stack
|
||||||
// if the inventory has changed, the old slot index is meaningless
|
// if the inventory has changed, the old slot index is meaningless
|
||||||
if (inventory !== insertion.inventory) return insertion.stack
|
if (inventory !== insertion.inventory) return insertion.stack
|
||||||
val extracted = inventory.extractStack(insertion.inventorySlot, ExactItemStackFilter(insertion.stack), ItemStack.EMPTY, insertion.totalCapacity, Simulation.ACTION)
|
val extracted = inventory.extractStack(
|
||||||
|
insertion.inventorySlot,
|
||||||
|
ExactItemStackFilter(insertion.stack),
|
||||||
|
ItemStack.EMPTY,
|
||||||
|
insertion.totalCapacity,
|
||||||
|
Simulation.ACTION
|
||||||
|
)
|
||||||
if (extracted.isEmpty) return insertion.stack
|
if (extracted.isEmpty) return insertion.stack
|
||||||
// if we extracted less than expected, make sure super.finishInsertion doesn't send more than we actually have
|
// if we extracted less than expected, make sure super.finishInsertion doesn't send more than we actually have
|
||||||
insertion.stack = extracted
|
insertion.stack = extracted
|
||||||
|
@ -97,7 +104,13 @@ class ExtractorBlockEntity(pos: BlockPos, state: BlockState): DeviceBlockEntity(
|
||||||
for (slot in 0 until inventory.slotCount) {
|
for (slot in 0 until inventory.slotCount) {
|
||||||
val slotStack = inventory.getInvStack(slot)
|
val slotStack = inventory.getInvStack(slot)
|
||||||
if (slotStack.isEmpty) continue
|
if (slotStack.isEmpty) continue
|
||||||
val extractable = inventory.extractStack(slot, ExactItemStackFilter(slotStack), ItemStack.EMPTY, slotStack.count, Simulation.SIMULATE)
|
val extractable = inventory.extractStack(
|
||||||
|
slot,
|
||||||
|
ExactItemStackFilter(slotStack),
|
||||||
|
ItemStack.EMPTY,
|
||||||
|
slotStack.count,
|
||||||
|
Simulation.SIMULATE
|
||||||
|
)
|
||||||
if (extractable.isEmpty) continue
|
if (extractable.isEmpty) continue
|
||||||
dispatchItemStack(extractable) { insertion ->
|
dispatchItemStack(extractable) { insertion ->
|
||||||
insertion.inventory = inventory
|
insertion.inventory = inventory
|
||||||
|
@ -126,7 +139,8 @@ class ExtractorBlockEntity(pos: BlockPos, state: BlockState): DeviceBlockEntity(
|
||||||
controller.activationMode = ActivationMode.valueOf(tag.getString("ActivationMode"))
|
controller.activationMode = ActivationMode.valueOf(tag.getString("ActivationMode"))
|
||||||
}
|
}
|
||||||
|
|
||||||
class PendingInsertion(stack: ItemStack, timestamp: Long): NetworkStackDispatcher.PendingInsertion<PendingInsertion>(stack, timestamp) {
|
class PendingInsertion(stack: ItemStack, timestamp: Long) :
|
||||||
|
NetworkStackDispatcher.PendingInsertion<PendingInsertion>(stack, timestamp) {
|
||||||
lateinit var inventory: FixedItemInv
|
lateinit var inventory: FixedItemInv
|
||||||
var inventorySlot by Delegates.notNull<Int>()
|
var inventorySlot by Delegates.notNull<Int>()
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,7 @@ import kotlin.math.min
|
||||||
/**
|
/**
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
*/
|
*/
|
||||||
class InserterBlock: FaceDeviceBlock<InserterBlockEntity>(
|
class InserterBlock : FaceDeviceBlock<InserterBlockEntity>(
|
||||||
Settings.of(Material.METAL)
|
Settings.of(Material.METAL)
|
||||||
.strength(1.5f)
|
.strength(1.5f)
|
||||||
.sounds(BlockSoundGroup.METAL)
|
.sounds(BlockSoundGroup.METAL)
|
||||||
|
@ -68,7 +68,14 @@ class InserterBlock: FaceDeviceBlock<InserterBlockEntity>(
|
||||||
arr[i] = 16.0 - arr[i]
|
arr[i] = 16.0 - arr[i]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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]))
|
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) }
|
||||||
}
|
}
|
||||||
|
@ -86,19 +93,33 @@ class InserterBlock: FaceDeviceBlock<InserterBlockEntity>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun neighborUpdate(state: BlockState, world: World, pos: BlockPos, neighborBlock: Block, neighborPos: BlockPos, bl: Boolean) {
|
override fun neighborUpdate(
|
||||||
|
state: BlockState,
|
||||||
|
world: World,
|
||||||
|
pos: BlockPos,
|
||||||
|
neighborBlock: Block,
|
||||||
|
neighborPos: BlockPos,
|
||||||
|
bl: Boolean
|
||||||
|
) {
|
||||||
if (!world.isClient) {
|
if (!world.isClient) {
|
||||||
getBlockEntity(world, pos)!!.updateInventory()
|
getBlockEntity(world, pos)!!.updateInventory()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onUse(state: BlockState, world: World, pos: BlockPos, player: PlayerEntity, hand: Hand, hitResult: BlockHitResult): ActionResult {
|
override fun onUse(
|
||||||
|
state: BlockState,
|
||||||
|
world: World,
|
||||||
|
pos: BlockPos,
|
||||||
|
player: PlayerEntity,
|
||||||
|
hand: Hand,
|
||||||
|
hitResult: BlockHitResult
|
||||||
|
): ActionResult {
|
||||||
if (!world.isClient) {
|
if (!world.isClient) {
|
||||||
val be = getBlockEntity(world, pos)!!
|
val be = getBlockEntity(world, pos)!!
|
||||||
|
|
||||||
be.markUpdate()
|
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 {
|
||||||
return InserterScreenHandler(syncId, playerInv, be)
|
return InserterScreenHandler(syncId, playerInv, be)
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@ import kotlin.math.min
|
||||||
/**
|
/**
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
*/
|
*/
|
||||||
class InserterBlockEntity(pos: BlockPos, state: BlockState): DeviceBlockEntity(PhyBlockEntities.INSERTER, pos, state),
|
class InserterBlockEntity(pos: BlockPos, state: BlockState) : DeviceBlockEntity(PhyBlockEntities.INSERTER, pos, state),
|
||||||
ItemStackPacketHandler,
|
ItemStackPacketHandler,
|
||||||
ActivationController.ActivatableDevice,
|
ActivationController.ActivatableDevice,
|
||||||
ClientConfigurableDevice,
|
ClientConfigurableDevice,
|
||||||
|
@ -46,7 +46,9 @@ class InserterBlockEntity(pos: BlockPos, state: BlockState): DeviceBlockEntity(P
|
||||||
var stackToExtract: ItemStack = ItemStack.EMPTY
|
var stackToExtract: ItemStack = ItemStack.EMPTY
|
||||||
override var ghostSlotStack: ItemStack
|
override var ghostSlotStack: ItemStack
|
||||||
get() = stackToExtract
|
get() = stackToExtract
|
||||||
set(value) { stackToExtract = value }
|
set(value) {
|
||||||
|
stackToExtract = value
|
||||||
|
}
|
||||||
var amountToExtract = 1
|
var amountToExtract = 1
|
||||||
override val controller = ActivationController(SLEEP_TIME, this)
|
override val controller = ActivationController(SLEEP_TIME, this)
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ class InserterScreen(
|
||||||
handler: InserterScreenHandler,
|
handler: InserterScreenHandler,
|
||||||
playerInv: PlayerInventory,
|
playerInv: PlayerInventory,
|
||||||
title: Text,
|
title: Text,
|
||||||
): HandledScreen<InserterScreenHandler>(
|
) : HandledScreen<InserterScreenHandler>(
|
||||||
handler,
|
handler,
|
||||||
playerInv,
|
playerInv,
|
||||||
title
|
title
|
||||||
|
|
|
@ -22,13 +22,13 @@ class InserterScreenHandler(
|
||||||
syncId: Int,
|
syncId: Int,
|
||||||
playerInv: PlayerInventory,
|
playerInv: PlayerInventory,
|
||||||
val inserter: InserterBlockEntity,
|
val inserter: InserterBlockEntity,
|
||||||
): ScreenHandler(PhyScreens.INSERTER, syncId) {
|
) : ScreenHandler(PhyScreens.INSERTER, syncId) {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val ID = Identifier(PhysicalConnectivity.MODID, "inserter")
|
val ID = Identifier(PhysicalConnectivity.MODID, "inserter")
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(syncId: Int, playerInv: PlayerInventory, buf: PacketByteBuf):
|
constructor(syncId: Int, playerInv: PlayerInventory, buf: PacketByteBuf) :
|
||||||
this(
|
this(
|
||||||
syncId,
|
syncId,
|
||||||
playerInv,
|
playerInv,
|
||||||
|
|
|
@ -23,7 +23,7 @@ import java.util.*
|
||||||
/**
|
/**
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
*/
|
*/
|
||||||
class MinerBlock: DeviceBlock<MinerBlockEntity>(
|
class MinerBlock : DeviceBlock<MinerBlockEntity>(
|
||||||
Settings.of(Material.METAL)
|
Settings.of(Material.METAL)
|
||||||
.strength(1.5f)
|
.strength(1.5f)
|
||||||
.sounds(BlockSoundGroup.METAL)
|
.sounds(BlockSoundGroup.METAL)
|
||||||
|
@ -38,7 +38,12 @@ class MinerBlock: DeviceBlock<MinerBlockEntity>(
|
||||||
return EnumSet.of(state[FACING].opposite)
|
return EnumSet.of(state[FACING].opposite)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getNetworkInterfaceForSide(side: Direction, state: BlockState, world: WorldAccess, pos: BlockPos): Interface? {
|
override fun getNetworkInterfaceForSide(
|
||||||
|
side: Direction,
|
||||||
|
state: BlockState,
|
||||||
|
world: WorldAccess,
|
||||||
|
pos: BlockPos
|
||||||
|
): Interface? {
|
||||||
return if (side == state[FACING]) {
|
return if (side == state[FACING]) {
|
||||||
null
|
null
|
||||||
} else {
|
} else {
|
||||||
|
@ -64,7 +69,14 @@ class MinerBlock: DeviceBlock<MinerBlockEntity>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun neighborUpdate(state: BlockState, world: World, pos: BlockPos, neighbor: Block, neighborPos: BlockPos, bl: Boolean) {
|
override fun neighborUpdate(
|
||||||
|
state: BlockState,
|
||||||
|
world: World,
|
||||||
|
pos: BlockPos,
|
||||||
|
neighbor: Block,
|
||||||
|
neighborPos: BlockPos,
|
||||||
|
bl: Boolean
|
||||||
|
) {
|
||||||
if (!world.isClient) {
|
if (!world.isClient) {
|
||||||
// getBlockEntity(world, pos)!!.updateBlockToMine()
|
// getBlockEntity(world, pos)!!.updateBlockToMine()
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@ import kotlin.math.min
|
||||||
/**
|
/**
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
*/
|
*/
|
||||||
class MinerBlockEntity(pos: BlockPos, state: BlockState): DeviceBlockEntity(PhyBlockEntities.MINER, pos, state),
|
class MinerBlockEntity(pos: BlockPos, state: BlockState) : DeviceBlockEntity(PhyBlockEntities.MINER, pos, state),
|
||||||
NetworkStackProvider,
|
NetworkStackProvider,
|
||||||
NetworkStackDispatcher<MinerBlockEntity.PendingInsertion>,
|
NetworkStackDispatcher<MinerBlockEntity.PendingInsertion>,
|
||||||
ActivationController.ActivatableDevice,
|
ActivationController.ActivatableDevice,
|
||||||
|
@ -184,7 +184,7 @@ class MinerBlockEntity(pos: BlockPos, state: BlockState): DeviceBlockEntity(PhyB
|
||||||
val friendlyName = TranslatableText("gui.phycon.miner_mode.${name.lowercase()}")
|
val friendlyName = TranslatableText("gui.phycon.miner_mode.${name.lowercase()}")
|
||||||
}
|
}
|
||||||
|
|
||||||
class MinerInvProxy(val miner: MinerBlockEntity): GroupedItemInvView {
|
class MinerInvProxy(val miner: MinerBlockEntity) : GroupedItemInvView {
|
||||||
companion object {
|
companion object {
|
||||||
val TOOL = ItemStack(Items.DIAMOND_PICKAXE)
|
val TOOL = ItemStack(Items.DIAMOND_PICKAXE)
|
||||||
}
|
}
|
||||||
|
@ -234,7 +234,8 @@ class MinerBlockEntity(pos: BlockPos, state: BlockState): DeviceBlockEntity(PhyB
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class PendingInsertion(stack: ItemStack, timestamp: Long): NetworkStackDispatcher.PendingInsertion<PendingInsertion>(stack, timestamp) {
|
class PendingInsertion(stack: ItemStack, timestamp: Long) :
|
||||||
|
NetworkStackDispatcher.PendingInsertion<PendingInsertion>(stack, timestamp) {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ import net.shadowfacts.phycon.block.FaceDeviceBlock
|
||||||
/**
|
/**
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
*/
|
*/
|
||||||
class InterfaceBlock: FaceDeviceBlock<InterfaceBlockEntity>(
|
class InterfaceBlock : FaceDeviceBlock<InterfaceBlockEntity>(
|
||||||
Settings.of(Material.METAL)
|
Settings.of(Material.METAL)
|
||||||
.strength(1.5f)
|
.strength(1.5f)
|
||||||
.sounds(BlockSoundGroup.METAL)
|
.sounds(BlockSoundGroup.METAL)
|
||||||
|
@ -48,7 +48,14 @@ class InterfaceBlock: FaceDeviceBlock<InterfaceBlockEntity>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun neighborUpdate(state: BlockState, world: World, pos: BlockPos, neighborBlock: Block, neighborPos: BlockPos, boolean_1: Boolean) {
|
override fun neighborUpdate(
|
||||||
|
state: BlockState,
|
||||||
|
world: World,
|
||||||
|
pos: BlockPos,
|
||||||
|
neighborBlock: Block,
|
||||||
|
neighborPos: BlockPos,
|
||||||
|
boolean_1: Boolean
|
||||||
|
) {
|
||||||
if (!world.isClient) {
|
if (!world.isClient) {
|
||||||
getBlockEntity(world, pos)!!.updateInventory()
|
getBlockEntity(world, pos)!!.updateInventory()
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,8 @@ import kotlin.math.min
|
||||||
/**
|
/**
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
*/
|
*/
|
||||||
class InterfaceBlockEntity(pos: BlockPos, state: BlockState): DeviceBlockEntity(PhyBlockEntities.INTERFACE, pos, state),
|
class InterfaceBlockEntity(pos: BlockPos, state: BlockState) :
|
||||||
|
DeviceBlockEntity(PhyBlockEntities.INTERFACE, pos, state),
|
||||||
ItemStackPacketHandler,
|
ItemStackPacketHandler,
|
||||||
NetworkStackProvider,
|
NetworkStackProvider,
|
||||||
NetworkStackReceiver,
|
NetworkStackReceiver,
|
||||||
|
|
|
@ -23,7 +23,7 @@ import java.util.*
|
||||||
/**
|
/**
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
*/
|
*/
|
||||||
class SwitchBlock: BlockWithEntity<SwitchBlockEntity>(
|
class SwitchBlock : BlockWithEntity<SwitchBlockEntity>(
|
||||||
Settings.of(Material.METAL)
|
Settings.of(Material.METAL)
|
||||||
.strength(1.5f)
|
.strength(1.5f)
|
||||||
.sounds(BlockSoundGroup.METAL)
|
.sounds(BlockSoundGroup.METAL)
|
||||||
|
@ -39,13 +39,22 @@ class SwitchBlock: BlockWithEntity<SwitchBlockEntity>(
|
||||||
return EnumSet.allOf(Direction::class.java)
|
return EnumSet.allOf(Direction::class.java)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getNetworkInterfaceForSide(side: Direction, state: BlockState, world: WorldAccess, pos: BlockPos): Interface? {
|
override fun getNetworkInterfaceForSide(
|
||||||
|
side: Direction,
|
||||||
|
state: BlockState,
|
||||||
|
world: WorldAccess,
|
||||||
|
pos: BlockPos
|
||||||
|
): Interface? {
|
||||||
return getBlockEntity(world, pos)?.interfaces?.find { it.side == side }
|
return getBlockEntity(world, pos)?.interfaces?.find { it.side == side }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun createBlockEntity(pos: BlockPos, state: BlockState) = SwitchBlockEntity(pos, state)
|
override fun createBlockEntity(pos: BlockPos, state: BlockState) = SwitchBlockEntity(pos, state)
|
||||||
|
|
||||||
override fun <T: BlockEntity> getTicker(world: World, state: BlockState, type: BlockEntityType<T>): BlockEntityTicker<T>? {
|
override fun <T : BlockEntity> getTicker(
|
||||||
|
world: World,
|
||||||
|
state: BlockState,
|
||||||
|
type: BlockEntityType<T>
|
||||||
|
): BlockEntityTicker<T>? {
|
||||||
return if (world.isClient) {
|
return if (world.isClient) {
|
||||||
null
|
null
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -29,7 +29,7 @@ import java.util.LinkedList
|
||||||
/**
|
/**
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
*/
|
*/
|
||||||
class SwitchBlockEntity(pos: BlockPos, state: BlockState): BlockEntity(PhyBlockEntities.SWITCH, pos, state) {
|
class SwitchBlockEntity(pos: BlockPos, state: BlockState) : BlockEntity(PhyBlockEntities.SWITCH, pos, state) {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
var SWITCHING_CAPACITY = 256 // 256 packets/tick
|
var SWITCHING_CAPACITY = 256 // 256 packets/tick
|
||||||
|
@ -69,7 +69,14 @@ class SwitchBlockEntity(pos: BlockPos, state: BlockState): BlockEntity(PhyBlockE
|
||||||
private fun resend(frame: EthernetFrame, fromItf: SwitchInterface) {
|
private fun resend(frame: EthernetFrame, fromItf: SwitchInterface) {
|
||||||
if (frame.destination.type != MACAddress.Type.BROADCAST && macTable.containsKey(frame.destination)) {
|
if (frame.destination.type != MACAddress.Type.BROADCAST && macTable.containsKey(frame.destination)) {
|
||||||
val dir = macTable[frame.destination]!!
|
val dir = macTable[frame.destination]!!
|
||||||
PhysicalConnectivity.NETWORK_LOGGER.debug("{} ({}, {}) forwarding {} to side {}", this, fromItf.side, fromItf.macAddress, frame, dir)
|
PhysicalConnectivity.NETWORK_LOGGER.debug(
|
||||||
|
"{} ({}, {}) forwarding {} to side {}",
|
||||||
|
this,
|
||||||
|
fromItf.side,
|
||||||
|
fromItf.macAddress,
|
||||||
|
frame,
|
||||||
|
dir
|
||||||
|
)
|
||||||
interfaceForSide(dir).send(frame)
|
interfaceForSide(dir).send(frame)
|
||||||
} else {
|
} else {
|
||||||
flood(frame, fromItf)
|
flood(frame, fromItf)
|
||||||
|
@ -77,7 +84,13 @@ class SwitchBlockEntity(pos: BlockPos, state: BlockState): BlockEntity(PhyBlockE
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun flood(frame: EthernetFrame, source: SwitchInterface) {
|
private fun flood(frame: EthernetFrame, source: SwitchInterface) {
|
||||||
PhysicalConnectivity.NETWORK_LOGGER.debug("{} ({}, {}) flooding {}", this, source.side, source.macAddress, frame)
|
PhysicalConnectivity.NETWORK_LOGGER.debug(
|
||||||
|
"{} ({}, {}) flooding {}",
|
||||||
|
this,
|
||||||
|
source.side,
|
||||||
|
source.macAddress,
|
||||||
|
frame
|
||||||
|
)
|
||||||
for (itf in interfaces) {
|
for (itf in interfaces) {
|
||||||
if (source == itf) continue
|
if (source == itf) continue
|
||||||
itf.send(frame)
|
itf.send(frame)
|
||||||
|
@ -184,7 +197,7 @@ class SwitchBlockEntity(pos: BlockPos, state: BlockState): BlockEntity(PhyBlockE
|
||||||
val side: Direction,
|
val side: Direction,
|
||||||
val switch: WeakReference<SwitchBlockEntity>,
|
val switch: WeakReference<SwitchBlockEntity>,
|
||||||
@JvmField var macAddress: MACAddress,
|
@JvmField var macAddress: MACAddress,
|
||||||
): Interface {
|
) : Interface {
|
||||||
override fun getMACAddress() = macAddress
|
override fun getMACAddress() = macAddress
|
||||||
|
|
||||||
override fun receive(frame: EthernetFrame) {
|
override fun receive(frame: EthernetFrame) {
|
||||||
|
|
|
@ -24,7 +24,7 @@ class SwitchConsoleScreen(
|
||||||
handler: SwitchConsoleScreenHandler,
|
handler: SwitchConsoleScreenHandler,
|
||||||
playerInventory: PlayerInventory,
|
playerInventory: PlayerInventory,
|
||||||
title: Text,
|
title: Text,
|
||||||
): CacaoHandledScreen<SwitchConsoleScreenHandler>(
|
) : CacaoHandledScreen<SwitchConsoleScreenHandler>(
|
||||||
handler,
|
handler,
|
||||||
playerInventory,
|
playerInventory,
|
||||||
title,
|
title,
|
||||||
|
@ -48,7 +48,7 @@ class SwitchConsoleScreen(
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class SwitchConsoleViewController(val switch: SwitchBlockEntity): ViewController() {
|
class SwitchConsoleViewController(val switch: SwitchBlockEntity) : ViewController() {
|
||||||
override fun viewDidLoad() {
|
override fun viewDidLoad() {
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ class SwitchConsoleViewController(val switch: SwitchBlockEntity): ViewController
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class SwitchPacketStatisticsView(val switch: SwitchBlockEntity): View() {
|
class SwitchPacketStatisticsView(val switch: SwitchBlockEntity) : View() {
|
||||||
|
|
||||||
init {
|
init {
|
||||||
intrinsicContentSize = Size(180.0, 90.0)
|
intrinsicContentSize = Size(180.0, 90.0)
|
||||||
|
@ -73,7 +73,13 @@ class SwitchPacketStatisticsView(val switch: SwitchBlockEntity): View() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// TODO: drawLine isn't working for some reason
|
// TODO: drawLine isn't working for some reason
|
||||||
RenderHelper.drawLine(Point(bounds.left, bounds.top), Point(bounds.right, bounds.bottom), 1.0, 2f, Color.MAGENTA)
|
RenderHelper.drawLine(
|
||||||
|
Point(bounds.left, bounds.top),
|
||||||
|
Point(bounds.right, bounds.bottom),
|
||||||
|
1.0,
|
||||||
|
2f,
|
||||||
|
Color.MAGENTA
|
||||||
|
)
|
||||||
return
|
return
|
||||||
val maxPackets = switch.packetStatistics.maxOf { it }
|
val maxPackets = switch.packetStatistics.maxOf { it }
|
||||||
val maxDataPointsCount = 60
|
val maxDataPointsCount = 60
|
||||||
|
|
|
@ -15,13 +15,13 @@ import net.shadowfacts.phycon.init.PhyScreens
|
||||||
class SwitchConsoleScreenHandler(
|
class SwitchConsoleScreenHandler(
|
||||||
syncId: Int,
|
syncId: Int,
|
||||||
val switch: SwitchBlockEntity,
|
val switch: SwitchBlockEntity,
|
||||||
): ScreenHandler(PhyScreens.SWITCH_CONSOLE, syncId) {
|
) : ScreenHandler(PhyScreens.SWITCH_CONSOLE, syncId) {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val ID = Identifier(PhysicalConnectivity.MODID, "switch_console")
|
val ID = Identifier(PhysicalConnectivity.MODID, "switch_console")
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(syncId: Int, playerInv: PlayerInventory, buf: PacketByteBuf):
|
constructor(syncId: Int, playerInv: PlayerInventory, buf: PacketByteBuf) :
|
||||||
this(
|
this(
|
||||||
syncId,
|
syncId,
|
||||||
PhyBlocks.SWITCH.getBlockEntity(playerInv.player.world, buf.readBlockPos())!!
|
PhyBlocks.SWITCH.getBlockEntity(playerInv.player.world, buf.readBlockPos())!!
|
||||||
|
|
|
@ -12,7 +12,7 @@ import net.shadowfacts.phycon.block.FaceDeviceBlock
|
||||||
/**
|
/**
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
*/
|
*/
|
||||||
class P2PInterfaceBlock: FaceDeviceBlock<P2PInterfaceBlockEntity>(
|
class P2PInterfaceBlock : FaceDeviceBlock<P2PInterfaceBlockEntity>(
|
||||||
Settings.of(Material.METAL)
|
Settings.of(Material.METAL)
|
||||||
.strength(1.5f)
|
.strength(1.5f)
|
||||||
.sounds(BlockSoundGroup.METAL)
|
.sounds(BlockSoundGroup.METAL)
|
||||||
|
|
|
@ -15,7 +15,8 @@ import net.shadowfacts.phycon.packet.RequestInventoryPacket
|
||||||
/**
|
/**
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
*/
|
*/
|
||||||
class P2PInterfaceBlockEntity(pos: BlockPos, state: BlockState): DeviceBlockEntity(PhyBlockEntities.P2P_INTERFACE, pos, state) {
|
class P2PInterfaceBlockEntity(pos: BlockPos, state: BlockState) :
|
||||||
|
DeviceBlockEntity(PhyBlockEntities.P2P_INTERFACE, pos, state) {
|
||||||
|
|
||||||
private var inventory: Storage<ItemVariant>? = null
|
private var inventory: Storage<ItemVariant>? = null
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ import net.shadowfacts.phycon.block.FaceDeviceBlock
|
||||||
/**
|
/**
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
*/
|
*/
|
||||||
class P2PReceiverBlock: FaceDeviceBlock<P2PReceiverBlockEntity>(
|
class P2PReceiverBlock : FaceDeviceBlock<P2PReceiverBlockEntity>(
|
||||||
Settings.of(Material.METAL)
|
Settings.of(Material.METAL)
|
||||||
.strength(1.5f)
|
.strength(1.5f)
|
||||||
.sounds(BlockSoundGroup.METAL)
|
.sounds(BlockSoundGroup.METAL)
|
||||||
|
|
|
@ -21,7 +21,8 @@ import java.lang.ref.WeakReference
|
||||||
/**
|
/**
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
*/
|
*/
|
||||||
class P2PReceiverBlockEntity(pos: BlockPos, state: BlockState): DeviceBlockEntity(PhyBlockEntities.P2P_RECEIVER, pos, state),
|
class P2PReceiverBlockEntity(pos: BlockPos, state: BlockState) :
|
||||||
|
DeviceBlockEntity(PhyBlockEntities.P2P_RECEIVER, pos, state),
|
||||||
ClientConfigurableDevice {
|
ClientConfigurableDevice {
|
||||||
|
|
||||||
enum class Status {
|
enum class Status {
|
||||||
|
|
|
@ -18,7 +18,7 @@ import net.shadowfacts.phycon.block.FaceDeviceBlock
|
||||||
/**
|
/**
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
*/
|
*/
|
||||||
class RedstoneControllerBlock: FaceDeviceBlock<RedstoneControllerBlockEntity>(
|
class RedstoneControllerBlock : FaceDeviceBlock<RedstoneControllerBlockEntity>(
|
||||||
Settings.of(Material.METAL)
|
Settings.of(Material.METAL)
|
||||||
.strength(1.5f)
|
.strength(1.5f)
|
||||||
.sounds(BlockSoundGroup.METAL)
|
.sounds(BlockSoundGroup.METAL)
|
||||||
|
@ -51,7 +51,14 @@ class RedstoneControllerBlock: FaceDeviceBlock<RedstoneControllerBlockEntity>(
|
||||||
return state.with(POWERED, isPowered(context.world, context.blockPos, state[FACING]))
|
return state.with(POWERED, isPowered(context.world, context.blockPos, state[FACING]))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun neighborUpdate(state: BlockState, world: World, pos: BlockPos, neighborBlock: Block, neighborPos: BlockPos, bl: Boolean) {
|
override fun neighborUpdate(
|
||||||
|
state: BlockState,
|
||||||
|
world: World,
|
||||||
|
pos: BlockPos,
|
||||||
|
neighborBlock: Block,
|
||||||
|
neighborPos: BlockPos,
|
||||||
|
bl: Boolean
|
||||||
|
) {
|
||||||
// this can't be done in getStateForNeighborUpdate because getEmittedRedstonePower is defined in World not WorldAccess
|
// this can't be done in getStateForNeighborUpdate because getEmittedRedstonePower is defined in World not WorldAccess
|
||||||
if (!world.isClient) {
|
if (!world.isClient) {
|
||||||
val wasLit = state[POWERED]
|
val wasLit = state[POWERED]
|
||||||
|
|
|
@ -14,7 +14,8 @@ import net.shadowfacts.phycon.util.RedstoneMode
|
||||||
/**
|
/**
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
*/
|
*/
|
||||||
class RedstoneControllerBlockEntity(pos: BlockPos, state: BlockState): DeviceBlockEntity(PhyBlockEntities.REDSTONE_CONTROLLER, pos, state),
|
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 }
|
||||||
|
|
|
@ -24,7 +24,7 @@ import net.shadowfacts.phycon.block.FaceDeviceBlock
|
||||||
/**
|
/**
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
*/
|
*/
|
||||||
class RedstoneEmitterBlock: FaceDeviceBlock<RedstoneEmitterBlockEntity>(
|
class RedstoneEmitterBlock : FaceDeviceBlock<RedstoneEmitterBlockEntity>(
|
||||||
Settings.of(Material.METAL)
|
Settings.of(Material.METAL)
|
||||||
.strength(1.5f)
|
.strength(1.5f)
|
||||||
.sounds(BlockSoundGroup.METAL)
|
.sounds(BlockSoundGroup.METAL)
|
||||||
|
@ -51,7 +51,12 @@ class RedstoneEmitterBlock: FaceDeviceBlock<RedstoneEmitterBlockEntity>(
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getStrongRedstonePower(state: BlockState, world: BlockView, pos: BlockPos, receivingSide: Direction): Int {
|
override fun getStrongRedstonePower(
|
||||||
|
state: BlockState,
|
||||||
|
world: BlockView,
|
||||||
|
pos: BlockPos,
|
||||||
|
receivingSide: Direction
|
||||||
|
): Int {
|
||||||
return if (receivingSide.opposite == state[FACING]) {
|
return if (receivingSide.opposite == state[FACING]) {
|
||||||
getBlockEntity(world, pos)!!.cachedEmittedPower
|
getBlockEntity(world, pos)!!.cachedEmittedPower
|
||||||
} else {
|
} else {
|
||||||
|
@ -59,17 +64,29 @@ class RedstoneEmitterBlock: FaceDeviceBlock<RedstoneEmitterBlockEntity>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getWeakRedstonePower(state: BlockState, world: BlockView, pos: BlockPos, receivingSide: Direction): Int {
|
override fun getWeakRedstonePower(
|
||||||
|
state: BlockState,
|
||||||
|
world: BlockView,
|
||||||
|
pos: BlockPos,
|
||||||
|
receivingSide: Direction
|
||||||
|
): Int {
|
||||||
return getStrongRedstonePower(state, world, pos, receivingSide)
|
return getStrongRedstonePower(state, world, pos, receivingSide)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onUse(state: BlockState, world: World, pos: BlockPos, player: PlayerEntity, hand: Hand, result: BlockHitResult): ActionResult {
|
override fun onUse(
|
||||||
|
state: BlockState,
|
||||||
|
world: World,
|
||||||
|
pos: BlockPos,
|
||||||
|
player: PlayerEntity,
|
||||||
|
hand: Hand,
|
||||||
|
result: BlockHitResult
|
||||||
|
): ActionResult {
|
||||||
if (!world.isClient) {
|
if (!world.isClient) {
|
||||||
val be = getBlockEntity(world, pos)!!
|
val be = getBlockEntity(world, pos)!!
|
||||||
|
|
||||||
be.markUpdate()
|
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 {
|
||||||
return RedstoneEmitterScreenHandler(syncId, playerInv, be)
|
return RedstoneEmitterScreenHandler(syncId, playerInv, be)
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,8 @@ import kotlin.math.round
|
||||||
/**
|
/**
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
*/
|
*/
|
||||||
class RedstoneEmitterBlockEntity(pos: BlockPos, state: BlockState): DeviceBlockEntity(PhyBlockEntities.REDSTONE_EMITTER, pos, state),
|
class RedstoneEmitterBlockEntity(pos: BlockPos, state: BlockState) :
|
||||||
|
DeviceBlockEntity(PhyBlockEntities.REDSTONE_EMITTER, pos, state),
|
||||||
ClientConfigurableDevice,
|
ClientConfigurableDevice,
|
||||||
GhostInv {
|
GhostInv {
|
||||||
|
|
||||||
|
@ -32,7 +33,9 @@ class RedstoneEmitterBlockEntity(pos: BlockPos, state: BlockState): DeviceBlockE
|
||||||
var stackToMonitor: ItemStack = ItemStack.EMPTY
|
var stackToMonitor: ItemStack = ItemStack.EMPTY
|
||||||
override var ghostSlotStack: ItemStack
|
override var ghostSlotStack: ItemStack
|
||||||
get() = stackToMonitor
|
get() = stackToMonitor
|
||||||
set(value) { stackToMonitor = value }
|
set(value) {
|
||||||
|
stackToMonitor = value
|
||||||
|
}
|
||||||
var maxAmount = 64
|
var maxAmount = 64
|
||||||
var mode = Mode.ANALOG
|
var mode = Mode.ANALOG
|
||||||
set(value) {
|
set(value) {
|
||||||
|
@ -91,6 +94,7 @@ class RedstoneEmitterBlockEntity(pos: BlockPos, state: BlockState): DeviceBlockE
|
||||||
} else {
|
} else {
|
||||||
1 + round(networkAmount / maxAmount.toDouble() * 14).toInt()
|
1 + round(networkAmount / maxAmount.toDouble() * 14).toInt()
|
||||||
}
|
}
|
||||||
|
|
||||||
Mode.DIGITAL -> if (networkAmount >= maxAmount) 15 else 0
|
Mode.DIGITAL -> if (networkAmount >= maxAmount) 15 else 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ class RedstoneEmitterScreen(
|
||||||
handler: RedstoneEmitterScreenHandler,
|
handler: RedstoneEmitterScreenHandler,
|
||||||
playerInv: PlayerInventory,
|
playerInv: PlayerInventory,
|
||||||
title: Text
|
title: Text
|
||||||
): CacaoHandledScreen<RedstoneEmitterScreenHandler>(
|
) : CacaoHandledScreen<RedstoneEmitterScreenHandler>(
|
||||||
handler,
|
handler,
|
||||||
playerInv,
|
playerInv,
|
||||||
title
|
title
|
||||||
|
@ -59,7 +59,7 @@ class RedstoneEmitterScreen(
|
||||||
|
|
||||||
class ViewController(
|
class ViewController(
|
||||||
private val emitter: RedstoneEmitterBlockEntity,
|
private val emitter: RedstoneEmitterBlockEntity,
|
||||||
): net.shadowfacts.cacao.viewcontroller.ViewController() {
|
) : net.shadowfacts.cacao.viewcontroller.ViewController() {
|
||||||
|
|
||||||
lateinit var halfLabel: Label
|
lateinit var halfLabel: Label
|
||||||
lateinit var fullLabel: Label
|
lateinit var fullLabel: Label
|
||||||
|
@ -90,7 +90,12 @@ class RedstoneEmitterScreen(
|
||||||
view.addSubview(hStack)
|
view.addSubview(hStack)
|
||||||
|
|
||||||
val zeroStack = hStack.addArrangedSubview(StackView(Axis.VERTICAL))
|
val zeroStack = hStack.addArrangedSubview(StackView(Axis.VERTICAL))
|
||||||
zeroStack.addArrangedSubview(Label(TranslatableText("gui.phycon.emitter.count", 0), textAlignment = Label.TextAlignment.CENTER)).apply {
|
zeroStack.addArrangedSubview(
|
||||||
|
Label(
|
||||||
|
TranslatableText("gui.phycon.emitter.count", 0),
|
||||||
|
textAlignment = Label.TextAlignment.CENTER
|
||||||
|
)
|
||||||
|
).apply {
|
||||||
textColor = Color.TEXT
|
textColor = Color.TEXT
|
||||||
}
|
}
|
||||||
zeroStack.addArrangedSubview(View())
|
zeroStack.addArrangedSubview(View())
|
||||||
|
|
|
@ -21,13 +21,13 @@ class RedstoneEmitterScreenHandler(
|
||||||
syncId: Int,
|
syncId: Int,
|
||||||
playerInv: PlayerInventory,
|
playerInv: PlayerInventory,
|
||||||
val emitter: RedstoneEmitterBlockEntity,
|
val emitter: RedstoneEmitterBlockEntity,
|
||||||
): ScreenHandler(PhyScreens.REDSTONE_EMITTER, syncId) {
|
) : ScreenHandler(PhyScreens.REDSTONE_EMITTER, syncId) {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val ID = Identifier(PhysicalConnectivity.MODID, "redstone_emitter")
|
val ID = Identifier(PhysicalConnectivity.MODID, "redstone_emitter")
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(syncId: Int, playerInv: PlayerInventory, buf: PacketByteBuf):
|
constructor(syncId: Int, playerInv: PlayerInventory, buf: PacketByteBuf) :
|
||||||
this(
|
this(
|
||||||
syncId,
|
syncId,
|
||||||
playerInv,
|
playerInv,
|
||||||
|
|
|
@ -28,7 +28,7 @@ import java.util.EnumSet
|
||||||
/**
|
/**
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
*/
|
*/
|
||||||
abstract class AbstractTerminalBlock<T: AbstractTerminalBlockEntity>: DeviceBlock<T>(
|
abstract class AbstractTerminalBlock<T : AbstractTerminalBlockEntity> : DeviceBlock<T>(
|
||||||
Settings.of(Material.METAL)
|
Settings.of(Material.METAL)
|
||||||
.strength(1.5f)
|
.strength(1.5f)
|
||||||
.sounds(BlockSoundGroup.METAL)
|
.sounds(BlockSoundGroup.METAL)
|
||||||
|
@ -55,7 +55,14 @@ abstract class AbstractTerminalBlock<T: AbstractTerminalBlockEntity>: DeviceBloc
|
||||||
return defaultState.with(FACING, context.playerLookDirection.opposite)
|
return defaultState.with(FACING, context.playerLookDirection.opposite)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onUse(state: BlockState, world: World, pos: BlockPos, player: PlayerEntity, hand: Hand, hitResult: BlockHitResult): ActionResult {
|
override fun onUse(
|
||||||
|
state: BlockState,
|
||||||
|
world: World,
|
||||||
|
pos: BlockPos,
|
||||||
|
player: PlayerEntity,
|
||||||
|
hand: Hand,
|
||||||
|
hitResult: BlockHitResult
|
||||||
|
): ActionResult {
|
||||||
getBlockEntity(world, pos)!!.onActivate(player)
|
getBlockEntity(world, pos)!!.onActivate(player)
|
||||||
return ActionResult.SUCCESS
|
return ActionResult.SUCCESS
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,8 @@ import kotlin.properties.Delegates
|
||||||
/**
|
/**
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
*/
|
*/
|
||||||
abstract class AbstractTerminalBlockEntity(type: BlockEntityType<*>, pos: BlockPos, state: BlockState): DeviceBlockEntity(type, pos, state),
|
abstract class AbstractTerminalBlockEntity(type: BlockEntityType<*>, pos: BlockPos, state: BlockState) :
|
||||||
|
DeviceBlockEntity(type, pos, state),
|
||||||
InventoryChangedListener,
|
InventoryChangedListener,
|
||||||
ItemStackPacketHandler,
|
ItemStackPacketHandler,
|
||||||
NetworkStackDispatcher<AbstractTerminalBlockEntity.PendingInsertion> {
|
NetworkStackDispatcher<AbstractTerminalBlockEntity.PendingInsertion> {
|
||||||
|
@ -259,7 +260,8 @@ abstract class AbstractTerminalBlockEntity(type: BlockEntityType<*>, pos: BlockP
|
||||||
fun netItemsChanged()
|
fun netItemsChanged()
|
||||||
}
|
}
|
||||||
|
|
||||||
class PendingInsertion(stack: ItemStack, timestamp: Long): NetworkStackDispatcher.PendingInsertion<PendingInsertion>(stack, timestamp) {
|
class PendingInsertion(stack: ItemStack, timestamp: Long) :
|
||||||
|
NetworkStackDispatcher.PendingInsertion<PendingInsertion>(stack, timestamp) {
|
||||||
var bufferSlot by Delegates.notNull<Int>()
|
var bufferSlot by Delegates.notNull<Int>()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,13 +27,13 @@ import kotlin.math.min
|
||||||
/**
|
/**
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
*/
|
*/
|
||||||
abstract class AbstractTerminalScreen<BE: AbstractTerminalBlockEntity, T: AbstractTerminalScreenHandler<BE>>(
|
abstract class AbstractTerminalScreen<BE : AbstractTerminalBlockEntity, T : AbstractTerminalScreenHandler<BE>>(
|
||||||
handler: T,
|
handler: T,
|
||||||
playerInv: PlayerInventory,
|
playerInv: PlayerInventory,
|
||||||
title: Text,
|
title: Text,
|
||||||
val terminalBackgroundWidth: Int,
|
val terminalBackgroundWidth: Int,
|
||||||
val terminalBackgroundHeight: Int,
|
val terminalBackgroundHeight: Int,
|
||||||
): CacaoHandledScreen<T>(handler, playerInv, title) {
|
) : CacaoHandledScreen<T>(handler, playerInv, title) {
|
||||||
|
|
||||||
interface SearchQueryListener {
|
interface SearchQueryListener {
|
||||||
fun terminalSearchQueryChanged(newValue: String)
|
fun terminalSearchQueryChanged(newValue: String)
|
||||||
|
@ -80,7 +80,13 @@ abstract class AbstractTerminalScreen<BE: AbstractTerminalBlockEntity, T: Abstra
|
||||||
|
|
||||||
fun requestUpdatedItems() {
|
fun requestUpdatedItems() {
|
||||||
val player = MinecraftClient.getInstance().player!!
|
val player = MinecraftClient.getInstance().player!!
|
||||||
player.networkHandler.sendPacket(C2STerminalUpdateDisplayedItems(handler.terminal, searchQuery, scrollPosition.toFloat()))
|
player.networkHandler.sendPacket(
|
||||||
|
C2STerminalUpdateDisplayedItems(
|
||||||
|
handler.terminal,
|
||||||
|
searchQuery,
|
||||||
|
scrollPosition.toFloat()
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun showRequestAmountDialog(stack: ItemStack) {
|
private fun showRequestAmountDialog(stack: ItemStack) {
|
||||||
|
@ -115,10 +121,12 @@ abstract class AbstractTerminalScreen<BE: AbstractTerminalBlockEntity, T: Abstra
|
||||||
val format = if (amount < 10_000) DECIMAL_FORMAT else FORMAT
|
val format = if (amount < 10_000) DECIMAL_FORMAT else FORMAT
|
||||||
format.format(amount / 1_000.0) + "K"
|
format.format(amount / 1_000.0) + "K"
|
||||||
}
|
}
|
||||||
|
|
||||||
amount < 1_000_000_000 -> {
|
amount < 1_000_000_000 -> {
|
||||||
val format = if (amount < 10_000_000) DECIMAL_FORMAT else FORMAT
|
val format = if (amount < 10_000_000) DECIMAL_FORMAT else FORMAT
|
||||||
format.format(amount / 1_000_000.0) + "M"
|
format.format(amount / 1_000_000.0) + "M"
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
DECIMAL_FORMAT.format(amount / 1000000000.0).toString() + "B"
|
DECIMAL_FORMAT.format(amount / 1000000000.0).toString() + "B"
|
||||||
}
|
}
|
||||||
|
@ -136,7 +144,18 @@ abstract class AbstractTerminalScreen<BE: AbstractTerminalBlockEntity, T: Abstra
|
||||||
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().positionMatrix, immediate, false, 0, 0xF000F0)
|
textRenderer.draw(
|
||||||
|
s,
|
||||||
|
textX,
|
||||||
|
textY,
|
||||||
|
0xffffff,
|
||||||
|
true,
|
||||||
|
matrixStack.peek().positionMatrix,
|
||||||
|
immediate,
|
||||||
|
false,
|
||||||
|
0,
|
||||||
|
0xF000F0
|
||||||
|
)
|
||||||
RenderSystem.enableDepthTest()
|
RenderSystem.enableDepthTest()
|
||||||
immediate.draw()
|
immediate.draw()
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,12 +28,12 @@ import kotlin.math.roundToInt
|
||||||
/**
|
/**
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
*/
|
*/
|
||||||
abstract class AbstractTerminalScreenHandler<T: AbstractTerminalBlockEntity>(
|
abstract class AbstractTerminalScreenHandler<T : AbstractTerminalBlockEntity>(
|
||||||
handlerType: ScreenHandlerType<*>,
|
handlerType: ScreenHandlerType<*>,
|
||||||
syncId: Int,
|
syncId: Int,
|
||||||
val playerInv: PlayerInventory,
|
val playerInv: PlayerInventory,
|
||||||
val terminal: T,
|
val terminal: T,
|
||||||
): ScreenHandler(handlerType, syncId),
|
) : ScreenHandler(handlerType, syncId),
|
||||||
AbstractTerminalBlockEntity.NetItemObserver {
|
AbstractTerminalBlockEntity.NetItemObserver {
|
||||||
|
|
||||||
private val rowsDisplayed = 6
|
private val rowsDisplayed = 6
|
||||||
|
@ -125,7 +125,16 @@ abstract class AbstractTerminalScreenHandler<T: AbstractTerminalBlockEntity>(
|
||||||
|
|
||||||
// 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, settings, scrollPosition, totalEntries))
|
(player as ServerPlayerEntity).networkHandler.sendPacket(
|
||||||
|
S2CTerminalUpdateDisplayedItems(
|
||||||
|
terminal,
|
||||||
|
itemEntries,
|
||||||
|
searchQuery,
|
||||||
|
settings,
|
||||||
|
scrollPosition,
|
||||||
|
totalEntries
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun totalRows(): Int {
|
fun totalRows(): Int {
|
||||||
|
@ -144,7 +153,12 @@ abstract class AbstractTerminalScreenHandler<T: AbstractTerminalBlockEntity>(
|
||||||
return currentScrollOffsetInRows() * 9
|
return currentScrollOffsetInRows() * 9
|
||||||
}
|
}
|
||||||
|
|
||||||
fun sendUpdatedItemsToClient(player: ServerPlayerEntity, query: String, settings: TerminalSettings, scrollPosition: Float) {
|
fun sendUpdatedItemsToClient(
|
||||||
|
player: ServerPlayerEntity,
|
||||||
|
query: String,
|
||||||
|
settings: TerminalSettings,
|
||||||
|
scrollPosition: Float
|
||||||
|
) {
|
||||||
this.searchQuery = query
|
this.searchQuery = query
|
||||||
this.settings = settings
|
this.settings = settings
|
||||||
this.scrollPosition = scrollPosition
|
this.scrollPosition = scrollPosition
|
||||||
|
@ -175,7 +189,8 @@ abstract class AbstractTerminalScreenHandler<T: AbstractTerminalBlockEntity>(
|
||||||
// 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) && !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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -203,8 +218,16 @@ abstract class AbstractTerminalScreenHandler<T: AbstractTerminalBlockEntity>(
|
||||||
terminal.internalBuffer.markSlot(slotId - bufferSlotsStart, TerminalBufferInventory.Mode.UNASSIGNED)
|
terminal.internalBuffer.markSlot(slotId - bufferSlotsStart, TerminalBufferInventory.Mode.UNASSIGNED)
|
||||||
}
|
}
|
||||||
} else if (isPlayerSlot(slotId)) {
|
} else if (isPlayerSlot(slotId)) {
|
||||||
val slotsInsertedInto = tryInsertItem(slot.stack, bufferSlotsStart until playerSlotsStart) { terminal.internalBuffer.getMode(it - bufferSlotsStart) != TerminalBufferInventory.Mode.FROM_NETWORK }
|
val slotsInsertedInto = tryInsertItem(
|
||||||
slotsInsertedInto.forEach { terminal.internalBuffer.markSlot(it - bufferSlotsStart, TerminalBufferInventory.Mode.TO_NETWORK) }
|
slot.stack,
|
||||||
|
bufferSlotsStart until playerSlotsStart
|
||||||
|
) { terminal.internalBuffer.getMode(it - bufferSlotsStart) != TerminalBufferInventory.Mode.FROM_NETWORK }
|
||||||
|
slotsInsertedInto.forEach {
|
||||||
|
terminal.internalBuffer.markSlot(
|
||||||
|
it - bufferSlotsStart,
|
||||||
|
TerminalBufferInventory.Mode.TO_NETWORK
|
||||||
|
)
|
||||||
|
}
|
||||||
if (slotsInsertedInto.isEmpty()) {
|
if (slotsInsertedInto.isEmpty()) {
|
||||||
return ItemStack.EMPTY
|
return ItemStack.EMPTY
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,11 +19,11 @@ import net.shadowfacts.phycon.util.TerminalSettings
|
||||||
/**
|
/**
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
*/
|
*/
|
||||||
abstract class AbstractTerminalViewController<BE: AbstractTerminalBlockEntity, S: AbstractTerminalScreen<BE, H>, H: AbstractTerminalScreenHandler<BE>>(
|
abstract class AbstractTerminalViewController<BE : AbstractTerminalBlockEntity, S : AbstractTerminalScreen<BE, H>, H : AbstractTerminalScreenHandler<BE>>(
|
||||||
val screen: S,
|
val screen: S,
|
||||||
val handler: H,
|
val handler: H,
|
||||||
val terminal: BE = handler.terminal,
|
val terminal: BE = handler.terminal,
|
||||||
): ViewController() {
|
) : ViewController() {
|
||||||
|
|
||||||
private lateinit var scrollTrack: ScrollTrackView
|
private lateinit var scrollTrack: ScrollTrackView
|
||||||
lateinit var settingsView: View
|
lateinit var settingsView: View
|
||||||
|
@ -162,13 +162,13 @@ abstract class AbstractTerminalViewController<BE: AbstractTerminalBlockEntity, S
|
||||||
screen.requestUpdatedItems()
|
screen.requestUpdatedItems()
|
||||||
}
|
}
|
||||||
|
|
||||||
class TerminalSearchField: TextField("") {
|
class TerminalSearchField : TextField("") {
|
||||||
override fun mouseClickedOutside(point: Point, mouseButton: MouseButton) {
|
override fun mouseClickedOutside(point: Point, mouseButton: MouseButton) {
|
||||||
// no-op
|
// no-op
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ScrollHandlingView(val vc: AbstractTerminalViewController<*, *, *>): View() {
|
class ScrollHandlingView(val vc: AbstractTerminalViewController<*, *, *>) : View() {
|
||||||
override fun mouseScrolled(point: Point, amount: Double): Boolean {
|
override fun mouseScrolled(point: Point, amount: Double): Boolean {
|
||||||
var newOffsetInRows = vc.handler.currentScrollOffsetInRows() - amount.toInt()
|
var newOffsetInRows = vc.handler.currentScrollOffsetInRows() - amount.toInt()
|
||||||
newOffsetInRows = MathHelper.clamp(newOffsetInRows, 0, vc.handler.maxScrollOffsetInRows())
|
newOffsetInRows = MathHelper.clamp(newOffsetInRows, 0, vc.handler.maxScrollOffsetInRows())
|
||||||
|
|
|
@ -9,7 +9,7 @@ import net.shadowfacts.phycon.PhysicalConnectivity
|
||||||
/**
|
/**
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
*/
|
*/
|
||||||
class CraftingTerminalBlock: AbstractTerminalBlock<CraftingTerminalBlockEntity>() {
|
class CraftingTerminalBlock : AbstractTerminalBlock<CraftingTerminalBlockEntity>() {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val ID = Identifier(PhysicalConnectivity.MODID, "crafting_terminal")
|
val ID = Identifier(PhysicalConnectivity.MODID, "crafting_terminal")
|
||||||
|
|
|
@ -26,7 +26,8 @@ import kotlin.math.min
|
||||||
/**
|
/**
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
*/
|
*/
|
||||||
class CraftingTerminalBlockEntity(pos: BlockPos, state: BlockState): AbstractTerminalBlockEntity(PhyBlockEntities.CRAFTING_TERMINAL, pos, state) {
|
class CraftingTerminalBlockEntity(pos: BlockPos, state: BlockState) :
|
||||||
|
AbstractTerminalBlockEntity(PhyBlockEntities.CRAFTING_TERMINAL, pos, state) {
|
||||||
|
|
||||||
val craftingInv = SimpleInventory(9)
|
val craftingInv = SimpleInventory(9)
|
||||||
|
|
||||||
|
@ -36,7 +37,7 @@ class CraftingTerminalBlockEntity(pos: BlockPos, state: BlockState): AbstractTer
|
||||||
super.onActivate(player)
|
super.onActivate(player)
|
||||||
|
|
||||||
if (!world!!.isClient) {
|
if (!world!!.isClient) {
|
||||||
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? {
|
||||||
return CraftingTerminalScreenHandler(syncId, playerInv, this@CraftingTerminalBlockEntity)
|
return CraftingTerminalScreenHandler(syncId, playerInv, this@CraftingTerminalBlockEntity)
|
||||||
}
|
}
|
||||||
|
@ -80,7 +81,8 @@ class CraftingTerminalBlockEntity(pos: BlockPos, state: BlockState): AbstractTer
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun doHandleItemStack(packet: ItemStackPacket): ItemStack {
|
override fun doHandleItemStack(packet: ItemStackPacket): ItemStack {
|
||||||
val craftingReq = completedCraftingStackRequests.find { ItemStackUtil.areEqualIgnoreAmounts(it.stack, packet.stack) }
|
val craftingReq =
|
||||||
|
completedCraftingStackRequests.find { ItemStackUtil.areEqualIgnoreAmounts(it.stack, packet.stack) }
|
||||||
if (craftingReq != null) {
|
if (craftingReq != null) {
|
||||||
var remaining = packet.stack.copy()
|
var remaining = packet.stack.copy()
|
||||||
|
|
||||||
|
@ -89,7 +91,8 @@ class CraftingTerminalBlockEntity(pos: BlockPos, state: BlockState): AbstractTer
|
||||||
if (currentStack.count >= currentStack.maxCount) continue
|
if (currentStack.count >= currentStack.maxCount) continue
|
||||||
if (!ItemStackUtil.areEqualIgnoreAmounts(currentStack, remaining)) continue
|
if (!ItemStackUtil.areEqualIgnoreAmounts(currentStack, remaining)) continue
|
||||||
|
|
||||||
val toInsert = minOf(remaining.count, currentStack.maxCount - currentStack.count, craftingReq.amountPerSlot[i])
|
val toInsert =
|
||||||
|
minOf(remaining.count, currentStack.maxCount - currentStack.count, craftingReq.amountPerSlot[i])
|
||||||
currentStack.count += toInsert
|
currentStack.count += toInsert
|
||||||
remaining.count -= toInsert
|
remaining.count -= toInsert
|
||||||
craftingReq.amountPerSlot[i] -= toInsert
|
craftingReq.amountPerSlot[i] -= toInsert
|
||||||
|
@ -131,7 +134,7 @@ class CraftingTerminalBlockEntity(pos: BlockPos, state: BlockState): AbstractTer
|
||||||
amount: Int,
|
amount: Int,
|
||||||
timestamp: Long,
|
timestamp: Long,
|
||||||
val amountPerSlot: IntArray,
|
val amountPerSlot: IntArray,
|
||||||
): StackLocateRequest(stack, amount, timestamp) {
|
) : StackLocateRequest(stack, amount, timestamp) {
|
||||||
var received: Int = 0
|
var received: Int = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ class CraftingTerminalScreen(
|
||||||
handler: CraftingTerminalScreenHandler,
|
handler: CraftingTerminalScreenHandler,
|
||||||
playerInv: PlayerInventory,
|
playerInv: PlayerInventory,
|
||||||
title: Text,
|
title: Text,
|
||||||
): AbstractTerminalScreen<CraftingTerminalBlockEntity, CraftingTerminalScreenHandler>(
|
) : AbstractTerminalScreen<CraftingTerminalBlockEntity, CraftingTerminalScreenHandler>(
|
||||||
handler,
|
handler,
|
||||||
playerInv,
|
playerInv,
|
||||||
title,
|
title,
|
||||||
|
|
|
@ -23,7 +23,12 @@ class CraftingTerminalScreenHandler(
|
||||||
syncId: Int,
|
syncId: Int,
|
||||||
playerInv: PlayerInventory,
|
playerInv: PlayerInventory,
|
||||||
terminal: CraftingTerminalBlockEntity,
|
terminal: CraftingTerminalBlockEntity,
|
||||||
): AbstractTerminalScreenHandler<CraftingTerminalBlockEntity>(PhyScreens.CRAFTING_TERMINAL, syncId, playerInv, terminal) {
|
) : AbstractTerminalScreenHandler<CraftingTerminalBlockEntity>(
|
||||||
|
PhyScreens.CRAFTING_TERMINAL,
|
||||||
|
syncId,
|
||||||
|
playerInv,
|
||||||
|
terminal
|
||||||
|
) {
|
||||||
|
|
||||||
val craftingInv = CraftingInv(this)
|
val craftingInv = CraftingInv(this)
|
||||||
val result = CraftingResultInventory()
|
val result = CraftingResultInventory()
|
||||||
|
@ -36,7 +41,7 @@ class CraftingTerminalScreenHandler(
|
||||||
override val xOffset: Int
|
override val xOffset: Int
|
||||||
get() = 5
|
get() = 5
|
||||||
|
|
||||||
constructor(syncId: Int, playerInv: PlayerInventory, buf: PacketByteBuf):
|
constructor(syncId: Int, playerInv: PlayerInventory, buf: PacketByteBuf) :
|
||||||
this(
|
this(
|
||||||
syncId,
|
syncId,
|
||||||
playerInv,
|
playerInv,
|
||||||
|
@ -73,7 +78,14 @@ class CraftingTerminalScreenHandler(
|
||||||
ItemStack.EMPTY
|
ItemStack.EMPTY
|
||||||
}
|
}
|
||||||
result.setStack(0, resultStack)
|
result.setStack(0, resultStack)
|
||||||
player.networkHandler.sendPacket(ScreenHandlerSlotUpdateS2CPacket(syncId, nextRevision(), resultSlot.id, resultStack))
|
player.networkHandler.sendPacket(
|
||||||
|
ScreenHandlerSlotUpdateS2CPacket(
|
||||||
|
syncId,
|
||||||
|
nextRevision(),
|
||||||
|
resultSlot.id,
|
||||||
|
resultStack
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,7 +137,7 @@ class CraftingTerminalScreenHandler(
|
||||||
}
|
}
|
||||||
|
|
||||||
// RecipeType.CRAFTING wants a CraftingInventory, but we can't store a CraftingInventory on the BE without a screen handler, so...
|
// RecipeType.CRAFTING wants a CraftingInventory, but we can't store a CraftingInventory on the BE without a screen handler, so...
|
||||||
class CraftingInv(val handler: CraftingTerminalScreenHandler): CraftingInventory(handler, 3, 3) {
|
class CraftingInv(val handler: CraftingTerminalScreenHandler) : CraftingInventory(handler, 3, 3) {
|
||||||
private val backing = handler.terminal.craftingInv
|
private val backing = handler.terminal.craftingInv
|
||||||
|
|
||||||
override fun isEmpty(): Boolean {
|
override fun isEmpty(): Boolean {
|
||||||
|
|
|
@ -23,7 +23,7 @@ import org.lwjgl.glfw.GLFW
|
||||||
class CraftingTerminalViewController(
|
class CraftingTerminalViewController(
|
||||||
screen: CraftingTerminalScreen,
|
screen: CraftingTerminalScreen,
|
||||||
handler: CraftingTerminalScreenHandler,
|
handler: CraftingTerminalScreenHandler,
|
||||||
): AbstractTerminalViewController<CraftingTerminalBlockEntity, CraftingTerminalScreen, CraftingTerminalScreenHandler>(
|
) : AbstractTerminalViewController<CraftingTerminalBlockEntity, CraftingTerminalScreen, CraftingTerminalScreenHandler>(
|
||||||
screen,
|
screen,
|
||||||
handler,
|
handler,
|
||||||
) {
|
) {
|
||||||
|
@ -57,7 +57,7 @@ class CraftingTerminalViewController(
|
||||||
}
|
}
|
||||||
|
|
||||||
val clearIcon = TextureView(CLEAR_ICON).apply {
|
val clearIcon = TextureView(CLEAR_ICON).apply {
|
||||||
intrinsicContentSize = Size(3.0,3.0)
|
intrinsicContentSize = Size(3.0, 3.0)
|
||||||
}
|
}
|
||||||
val clearButton = view.addSubview(Button(clearIcon, padding = 2.0, handler = ::clearPressed)).apply {
|
val clearButton = view.addSubview(Button(clearIcon, padding = 2.0, handler = ::clearPressed)).apply {
|
||||||
background = TextureView(SMALL_BUTTON)
|
background = TextureView(SMALL_BUTTON)
|
||||||
|
@ -73,7 +73,7 @@ class CraftingTerminalViewController(
|
||||||
intrinsicContentSize = Size(3.0, 3.0)
|
intrinsicContentSize = Size(3.0, 3.0)
|
||||||
}
|
}
|
||||||
val plusButton = view.addSubview(Button(plusIcon, padding = 2.0, handler = ::plusPressed)).apply {
|
val plusButton = view.addSubview(Button(plusIcon, padding = 2.0, handler = ::plusPressed)).apply {
|
||||||
background= TextureView(SMALL_BUTTON)
|
background = TextureView(SMALL_BUTTON)
|
||||||
hoveredBackground = TextureView(SMALL_BUTTON_HOVERED)
|
hoveredBackground = TextureView(SMALL_BUTTON_HOVERED)
|
||||||
tooltip = TranslatableText("gui.phycon.terminal.more_crafting")
|
tooltip = TranslatableText("gui.phycon.terminal.more_crafting")
|
||||||
}
|
}
|
||||||
|
@ -84,7 +84,12 @@ class CraftingTerminalViewController(
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun clearPressed(button: Button) {
|
private fun clearPressed(button: Button) {
|
||||||
MinecraftClient.getInstance().player!!.networkHandler.sendPacket(C2STerminalCraftingButton(terminal, C2STerminalCraftingButton.Action.CLEAR_GRID))
|
MinecraftClient.getInstance().player!!.networkHandler.sendPacket(
|
||||||
|
C2STerminalCraftingButton(
|
||||||
|
terminal,
|
||||||
|
C2STerminalCraftingButton.Action.CLEAR_GRID
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun plusPressed(button: Button) {
|
private fun plusPressed(button: Button) {
|
||||||
|
|
|
@ -17,12 +17,12 @@ import java.util.EnumMap
|
||||||
*/
|
*/
|
||||||
class SettingButton<E>(
|
class SettingButton<E>(
|
||||||
val key: TerminalSettings.SettingKey<E>,
|
val key: TerminalSettings.SettingKey<E>,
|
||||||
): AbstractButton<SettingButton<E>>(
|
) : AbstractButton<SettingButton<E>>(
|
||||||
TextureView(null).apply {
|
TextureView(null).apply {
|
||||||
intrinsicContentSize = Size(16.0, 16.0)
|
intrinsicContentSize = Size(16.0, 16.0)
|
||||||
},
|
},
|
||||||
padding = 2.0
|
padding = 2.0
|
||||||
) where E: Enum<E>, E: TerminalSetting {
|
) where E : Enum<E>, E : TerminalSetting {
|
||||||
|
|
||||||
private val textureCache = EnumMap<E, Texture>(key.clazz)
|
private val textureCache = EnumMap<E, Texture>(key.clazz)
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ import net.shadowfacts.phycon.PhysicalConnectivity
|
||||||
/**
|
/**
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
*/
|
*/
|
||||||
class TerminalBlock: AbstractTerminalBlock<TerminalBlockEntity>() {
|
class TerminalBlock : AbstractTerminalBlock<TerminalBlockEntity>() {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val ID = Identifier(PhysicalConnectivity.MODID, "terminal")
|
val ID = Identifier(PhysicalConnectivity.MODID, "terminal")
|
||||||
|
|
|
@ -15,13 +15,14 @@ import net.shadowfacts.phycon.packet.RequestInventoryPacket
|
||||||
/**
|
/**
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
*/
|
*/
|
||||||
class TerminalBlockEntity(pos: BlockPos, state: BlockState): AbstractTerminalBlockEntity(PhyBlockEntities.TERMINAL, pos, state) {
|
class TerminalBlockEntity(pos: BlockPos, state: BlockState) :
|
||||||
|
AbstractTerminalBlockEntity(PhyBlockEntities.TERMINAL, pos, state) {
|
||||||
|
|
||||||
override fun onActivate(player: PlayerEntity) {
|
override fun onActivate(player: PlayerEntity) {
|
||||||
super.onActivate(player)
|
super.onActivate(player)
|
||||||
|
|
||||||
if (!world!!.isClient) {
|
if (!world!!.isClient) {
|
||||||
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 {
|
||||||
return TerminalScreenHandler(syncId, playerInv, this@TerminalBlockEntity)
|
return TerminalScreenHandler(syncId, playerInv, this@TerminalBlockEntity)
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ import kotlin.math.min
|
||||||
/**
|
/**
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
*/
|
*/
|
||||||
class TerminalBufferInventory(size: Int): SimpleInventory(size) {
|
class TerminalBufferInventory(size: Int) : SimpleInventory(size) {
|
||||||
|
|
||||||
enum class Mode {
|
enum class Mode {
|
||||||
TO_NETWORK, FROM_NETWORK, UNASSIGNED
|
TO_NETWORK, FROM_NETWORK, UNASSIGNED
|
||||||
|
|
|
@ -8,7 +8,7 @@ import net.minecraft.item.ItemStack
|
||||||
/**
|
/**
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
*/
|
*/
|
||||||
class TerminalFakeSlot(fakeInv: FakeInventory, slot: Int, x: Int, y: Int): Slot(fakeInv, slot, x, y) {
|
class TerminalFakeSlot(fakeInv: FakeInventory, slot: Int, x: Int, y: Int) : Slot(fakeInv, slot, x, y) {
|
||||||
|
|
||||||
override fun canInsert(stack: ItemStack): Boolean {
|
override fun canInsert(stack: ItemStack): Boolean {
|
||||||
return false
|
return false
|
||||||
|
@ -23,7 +23,7 @@ class TerminalFakeSlot(fakeInv: FakeInventory, slot: Int, x: Int, y: Int): Slot(
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class FakeInventory(val screenHandler: AbstractTerminalScreenHandler<*>): Inventory {
|
class FakeInventory(val screenHandler: AbstractTerminalScreenHandler<*>) : Inventory {
|
||||||
override fun getStack(slot: Int): ItemStack {
|
override fun getStack(slot: Int): ItemStack {
|
||||||
if (slot >= screenHandler.itemsForDisplay.size) return ItemStack.EMPTY
|
if (slot >= screenHandler.itemsForDisplay.size) return ItemStack.EMPTY
|
||||||
return screenHandler.itemsForDisplay[slot]
|
return screenHandler.itemsForDisplay[slot]
|
||||||
|
|
|
@ -21,10 +21,11 @@ import kotlin.math.floor
|
||||||
class TerminalRequestAmountViewController(
|
class TerminalRequestAmountViewController(
|
||||||
val screen: AbstractTerminalScreen<*, *>,
|
val screen: AbstractTerminalScreen<*, *>,
|
||||||
val stack: ItemStack,
|
val stack: ItemStack,
|
||||||
): ViewController() {
|
) : ViewController() {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val BACKGROUND = Texture(Identifier(PhysicalConnectivity.MODID, "textures/gui/terminal_amount.png"), 0, 0)
|
private val BACKGROUND =
|
||||||
|
Texture(Identifier(PhysicalConnectivity.MODID, "textures/gui/terminal_amount.png"), 0, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
lateinit var field: NumberField
|
lateinit var field: NumberField
|
||||||
|
@ -137,7 +138,7 @@ class TerminalRequestAmountViewController(
|
||||||
screen.amountVC = null
|
screen.amountVC = null
|
||||||
}
|
}
|
||||||
|
|
||||||
class AmountField(val vc: TerminalRequestAmountViewController): NumberField(1) {
|
class AmountField(val vc: TerminalRequestAmountViewController) : NumberField(1) {
|
||||||
override fun keyPressed(keyCode: Int, modifiers: KeyModifiers): Boolean {
|
override fun keyPressed(keyCode: Int, modifiers: KeyModifiers): Boolean {
|
||||||
return if (keyCode == GLFW.GLFW_KEY_ENTER) {
|
return if (keyCode == GLFW.GLFW_KEY_ENTER) {
|
||||||
vc.doRequest()
|
vc.doRequest()
|
||||||
|
|
|
@ -12,7 +12,7 @@ class TerminalScreen(
|
||||||
handler: TerminalScreenHandler,
|
handler: TerminalScreenHandler,
|
||||||
playerInv: PlayerInventory,
|
playerInv: PlayerInventory,
|
||||||
title: Text,
|
title: Text,
|
||||||
): AbstractTerminalScreen<TerminalBlockEntity, TerminalScreenHandler>(
|
) : AbstractTerminalScreen<TerminalBlockEntity, TerminalScreenHandler>(
|
||||||
handler,
|
handler,
|
||||||
playerInv,
|
playerInv,
|
||||||
title,
|
title,
|
||||||
|
|
|
@ -12,9 +12,9 @@ class TerminalScreenHandler(
|
||||||
syncId: Int,
|
syncId: Int,
|
||||||
playerInv: PlayerInventory,
|
playerInv: PlayerInventory,
|
||||||
terminal: TerminalBlockEntity,
|
terminal: TerminalBlockEntity,
|
||||||
): AbstractTerminalScreenHandler<TerminalBlockEntity>(PhyScreens.TERMINAL, syncId, playerInv, terminal) {
|
) : AbstractTerminalScreenHandler<TerminalBlockEntity>(PhyScreens.TERMINAL, syncId, playerInv, terminal) {
|
||||||
|
|
||||||
constructor(syncId: Int, playerInv: PlayerInventory, buf: PacketByteBuf):
|
constructor(syncId: Int, playerInv: PlayerInventory, buf: PacketByteBuf) :
|
||||||
this(
|
this(
|
||||||
syncId,
|
syncId,
|
||||||
playerInv,
|
playerInv,
|
||||||
|
|
|
@ -6,7 +6,7 @@ package net.shadowfacts.phycon.block.terminal
|
||||||
class TerminalViewController(
|
class TerminalViewController(
|
||||||
screen: TerminalScreen,
|
screen: TerminalScreen,
|
||||||
handler: TerminalScreenHandler,
|
handler: TerminalScreenHandler,
|
||||||
): AbstractTerminalViewController<TerminalBlockEntity, TerminalScreen, TerminalScreenHandler>(
|
) : AbstractTerminalViewController<TerminalBlockEntity, TerminalScreen, TerminalScreenHandler>(
|
||||||
screen,
|
screen,
|
||||||
handler,
|
handler,
|
||||||
) {
|
) {
|
||||||
|
|
|
@ -11,7 +11,7 @@ import net.shadowfacts.phycon.client.model.ScreenDeviceModel
|
||||||
/**
|
/**
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
*/
|
*/
|
||||||
class PhyExtendedModelProvider(resourceManager: ResourceManager): ModelResourceProvider {
|
class PhyExtendedModelProvider(resourceManager: ResourceManager) : ModelResourceProvider {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val TERMINAL = Identifier(PhysicalConnectivity.MODID, "block/terminal")
|
val TERMINAL = Identifier(PhysicalConnectivity.MODID, "block/terminal")
|
||||||
|
|
|
@ -22,7 +22,7 @@ import java.util.function.Function
|
||||||
*/
|
*/
|
||||||
class ColoredCableModel(
|
class ColoredCableModel(
|
||||||
val color: DyeColor,
|
val color: DyeColor,
|
||||||
): UnbakedModel, BakedModel {
|
) : UnbakedModel, BakedModel {
|
||||||
companion object {
|
companion object {
|
||||||
val SIDE = Identifier(PhysicalConnectivity.MODID, "block/cable_side")
|
val SIDE = Identifier(PhysicalConnectivity.MODID, "block/cable_side")
|
||||||
val CENTER = Identifier(PhysicalConnectivity.MODID, "block/cable_center")
|
val CENTER = Identifier(PhysicalConnectivity.MODID, "block/cable_center")
|
||||||
|
@ -86,7 +86,12 @@ class ColoredCableModel(
|
||||||
rotationContainer: ModelBakeSettings,
|
rotationContainer: ModelBakeSettings,
|
||||||
modelId: Identifier
|
modelId: Identifier
|
||||||
): BakedModel {
|
): BakedModel {
|
||||||
centerSprite = textureGetter.apply(SpriteIdentifier(PlayerScreenHandler.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)
|
||||||
|
|
|
@ -17,13 +17,14 @@ import java.util.function.Function
|
||||||
/**
|
/**
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
*/
|
*/
|
||||||
abstract class FaceDeviceModel: UnbakedModel, BakedModel {
|
abstract class FaceDeviceModel : UnbakedModel, BakedModel {
|
||||||
|
|
||||||
private val interfaceCableStraightID = Identifier(PhysicalConnectivity.MODID, "block/interface_cable_straight")
|
private val interfaceCableStraightID = Identifier(PhysicalConnectivity.MODID, "block/interface_cable_straight")
|
||||||
private val interfaceCableCornerID = Identifier(PhysicalConnectivity.MODID, "block/interface_cable_corner")
|
private val interfaceCableCornerID = Identifier(PhysicalConnectivity.MODID, "block/interface_cable_corner")
|
||||||
private val interfaceCableCorner2ID = Identifier(PhysicalConnectivity.MODID, "block/interface_cable_corner_2")
|
private val interfaceCableCorner2ID = Identifier(PhysicalConnectivity.MODID, "block/interface_cable_corner_2")
|
||||||
private val interfaceCableCapID = Identifier(PhysicalConnectivity.MODID, "block/interface_cable_cap")
|
private val interfaceCableCapID = Identifier(PhysicalConnectivity.MODID, "block/interface_cable_cap")
|
||||||
// private var interfaceCableStraight = Array<BakedModel?>(6) { null }
|
|
||||||
|
// private var interfaceCableStraight = Array<BakedModel?>(6) { null }
|
||||||
// private var interfaceCableCap = Array<BakedModel?>(6) { null }
|
// private var interfaceCableCap = Array<BakedModel?>(6) { null }
|
||||||
// private var interfaceCableCorner = mutableMapOf<ModelRotation, BakedModel>()
|
// private var interfaceCableCorner = mutableMapOf<ModelRotation, BakedModel>()
|
||||||
// private var interfaceCableCorner2 = mutableMapOf<ModelRotation, BakedModel>()
|
// private var interfaceCableCorner2 = mutableMapOf<ModelRotation, BakedModel>()
|
||||||
|
@ -65,7 +66,8 @@ abstract class FaceDeviceModel: UnbakedModel, BakedModel {
|
||||||
for (tex in depTextures) {
|
for (tex in depTextures) {
|
||||||
if (tex.textureId.namespace == PhysicalConnectivity.MODID && tex.textureId.path.startsWith("block/cable/color/")) {
|
if (tex.textureId.namespace == PhysicalConnectivity.MODID && tex.textureId.path.startsWith("block/cable/color/")) {
|
||||||
for (color in DyeColor.values()) {
|
for (color in DyeColor.values()) {
|
||||||
val newPath = tex.textureId.path.replace("block/cable/color/", "block/cable/${color.getName()}/")
|
val newPath =
|
||||||
|
tex.textureId.path.replace("block/cable/color/", "block/cable/${color.getName()}/")
|
||||||
val substituted = SpriteIdentifier(tex.atlasId, Identifier(PhysicalConnectivity.MODID, newPath))
|
val substituted = SpriteIdentifier(tex.atlasId, Identifier(PhysicalConnectivity.MODID, newPath))
|
||||||
textures.add(substituted)
|
textures.add(substituted)
|
||||||
}
|
}
|
||||||
|
@ -77,7 +79,12 @@ abstract class FaceDeviceModel: UnbakedModel, BakedModel {
|
||||||
return textures
|
return textures
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun bake(loader: ModelLoader, textureGetter: Function<SpriteIdentifier, Sprite>, rotationContainer: ModelBakeSettings, modelId: Identifier): BakedModel {
|
override fun bake(
|
||||||
|
loader: ModelLoader,
|
||||||
|
textureGetter: Function<SpriteIdentifier, Sprite>,
|
||||||
|
rotationContainer: ModelBakeSettings,
|
||||||
|
modelId: Identifier
|
||||||
|
): BakedModel {
|
||||||
bakeSideModels(loader, textureGetter)
|
bakeSideModels(loader, textureGetter)
|
||||||
|
|
||||||
DyeColor.values().forEach { color ->
|
DyeColor.values().forEach { color ->
|
||||||
|
@ -132,6 +139,7 @@ abstract class FaceDeviceModel: UnbakedModel, BakedModel {
|
||||||
FaceCableConnection.WEST -> interfaceCableCorner[color]!![ModelRotation.X0_Y270]
|
FaceCableConnection.WEST -> interfaceCableCorner[color]!![ModelRotation.X0_Y270]
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
|
|
||||||
Direction.UP -> when (connection) {
|
Direction.UP -> when (connection) {
|
||||||
FaceCableConnection.NORTH -> interfaceCableCorner[color]!![ModelRotation.X180_Y180]
|
FaceCableConnection.NORTH -> interfaceCableCorner[color]!![ModelRotation.X180_Y180]
|
||||||
FaceCableConnection.EAST -> interfaceCableCorner[color]!![ModelRotation.X180_Y270]
|
FaceCableConnection.EAST -> interfaceCableCorner[color]!![ModelRotation.X180_Y270]
|
||||||
|
@ -139,6 +147,7 @@ abstract class FaceDeviceModel: UnbakedModel, BakedModel {
|
||||||
FaceCableConnection.WEST -> interfaceCableCorner[color]!![ModelRotation.X180_Y90]
|
FaceCableConnection.WEST -> interfaceCableCorner[color]!![ModelRotation.X180_Y90]
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
|
|
||||||
Direction.NORTH -> when (connection) {
|
Direction.NORTH -> when (connection) {
|
||||||
FaceCableConnection.UP -> interfaceCableCorner[color]!![ModelRotation.X270_Y0]
|
FaceCableConnection.UP -> interfaceCableCorner[color]!![ModelRotation.X270_Y0]
|
||||||
FaceCableConnection.EAST -> interfaceCableCorner2[color]!![ModelRotation.X180_Y180]
|
FaceCableConnection.EAST -> interfaceCableCorner2[color]!![ModelRotation.X180_Y180]
|
||||||
|
@ -146,6 +155,7 @@ abstract class FaceDeviceModel: UnbakedModel, BakedModel {
|
||||||
FaceCableConnection.WEST -> interfaceCableCorner2[color]!![ModelRotation.X0_Y0]
|
FaceCableConnection.WEST -> interfaceCableCorner2[color]!![ModelRotation.X0_Y0]
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
|
|
||||||
Direction.SOUTH -> when (connection) {
|
Direction.SOUTH -> when (connection) {
|
||||||
FaceCableConnection.UP -> interfaceCableCorner[color]!![ModelRotation.X270_Y180]
|
FaceCableConnection.UP -> interfaceCableCorner[color]!![ModelRotation.X270_Y180]
|
||||||
FaceCableConnection.WEST -> interfaceCableCorner2[color]!![ModelRotation.X180_Y0]
|
FaceCableConnection.WEST -> interfaceCableCorner2[color]!![ModelRotation.X180_Y0]
|
||||||
|
@ -153,6 +163,7 @@ abstract class FaceDeviceModel: UnbakedModel, BakedModel {
|
||||||
FaceCableConnection.EAST -> interfaceCableCorner2[color]!![ModelRotation.X0_Y180]
|
FaceCableConnection.EAST -> interfaceCableCorner2[color]!![ModelRotation.X0_Y180]
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
|
|
||||||
Direction.WEST -> when (connection) {
|
Direction.WEST -> when (connection) {
|
||||||
FaceCableConnection.UP -> interfaceCableCorner[color]!![ModelRotation.X270_Y270]
|
FaceCableConnection.UP -> interfaceCableCorner[color]!![ModelRotation.X270_Y270]
|
||||||
FaceCableConnection.NORTH -> interfaceCableCorner2[color]!![ModelRotation.X180_Y90]
|
FaceCableConnection.NORTH -> interfaceCableCorner2[color]!![ModelRotation.X180_Y90]
|
||||||
|
@ -160,6 +171,7 @@ abstract class FaceDeviceModel: UnbakedModel, BakedModel {
|
||||||
FaceCableConnection.SOUTH -> interfaceCableCorner2[color]!![ModelRotation.X0_Y270]
|
FaceCableConnection.SOUTH -> interfaceCableCorner2[color]!![ModelRotation.X0_Y270]
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
|
|
||||||
Direction.EAST -> when (connection) {
|
Direction.EAST -> when (connection) {
|
||||||
FaceCableConnection.UP -> interfaceCableCorner[color]!![ModelRotation.X270_Y90]
|
FaceCableConnection.UP -> interfaceCableCorner[color]!![ModelRotation.X270_Y90]
|
||||||
FaceCableConnection.SOUTH -> interfaceCableCorner2[color]!![ModelRotation.X180_Y270]
|
FaceCableConnection.SOUTH -> interfaceCableCorner2[color]!![ModelRotation.X180_Y270]
|
||||||
|
@ -167,6 +179,7 @@ abstract class FaceDeviceModel: UnbakedModel, BakedModel {
|
||||||
FaceCableConnection.NORTH -> interfaceCableCorner2[color]!![ModelRotation.X0_Y90]
|
FaceCableConnection.NORTH -> interfaceCableCorner2[color]!![ModelRotation.X0_Y90]
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
model?.getQuads(state, face, random) ?: listOf()
|
model?.getQuads(state, face, random) ?: listOf()
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue