Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4faae33d43 | ||
|
|
bd8f761ddb | ||
|
|
d5af099120 | ||
|
|
825e1ee110 | ||
|
|
ee0dc24207 | ||
|
|
e5d702bb5a | ||
|
|
c6e514216c | ||
|
|
f80a2850bb | ||
|
|
64fe6cefde | ||
|
|
26f337c0fd | ||
|
|
9fc81c1b33 | ||
|
|
5c599dbb9a | ||
|
|
d5a94ff784 | ||
|
|
024f299486 | ||
|
|
9a2b588568 | ||
|
|
b6fb5e8776 | ||
|
|
987b9bb275 | ||
|
|
b04ab8b95b | ||
|
|
dab0623d61 | ||
|
|
cb5b6ec68b | ||
|
|
ea57c9dc5d | ||
|
|
9abab091d9 | ||
|
|
e2e50d2f1b | ||
|
|
4ac88ba192 | ||
|
|
37eccce8b1 | ||
|
|
e44db7c380 | ||
|
|
d57bb42720 | ||
|
|
f0c44f040f | ||
|
|
2d6e2f87ed | ||
|
|
8b4193a5db | ||
|
|
667dfe32e3 | ||
|
|
218253765e | ||
|
|
ff082adf67 | ||
|
|
66959816ef | ||
|
|
0e85835a87 | ||
|
|
e165d4958d | ||
|
|
e0736e1988 | ||
|
|
724ff86a21 | ||
|
|
97427fa58b | ||
|
|
c9d47a3e21 | ||
|
|
c5c884ca2e | ||
|
|
f086c32b95 | ||
|
|
ecea176300 | ||
|
|
c00413bb32 | ||
|
|
be78012ce6 | ||
|
|
3844dd6314 | ||
|
|
080077189f | ||
|
|
4fa86c7742 | ||
|
|
3c9cff5027 | ||
|
|
a1047e05d4 | ||
|
|
b7c1157c5c | ||
|
|
cc8a51abcd | ||
|
|
38174155bf | ||
|
|
2698006f93 | ||
|
|
aa38674fc8 | ||
|
|
9ca0742386 | ||
|
|
32d291890e | ||
|
|
381fd1d5e2 | ||
|
|
a2fbe16ede | ||
|
|
0b478ebd5a | ||
|
|
b0b07e8edd | ||
|
|
824773150a | ||
|
|
3dc285cc70 | ||
|
|
e12d0bea66 | ||
|
|
5bc4994091 | ||
|
|
2b992dfd51 |
@@ -0,0 +1,20 @@
|
||||
package com.cobblemon.mod.common.mixin.invoker;
|
||||
|
||||
import net.minecraft.block.AbstractBlock;
|
||||
import net.minecraft.block.BlockSetType;
|
||||
import net.minecraft.block.PressurePlateBlock;
|
||||
import net.minecraft.resource.featuretoggle.FeatureSet;
|
||||
import net.minecraft.screen.ScreenHandler;
|
||||
import net.minecraft.screen.ScreenHandlerType;
|
||||
import net.minecraft.screen.ScreenHandlerType.Factory;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.gen.Invoker;
|
||||
|
||||
@Mixin(ScreenHandlerType.class)
|
||||
public interface ScreenHandlerTypeInvoker {
|
||||
@Invoker("<init>")
|
||||
static <T extends ScreenHandler> ScreenHandlerType<T> cobblemon$create(Factory<T> factory, FeatureSet requiredFeatures) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
@@ -45,6 +45,8 @@ object CobblemonBlockEntities : PlatformRegistry<Registry<BlockEntityType<*>>, R
|
||||
val SIGN: BlockEntityType<CobblemonSignBlockEntity> = this.create("sign", BlockEntityType.Builder.create(::CobblemonSignBlockEntity, CobblemonBlocks.APRICORN_SIGN, CobblemonBlocks.APRICORN_WALL_SIGN).build(null))
|
||||
@JvmField
|
||||
val HANGING_SIGN: BlockEntityType<CobblemonHangingSignBlockEntity> = this.create("hanging_sign", BlockEntityType.Builder.create(::CobblemonHangingSignBlockEntity, CobblemonBlocks.APRICORN_HANGING_SIGN, CobblemonBlocks.APRICORN_WALL_HANGING_SIGN).build(null))
|
||||
@JvmField
|
||||
val TM_BLOCK: BlockEntityType<TMBlockEntity> = this.create("tm_block", BlockEntityType.Builder.create(::TMBlockEntity, CobblemonBlocks.TM_MACHINE).build(null))
|
||||
|
||||
@JvmField
|
||||
val GILDED_CHEST: BlockEntityType<GildedChestBlockEntity> = this.create("chest", BlockEntityType.Builder.create(::GildedChestBlockEntity,
|
||||
|
||||
@@ -385,6 +385,17 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, RegistryKey<Registry<
|
||||
.luminance { if ((it.get(PCBlock.ON) as Boolean) && (it.get(PCBlock.PART) == PCBlock.PCPart.TOP)) 10 else 0 }
|
||||
)
|
||||
)
|
||||
val TM_MACHINE = create(
|
||||
"tm_machine",
|
||||
TMBlock(
|
||||
AbstractBlock.Settings.create()
|
||||
.mapColor(MapColor.GREEN)
|
||||
.sounds(BlockSoundGroup.METAL)
|
||||
.pistonBehavior(PistonBehavior.BLOCK)
|
||||
.nonOpaque()
|
||||
.luminance { if (it.get(TMBlock.ON) as Boolean) 10 else 0 }
|
||||
)
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val DISPLAY_CASE = create(
|
||||
@@ -399,6 +410,19 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, RegistryKey<Registry<
|
||||
)
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val MODIFICATION_STATION = create(
|
||||
"modification_station",
|
||||
ModStationBlock(
|
||||
AbstractBlock.Settings.create()
|
||||
.sounds(BlockSoundGroup.WOOD)
|
||||
.nonOpaque()
|
||||
.pistonBehavior(PistonBehavior.BLOCK)
|
||||
.mapColor(MapColor.BROWN)
|
||||
.strength(0.3f)
|
||||
)
|
||||
)
|
||||
|
||||
val RED_MINT = create("red_mint", MintBlock(MintType.RED, AbstractBlock.Settings.create().mapColor(MapColor.RED).noCollision().ticksRandomly().breakInstantly().sounds(CobblemonSounds.MINT_SOUNDS)))
|
||||
@JvmField
|
||||
val BLUE_MINT = create("blue_mint", MintBlock(MintType.BLUE, AbstractBlock.Settings.create().mapColor(MapColor.BLUE).noCollision().ticksRandomly().breakInstantly().sounds(CobblemonSounds.MINT_SOUNDS)))
|
||||
@@ -432,6 +456,67 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, RegistryKey<Registry<
|
||||
@JvmField
|
||||
val POTTED_PEP_UP_FLOWER = this.create("potted_pep_up_flower", BlocksInvoker.createFlowerPotBlock(PEP_UP_FLOWER))
|
||||
|
||||
@JvmField
|
||||
val NORMAL_TYPE_GEM_BLOCK = this.create("normal_type_gem_block", Block(AbstractBlock.Settings.copy(Blocks.AMETHYST_BLOCK)))
|
||||
@JvmField
|
||||
val NORMAL_TYPE_GEM = typeGem(
|
||||
"normal_type_gem",
|
||||
GrowableStoneBlock.STAGE_3,
|
||||
7,
|
||||
3,
|
||||
null,
|
||||
NORMAL_TYPE_GEM_BLOCK
|
||||
)
|
||||
@JvmField
|
||||
val LARGE_BUDDING_NORMAL_TYPE_GEM = typeGem(
|
||||
"large_budding_normal_type_gem",
|
||||
GrowableStoneBlock.STAGE_2,
|
||||
5,
|
||||
3,
|
||||
NORMAL_TYPE_GEM,
|
||||
NORMAL_TYPE_GEM_BLOCK
|
||||
)
|
||||
@JvmField
|
||||
val MEDIUM_BUDDING_NORMAL_TYPE_GEM = typeGem(
|
||||
"medium_budding_normal_type_gem",
|
||||
GrowableStoneBlock.STAGE_1,
|
||||
4,
|
||||
3,
|
||||
LARGE_BUDDING_NORMAL_TYPE_GEM,
|
||||
NORMAL_TYPE_GEM_BLOCK
|
||||
)
|
||||
@JvmField
|
||||
val SMALL_BUDDING_NORMAL_TYPE_GEM = typeGem(
|
||||
"small_budding_normal_type_gem",
|
||||
GrowableStoneBlock.STAGE_0,
|
||||
3,
|
||||
4,
|
||||
MEDIUM_BUDDING_NORMAL_TYPE_GEM,
|
||||
NORMAL_TYPE_GEM_BLOCK
|
||||
)
|
||||
|
||||
private fun typeGem(
|
||||
name: String,
|
||||
stage: Int,
|
||||
height: Int,
|
||||
xzOffset: Int,
|
||||
nextStage: Block?,
|
||||
baseBlock: Block
|
||||
): TypeGemBlock {
|
||||
return this.create(name, TypeGemBlock(
|
||||
settings = AbstractBlock.Settings.create()
|
||||
.pistonBehavior(PistonBehavior.DESTROY)
|
||||
.nonOpaque()
|
||||
.strength(1.5F)
|
||||
.sounds(CobblemonSounds.TYPE_GEM_SOUNDS),
|
||||
stage = stage,
|
||||
height = height,
|
||||
xzOffset = xzOffset,
|
||||
nextStage = nextStage,
|
||||
baseBlock = baseBlock
|
||||
))
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a map of all the blocks that can be stripped with an axe in the format of input - output.
|
||||
*
|
||||
@@ -442,8 +527,6 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, RegistryKey<Registry<
|
||||
APRICORN_LOG to STRIPPED_APRICORN_LOG
|
||||
)
|
||||
|
||||
|
||||
|
||||
private fun apricornBlock(name: String, apricorn: Apricorn): ApricornBlock = this.create(name, ApricornBlock(AbstractBlock.Settings.create().mapColor(apricorn.mapColor()).ticksRandomly().strength(Blocks.OAK_LOG.hardness, Blocks.OAK_LOG.blastResistance).sounds(BlockSoundGroup.WOOD).nonOpaque(), apricorn))
|
||||
|
||||
private fun tumblestoneBlock(name: String, stage: Int, height: Int, xzOffset: Int, nextStage: Block?) : Block {
|
||||
|
||||
@@ -26,6 +26,7 @@ import net.minecraft.registry.tag.TagKey
|
||||
import net.minecraft.resource.ResourceManager
|
||||
import net.minecraft.resource.ResourceReloader
|
||||
import net.minecraft.resource.ResourceType
|
||||
import net.minecraft.screen.ScreenHandlerType
|
||||
import net.minecraft.server.MinecraftServer
|
||||
import net.minecraft.server.network.ServerPlayerEntity
|
||||
import net.minecraft.text.Text
|
||||
@@ -158,6 +159,8 @@ interface CobblemonImplementation {
|
||||
*/
|
||||
fun registerResourceReloader(identifier: Identifier, reloader: ResourceReloader, type: ResourceType, dependencies: Collection<Identifier>)
|
||||
|
||||
fun registerScreenHandlerType(identifier: Identifier, screenHandlerType: ScreenHandlerType<*>)
|
||||
|
||||
/**
|
||||
* TODO
|
||||
*
|
||||
|
||||
@@ -258,10 +258,13 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, RegistryKey<Registry<It
|
||||
val HEALING_MACHINE = blockItem("healing_machine", CobblemonBlocks.HEALING_MACHINE)
|
||||
@JvmField
|
||||
val PC = blockItem("pc", CobblemonBlocks.PC)
|
||||
val TM_MACHINE = blockItem("tm_machine", CobblemonBlocks.TM_MACHINE)
|
||||
@JvmField
|
||||
val PASTURE = blockItem("pasture", CobblemonBlocks.PASTURE)
|
||||
@JvmField
|
||||
val DISPLAY_CASE = blockItem("display_case", CobblemonBlocks.DISPLAY_CASE)
|
||||
@JvmField
|
||||
val MOD_STATION = blockItem("modification_station", CobblemonBlocks.MODIFICATION_STATION)
|
||||
|
||||
// Evolution items
|
||||
@JvmField val LINK_CABLE = create("link_cable", LinkCableItem())
|
||||
@@ -867,6 +870,10 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, RegistryKey<Registry<It
|
||||
val RELIC_COIN_POUCH = blockItem("relic_coin_pouch", CobblemonBlocks.RELIC_COIN_POUCH)
|
||||
@JvmField
|
||||
val RELIC_COIN_SACK = blockItem("relic_coin_sack", CobblemonBlocks.RELIC_COIN_SACK)
|
||||
@JvmField
|
||||
val TECHNICAL_MACHINE = this.create("technical_machine", TechnicalMachineItem(Item.Settings()))
|
||||
@JvmField
|
||||
val BLANK_TM = this.create("blank_tm", CobblemonItem(Item.Settings()))
|
||||
|
||||
// Type Gems
|
||||
@JvmField
|
||||
|
||||
@@ -43,6 +43,8 @@ import com.cobblemon.mod.common.client.net.dialogue.DialogueClosedHandler
|
||||
import com.cobblemon.mod.common.client.net.dialogue.DialogueOpenedHandler
|
||||
import com.cobblemon.mod.common.client.net.effect.SpawnSnowstormEntityParticleHandler
|
||||
import com.cobblemon.mod.common.client.net.effect.SpawnSnowstormParticleHandler
|
||||
import com.cobblemon.mod.common.client.net.gui.CraftBlankTMPacketHandler
|
||||
import com.cobblemon.mod.common.client.net.gui.CraftTMPacketHandler
|
||||
import com.cobblemon.mod.common.client.net.gui.InteractPokemonUIPacketHandler
|
||||
import com.cobblemon.mod.common.client.net.gui.SummaryUIPacketHandler
|
||||
import com.cobblemon.mod.common.client.net.pasture.ClosePastureHandler
|
||||
@@ -131,6 +133,8 @@ import com.cobblemon.mod.common.net.messages.client.trade.TradeOfferExpiredPacke
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.TradeOfferNotificationPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.TradeStartedPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.TradeUpdatedPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.ui.CraftBlankTMPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.ui.CraftTMPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.ui.InteractPokemonUIPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.ui.SummaryUIPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.*
|
||||
@@ -432,6 +436,10 @@ object CobblemonNetwork : NetworkManager {
|
||||
this.createServerBound(PartyPokemonMoveSelectedPacket.ID, PartyPokemonMoveSelectedPacket::decode, PartyPokemonMoveSelectedHandler)
|
||||
this.createServerBound(PartyMoveSelectCancelledPacket.ID, PartyMoveSelectCancelledPacket::decode, PartyMoveSelectCancelledHandler)
|
||||
|
||||
// TM Machine packets
|
||||
this.createServerBound(CraftTMPacket.ID, CraftTMPacket::decode, CraftTMPacketHandler)
|
||||
this.createServerBound(CraftBlankTMPacket.ID, CraftBlankTMPacket::decode, CraftBlankTMPacketHandler)
|
||||
|
||||
// Dialogue packets
|
||||
this.createServerBound(EscapeDialoguePacket.ID, EscapeDialoguePacket::decode, EscapeDialogueHandler)
|
||||
this.createServerBound(InputToDialoguePacket.ID, InputToDialoguePacket::decode, InputToDialogueHandler)
|
||||
|
||||
@@ -240,6 +240,19 @@ object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, RegistryKey<Regi
|
||||
TUMBLESTONE_HIT,
|
||||
TUMBLESTONE_STEP
|
||||
)
|
||||
@JvmField
|
||||
val TM_USE = this.create("tm.use")
|
||||
@JvmField
|
||||
val TMM_CRAFT = this.create("tmm.craft")
|
||||
@JvmField
|
||||
val TMM_CRAFT_BLANK = this.create("tmm.craft_blank")
|
||||
@JvmField
|
||||
val TMM_OFF = this.create("tmm.off")
|
||||
@JvmField
|
||||
val TMM_ON = this.create("tmm.on")
|
||||
|
||||
@JvmField
|
||||
val TYPE_GEM_SOUNDS = TUMBLESTONE_BLOCK_SOUNDS
|
||||
|
||||
@JvmField
|
||||
val BERRY_BUSH_SOUNDS = BlockSoundGroup(1f, 1f,
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.pokemon.moves
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.data.ClientDataSynchronizer
|
||||
import com.cobblemon.mod.common.api.moves.MoveTemplate
|
||||
import com.cobblemon.mod.common.api.moves.Moves
|
||||
@@ -93,6 +94,20 @@ open class Learnset : ClientDataSynchronizer<Learnset> {
|
||||
.flatMap { it.value }
|
||||
.toSet()
|
||||
|
||||
fun tmLearnableMoves(): MutableList<MoveTemplate> {
|
||||
val moves = mutableListOf<MoveTemplate>()
|
||||
|
||||
moves.addAll(tmMoves)
|
||||
moves.addAll(tutorMoves)
|
||||
moves.addAll(eggMoves)
|
||||
moves.addAll(getLevelUpMovesUpTo(Cobblemon.config.maxPokemonLevel))
|
||||
moves.addAll(evolutionMoves)
|
||||
moves.addAll(formChangeMoves)
|
||||
|
||||
return moves
|
||||
}
|
||||
|
||||
|
||||
// We only sync level up moves atm
|
||||
override fun shouldSynchronize(other: Learnset) = other.levelUpMoves != this.levelUpMoves
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ package com.cobblemon.mod.common.api.storage.player
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.CobblemonNetwork.sendPacket
|
||||
import com.cobblemon.mod.common.api.tms.TechnicalMachine
|
||||
import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.net.messages.client.starter.SetClientPlayerDataPacket
|
||||
import java.util.UUID
|
||||
@@ -23,6 +24,7 @@ data class PlayerData(
|
||||
var starterSelected: Boolean,
|
||||
var starterUUID: UUID?,
|
||||
var keyItems: MutableSet<Identifier>,
|
||||
var tmSet: MutableSet<Identifier>,
|
||||
var battleTheme: Identifier?,
|
||||
val extraData: MutableMap<String, PlayerDataExtension>,
|
||||
) {
|
||||
@@ -42,6 +44,7 @@ data class PlayerData(
|
||||
starterUUID = null,
|
||||
keyItems = mutableSetOf(),
|
||||
battleTheme = CobblemonSounds.PVP_BATTLE.id,
|
||||
tmSet = mutableSetOf(),
|
||||
extraData = mutableMapOf()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -10,6 +10,8 @@ package com.cobblemon.mod.common.api.storage.player.adapter
|
||||
|
||||
import com.cobblemon.mod.common.api.storage.player.PlayerData
|
||||
import com.cobblemon.mod.common.api.storage.player.PlayerDataExtension
|
||||
import com.cobblemon.mod.common.api.tms.ObtainMethod
|
||||
import com.cobblemon.mod.common.util.adapters.CobblemonObtainMethodAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.IdentifierAdapter
|
||||
import com.cobblemon.mod.common.util.fromJson
|
||||
import com.google.gson.GsonBuilder
|
||||
@@ -31,6 +33,7 @@ class JsonPlayerData: PlayerDataStoreAdapter {
|
||||
.setPrettyPrinting()
|
||||
.disableHtmlEscaping()
|
||||
.registerTypeAdapter(PlayerDataExtension::class.java, PlayerDataExtensionAdapter)
|
||||
.registerTypeAdapter(ObtainMethod::class.java, CobblemonObtainMethodAdapter)
|
||||
.registerTypeAdapter(Identifier::class.java, IdentifierAdapter)
|
||||
.create()
|
||||
}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.tms
|
||||
|
||||
import net.minecraft.server.network.ServerPlayerEntity
|
||||
|
||||
interface ObtainMethod {
|
||||
/**
|
||||
* Whether to check this [ObtainMethod] once every second.
|
||||
*/
|
||||
val passive: Boolean
|
||||
|
||||
/**
|
||||
* Checks if the [ObtainMethod] condition is true.
|
||||
*
|
||||
* @param player The player to use when checking.
|
||||
* @return Whether the check succeeded.
|
||||
*/
|
||||
fun matches(player: ServerPlayerEntity): Boolean
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.cobblemon.mod.common.api.tms
|
||||
|
||||
import com.google.gson.JsonDeserializer
|
||||
import com.google.gson.JsonSerializer
|
||||
import net.minecraft.util.Identifier
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
/**
|
||||
* A type adapter for [ObtainMethod]s.
|
||||
* For the default implementation see [CobblemonObtainMethodAdapter].
|
||||
*
|
||||
* @author Apion
|
||||
* @since November 22nd, 2023
|
||||
*/
|
||||
interface ObtainMethodAdapter : JsonDeserializer<ObtainMethod>, JsonSerializer<ObtainMethod> {
|
||||
/**
|
||||
* Register a [ObtainMethod] to be used by this adapter.
|
||||
*
|
||||
* @param type The [KClass] of the [ObtainMethod].
|
||||
* @param identifier The expected [Identifier] in the parsed JSON.
|
||||
*/
|
||||
fun register(type: KClass<out ObtainMethod>, identifier: Identifier)
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.tms
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.moves.Moves
|
||||
import com.cobblemon.mod.common.api.types.ElementalType
|
||||
import com.cobblemon.mod.common.api.types.ElementalTypes
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.tms.obtain.NoneObtainMethod
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
import net.minecraft.item.Item
|
||||
import net.minecraft.item.Items
|
||||
import net.minecraft.registry.Registries
|
||||
import net.minecraft.server.network.ServerPlayerEntity
|
||||
import net.minecraft.text.MutableText
|
||||
import net.minecraft.text.Text
|
||||
import net.minecraft.util.Identifier
|
||||
|
||||
class TechnicalMachine(
|
||||
val moveName: String,
|
||||
val recipe: TechnicalMachineRecipe?,
|
||||
val obtainMethods: List<ObtainMethod> = emptyList(),
|
||||
val type: String,
|
||||
val primaryColor: Int?,
|
||||
val secondaryColor: Int?
|
||||
) {
|
||||
|
||||
companion object {
|
||||
/**
|
||||
* Filters all available [TechnicalMachines] based on three optional arguments
|
||||
*
|
||||
* @param search A [String] to check against move names
|
||||
* @param type An [ElementalType] to check for
|
||||
* @param pokemon A [Pokemon] to check the [Learnset] of
|
||||
* @return A [MutableSet] of [TechnicalMachine] that passed the filter
|
||||
* @author whatsy
|
||||
*/
|
||||
fun filterTms(search: String?, type: ElementalType?, pokemon: Pokemon?): MutableSet<TechnicalMachine> {
|
||||
val tms = TechnicalMachines.tmMap.values.toMutableSet()
|
||||
|
||||
type?.let {
|
||||
val iterator = tms.iterator()
|
||||
while (iterator.hasNext()) {
|
||||
val tm = iterator.next()
|
||||
if (ElementalTypes.get(tm.type) != type) {
|
||||
iterator.remove()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pokemon?.let {
|
||||
val iterator = tms.iterator()
|
||||
while (iterator.hasNext()) {
|
||||
val tm = iterator.next()
|
||||
val move = Moves.getByName(tm.moveName)
|
||||
if (!pokemon.species.moves.tmLearnableMoves().contains(move)) {
|
||||
iterator.remove()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
search?.let {
|
||||
val iterator = tms.iterator()
|
||||
while (iterator.hasNext()) {
|
||||
val tm = iterator.next()
|
||||
if (!tm.translatedMoveName().toString().contains(search, true)) {
|
||||
iterator.remove()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tms
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the [Identifier] of this [TechnicalMachine]
|
||||
*
|
||||
* @return The [Identifier] of this [TechnicalMachine] (or null if not found)
|
||||
* @author whatsy
|
||||
*/
|
||||
fun id(): Identifier? {
|
||||
TechnicalMachines.tmMap.forEach {
|
||||
if (TechnicalMachines.tmMap[it.key] == this) return it.key
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlocks this [TechnicalMachine] for the player.
|
||||
*
|
||||
* @param player The [ServerPlayerEntity] to give this [TechnicalMachine] to.
|
||||
* @return Whether the player was successfully granted the [TechnicalMachine]
|
||||
* @author whatsy
|
||||
*/
|
||||
fun unlock(player: ServerPlayerEntity): Boolean {
|
||||
if (id() == null) return false
|
||||
Cobblemon.playerData.get(player).tmSet.add(id()!!)
|
||||
if (!obtainMethods.any { it is NoneObtainMethod }) player.sendMessage(lang("tms.unlock_tm", lang("move.$moveName")))
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a [MutableText] of the translated move name of this [TechnicalMachine]
|
||||
*
|
||||
* @return This [TechnicalMachine]'s move name, translated
|
||||
* @author whatsy
|
||||
*/
|
||||
fun translatedMoveName(): MutableText {
|
||||
return lang("move." + this.moveName)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.tms
|
||||
|
||||
import net.minecraft.util.Identifier
|
||||
|
||||
/**
|
||||
* Represents the ingredients necessary to craft a [TechnicalMachine] in the [TMBlock]
|
||||
*/
|
||||
data class TechnicalMachineRecipe(
|
||||
val item: Identifier,
|
||||
val count: Int
|
||||
)
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.tms
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.CobblemonItems
|
||||
import com.cobblemon.mod.common.api.data.JsonDataRegistry
|
||||
import com.cobblemon.mod.common.api.reactive.SimpleObservable
|
||||
import com.cobblemon.mod.common.item.CobblemonItem
|
||||
import com.cobblemon.mod.common.item.TechnicalMachineItem
|
||||
import com.cobblemon.mod.common.registry.ItemTagCondition
|
||||
import com.cobblemon.mod.common.util.adapters.CobblemonObtainMethodAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.IdentifierAdapter
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.google.gson.GsonBuilder
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.registry.Registries
|
||||
import net.minecraft.resource.ResourceType
|
||||
import net.minecraft.server.network.ServerPlayerEntity
|
||||
import net.minecraft.util.Identifier
|
||||
|
||||
object TechnicalMachines : JsonDataRegistry<TechnicalMachine> {
|
||||
override val gson = GsonBuilder()
|
||||
.registerTypeAdapter(Identifier::class.java, IdentifierAdapter)
|
||||
.registerTypeAdapter(ObtainMethod::class.java, CobblemonObtainMethodAdapter)
|
||||
.create()
|
||||
override val typeToken = TypeToken.get(TechnicalMachine::class.java)
|
||||
override val resourcePath = "tms"
|
||||
override val id = cobblemonResource("technical_machines")
|
||||
override val type = ResourceType.SERVER_DATA
|
||||
override val observable = SimpleObservable<TechnicalMachines>()
|
||||
|
||||
val tmMap = mutableMapOf<Identifier, TechnicalMachine>()
|
||||
|
||||
val tagMap = mutableMapOf<ItemTagCondition, TechnicalMachine>()
|
||||
|
||||
val passiveTms = mutableMapOf<Identifier, TechnicalMachine>()
|
||||
override fun reload(data: Map<Identifier, TechnicalMachine>) {
|
||||
data.forEach {id, tm ->
|
||||
tmMap[id] = tm
|
||||
if (tm.obtainMethods.any { it.passive }) passiveTms.put(id, tm)
|
||||
}
|
||||
}
|
||||
override fun sync(player: ServerPlayerEntity) { }
|
||||
|
||||
fun getTechnicalMachineFromStack(item: ItemStack?): TechnicalMachine? {
|
||||
if (item == null) {
|
||||
return null
|
||||
}
|
||||
return TechnicalMachineItem.getMoveNbt(item)
|
||||
}
|
||||
|
||||
fun getStackFromTechnicalMachine(tm: TechnicalMachine): ItemStack {
|
||||
val tmItem = CobblemonItems.TECHNICAL_MACHINE.defaultStack
|
||||
return CobblemonItems.TECHNICAL_MACHINE.setNbt(tmItem,tm.id().toString())
|
||||
}
|
||||
|
||||
fun isTechnicalMachine(item: ItemStack): Boolean {
|
||||
return item.item is TechnicalMachineItem
|
||||
}
|
||||
|
||||
|
||||
fun checkPassives(player: ServerPlayerEntity) {
|
||||
val playerTms = Cobblemon.playerData.get(player).tmSet
|
||||
passiveTms.forEach { (id, tm) ->
|
||||
if (tm.obtainMethods.all { it.matches(player) } && !playerTms.contains(id)) tm.unlock(player)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,17 +13,23 @@ import net.minecraft.text.MutableText
|
||||
import net.minecraft.util.Identifier
|
||||
|
||||
/**
|
||||
* Class representing a type of a Pokemon or Move
|
||||
* Class representing a type of Pokémon or Move
|
||||
*
|
||||
* @param name: The English name used to load / find it (spaces -> _)
|
||||
* @param displayName: A Component used to display the name, normally a TranslatableText
|
||||
* @param textureXMultiplier: The multiplier by which the TypeWidget shall move the display
|
||||
* @param resourceLocation: The location of the resource used in the TypeWidget
|
||||
* @param primaryColor: The primary color of this type used to color [TechnicalMachineItem].
|
||||
* @param secondaryColor: The secondary color of this type used to color [TechnicalMachineItem]
|
||||
* @param typeGem: The Type Gem item used to craft a [TechnicalMachineItem] of this type.
|
||||
*/
|
||||
class ElementalType(
|
||||
val name: String,
|
||||
val displayName: MutableText,
|
||||
val hue: Int,
|
||||
val textureXMultiplier: Int,
|
||||
val resourceLocation: Identifier = Identifier(Cobblemon.MODID, "ui/types.png")
|
||||
val resourceLocation: Identifier = Identifier(Cobblemon.MODID, "ui/types.png"),
|
||||
val primaryColor: Int,
|
||||
val secondaryColor: Int,
|
||||
val typeGem: Identifier
|
||||
)
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.types
|
||||
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.text.MutableText
|
||||
import net.minecraft.text.Text
|
||||
|
||||
@@ -22,134 +23,180 @@ object ElementalTypes {
|
||||
name = "normal",
|
||||
displayName = Text.translatable("cobblemon.type.normal"),
|
||||
hue = 0xDDDDCF,
|
||||
textureXMultiplier = 0
|
||||
textureXMultiplier = 0,
|
||||
primaryColor = 0xCCCCC1,
|
||||
secondaryColor = 0xF9FFFC
|
||||
)
|
||||
|
||||
val FIRE = register(
|
||||
name = "fire",
|
||||
displayName = Text.translatable("cobblemon.type.fire"),
|
||||
hue = 0xE55C32,
|
||||
textureXMultiplier = 1
|
||||
textureXMultiplier = 1,
|
||||
primaryColor = 0xFF8766,
|
||||
secondaryColor = 0xFFD9A5
|
||||
)
|
||||
|
||||
val WATER = register(
|
||||
name = "water",
|
||||
displayName = Text.translatable("cobblemon.type.water"),
|
||||
hue = 0x4A9BE8,
|
||||
textureXMultiplier = 2
|
||||
textureXMultiplier = 2,
|
||||
primaryColor = 0x7F9DFF,
|
||||
secondaryColor = 0xA5EEFF
|
||||
)
|
||||
|
||||
val GRASS = register(
|
||||
name = "grass",
|
||||
displayName = Text.translatable("cobblemon.type.grass"),
|
||||
hue = 0x4DBC3C,
|
||||
textureXMultiplier = 3
|
||||
textureXMultiplier = 3,
|
||||
primaryColor = 0x66CC99,
|
||||
secondaryColor = 0xD6FFA5
|
||||
)
|
||||
|
||||
val ELECTRIC = register(
|
||||
name = "electric",
|
||||
displayName = Text.translatable("cobblemon.type.electric"),
|
||||
hue = 0xEFD128,
|
||||
textureXMultiplier = 4
|
||||
textureXMultiplier = 4,
|
||||
primaryColor = 0xFFCF3F,
|
||||
secondaryColor = 0xFFFFBF
|
||||
)
|
||||
|
||||
val ICE = register(
|
||||
name = "ice",
|
||||
displayName = Text.translatable("cobblemon.type.ice"),
|
||||
hue = 0x6BC3EF,
|
||||
textureXMultiplier = 5
|
||||
textureXMultiplier = 5,
|
||||
primaryColor = 0x8CC7FF,
|
||||
secondaryColor = 0xD6FFFF
|
||||
)
|
||||
|
||||
val FIGHTING = register(
|
||||
name = "fighting",
|
||||
displayName = Text.translatable("cobblemon.type.fighting"),
|
||||
hue = 0xC44C5C,
|
||||
textureXMultiplier = 6
|
||||
textureXMultiplier = 6,
|
||||
primaryColor = 0xCC6673,
|
||||
secondaryColor = 0xFFADA5
|
||||
)
|
||||
|
||||
val POISON = register(
|
||||
name = "poison",
|
||||
displayName = Text.translatable("cobblemon.type.poison"),
|
||||
hue = 0xA24BD8,
|
||||
textureXMultiplier = 7
|
||||
textureXMultiplier = 7,
|
||||
primaryColor = 0x8D66CC,
|
||||
secondaryColor = 0xEDA5FF
|
||||
)
|
||||
|
||||
val GROUND = register(
|
||||
name = "ground",
|
||||
displayName = Text.translatable("cobblemon.type.ground"),
|
||||
hue = 0xD89950,
|
||||
textureXMultiplier = 8
|
||||
textureXMultiplier = 8,
|
||||
primaryColor = 0xE5A27E,
|
||||
secondaryColor = 0xFFE1A5
|
||||
)
|
||||
|
||||
val FLYING = register(
|
||||
name = "flying",
|
||||
displayName = Text.translatable("cobblemon.type.flying"),
|
||||
hue = 0xBCC1FF,
|
||||
textureXMultiplier = 9
|
||||
textureXMultiplier = 9,
|
||||
primaryColor = 0x8CB6FF,
|
||||
secondaryColor = 0xE8DDFF
|
||||
)
|
||||
|
||||
val PSYCHIC = register(
|
||||
name = "psychic",
|
||||
displayName = Text.translatable("cobblemon.type.psychic"),
|
||||
hue = 0xD86AD6,
|
||||
textureXMultiplier = 10
|
||||
textureXMultiplier = 10,
|
||||
primaryColor = 0xE48CFF,
|
||||
secondaryColor = 0xFFCCF6
|
||||
)
|
||||
|
||||
val BUG = register(
|
||||
name = "bug",
|
||||
displayName = Text.translatable("cobblemon.type.bug"),
|
||||
hue = 0xA2C831,
|
||||
textureXMultiplier = 11
|
||||
textureXMultiplier = 11,
|
||||
primaryColor = 0xAFCC66,
|
||||
secondaryColor = 0xF6FFBF
|
||||
)
|
||||
|
||||
val ROCK = register(
|
||||
name = "rock",
|
||||
displayName = Text.translatable("cobblemon.type.rock"),
|
||||
hue = 0xAA9666,
|
||||
textureXMultiplier = 12
|
||||
textureXMultiplier = 12,
|
||||
primaryColor = 0x997F4C,
|
||||
secondaryColor = 0xDBC6A4
|
||||
)
|
||||
|
||||
val GHOST = register(
|
||||
name = "ghost",
|
||||
displayName = Text.translatable("cobblemon.type.ghost"),
|
||||
hue = 0x9572E5,
|
||||
textureXMultiplier = 13
|
||||
textureXMultiplier = 13,
|
||||
primaryColor = 0x8E8CFF,
|
||||
secondaryColor = 0xE8A5FF
|
||||
)
|
||||
|
||||
val DRAGON = register(
|
||||
name = "dragon",
|
||||
displayName = Text.translatable("cobblemon.type.dragon"),
|
||||
hue = 0x535DE8,
|
||||
textureXMultiplier = 14
|
||||
textureXMultiplier = 14,
|
||||
primaryColor = 0xBA8CFF,
|
||||
secondaryColor = 0xA5E5FF
|
||||
)
|
||||
|
||||
val DARK = register(
|
||||
name = "dark",
|
||||
displayName = Text.translatable("cobblemon.type.dark"),
|
||||
hue = 0x5C6CB2,
|
||||
textureXMultiplier = 15
|
||||
textureXMultiplier = 15,
|
||||
primaryColor = 0x5966B2,
|
||||
secondaryColor = 0xA5B1FF
|
||||
)
|
||||
|
||||
val STEEL = register(
|
||||
name = "steel",
|
||||
displayName = Text.translatable("cobblemon.type.steel"),
|
||||
hue = 0xC3CCE0,
|
||||
textureXMultiplier = 16
|
||||
textureXMultiplier = 16,
|
||||
primaryColor = 0x858EB2,
|
||||
secondaryColor = 0xF4FFFD
|
||||
)
|
||||
|
||||
val FAIRY = register(
|
||||
name = "fairy",
|
||||
displayName = Text.translatable("cobblemon.type.fairy"),
|
||||
hue = 0xEA727E,
|
||||
textureXMultiplier = 17
|
||||
textureXMultiplier = 17,
|
||||
primaryColor = 0xFF8CB6,
|
||||
secondaryColor = 0xFFD0CC
|
||||
)
|
||||
|
||||
fun register(name: String, displayName: MutableText, hue: Int, textureXMultiplier: Int): ElementalType {
|
||||
fun register(
|
||||
name: String,
|
||||
displayName: MutableText,
|
||||
hue: Int,
|
||||
textureXMultiplier: Int,
|
||||
primaryColor: Int,
|
||||
secondaryColor: Int
|
||||
): ElementalType {
|
||||
return ElementalType(
|
||||
name = name,
|
||||
displayName = displayName,
|
||||
hue = hue,
|
||||
textureXMultiplier = textureXMultiplier
|
||||
textureXMultiplier = textureXMultiplier,
|
||||
primaryColor = primaryColor,
|
||||
secondaryColor = secondaryColor,
|
||||
typeGem = cobblemonResource("${name}_gem")
|
||||
).also {
|
||||
allTypes.add(it)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
package com.cobblemon.mod.common.block
|
||||
|
||||
import net.minecraft.block.AbstractBlock.Settings
|
||||
import net.minecraft.block.Block
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.block.Blocks
|
||||
import net.minecraft.block.HorizontalFacingBlock
|
||||
import net.minecraft.entity.LivingEntity
|
||||
import net.minecraft.entity.ai.pathing.NavigationType
|
||||
import net.minecraft.entity.player.PlayerEntity
|
||||
import net.minecraft.fluid.Fluids
|
||||
import net.minecraft.item.ItemPlacementContext
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.screen.NamedScreenHandlerFactory
|
||||
import net.minecraft.state.StateManager
|
||||
import net.minecraft.state.property.EnumProperty
|
||||
import net.minecraft.util.*
|
||||
import net.minecraft.util.hit.BlockHitResult
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.util.math.Direction
|
||||
import net.minecraft.world.BlockView
|
||||
import net.minecraft.world.World
|
||||
import net.minecraft.world.WorldAccess
|
||||
import net.minecraft.world.WorldView
|
||||
|
||||
class ModStationBlock(settings: Settings) : Block(settings) {
|
||||
|
||||
companion object {
|
||||
val PART = EnumProperty.of("part", ModStationPart::class.java)
|
||||
}
|
||||
|
||||
enum class ModStationPart(private val label: String) : StringIdentifiable {
|
||||
TOP("top"),
|
||||
BOTTOM("bottom");
|
||||
|
||||
override fun asString() = label
|
||||
}
|
||||
|
||||
init {
|
||||
defaultState = this.stateManager.defaultState.with(
|
||||
HorizontalFacingBlock.FACING, Direction.SOUTH
|
||||
).with(PART, ModStationPart.BOTTOM)
|
||||
}
|
||||
|
||||
override fun onPlaced(
|
||||
world: World,
|
||||
pos: BlockPos,
|
||||
state: BlockState,
|
||||
placer: LivingEntity?,
|
||||
itemStack: ItemStack
|
||||
) {
|
||||
world.setBlockState(pos.up(), state
|
||||
.with(PART, ModStationPart.TOP)
|
||||
)
|
||||
world.updateNeighbors(pos, Blocks.AIR)
|
||||
state.updateNeighbors(world, pos, 3)
|
||||
}
|
||||
|
||||
override fun getPlacementState(blockPlaceContext: ItemPlacementContext): BlockState? {
|
||||
val abovePosition = blockPlaceContext.blockPos.up()
|
||||
val world = blockPlaceContext.world
|
||||
if (world.getBlockState(abovePosition).canReplace(blockPlaceContext) && !world.isOutOfHeightLimit(abovePosition)) {
|
||||
return defaultState
|
||||
.with(HorizontalFacingBlock.FACING, blockPlaceContext.horizontalPlayerFacing)
|
||||
.with(PART, ModStationPart.BOTTOM)
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
override fun canPlaceAt(state: BlockState, world: WorldView, pos: BlockPos): Boolean {
|
||||
val blockPos = pos.down()
|
||||
val blockState = world.getBlockState(blockPos)
|
||||
return if (state.get(PART) == ModStationPart.BOTTOM) blockState.isSideSolidFullSquare(world, blockPos, Direction.UP) else blockState.isOf(this)
|
||||
}
|
||||
|
||||
override fun canPathfindThrough(
|
||||
state: BlockState?,
|
||||
world: BlockView?,
|
||||
pos: BlockPos?,
|
||||
type: NavigationType?
|
||||
) = false
|
||||
|
||||
override fun appendProperties(builder: StateManager.Builder<Block, BlockState>) {
|
||||
builder.add(HorizontalFacingBlock.FACING)
|
||||
builder.add(PART)
|
||||
}
|
||||
|
||||
override fun rotate(blockState: BlockState, rotation: BlockRotation) = blockState.with(HorizontalFacingBlock.FACING, rotation.rotate(blockState.get(HorizontalFacingBlock.FACING)))
|
||||
|
||||
override fun mirror(blockState: BlockState, mirror: BlockMirror): BlockState {
|
||||
return blockState.rotate(mirror.getRotation(blockState.get(HorizontalFacingBlock.FACING)))
|
||||
}
|
||||
|
||||
override fun onStateReplaced(state: BlockState, world: World, pos: BlockPos?, newState: BlockState, moved: Boolean) {
|
||||
if (!state.isOf(newState.block)) super.onStateReplaced(state, world, pos, newState, moved)
|
||||
}
|
||||
|
||||
override fun getStateForNeighborUpdate(
|
||||
state: BlockState,
|
||||
direction: Direction,
|
||||
neighborState: BlockState,
|
||||
world: WorldAccess,
|
||||
pos: BlockPos,
|
||||
neighborPos: BlockPos
|
||||
): BlockState {
|
||||
val isStation = neighborState.isOf(this)
|
||||
val part = state.get(PART)
|
||||
if (!isStation && part == ModStationPart.TOP && neighborPos == pos.down()) {
|
||||
return Blocks.AIR.defaultState
|
||||
} else if (!isStation && part == ModStationPart.BOTTOM && neighborPos == pos.up()) {
|
||||
return Blocks.AIR.defaultState
|
||||
}
|
||||
|
||||
return state
|
||||
}
|
||||
|
||||
override fun onUse(
|
||||
state: BlockState,
|
||||
world: World,
|
||||
pos: BlockPos,
|
||||
player: PlayerEntity,
|
||||
hand: Hand,
|
||||
hit: BlockHitResult
|
||||
): ActionResult {
|
||||
player.openHandledScreen(state.createScreenHandlerFactory(world, pos))
|
||||
return ActionResult.CONSUME
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,547 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.block
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonItems
|
||||
import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.api.tms.TechnicalMachine
|
||||
import com.cobblemon.mod.common.api.tms.TechnicalMachines
|
||||
import com.cobblemon.mod.common.api.types.ElementalTypes
|
||||
import com.cobblemon.mod.common.block.entity.TMBlockEntity
|
||||
import com.cobblemon.mod.common.gui.TMMScreenHandler
|
||||
import com.cobblemon.mod.common.util.playSoundServer
|
||||
import com.cobblemon.mod.common.util.toVec3d
|
||||
import net.minecraft.block.*
|
||||
import net.minecraft.block.entity.BlockEntity
|
||||
import net.minecraft.block.entity.BrewingStandBlockEntity
|
||||
import net.minecraft.entity.ItemEntity
|
||||
import net.minecraft.entity.ai.pathing.NavigationType
|
||||
import net.minecraft.entity.player.PlayerEntity
|
||||
import net.minecraft.fluid.FluidState
|
||||
import net.minecraft.fluid.Fluids
|
||||
import net.minecraft.inventory.SidedInventory
|
||||
import net.minecraft.item.ItemPlacementContext
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.item.Items
|
||||
import net.minecraft.registry.Registries
|
||||
import net.minecraft.screen.NamedScreenHandlerFactory
|
||||
import net.minecraft.screen.SimpleNamedScreenHandlerFactory
|
||||
import net.minecraft.server.network.ServerPlayerEntity
|
||||
import net.minecraft.server.world.ServerWorld
|
||||
import net.minecraft.sound.SoundCategory
|
||||
import net.minecraft.stat.Stats
|
||||
import net.minecraft.state.StateManager
|
||||
import net.minecraft.state.property.BooleanProperty
|
||||
import net.minecraft.state.property.Properties
|
||||
import net.minecraft.text.Text
|
||||
import net.minecraft.util.ActionResult
|
||||
import net.minecraft.util.BlockMirror
|
||||
import net.minecraft.util.BlockRotation
|
||||
import net.minecraft.util.Hand
|
||||
import net.minecraft.util.hit.BlockHitResult
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.util.math.Direction
|
||||
import net.minecraft.util.shape.VoxelShape
|
||||
import net.minecraft.util.shape.VoxelShapes
|
||||
import net.minecraft.world.BlockView
|
||||
import net.minecraft.world.World
|
||||
import net.minecraft.world.WorldAccess
|
||||
|
||||
class TMBlock(properties: Settings): BlockWithEntity(properties), Waterloggable, InventoryProvider {
|
||||
/*val FACING = Properties.FACING
|
||||
val TRIGGERED = Properties.TRIGGERED
|
||||
val WATERLOGGED = Properties.WATERLOGGED*/
|
||||
|
||||
//var filterTM: TechnicalMachine? = null
|
||||
//var previousFilterTM: TechnicalMachine? = null
|
||||
var loadedMaterials: MutableList<ItemStack> = mutableListOf()
|
||||
//val inv = TMBlockInventory(this)
|
||||
|
||||
/*class TMBlockInventory(val tmBlock: TMBlock) : SidedInventory {
|
||||
override fun clear() {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun size(): Int {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun isEmpty(): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun getStack(slot: Int): ItemStack {
|
||||
return ItemStack.EMPTY
|
||||
}
|
||||
|
||||
override fun removeStack(slot: Int, amount: Int): ItemStack {
|
||||
return ItemStack.EMPTY
|
||||
}
|
||||
|
||||
override fun removeStack(slot: Int): ItemStack {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun setStack(slot: Int, stack: ItemStack?) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun markDirty() {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun canPlayerUse(player: PlayerEntity?): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun getAvailableSlots(side: Direction?): IntArray {
|
||||
return IntArray(1)
|
||||
}
|
||||
|
||||
override fun canInsert(slot: Int, stack: ItemStack?, dir: Direction?): Boolean {
|
||||
// todo only allow for hopper to insert materials if it has a filterTM in it
|
||||
if (tmBlock.filterTM != null && stack != null) {
|
||||
|
||||
// if material is needed then load it
|
||||
if (tmBlock.materialNeeded(tmBlock.filterTM!!, stack)) {
|
||||
tmBlock.loadMaterial(stack)
|
||||
return true
|
||||
}
|
||||
else
|
||||
return false
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
override fun canExtract(slot: Int, stack: ItemStack?, dir: Direction?): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
}*/
|
||||
companion object {
|
||||
//val WATERLOGGED = BooleanProperty.of("waterlogged")
|
||||
val ON = BooleanProperty.of("on")
|
||||
val FACING = Properties.FACING
|
||||
val TRIGGERED = Properties.TRIGGERED
|
||||
val WATERLOGGED = Properties.WATERLOGGED
|
||||
|
||||
private var NORTH_OUTLINE = VoxelShapes.union(
|
||||
VoxelShapes.cuboid(0.0, 0.0, 0.0, 1.0, 0.3125, 0.9375),
|
||||
VoxelShapes.cuboid(0.0, 0.3125, 0.75, 1.0, 0.9375, 0.9375),
|
||||
VoxelShapes.cuboid(0.0625, 0.3125, 0.0625, 0.9375, 0.875, 0.9375)
|
||||
)
|
||||
|
||||
private var SOUTH_OUTLINE = VoxelShapes.union(
|
||||
VoxelShapes.cuboid(0.0, 0.0, 0.0625, 1.0, 0.3125, 1.0),
|
||||
VoxelShapes.cuboid(0.0, 0.3125, 0.0625, 1.0, 0.9375, 0.25),
|
||||
VoxelShapes.cuboid(0.0625, 0.3125, 0.0625, 0.9375, 0.875, 0.9375)
|
||||
)
|
||||
|
||||
private var WEST_OUTLINE = VoxelShapes.union(
|
||||
VoxelShapes.cuboid(0.0, 0.0, 0.0, 0.9375, 0.3125, 1.0),
|
||||
VoxelShapes.cuboid(0.75, 0.3125, 0.0, 0.9375, 0.9375, 1.0),
|
||||
VoxelShapes.cuboid(0.0625, 0.3125, 0.0625, 0.9375, 0.875, 0.9375)
|
||||
)
|
||||
|
||||
private var EAST_OUTLINE = VoxelShapes.union(
|
||||
VoxelShapes.cuboid(0.0625, 0.0, 0.0, 1.0, 0.3125, 1.0),
|
||||
VoxelShapes.cuboid(0.0625, 0.3125, 0.0, 0.25, 0.9375, 1.0),
|
||||
VoxelShapes.cuboid(0.0625, 0.3125, 0.0625, 0.9375, 0.875, 0.9375)
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
init {
|
||||
defaultState = this.stateManager.defaultState.with(FACING, Direction.NORTH)
|
||||
.with(WATERLOGGED, false)
|
||||
.with(ON, false)
|
||||
.with(TRIGGERED, false)
|
||||
}
|
||||
|
||||
override fun getPlacementState(blockPlaceContext: ItemPlacementContext): BlockState? {
|
||||
return defaultState
|
||||
.with(FACING, blockPlaceContext.horizontalPlayerFacing)
|
||||
.with(WATERLOGGED, blockPlaceContext.world.getFluidState(blockPlaceContext.blockPos).fluid == Fluids.WATER)
|
||||
.with(ON, false)
|
||||
}
|
||||
|
||||
override fun onBreak(world: World, pos: BlockPos, state: BlockState, player: PlayerEntity?) {
|
||||
super.onBreak(world, pos, state, player)
|
||||
// todo dump materials and filterTM on the ground
|
||||
|
||||
}
|
||||
|
||||
@Deprecated("Deprecated in Java")
|
||||
override fun neighborUpdate(state: BlockState, world: World, pos: BlockPos, sourceBlock: Block?, sourcePos: BlockPos?, notify: Boolean) {
|
||||
val bl = world.isReceivingRedstonePower(pos) || world.isReceivingRedstonePower(pos.up())
|
||||
val bl2 = state.get(TRIGGERED)
|
||||
if (bl && !bl2) {
|
||||
world.scheduleBlockTick(pos, this, 4)
|
||||
world.setBlockState(pos, state.with(TRIGGERED, true) as BlockState, NO_REDRAW)
|
||||
} else if (!bl && bl2) {
|
||||
world.setBlockState(pos, state.with(TRIGGERED, false) as BlockState, NO_REDRAW)
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated("Deprecated in Java")
|
||||
override fun scheduledTick(state: BlockState?, world: ServerWorld?, pos: BlockPos?, random: net.minecraft.util.math.random.Random?) {
|
||||
val inventory = (world!!.getBlockEntity(pos) as TMBlockEntity).tmmInventory
|
||||
val tmEntity = (world.getBlockEntity(pos) as TMBlockEntity)
|
||||
|
||||
if(world == null || pos == null) {
|
||||
return
|
||||
}
|
||||
//val tankEntity = world.getBlockEntity(pos) as MultiblockEntity
|
||||
|
||||
if (tmEntity.blockState.get(ON)) {
|
||||
//print("TMM is in use so scheduled Tick is disabled")
|
||||
return
|
||||
}
|
||||
|
||||
//this.onTriggerEvent(state, world, pos, random)
|
||||
// todo if the output slot is empty then try to craft a TM to that slot
|
||||
if (ItemStack.areItemsEqual(inventory.items!!.get(3), ItemStack.EMPTY)) {
|
||||
if (state?.let { getInventory(it, world, pos) } != null) {
|
||||
val itemStack: ItemStack
|
||||
itemStack = if (inventory.filterTM != null)
|
||||
inventory.filterTM!!.copy()
|
||||
else
|
||||
ItemStack(CobblemonItems.BLANK_TM, 1)
|
||||
val tm = TechnicalMachines.getTechnicalMachineFromStack(itemStack)
|
||||
// todo use isReadyToCraftTM to finalize the creation
|
||||
if (((inventory.filterTM != null && tm != null) && isReadyToCraftTM(state, world, pos, tm)) || isReadyToCraftBlankTM(state, world, pos)) {
|
||||
|
||||
// create TM item to the output slot
|
||||
inventory.items!!.set(3, itemStack)
|
||||
tmEntity.markDirty()
|
||||
|
||||
// Play sound for TM creation
|
||||
world.playSoundServer(tmEntity.blockPos.toVec3d(), CobblemonSounds.TMM_CRAFT, SoundCategory.BLOCKS)
|
||||
}
|
||||
}
|
||||
}
|
||||
// todo if there is an item in the output slot then spit it out
|
||||
else {
|
||||
if (state?.let { getInventory(it, world, pos) } != null) {
|
||||
|
||||
val itemStack = inventory.items!!.get(3)
|
||||
|
||||
// Get the direction the block is facing
|
||||
val facingDirection = state.get(Properties.FACING)?.opposite ?: return
|
||||
|
||||
// Calculate the center position of the block
|
||||
val frontOffset = 0.5 // Half block offset to the front
|
||||
val spawnX = pos.x + 0.5 + facingDirection.offsetX * frontOffset
|
||||
val spawnY = pos.y + 0.3 + facingDirection.offsetY * frontOffset
|
||||
val spawnZ = pos.z + 0.5 + facingDirection.offsetZ * frontOffset
|
||||
|
||||
// Create the ItemEntity at the center of the block
|
||||
val itemEntity = ItemEntity(world, spawnX, spawnY, spawnZ, itemStack).copy()
|
||||
|
||||
// Create the ItemEntity
|
||||
itemEntity.setVelocity(0.0, 0.0, 0.0)
|
||||
|
||||
// Add the ItemEntity to the world
|
||||
world.spawnEntity(itemEntity)
|
||||
|
||||
//clear inventory of SidedInventory
|
||||
inventory.items?.clear()
|
||||
tmEntity.markDirty()
|
||||
//getInventory(state, world, pos).clear()
|
||||
}
|
||||
}
|
||||
|
||||
/*if (state?.let { getInventory(it, world, pos) } != null) {
|
||||
val itemStack: ItemStack
|
||||
itemStack = if (inventory.filterTM != null)
|
||||
inventory.filterTM!!
|
||||
else
|
||||
ItemStack(CobblemonItems.BLANK_TM, 1)
|
||||
val tm = TechnicalMachines.getTechnicalMachineFromStack(itemStack)
|
||||
// todo use isReadyToCraftTM to finalize the creation
|
||||
if ((inventory.filterTM != null && isReadyToCraftTM(state, world, pos, tm!!)) || isReadyToCraftBlankTM(state, world, pos)) {
|
||||
// Get the direction the block is facing
|
||||
val facingDirection = state.get(Properties.FACING)?.opposite ?: return
|
||||
|
||||
// Calculate the center position of the block
|
||||
val frontOffset = 0.5 // Half block offset to the front
|
||||
val spawnX = pos.x + 0.5 + facingDirection.offsetX * frontOffset
|
||||
val spawnY = pos.y + 0.3 + facingDirection.offsetY * frontOffset
|
||||
val spawnZ = pos.z + 0.5 + facingDirection.offsetZ * frontOffset
|
||||
|
||||
// Create the ItemEntity at the center of the block
|
||||
val itemEntity = ItemEntity(world, spawnX, spawnY, spawnZ, itemStack).copy()
|
||||
|
||||
// Create the ItemEntity
|
||||
itemEntity.setVelocity(0.0, 0.0, 0.0)
|
||||
|
||||
// Add the ItemEntity to the world
|
||||
world.spawnEntity(itemEntity)
|
||||
|
||||
//clear inventory of SidedInventory
|
||||
inventory.items?.clear()
|
||||
//getInventory(state, world, pos).clear()
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
/*val currentTm = filterTM ?: return sendPacketToServer(CraftBlankTMPacket(handler.input.getStack(2)))
|
||||
sendPacketToServer(
|
||||
CraftTMPacket(
|
||||
currentTm,
|
||||
handler.input.getStack(0),
|
||||
handler.input.getStack(1),
|
||||
handler.input.getStack(2)
|
||||
)
|
||||
)*/
|
||||
|
||||
@Deprecated("Deprecated in Java")
|
||||
override fun canPathfindThrough(blockState: BlockState, blockGetter: BlockView, blockPos: BlockPos, pathComputationType: NavigationType) = false
|
||||
|
||||
@Deprecated("Deprecated in Java")
|
||||
override fun hasComparatorOutput(state: BlockState?): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
@Deprecated("Deprecated in Java")
|
||||
override fun getComparatorOutput(state: BlockState, world: World?, pos: BlockPos?): Int {
|
||||
|
||||
if(world == null || pos == null) {
|
||||
return 0
|
||||
}
|
||||
val tmBlockEntity = world.getBlockEntity(pos) as TMBlockEntity
|
||||
val tm = TechnicalMachines.getTechnicalMachineFromStack(tmBlockEntity.tmmInventory.filterTM)
|
||||
|
||||
// if TMM has already crafted something and something is in the output slot do not send signal out
|
||||
if (!ItemStack.areItemsEqual(tmBlockEntity.tmmInventory.items?.get(3), ItemStack.EMPTY))
|
||||
return 0
|
||||
|
||||
// if the TMM is ready to craft send signal of 15 out
|
||||
if ((tm != null && isReadyToCraftTM(state, world, pos, tm)) || isReadyToCraftBlankTM(state, world, pos))
|
||||
return 15
|
||||
|
||||
/*if (tmBlockEntity.automationDelay > 0)
|
||||
tmBlockEntity.automationDelay--
|
||||
|
||||
if ((tmBlockEntity.tmmInventory.filterTM != null && isReadyToCraftTM(state, world, pos, tmBlockEntity.tmmInventory.filterTM!!)) || isReadyToCraftBlankTM(state, world, pos)) {
|
||||
if (tmBlockEntity.automationDelay == 0) {
|
||||
tmBlockEntity.resetAutomationDelay()
|
||||
return 15
|
||||
}
|
||||
else
|
||||
return 0
|
||||
}*/
|
||||
return 0
|
||||
}
|
||||
|
||||
|
||||
override fun getInventory(
|
||||
state: BlockState,
|
||||
world: WorldAccess,
|
||||
pos: BlockPos
|
||||
): SidedInventory {
|
||||
val tmBlockEntity = world.getBlockEntity(pos) as TMBlockEntity
|
||||
|
||||
return tmBlockEntity.tmmInventory
|
||||
}
|
||||
|
||||
|
||||
override fun appendProperties(builder: StateManager.Builder<Block, BlockState>) {
|
||||
builder.add(FACING)
|
||||
builder.add(WATERLOGGED)
|
||||
builder.add(ON)
|
||||
builder.add(TRIGGERED)
|
||||
}
|
||||
|
||||
override fun createBlockEntity(pos: BlockPos, state: BlockState): BlockEntity {
|
||||
return TMBlockEntity(pos, state)
|
||||
}
|
||||
|
||||
@Deprecated("Deprecated in Java")
|
||||
override fun rotate(blockState: BlockState, rotation: BlockRotation) =
|
||||
blockState.with(FACING, rotation.rotate(blockState.get(FACING)))
|
||||
|
||||
@Deprecated("Deprecated in Java")
|
||||
override fun mirror(blockState: BlockState, mirror: BlockMirror): BlockState {
|
||||
return blockState.rotate(mirror.getRotation(blockState.get(FACING)))
|
||||
}
|
||||
|
||||
@Deprecated("Deprecated in Java")
|
||||
override fun onStateReplaced(state: BlockState, world: World, pos: BlockPos?, newState: BlockState, moved: Boolean) {
|
||||
if (!state.isOf(newState.block)) super.onStateReplaced(state, world, pos, newState, moved)
|
||||
}
|
||||
|
||||
@Deprecated("Deprecated in Java")
|
||||
override fun onUse(
|
||||
blockState: BlockState,
|
||||
world: World,
|
||||
pos: BlockPos,
|
||||
player: PlayerEntity,
|
||||
interactionHand: Hand,
|
||||
blockHitResult: BlockHitResult
|
||||
): ActionResult {
|
||||
|
||||
// clear filter TM on client
|
||||
if (world.isClient) {
|
||||
val tmBlockEntity = world.getBlockEntity(pos)
|
||||
|
||||
val inventory = (tmBlockEntity as TMBlockEntity).tmmInventory
|
||||
|
||||
inventory.filterTM = null
|
||||
|
||||
return ActionResult.SUCCESS
|
||||
}
|
||||
|
||||
val tmBlockEntity = world.getBlockEntity(pos)
|
||||
|
||||
if (tmBlockEntity is TMBlockEntity) {
|
||||
// Set the block state to ON when the block is used
|
||||
tmBlockEntity.stateManager.openContainer(player, world, pos, blockState)
|
||||
player.openHandledScreen(tmBlockEntity as TMBlockEntity?)
|
||||
}
|
||||
|
||||
val inventory = (tmBlockEntity as TMBlockEntity).tmmInventory // (world.getBlockEntity(pos) as TMBlockEntity).tmmInventory
|
||||
|
||||
// remove all machine from machine upon use
|
||||
// inventory.items?.forEach {
|
||||
// // Get the direction the block is facing
|
||||
// val facingDirection = blockState.get(Properties.FACING).opposite
|
||||
//
|
||||
// // Calculate the center position of the block
|
||||
// val frontOffset = 0.5 // Half block offset to the front
|
||||
// val spawnX = pos.x + 0.5 + facingDirection.offsetX * frontOffset
|
||||
// val spawnY = pos.y + 0.3 + facingDirection.offsetY * frontOffset
|
||||
// val spawnZ = pos.z + 0.5 + facingDirection.offsetZ * frontOffset
|
||||
//
|
||||
// // Create the ItemEntity at the center of the block
|
||||
// val itemEntity = ItemEntity(world, spawnX, spawnY, spawnZ, it)
|
||||
//
|
||||
// // Create the ItemEntity
|
||||
// itemEntity.setVelocity(0.0, 0.0, 0.0)
|
||||
//
|
||||
// // Add the ItemEntity to the world
|
||||
// world.spawnEntity(itemEntity)
|
||||
// }
|
||||
//
|
||||
// inventory.items?.clear()
|
||||
|
||||
// spit out any disc filters
|
||||
if (inventory.filterTM != null) {
|
||||
// spit out the filter TM and set filterTM to null
|
||||
|
||||
val filterTMStack = inventory.filterTM!!
|
||||
|
||||
// Get the direction the block is facing
|
||||
val facingDirection = blockState.get(Properties.FACING).opposite
|
||||
|
||||
// Calculate the center position of the block
|
||||
val frontOffset = 0.5 // Half block offset to the front
|
||||
val spawnX = pos.x + 0.5 + facingDirection.offsetX * frontOffset
|
||||
val spawnY = pos.y + 0.3 + facingDirection.offsetY * frontOffset
|
||||
val spawnZ = pos.z + 0.5 + facingDirection.offsetZ * frontOffset
|
||||
|
||||
// Create the ItemEntity at the center of the block
|
||||
val itemEntity = ItemEntity(world, spawnX, spawnY, spawnZ, filterTMStack).copy()
|
||||
|
||||
// Create the ItemEntity
|
||||
itemEntity.setVelocity(0.0, 0.0, 0.0)
|
||||
|
||||
// Add the ItemEntity to the world
|
||||
world.spawnEntity(itemEntity)
|
||||
|
||||
inventory.filterTM = null
|
||||
}
|
||||
|
||||
val blockEntity = world.getBlockEntity(pos)
|
||||
if (blockEntity is TMBlockEntity) {
|
||||
//player.openHandledScreen(blockEntity as TMBlockEntity?)
|
||||
player.playSound(CobblemonSounds.TMM_ON, SoundCategory.BLOCKS, 1.0f, 1.0f)
|
||||
|
||||
// todo maybe uncomment this
|
||||
//val serverPlayer = player as ServerPlayerEntity
|
||||
//serverPlayer.openHandledScreen(blockState.createScreenHandlerFactory(world, pos))
|
||||
}
|
||||
return ActionResult.CONSUME
|
||||
}
|
||||
|
||||
// override fun createScreenHandlerFactory(
|
||||
// state: BlockState?,
|
||||
// world: World?,
|
||||
// pos: BlockPos?
|
||||
// ): NamedScreenHandlerFactory {
|
||||
// return SimpleNamedScreenHandlerFactory(::TMMScreenHandler, Text.of("TM Machine"))
|
||||
// }
|
||||
|
||||
/*fun loadMaterial(itemStack: ItemStack) {
|
||||
loadedMaterials.add(itemStack)
|
||||
}*/
|
||||
|
||||
fun isReadyToCraftTM(state: BlockState?, world: WorldAccess, pos: BlockPos, tm: TechnicalMachine): Boolean {
|
||||
val typeGem = Registries.ITEM.get(tm.let { ElementalTypes.get(it.type)?.typeGem }).defaultStack
|
||||
val recipeItem = Registries.ITEM.get(tm.recipe?.item)
|
||||
|
||||
val inventory = state?.let { getInventory(it, world, pos) }
|
||||
|
||||
return (inventory!!.count(CobblemonItems.BLANK_TM) == 1
|
||||
&& inventory.count(typeGem.item) == 1
|
||||
&& ((inventory.count(recipeItem) == tm.recipe?.count) || (ItemStack.areItemsEqual(recipeItem.defaultStack, ItemStack.EMPTY))))
|
||||
}
|
||||
|
||||
fun isReadyToCraftBlankTM(state: BlockState?, world: WorldAccess, pos: BlockPos): Boolean {
|
||||
val inventory = state?.let { getInventory(it, world, pos) }
|
||||
|
||||
return (inventory!!.count(Items.AMETHYST_SHARD) == 1)
|
||||
}
|
||||
|
||||
/*fun materialNeeded(tm: TechnicalMachine, itemStack: ItemStack): Boolean {
|
||||
val typeGem = Registries.ITEM.get(ElementalTypes.get(tm.type)?.typeGem).defaultStack
|
||||
val recipeItem = Registries.ITEM.get(tm.recipe?.item)
|
||||
|
||||
// if blank TM is needed still
|
||||
if ((itemStack !in loadedMaterials && itemStack == CobblemonItems.BLANK_TM.defaultStack))
|
||||
return true // load in blank TM
|
||||
// if type gem is needed still
|
||||
else if ((itemStack !in loadedMaterials && itemStack == typeGem))
|
||||
return true // load in Type Gem
|
||||
// if the itemStack is listed as needed in the recipe and the count is not currently met
|
||||
else if (itemStack.item == recipeItem && loadedMaterials.count { it == itemStack } < tm.recipe?.count!!)
|
||||
return true
|
||||
else
|
||||
return false
|
||||
}*/
|
||||
|
||||
/*fun clearLoadedMaterials() {
|
||||
loadedMaterials.clear()
|
||||
}*/
|
||||
|
||||
@Deprecated("Deprecated in Java")
|
||||
override fun getRenderType(blockState: BlockState): BlockRenderType {
|
||||
return BlockRenderType.MODEL
|
||||
}
|
||||
|
||||
override fun getFluidState(state: BlockState): FluidState? {
|
||||
return if (state.get(WATERLOGGED)) {
|
||||
Fluids.WATER.getStill(false)
|
||||
} else super.getFluidState(state)
|
||||
}
|
||||
|
||||
override fun getOutlineShape(
|
||||
state: BlockState,
|
||||
world: BlockView,
|
||||
pos: BlockPos,
|
||||
context: ShapeContext
|
||||
): VoxelShape {
|
||||
return when (state.get(FACING)) {
|
||||
Direction.NORTH -> NORTH_OUTLINE
|
||||
Direction.SOUTH -> SOUTH_OUTLINE
|
||||
Direction.WEST -> WEST_OUTLINE
|
||||
else -> EAST_OUTLINE
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.cobblemon.mod.common.block
|
||||
|
||||
import net.minecraft.block.*
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.world.BlockView
|
||||
|
||||
class TypeGemBlock(
|
||||
settings: Settings,
|
||||
stage: Int,
|
||||
height: Int,
|
||||
xzOffset: Int,
|
||||
nextStage: Block?,
|
||||
val baseBlock: Block
|
||||
) : GrowableStoneBlock(settings, stage, height, xzOffset, nextStage) {
|
||||
override fun canGrow(pos: BlockPos, world: BlockView): Boolean {
|
||||
val state = world.getBlockState(pos)
|
||||
val dir = state.get(FACING).opposite
|
||||
return (world.getBlockState(pos.offset(dir)).block == baseBlock)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,349 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.block.entity
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonBlockEntities
|
||||
import com.cobblemon.mod.common.CobblemonItems
|
||||
import com.cobblemon.mod.common.api.tms.TechnicalMachine
|
||||
import com.cobblemon.mod.common.api.tms.TechnicalMachines
|
||||
import com.cobblemon.mod.common.api.types.ElementalTypes
|
||||
import com.cobblemon.mod.common.block.TMBlock
|
||||
import com.cobblemon.mod.common.gui.TMMScreenHandler
|
||||
import net.minecraft.block.Block
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.block.entity.LockableContainerBlockEntity
|
||||
import net.minecraft.block.entity.ViewerCountManager
|
||||
import net.minecraft.entity.player.PlayerEntity
|
||||
import net.minecraft.entity.player.PlayerInventory
|
||||
import net.minecraft.inventory.Inventories
|
||||
import net.minecraft.inventory.Inventory
|
||||
import net.minecraft.inventory.SidedInventory
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.item.Items
|
||||
import net.minecraft.nbt.NbtCompound
|
||||
import net.minecraft.network.listener.ClientPlayPacketListener
|
||||
import net.minecraft.network.packet.Packet
|
||||
import net.minecraft.network.packet.s2c.play.BlockEntityUpdateS2CPacket
|
||||
import net.minecraft.registry.Registries
|
||||
import net.minecraft.screen.ScreenHandler
|
||||
import net.minecraft.text.Text
|
||||
import net.minecraft.util.collection.DefaultedList
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.util.math.Direction
|
||||
import net.minecraft.world.World
|
||||
|
||||
|
||||
class TMBlockEntity(
|
||||
val blockPos: BlockPos,
|
||||
val blockState: BlockState
|
||||
) : LockableContainerBlockEntity(CobblemonBlockEntities.TM_BLOCK, blockPos, blockState) {
|
||||
var tmmInventory = TMBlockInventory(this)
|
||||
var automationDelay: Int = AUTOMATION_DELAY
|
||||
var partialTicks = 0.0f
|
||||
|
||||
val stateManager: ViewerCountManager = object : ViewerCountManager() {
|
||||
override fun onContainerOpen(world: World, pos: BlockPos, state: BlockState) {
|
||||
this@TMBlockEntity.setOpen(state, true)
|
||||
}
|
||||
|
||||
override fun onContainerClose(world: World, pos: BlockPos, state: BlockState) {
|
||||
this@TMBlockEntity.setOpen(state, false)
|
||||
}
|
||||
|
||||
override fun onViewerCountUpdate(world: World, pos: BlockPos, state: BlockState, oldViewerCount: Int, newViewerCount: Int) {}
|
||||
override fun isPlayerViewing(player: PlayerEntity): Boolean {
|
||||
if (player.currentScreenHandler is TMMScreenHandler) {
|
||||
val inventory = (player.currentScreenHandler as TMMScreenHandler).inventory
|
||||
return inventory === this@TMBlockEntity
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
companion object {
|
||||
const val AUTOMATION_DELAY = 4
|
||||
const val FILTER_TM_NBT = "FilterTM"
|
||||
}
|
||||
|
||||
fun setOpen(state: BlockState, open: Boolean) {
|
||||
world!!.setBlockState(getPos(), state.with(TMBlock.ON, open), Block.NOTIFY_ALL)
|
||||
}
|
||||
|
||||
fun tick() {
|
||||
if (!removed) {
|
||||
stateManager.updateViewerCount(getWorld(), getPos(), cachedState)
|
||||
}
|
||||
}
|
||||
|
||||
//var filterTM: TechnicalMachine? = null
|
||||
//private var inventory: DefaultedList<ItemStack> = DefaultedList.ofSize(size(), ItemStack.EMPTY)
|
||||
|
||||
|
||||
/*override fun size(): Int { return 3 }
|
||||
override fun getContainerName(): Text {
|
||||
return Text.translatable("container.tmblock")
|
||||
}
|
||||
|
||||
override fun getInvStackList(): DefaultedList<ItemStack> {
|
||||
return inventory
|
||||
}
|
||||
|
||||
override fun setInvStackList(list: DefaultedList<ItemStack>?) {
|
||||
if (list != null) {
|
||||
this.inventory = list
|
||||
}
|
||||
}*/
|
||||
|
||||
fun resetAutomationDelay() {
|
||||
automationDelay = AUTOMATION_DELAY
|
||||
}
|
||||
|
||||
|
||||
fun materialNeeded(tm: TechnicalMachine?, slot: Int, itemStack: ItemStack): Boolean {
|
||||
val typeGem = Registries.ITEM.get(tm?.type?.let { ElementalTypes.get(it)?.typeGem }).defaultStack
|
||||
val recipeItem = Registries.ITEM.get(tm?.recipe?.item)
|
||||
//val inventory = tmmInventory.inventory
|
||||
val inventory = tmmInventory.items
|
||||
|
||||
//inventory.count { it.value == CobblemonItems.BLANK_TM.defaultStack }
|
||||
//ItemStack.areEqual()
|
||||
|
||||
|
||||
if (inventory != null) {
|
||||
if (tmmInventory.filterTM != null) {
|
||||
// if blank TM is needed still
|
||||
if (slot == 0 && (inventory.none { it?.count == 1 && it.item == CobblemonItems.BLANK_TM }) && ItemStack.areEqual(itemStack, ItemStack(CobblemonItems.BLANK_TM, 1)))
|
||||
return true // load in blank TM
|
||||
// if type gem is needed still
|
||||
else if (slot == 1 && inventory.none { ItemStack.areEqual(it, typeGem) } && ItemStack.areEqual(itemStack, typeGem))
|
||||
return true // load in Type Gem
|
||||
// if the itemStack is listed as needed in the recipe and the count is not currently met
|
||||
else if (slot == 2 && inventory.none { it?.count == tm?.recipe?.count && ItemStack.areItemsEqual(it, ItemStack(recipeItem, 1)) } && ItemStack.areEqual(itemStack, ItemStack(recipeItem, 1)))
|
||||
return true
|
||||
else
|
||||
return false
|
||||
}
|
||||
else if (tmmInventory.filterTM == null && ItemStack.areItemsEqual(itemStack,Items.AMETHYST_SHARD.defaultStack)) {
|
||||
return (slot == 2 && inventory.none { it?.count == 1 && ItemStack.areItemsEqual(it, Items.AMETHYST_SHARD.defaultStack) })
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
override fun toInitialChunkDataNbt(): NbtCompound {
|
||||
val res = NbtCompound()
|
||||
writeNbt(res)
|
||||
return res
|
||||
}
|
||||
|
||||
override fun clear() {
|
||||
tmmInventory.clear()
|
||||
}
|
||||
|
||||
override fun size(): Int {
|
||||
return this.tmmInventory.size()
|
||||
}
|
||||
|
||||
override fun isEmpty(): Boolean {
|
||||
return this.tmmInventory.isEmpty()
|
||||
}
|
||||
|
||||
override fun getStack(slot: Int): ItemStack {
|
||||
return this.tmmInventory.getStack(slot)
|
||||
}
|
||||
|
||||
override fun removeStack(slot: Int, amount: Int): ItemStack {
|
||||
return this.tmmInventory.removeStack(slot, amount)
|
||||
}
|
||||
|
||||
override fun removeStack(slot: Int): ItemStack {
|
||||
return this.tmmInventory.removeStack(slot)
|
||||
}
|
||||
|
||||
override fun setStack(slot: Int, stack: ItemStack?) {
|
||||
return this.tmmInventory.setStack(slot, stack)
|
||||
}
|
||||
|
||||
override fun canPlayerUse(player: PlayerEntity?): Boolean {
|
||||
return this.tmmInventory.canPlayerUse(player)
|
||||
}
|
||||
|
||||
override fun getContainerName(): Text {
|
||||
return Text.translatable("container.brewing")
|
||||
}
|
||||
|
||||
|
||||
override fun createScreenHandler(syncId: Int, playerInventory: PlayerInventory?): ScreenHandler {
|
||||
return TMMScreenHandler(syncId, playerInventory!!, this.tmmInventory, this)
|
||||
}
|
||||
|
||||
override fun toUpdatePacket(): Packet<ClientPlayPacketListener>? {
|
||||
return BlockEntityUpdateS2CPacket.create(this)
|
||||
}
|
||||
|
||||
override fun writeNbt(nbt: NbtCompound) {
|
||||
super.writeNbt(nbt)
|
||||
Inventories.writeNbt(nbt, tmmInventory.items)
|
||||
val filterTmCompound = tmmInventory.filterTM?.writeNbt(NbtCompound())
|
||||
if (filterTmCompound != null)
|
||||
nbt.put(FILTER_TM_NBT, filterTmCompound)
|
||||
}
|
||||
|
||||
override fun readNbt(nbt: NbtCompound) {
|
||||
super.readNbt(nbt)
|
||||
Inventories.readNbt(nbt, tmmInventory.items)
|
||||
if (nbt.contains(FILTER_TM_NBT)) {
|
||||
val itemStack = CobblemonItems.TECHNICAL_MACHINE.defaultStack
|
||||
|
||||
tmmInventory.filterTM = ItemStack.fromNbt(nbt.getCompound(FILTER_TM_NBT))
|
||||
|
||||
val test = 2
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun markDirty() {
|
||||
super.markDirty()
|
||||
if (this.world != null && !this.world!!.isClient) {
|
||||
val currentState = world!!.getBlockState(pos)
|
||||
world!!.setBlockState(pos, currentState, 3) // Flags: 2 | 1 = Block update | Render update
|
||||
this.world!!.updateNeighborsAlways(this.pos, this.cachedState.block)
|
||||
}
|
||||
}
|
||||
|
||||
class TMBlockInventory(val tmBlockEntity: TMBlockEntity) : SidedInventory {
|
||||
|
||||
private val BLANK_DISC_SLOT_INDEX = 0
|
||||
private val GEM_SLOT_INDEX = 1
|
||||
private val MISC_SLOT_INDEX = 2
|
||||
private val OUTPUT_SLOT_INDEX = 3
|
||||
private val INPUT_SLOTS = intArrayOf(0, 1, 2, 3)
|
||||
val entityPos = this.tmBlockEntity.blockPos
|
||||
val entityState = this.tmBlockEntity.blockState
|
||||
val entityWorld = this.tmBlockEntity.world
|
||||
|
||||
var filterTM: ItemStack? = null
|
||||
//var inventory: MutableMap<Int, ItemStack?> = mutableMapOf(0 to ItemStack.EMPTY, 1 to ItemStack.EMPTY, 2 to ItemStack.EMPTY)
|
||||
var items: DefaultedList<ItemStack?>? = DefaultedList.ofSize(4, ItemStack.EMPTY)
|
||||
|
||||
fun hasFilterTM(): Boolean {
|
||||
return filterTM != null
|
||||
}
|
||||
|
||||
override fun clear() {
|
||||
tmBlockEntity.markDirty()
|
||||
this.items?.clear()
|
||||
}
|
||||
|
||||
override fun size(): Int {
|
||||
return this.items?.size ?: 0;
|
||||
}
|
||||
|
||||
/*fun getInvSize(): Int {
|
||||
return size()
|
||||
}*/
|
||||
|
||||
fun getInvStack(slot: Int): ItemStack {
|
||||
return items?.get(slot) ?: ItemStack.EMPTY
|
||||
}
|
||||
|
||||
override fun isEmpty(): Boolean {
|
||||
for (i in 0 until size()) {
|
||||
val stack: ItemStack = getInvStack(i)
|
||||
if (!stack.isEmpty) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
/*override fun isEmpty(): Boolean {
|
||||
return !inventory.any { it.value != ItemStack.EMPTY }
|
||||
}*/
|
||||
|
||||
override fun getStack(slot: Int): ItemStack {
|
||||
return items?.get(slot) ?: ItemStack.EMPTY
|
||||
}
|
||||
|
||||
override fun getAvailableSlots(side: Direction?): IntArray? {
|
||||
return if (side == Direction.DOWN) {
|
||||
return listOf(this.OUTPUT_SLOT_INDEX).toIntArray()
|
||||
}
|
||||
else this.INPUT_SLOTS
|
||||
|
||||
|
||||
// val result = this.items?.size?.let { IntArray(it) }
|
||||
// if (result != null) {
|
||||
// for (i in result.indices) {
|
||||
// result[i] = i
|
||||
// }
|
||||
// }
|
||||
// return result
|
||||
}
|
||||
|
||||
override fun removeStack(slot: Int, amount: Int): ItemStack {
|
||||
tmBlockEntity.markDirty()
|
||||
return Inventories.splitStack(items, slot, amount)
|
||||
}
|
||||
|
||||
override fun removeStack(slot: Int): ItemStack {
|
||||
val slotStack = items?.get(slot)
|
||||
items?.set(slot, ItemStack.EMPTY)
|
||||
tmBlockEntity.markDirty()
|
||||
return slotStack ?: ItemStack.EMPTY
|
||||
}
|
||||
|
||||
override fun setStack(slot: Int, stack: ItemStack?) {
|
||||
items?.set(slot, stack)
|
||||
tmBlockEntity.markDirty()
|
||||
}
|
||||
|
||||
override fun markDirty() {
|
||||
if (tmBlockEntity.world != null)
|
||||
tmBlockEntity.markDirty()
|
||||
}
|
||||
|
||||
override fun canPlayerUse(player: PlayerEntity?): Boolean {
|
||||
return Inventory.canPlayerUse(this.tmBlockEntity, player)
|
||||
}
|
||||
|
||||
/*override fun getAvailableSlots(side: Direction?): IntArray {
|
||||
return IntArray(3)
|
||||
}*/
|
||||
|
||||
override fun canInsert(slot: Int, stack: ItemStack?, dir: Direction?): Boolean {
|
||||
if (this.entityState.get(TMBlock.ON)) {
|
||||
// print("TMM is in use so canInsert is disabled")
|
||||
return false
|
||||
}
|
||||
|
||||
if (stack != null && slot < this.INPUT_SLOTS.size) {
|
||||
val tm = TechnicalMachines.getTechnicalMachineFromStack(tmBlockEntity.tmmInventory.filterTM)
|
||||
// if material is needed then load it
|
||||
if (tmBlockEntity.materialNeeded(tm, slot, stack) && (ItemStack.areEqual(items?.get(slot) ?: ItemStack.EMPTY, ItemStack.EMPTY) || ItemStack.areItemsEqual(items?.get(slot) ?: ItemStack.EMPTY, stack))) {
|
||||
//tmBlockEntity.loadMaterial(stack)
|
||||
return true
|
||||
}
|
||||
else
|
||||
return false
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
override fun canExtract(slot: Int, stack: ItemStack?, dir: Direction?): Boolean {
|
||||
if (this.entityState.get(TMBlock.ON)) {
|
||||
//print("TMM is in use so canExtract is disabled")
|
||||
return false
|
||||
}
|
||||
|
||||
return dir == Direction.DOWN && slot == this.OUTPUT_SLOT_INDEX
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -62,6 +62,7 @@ object CobblemonBakingOverrides {
|
||||
cobblemonModel("restoration_tank_connector", "none")
|
||||
)
|
||||
|
||||
|
||||
fun registerOverride(modelLocation: Identifier, modelIdentifier: ModelIdentifier): BakingOverride {
|
||||
val result = BakingOverride(modelLocation, modelIdentifier)
|
||||
models.add(result)
|
||||
|
||||
@@ -18,9 +18,12 @@ import com.cobblemon.mod.common.CobblemonEntities
|
||||
import com.cobblemon.mod.common.CobblemonItems
|
||||
import com.cobblemon.mod.common.api.scheduling.ClientTaskTracker
|
||||
import com.cobblemon.mod.common.api.text.gray
|
||||
import com.cobblemon.mod.common.api.types.ElementalTypes
|
||||
import com.cobblemon.mod.common.client.battle.ClientBattle
|
||||
import com.cobblemon.mod.common.client.gui.PartyOverlay
|
||||
import com.cobblemon.mod.common.client.gui.battle.BattleOverlay
|
||||
import com.cobblemon.mod.common.client.gui.modstation.ModStationHandledScreen
|
||||
import com.cobblemon.mod.common.client.gui.tm.TMMHandledScreen
|
||||
import com.cobblemon.mod.common.client.particle.BedrockParticleEffectRepository
|
||||
import com.cobblemon.mod.common.client.render.block.BerryBlockRenderer
|
||||
import com.cobblemon.mod.common.client.render.block.FossilAnalyzerRenderer
|
||||
@@ -28,6 +31,7 @@ import com.cobblemon.mod.common.client.render.block.RestorationTankRenderer
|
||||
import com.cobblemon.mod.common.client.render.block.GildedChestBlockRenderer
|
||||
import com.cobblemon.mod.common.client.render.block.HealingMachineRenderer
|
||||
import com.cobblemon.mod.common.client.render.block.*
|
||||
import com.cobblemon.mod.common.client.render.block.TMBlockRenderer
|
||||
import com.cobblemon.mod.common.client.render.boat.CobblemonBoatRenderer
|
||||
import com.cobblemon.mod.common.client.render.generic.GenericBedrockRenderer
|
||||
import com.cobblemon.mod.common.client.render.item.CobblemonBuiltinItemRendererRegistry
|
||||
@@ -46,14 +50,19 @@ import com.cobblemon.mod.common.client.storage.ClientStorageManager
|
||||
import com.cobblemon.mod.common.client.trade.ClientTrade
|
||||
import com.cobblemon.mod.common.data.CobblemonDataProvider
|
||||
import com.cobblemon.mod.common.entity.boat.CobblemonBoatType
|
||||
import com.cobblemon.mod.common.gui.CobblemonScreenHandlers
|
||||
import com.cobblemon.mod.common.item.PokeBallItem
|
||||
import com.cobblemon.mod.common.item.TechnicalMachineItem
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.FossilModelRepository
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.GenericBedrockEntityModelRepository
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.MiscModelRepository
|
||||
import com.cobblemon.mod.common.platform.events.PlatformEvents
|
||||
import com.cobblemon.mod.common.util.DataKeys
|
||||
import com.cobblemon.mod.common.util.asTranslated
|
||||
import net.minecraft.client.color.block.BlockColorProvider
|
||||
import net.minecraft.client.color.item.ItemColorProvider
|
||||
import net.minecraft.client.gui.DrawContext
|
||||
import net.minecraft.client.gui.screen.ingame.HandledScreens
|
||||
import net.minecraft.client.render.RenderLayer
|
||||
import net.minecraft.client.render.block.entity.HangingSignBlockEntityRenderer
|
||||
import net.minecraft.client.render.block.entity.SignBlockEntityRenderer
|
||||
@@ -107,9 +116,10 @@ object CobblemonClient {
|
||||
|
||||
this.registerBlockEntityRenderers()
|
||||
registerBlockRenderTypes()
|
||||
//registerColors()
|
||||
registerColors()
|
||||
registerFlywheelRenderers()
|
||||
this.registerEntityRenderers()
|
||||
registerHandledScreens()
|
||||
Berries.observable.subscribe {
|
||||
BerryModelRepository.patchModels()
|
||||
}
|
||||
@@ -149,21 +159,24 @@ object CobblemonClient {
|
||||
// .apply()
|
||||
}
|
||||
|
||||
/*
|
||||
fun registerColors() {
|
||||
this.implementation.registerBlockColors(BlockColorProvider { _, _, _, _ ->
|
||||
return@BlockColorProvider 0xE0A33A
|
||||
}, CobblemonBlocks.APRICORN_LEAVES)
|
||||
this.implementation.registerItemColors(ItemColorProvider { _, _ ->
|
||||
|
||||
this.implementation.registerItemColors(ItemColorProvider { stack, tint ->
|
||||
return@ItemColorProvider 0xE0A33A
|
||||
}, CobblemonItems.APRICORN_LEAVES)
|
||||
}, CobblemonItems.TECHNICAL_MACHINE)
|
||||
|
||||
this.implementation.registerItemColors(TechnicalMachineItem::getItemColor, CobblemonItems.TECHNICAL_MACHINE)
|
||||
}
|
||||
*/
|
||||
|
||||
private fun registerBlockRenderTypes() {
|
||||
|
||||
this.implementation.registerBlockRenderType(RenderLayer.getCutoutMipped(), CobblemonBlocks.APRICORN_LEAVES)
|
||||
|
||||
this.implementation.registerBlockRenderType(RenderLayer.getTranslucent(), CobblemonBlocks.TM_MACHINE)
|
||||
|
||||
this.implementation.registerBlockRenderType(
|
||||
RenderLayer.getCutout(),
|
||||
CobblemonBlocks.GILDED_CHEST,
|
||||
@@ -251,6 +264,7 @@ object CobblemonClient {
|
||||
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.HANGING_SIGN, ::HangingSignBlockEntityRenderer)
|
||||
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.FOSSIL_ANALYZER, ::FossilAnalyzerRenderer)
|
||||
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.RESTORATION_TANK, ::RestorationTankRenderer)
|
||||
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.TM_BLOCK, ::TMBlockRenderer)
|
||||
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.GILDED_CHEST, ::GildedChestBlockRenderer)
|
||||
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.DISPLAY_CASE, ::DisplayCaseRenderer)
|
||||
}
|
||||
@@ -306,4 +320,15 @@ object CobblemonClient {
|
||||
}
|
||||
}
|
||||
|
||||
private fun registerHandledScreens() {
|
||||
HandledScreens.register(
|
||||
CobblemonScreenHandlers.TMM_SCREEN,
|
||||
::TMMHandledScreen
|
||||
)
|
||||
HandledScreens.register(
|
||||
CobblemonScreenHandlers.MOD_STATION_SCREEN,
|
||||
::ModStationHandledScreen
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.gui
|
||||
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.api.types.ElementalType
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.client.gui.DrawContext
|
||||
import net.minecraft.client.util.math.MatrixStack
|
||||
|
||||
class TypeReturnIcon(
|
||||
val x: Number,
|
||||
val y: Number,
|
||||
val centeredX: Boolean = false,
|
||||
val small: Boolean = false,
|
||||
val secondaryOffset: Float = 15F,
|
||||
val doubleCenteredOffset: Float = 7.5F,
|
||||
val opacity: Float = 1F
|
||||
) {
|
||||
companion object {
|
||||
private const val TYPE_ICON_DIAMETER = 36
|
||||
private const val SCALE = 0.5F
|
||||
|
||||
private val typeReturnResource = cobblemonResource("textures/gui/type_return.png")
|
||||
private val smallTypeReturnResource = cobblemonResource("textures/gui/type_return_small.png")
|
||||
}
|
||||
|
||||
fun render(context: DrawContext) {
|
||||
val diameter = if (small) (TYPE_ICON_DIAMETER / 2) else TYPE_ICON_DIAMETER
|
||||
|
||||
blitk(
|
||||
matrixStack = context.matrices,
|
||||
texture = if (small) smallTypeReturnResource else typeReturnResource,
|
||||
x = (x.toFloat()) / SCALE - 9,
|
||||
y = y.toFloat() / SCALE,
|
||||
height = diameter,
|
||||
width = diameter,
|
||||
alpha = opacity,
|
||||
scale = SCALE
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.cobblemon.mod.common.client.gui.modstation
|
||||
|
||||
import com.cobblemon.mod.common.gui.ModStationScreenHandler
|
||||
import net.minecraft.client.gui.DrawContext
|
||||
import net.minecraft.client.gui.screen.ingame.HandledScreen
|
||||
import net.minecraft.entity.player.PlayerInventory
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.screen.ScreenHandler
|
||||
import net.minecraft.screen.ScreenHandlerListener
|
||||
import net.minecraft.text.Text
|
||||
|
||||
class ModStationHandledScreen(
|
||||
val handler: ModStationScreenHandler,
|
||||
val inventory: PlayerInventory,
|
||||
title: Text?
|
||||
) : HandledScreen<ModStationScreenHandler>(handler, inventory, title), ScreenHandlerListener {
|
||||
override fun drawBackground(context: DrawContext?, delta: Float, mouseX: Int, mouseY: Int) {
|
||||
|
||||
}
|
||||
|
||||
override fun onSlotUpdate(handler: ScreenHandler?, slotId: Int, stack: ItemStack?) {
|
||||
|
||||
}
|
||||
|
||||
override fun onPropertyUpdate(handler: ScreenHandler?, property: Int, value: Int) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.cobblemon.mod.common.client.gui.tm
|
||||
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.client.gui.DrawContext
|
||||
import net.minecraft.client.gui.widget.ButtonWidget
|
||||
import net.minecraft.client.sound.SoundManager
|
||||
import net.minecraft.text.Text
|
||||
|
||||
class DiscButton(
|
||||
pX: Int, pY: Int,
|
||||
onPress: PressAction,
|
||||
): ButtonWidget(pX, pY, WIDTH.toInt(), HEIGHT.toInt(), Text.literal("All Types"), onPress, DEFAULT_NARRATION_SUPPLIER) {
|
||||
|
||||
companion object {
|
||||
private const val WIDTH = 53F
|
||||
private const val HEIGHT = 53F
|
||||
val DISC_BUTTON = cobblemonResource("textures/gui/tm/disc_button.png")
|
||||
}
|
||||
|
||||
override fun renderButton(context: DrawContext, pMouseX: Int, pMouseY: Int, pPartialTicks: Float) {
|
||||
blitk(
|
||||
matrixStack = context.matrices,
|
||||
texture = DISC_BUTTON,
|
||||
x = x,
|
||||
y = y,
|
||||
width = WIDTH,
|
||||
height = HEIGHT,
|
||||
vOffset = if (isHovered(pMouseX.toDouble(), pMouseY.toDouble())) HEIGHT else 0,
|
||||
textureHeight = HEIGHT * 2
|
||||
)
|
||||
}
|
||||
|
||||
override fun playDownSound(soundManager: SoundManager) {}
|
||||
fun isHovered(mouseX: Double, mouseY: Double) = mouseX.toFloat() in (x.toFloat()..(x.toFloat() + WIDTH)) && mouseY.toFloat() in (y.toFloat()..(y.toFloat() + HEIGHT))
|
||||
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package com.cobblemon.mod.common.client.gui.tm
|
||||
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.client.gui.DrawContext
|
||||
import net.minecraft.client.gui.widget.ButtonWidget
|
||||
import net.minecraft.client.sound.SoundManager
|
||||
import net.minecraft.text.Text
|
||||
|
||||
class EjectButton(
|
||||
pX: Int, pY: Int,
|
||||
val small: Boolean = false,
|
||||
onPress: PressAction
|
||||
): ButtonWidget(
|
||||
pX,
|
||||
pY,
|
||||
if (small) SMALL_WIDTH.toInt() else LARGE_WIDTH.toInt(),
|
||||
if (small) SMALL_HEIGHT.toInt() else LARGE_HEIGHT.toInt(),
|
||||
Text.literal("Eject"),
|
||||
onPress,
|
||||
DEFAULT_NARRATION_SUPPLIER
|
||||
) {
|
||||
|
||||
companion object {
|
||||
private const val LARGE_WIDTH = 54F
|
||||
private const val LARGE_HEIGHT = 14F
|
||||
private const val SMALL_WIDTH = 14F
|
||||
private const val SMALL_HEIGHT = 14F
|
||||
val SMALL_BUTTON = cobblemonResource("textures/gui/tm/eject_button_small.png")
|
||||
val LARGE_BUTTON = cobblemonResource("textures/gui/tm/eject_button_large.png")
|
||||
}
|
||||
|
||||
val height = if (small) SMALL_HEIGHT else LARGE_HEIGHT
|
||||
val width = if (small) SMALL_WIDTH else LARGE_WIDTH
|
||||
val texture = if (small) SMALL_BUTTON else LARGE_BUTTON
|
||||
|
||||
override fun renderButton(context: DrawContext, pMouseX: Int, pMouseY: Int, pPartialTicks: Float) {
|
||||
blitk(
|
||||
matrixStack = context.matrices,
|
||||
texture = texture,
|
||||
x = x,
|
||||
y = y,
|
||||
width = width,
|
||||
height = height,
|
||||
vOffset = if (isHovered(pMouseX.toDouble(), pMouseY.toDouble())) height else 0,
|
||||
textureHeight = height * 2
|
||||
)
|
||||
}
|
||||
|
||||
override fun playDownSound(soundManager: SoundManager) {}
|
||||
fun isHovered(mouseX: Double, mouseY: Double) = mouseX.toFloat() in (x.toFloat()..(x.toFloat() + width)) && mouseY.toFloat() in (y.toFloat()..(y.toFloat() + height))
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package com.cobblemon.mod.common.client.gui.tm
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonItems
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.api.tms.TechnicalMachine
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.client.render.renderScaledGuiItemIcon
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.client.gui.DrawContext
|
||||
import net.minecraft.client.gui.widget.ButtonWidget
|
||||
import net.minecraft.client.sound.SoundManager
|
||||
import net.minecraft.text.Text
|
||||
|
||||
class TMListingButton(
|
||||
pX: Int, pY: Int,
|
||||
onPress: PressAction,
|
||||
val tm: TechnicalMachine
|
||||
): ButtonWidget(pX, pY, WIDTH.toInt(), HEIGHT.toInt(), Text.literal("All Types"), onPress, DEFAULT_NARRATION_SUPPLIER) {
|
||||
|
||||
companion object {
|
||||
private const val HEIGHT = 20F
|
||||
private const val WIDTH = 140F
|
||||
val TM_LISTING_BUTTON = cobblemonResource("textures/gui/tm/tm_selection_listing.png")
|
||||
}
|
||||
|
||||
override fun renderButton(context: DrawContext, pMouseX: Int, pMouseY: Int, pPartialTicks: Float) {
|
||||
blitk(
|
||||
matrixStack = context.matrices,
|
||||
texture = TM_LISTING_BUTTON,
|
||||
x = x,
|
||||
y = y,
|
||||
width = WIDTH,
|
||||
height = HEIGHT,
|
||||
vOffset = if (isHovered(pMouseX.toDouble(), pMouseY.toDouble())) HEIGHT else 0,
|
||||
textureHeight = HEIGHT * 2
|
||||
)
|
||||
|
||||
val item = CobblemonItems.TECHNICAL_MACHINE
|
||||
|
||||
renderScaledGuiItemIcon(
|
||||
itemStack = item.setNbt(item.defaultStack, tm.id().toString()),
|
||||
x = x.toDouble() + 2,
|
||||
y = y.toDouble() + 2
|
||||
)
|
||||
|
||||
drawScaledText(
|
||||
context = context,
|
||||
text = tm.translatedMoveName(),
|
||||
x = x + 25,
|
||||
y = y + 7.5,
|
||||
scale = 0.75f
|
||||
)
|
||||
}
|
||||
|
||||
override fun playDownSound(soundManager: SoundManager) {}
|
||||
fun isHovered(mouseX: Double, mouseY: Double) = mouseX.toFloat() in (x.toFloat()..(x.toFloat() + WIDTH)) && mouseY.toFloat() in (y.toFloat()..(y.toFloat() + HEIGHT))
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,611 @@
|
||||
package com.cobblemon.mod.common.client.gui.tm
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonItems
|
||||
import com.cobblemon.mod.common.CobblemonNetwork.sendPacketToServer
|
||||
import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.api.gui.ColourLibrary
|
||||
import com.cobblemon.mod.common.api.gui.MultiLineLabelK
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.api.moves.Moves
|
||||
import com.cobblemon.mod.common.api.reactive.SettableObservable
|
||||
import com.cobblemon.mod.common.api.text.bold
|
||||
import com.cobblemon.mod.common.api.tms.TechnicalMachine
|
||||
import com.cobblemon.mod.common.api.tms.TechnicalMachineRecipe
|
||||
import com.cobblemon.mod.common.api.types.ElementalType
|
||||
import com.cobblemon.mod.common.api.types.ElementalTypes
|
||||
import com.cobblemon.mod.common.block.TMBlock
|
||||
import com.cobblemon.mod.common.block.entity.TMBlockEntity
|
||||
import com.cobblemon.mod.common.client.CobblemonClient
|
||||
import com.cobblemon.mod.common.client.gui.ExitButton
|
||||
import com.cobblemon.mod.common.client.gui.MoveCategoryIcon
|
||||
import com.cobblemon.mod.common.client.gui.TypeIcon
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.client.render.renderScaledGuiItemIcon
|
||||
import com.cobblemon.mod.common.gui.TMMScreenHandler
|
||||
import com.cobblemon.mod.common.net.messages.client.ui.CraftBlankTMPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.ui.CraftTMPacket
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.pokemon.activestate.PokemonState
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
import net.minecraft.client.gui.DrawContext
|
||||
import net.minecraft.client.gui.Drawable
|
||||
import net.minecraft.client.gui.Element
|
||||
import net.minecraft.client.gui.Selectable
|
||||
import net.minecraft.client.gui.screen.ingame.HandledScreen
|
||||
import net.minecraft.entity.player.PlayerInventory
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.item.Items
|
||||
import net.minecraft.registry.Registries
|
||||
import net.minecraft.screen.ScreenHandler
|
||||
import net.minecraft.screen.ScreenHandlerListener
|
||||
import net.minecraft.text.Text
|
||||
import net.minecraft.util.Identifier
|
||||
|
||||
class TMMHandledScreen(
|
||||
val handler: TMMScreenHandler,
|
||||
val inventory: PlayerInventory,
|
||||
title: Text?
|
||||
) : HandledScreen<TMMScreenHandler>(handler, inventory, title), ScreenHandlerListener {
|
||||
|
||||
companion object {
|
||||
val TEXTURE_HEIGHT = 222
|
||||
val TEXTURE_WIDTH = 254
|
||||
|
||||
val TYPE_MENU_MODE = 1
|
||||
val TM_BROWSING_MODE = 2
|
||||
|
||||
val TYPE_SELECTION_BASE = cobblemonResource("textures/gui/tm/type_selection_base.png")
|
||||
val TM_SELECTION_BASE = cobblemonResource("textures/gui/tm/tm_selection_base.png")
|
||||
val TM_SELECTION_BORDER = cobblemonResource("textures/gui/tm/tm_selection_border.png")
|
||||
val TM_SELECTION_LISTING = cobblemonResource("textures/gui/tm/tm_selection_listing.png")
|
||||
val EJECT_BUTTON_SMALL = cobblemonResource("textures/gui/tm/eject_button_small.png")
|
||||
val EJECT_BUTTON_LARGE = cobblemonResource("textures/gui/tm/eject_button_large.png")
|
||||
val PARTY_SLOT = cobblemonResource("textures/gui/tm/party_slot.png")
|
||||
val TEACH_BUTTON = cobblemonResource("textures/gui/tm/teach_button.png")
|
||||
}
|
||||
|
||||
// val selectedTM: TechnicalMachine? = TechnicalMachines.tmMap[cobblemonResource("thunderbolt")]!!
|
||||
var selectedTM: TechnicalMachine? = null
|
||||
var tmList: SettableObservable<MutableList<TechnicalMachine>> = SettableObservable(mutableListOf())
|
||||
var output: ItemStack? = null
|
||||
val children: MutableMap<String, Element> = mutableMapOf()
|
||||
var mode: Int = TYPE_MENU_MODE
|
||||
var sortType: ElementalType? = null
|
||||
var selectedPokemon: Pokemon? = null
|
||||
var scroll: TMScrollingList? = null
|
||||
|
||||
init {
|
||||
scroll = TMScrollingList(
|
||||
x = x + 132,
|
||||
y = y + 45,
|
||||
parent = this
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
// val selectedTM = TechnicalMachine("stompingtantrum", null, emptyList(), "ground", null, null)
|
||||
|
||||
/**
|
||||
* Used instead of `addDrawableChild()` to avoid re-drawing children.
|
||||
*/
|
||||
private fun <T> addChild(drawableElement: T, identifier: String) where T : Element, T : Drawable, T : Selectable {
|
||||
if (children.contains(identifier)) return
|
||||
addDrawableChild(drawableElement)
|
||||
children[identifier] = drawableElement
|
||||
}
|
||||
|
||||
override fun mouseClicked(mouseX: Double, mouseY: Double, button: Int): Boolean {
|
||||
if (scroll?.isHovered(mouseX, mouseY) == true) {
|
||||
scroll!!.mouseClicked(mouseX, mouseY, button)
|
||||
}
|
||||
return super.mouseClicked(mouseX, mouseY, button)
|
||||
}
|
||||
|
||||
override fun mouseScrolled(mouseX: Double, mouseY: Double, amount: Double): Boolean {
|
||||
if (scroll?.isHovered(mouseX, mouseY) == true) {
|
||||
scroll!!.mouseScrolled(mouseX, mouseY, amount)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
override fun mouseDragged(mouseX: Double, mouseY: Double, button: Int, deltaX: Double, deltaY: Double): Boolean {
|
||||
if (mode != TYPE_MENU_MODE) scroll?.mouseDragged(
|
||||
mouseX,
|
||||
mouseY,
|
||||
button,
|
||||
deltaX,
|
||||
deltaY
|
||||
)
|
||||
return super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY)
|
||||
}
|
||||
|
||||
fun drawBlankCraftingRecipe(context: DrawContext) {
|
||||
val x = (width - TEXTURE_WIDTH) / 2
|
||||
val y = (height - TEXTURE_HEIGHT) / 2
|
||||
// ingredient
|
||||
renderScaledGuiItemIcon(
|
||||
itemStack = Items.AMETHYST_SHARD.defaultStack,
|
||||
x = (x + 197 + 36).toDouble(),
|
||||
y = (y + 127).toDouble(),
|
||||
zTranslation = 1f
|
||||
)
|
||||
|
||||
drawScaledText(
|
||||
context = context,
|
||||
text = lang("ui.tms.material_cost"),
|
||||
x = (x + 223),
|
||||
y = (y + 117.5),
|
||||
scale = 0.5f,
|
||||
centered = true
|
||||
)
|
||||
|
||||
drawScaledText(
|
||||
context = context,
|
||||
text = Text.translatable(CobblemonItems.BLANK_TM.translationKey).bold(),
|
||||
x = (x + 223),
|
||||
y = (y + 12),
|
||||
scale = 0.5f,
|
||||
centered = true
|
||||
)
|
||||
|
||||
drawScaledText(
|
||||
context = context,
|
||||
text = lang("ui.power"),
|
||||
x = (x + 199),
|
||||
y = (y + 25),
|
||||
scale = 0.5f
|
||||
)
|
||||
|
||||
drawScaledText(
|
||||
context = context,
|
||||
text = Text.literal("-"),
|
||||
x = (x + 241),
|
||||
y = (y + 25),
|
||||
scale = 0.5f,
|
||||
centered = true
|
||||
)
|
||||
|
||||
drawScaledText(
|
||||
context = context,
|
||||
text = lang("ui.accuracy_short"),
|
||||
x = (x + 199),
|
||||
y = (y + 35),
|
||||
scale = 0.5f
|
||||
)
|
||||
|
||||
drawScaledText(
|
||||
context = context,
|
||||
text = Text.literal("-"),
|
||||
x = (x + 241),
|
||||
y = (y + 35),
|
||||
scale = 0.5f,
|
||||
centered = true
|
||||
)
|
||||
|
||||
drawScaledText(
|
||||
context = context,
|
||||
text = lang("ui.pp"),
|
||||
x = (x + 199),
|
||||
y = (y + 45),
|
||||
scale = 0.5f
|
||||
)
|
||||
|
||||
drawScaledText(
|
||||
context = context,
|
||||
text = Text.literal("-"),
|
||||
x = (x + 241),
|
||||
y = (y + 45),
|
||||
scale = 0.5f,
|
||||
centered = true
|
||||
)
|
||||
|
||||
drawScaledText(
|
||||
context = context,
|
||||
text = lang("ui.summary.title"),
|
||||
x = (x + 199),
|
||||
y = (y + 54.5),
|
||||
scale = 0.5f
|
||||
)
|
||||
|
||||
val scale = 0.5f
|
||||
|
||||
context.matrices.push()
|
||||
context.matrices.scale(scale, scale, 1f)
|
||||
MultiLineLabelK.create(
|
||||
component = lang("ui.tms.blank_tm_desc"),
|
||||
width = 49 / scale,
|
||||
maxLines = 7
|
||||
).renderLeftAligned(
|
||||
context = context,
|
||||
x = (x + 199) / scale,
|
||||
y = (y + 62) / scale,
|
||||
ySpacing = 5.5 / scale,
|
||||
colour = ColourLibrary.WHITE,
|
||||
shadow = true
|
||||
)
|
||||
context.matrices.pop()
|
||||
}
|
||||
|
||||
fun drawMoveInfo(context: DrawContext, delta: Float, mouseX: Int, mouseY: Int) {
|
||||
val currentTm = selectedTM
|
||||
if (currentTm == null) {
|
||||
return drawBlankCraftingRecipe(context)
|
||||
}
|
||||
|
||||
val x = (width - TEXTURE_WIDTH) / 2
|
||||
val y = (height - TEXTURE_HEIGHT) / 2
|
||||
val move = Moves.getByNameOrDummy(currentTm.moveName)
|
||||
// blank tm
|
||||
renderScaledGuiItemIcon(
|
||||
itemStack = CobblemonItems.BLANK_TM.defaultStack,
|
||||
x = (x + 197).toDouble(),
|
||||
y = (y + 127).toDouble(),
|
||||
)
|
||||
|
||||
val typeGem = Registries.ITEM.get(ElementalTypes.get(currentTm.type)?.typeGem).defaultStack
|
||||
// type gem
|
||||
renderScaledGuiItemIcon(
|
||||
itemStack = typeGem ?: ItemStack.EMPTY,
|
||||
x = (x + 197 + 18).toDouble(),
|
||||
y = (y + 127).toDouble(),
|
||||
)
|
||||
|
||||
val recipe = currentTm.recipe ?: TechnicalMachineRecipe(Identifier.of("minecraft", "air")!!, 1)
|
||||
// ingredient
|
||||
renderScaledGuiItemIcon(
|
||||
itemStack = Registries.ITEM.get(recipe.item).defaultStack,
|
||||
x = (x + 197 + 36).toDouble(),
|
||||
y = (y + 127).toDouble(),
|
||||
zTranslation = 1f
|
||||
)
|
||||
|
||||
context.matrices.push()
|
||||
context.matrices.translate(0f, 0f, 2f)
|
||||
|
||||
if (recipe.count > 1) {
|
||||
val xIncrease = if (recipe.count < 10) 47 else 41
|
||||
drawScaledText(
|
||||
context = context,
|
||||
text = Text.literal(recipe.count.toString()),
|
||||
x = (x + 197 + xIncrease).toDouble(),
|
||||
y = (y + 136).toDouble(),
|
||||
shadow = true
|
||||
)
|
||||
}
|
||||
|
||||
context.matrices.pop()
|
||||
|
||||
drawScaledText(
|
||||
context = context,
|
||||
text = lang("ui.tms.material_cost"),
|
||||
x = (x + 223),
|
||||
y = (y + 117.5),
|
||||
scale = 0.5f,
|
||||
centered = true
|
||||
)
|
||||
|
||||
drawScaledText(
|
||||
context = context,
|
||||
text = currentTm.translatedMoveName().bold(),
|
||||
x = (x + 223),
|
||||
y = (y + 12),
|
||||
scale = 0.5f,
|
||||
centered = true
|
||||
)
|
||||
|
||||
MoveCategoryIcon(
|
||||
x = (x + 237.5),
|
||||
y = (y + 52.5),
|
||||
category = Moves.getByNameOrDummy(currentTm.moveName).damageCategory
|
||||
).render(context)
|
||||
|
||||
drawScaledText(
|
||||
context = context,
|
||||
text = lang("ui.power"),
|
||||
x = (x + 199),
|
||||
y = (y + 25),
|
||||
scale = 0.5f
|
||||
)
|
||||
|
||||
drawScaledText(
|
||||
context = context,
|
||||
text = Text.literal(move.power.toInt().toString()),
|
||||
x = (x + 241),
|
||||
y = (y + 25),
|
||||
scale = 0.5f,
|
||||
centered = true
|
||||
)
|
||||
|
||||
drawScaledText(
|
||||
context = context,
|
||||
text = lang("ui.accuracy_short"),
|
||||
x = (x + 199),
|
||||
y = (y + 35),
|
||||
scale = 0.5f
|
||||
)
|
||||
|
||||
drawScaledText(
|
||||
context = context,
|
||||
text = Text.literal(move.accuracy.toInt().toString() + "%"),
|
||||
x = (x + 241),
|
||||
y = (y + 35),
|
||||
scale = 0.5f,
|
||||
centered = true
|
||||
)
|
||||
|
||||
drawScaledText(
|
||||
context = context,
|
||||
text = lang("ui.pp"),
|
||||
x = (x + 199),
|
||||
y = (y + 45),
|
||||
scale = 0.5f
|
||||
)
|
||||
|
||||
drawScaledText(
|
||||
context = context,
|
||||
text = Text.literal(move.pp.toString()),
|
||||
x = (x + 241),
|
||||
y = (y + 45),
|
||||
scale = 0.5f,
|
||||
centered = true
|
||||
)
|
||||
|
||||
drawScaledText(
|
||||
context = context,
|
||||
text = lang("ui.summary.title"),
|
||||
x = (x + 199),
|
||||
y = (y + 54.5),
|
||||
scale = 0.5f
|
||||
)
|
||||
|
||||
val scale = 0.5f
|
||||
|
||||
context.matrices.push()
|
||||
context.matrices.scale(scale, scale, 1f)
|
||||
MultiLineLabelK.create(
|
||||
component = lang("move.${currentTm.moveName}.desc"),
|
||||
width = 49 / scale,
|
||||
maxLines = 7
|
||||
).renderLeftAligned(
|
||||
context = context,
|
||||
x = (x + 199) / scale,
|
||||
y = (y + 62) / scale,
|
||||
ySpacing = 5.5 / scale,
|
||||
colour = ColourLibrary.WHITE,
|
||||
shadow = true
|
||||
)
|
||||
context.matrices.pop()
|
||||
}
|
||||
|
||||
fun drawTypeMenu(context: DrawContext, delta: Float, mouseX: Int, mouseY: Int) {
|
||||
val x = (width - TEXTURE_WIDTH) / 2
|
||||
val y = (height - TEXTURE_HEIGHT) / 2
|
||||
|
||||
blitk(
|
||||
matrixStack = context.matrices,
|
||||
texture = TYPE_SELECTION_BASE,
|
||||
x = x, // horizontal placement of GUI
|
||||
y = y, // vertical placement of GUI
|
||||
|
||||
width = TEXTURE_WIDTH, // scale of the GUI width
|
||||
height = TEXTURE_HEIGHT // scale of the GUI height
|
||||
)
|
||||
|
||||
fun drawTypeRow(drawX: Int, drawY: Int, types: List<ElementalType>) {
|
||||
var xOffset = 0
|
||||
for (type in types) {
|
||||
addChild(TypeButton(
|
||||
pX = drawX + 32 + xOffset,
|
||||
pY = drawY + 16,
|
||||
type = type,
|
||||
onPress = {
|
||||
inventory.player.playSound(CobblemonSounds.GUI_CLICK, 1f, 1f)
|
||||
tmList.set(TechnicalMachine.filterTms(null, type, null).toMutableList())
|
||||
sortType = type
|
||||
mode = TM_BROWSING_MODE
|
||||
clearGUI()
|
||||
scroll?.scrollAmount = 0.0
|
||||
}
|
||||
), "${type.name}type")
|
||||
xOffset += 24
|
||||
}
|
||||
}
|
||||
|
||||
drawTypeRow(x, y, listOf(
|
||||
ElementalTypes.NORMAL,
|
||||
ElementalTypes.FIRE,
|
||||
ElementalTypes.WATER,
|
||||
ElementalTypes.GRASS,
|
||||
ElementalTypes.ELECTRIC,
|
||||
ElementalTypes.ICE
|
||||
))
|
||||
|
||||
drawTypeRow(x + 12, y + 24, listOf(
|
||||
ElementalTypes.FIGHTING,
|
||||
ElementalTypes.POISON,
|
||||
ElementalTypes.GROUND,
|
||||
ElementalTypes.FLYING,
|
||||
))
|
||||
|
||||
drawTypeRow(x, y + 48, listOf(
|
||||
ElementalTypes.PSYCHIC,
|
||||
ElementalTypes.BUG,
|
||||
ElementalTypes.ROCK,
|
||||
ElementalTypes.GHOST,
|
||||
))
|
||||
|
||||
drawTypeRow(x + 12, y + 72, listOf(
|
||||
ElementalTypes.DRAGON,
|
||||
ElementalTypes.DARK,
|
||||
ElementalTypes.STEEL,
|
||||
ElementalTypes.FAIRY,
|
||||
))
|
||||
|
||||
addChild(
|
||||
DiscButton(
|
||||
pX = x + 134,
|
||||
pY = y + 50,
|
||||
onPress = {
|
||||
inventory.player.playSound(CobblemonSounds.GUI_CLICK, 1f, 1f)
|
||||
tmList.set(TechnicalMachine.filterTms(null, null, null).toMutableList())
|
||||
mode = TM_BROWSING_MODE
|
||||
sortType = null
|
||||
scroll?.scrollAmount = 0.0
|
||||
clearGUI()
|
||||
}
|
||||
), "disc"
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
fun drawTmSelectMenu(context: DrawContext, delta: Float, mouseX: Int, mouseY: Int) {
|
||||
val x = (width - TEXTURE_WIDTH) / 2
|
||||
val y = (height - TEXTURE_HEIGHT) / 2
|
||||
|
||||
blitk(
|
||||
matrixStack = context.matrices,
|
||||
texture = TM_SELECTION_BASE,
|
||||
x = x, // horizontal placement of GUI
|
||||
y = y, // vertical placement of GUI
|
||||
|
||||
width = TEXTURE_WIDTH, // scale of the GUI width
|
||||
height = TEXTURE_HEIGHT // scale of the GUI height
|
||||
)
|
||||
|
||||
blitk(
|
||||
matrixStack = context.matrices,
|
||||
texture = TM_SELECTION_BORDER,
|
||||
x = x + 31, // horizontal placement of GUI
|
||||
y = y + 14, // vertical placement of GUI
|
||||
width = 157,
|
||||
height = 101
|
||||
)
|
||||
|
||||
val displayType = sortType
|
||||
|
||||
addChild(
|
||||
TypeButton(
|
||||
pX = x + 31,
|
||||
pY = y + 16,
|
||||
type = displayType,
|
||||
onPress = {
|
||||
mode = TYPE_MENU_MODE
|
||||
inventory.player.playSound(CobblemonSounds.GUI_CLICK, 1f, 1f)
|
||||
clearGUI()
|
||||
}
|
||||
), "returnTypeMenu"
|
||||
)
|
||||
|
||||
scroll?.render(context, mouseX, mouseY, delta)
|
||||
}
|
||||
|
||||
fun clearGUI() {
|
||||
val iterator = children.iterator()
|
||||
while (iterator.hasNext()) {
|
||||
val (id, _) = iterator.next()
|
||||
iterator.remove()
|
||||
children.remove(id)
|
||||
}
|
||||
clearChildren()
|
||||
}
|
||||
|
||||
override fun drawBackground(context: DrawContext, delta: Float, mouseX: Int, mouseY: Int) {
|
||||
super.renderBackground(context)
|
||||
val x = (width - TEXTURE_WIDTH) / 2
|
||||
val y = (height - TEXTURE_HEIGHT) / 2
|
||||
|
||||
|
||||
blitk(
|
||||
matrixStack = context.matrices,
|
||||
texture = TYPE_SELECTION_BASE,
|
||||
x = x, // horizontal placement of GUI
|
||||
y = y, // vertical placement of GUI
|
||||
|
||||
width = TEXTURE_WIDTH, // scale of the GUI width
|
||||
height = TEXTURE_HEIGHT // scale of the GUI height
|
||||
)
|
||||
|
||||
when (mode) {
|
||||
TYPE_MENU_MODE -> drawTypeMenu(context, delta, mouseX, mouseY)
|
||||
else -> drawTmSelectMenu(context, delta, mouseX, mouseY)
|
||||
}
|
||||
drawMoveInfo(context, delta, mouseX, mouseY)
|
||||
inventory.markDirty()
|
||||
|
||||
addChild(
|
||||
EjectButton(
|
||||
pX = x + 196,
|
||||
pY = y + 168,
|
||||
small = false,
|
||||
onPress = {
|
||||
inventory.player.playSound(CobblemonSounds.GUI_CLICK, 1f, 1f)
|
||||
val currentTm = selectedTM ?: return@EjectButton sendPacketToServer(CraftBlankTMPacket(handler.input.getStack(2)))
|
||||
|
||||
sendPacketToServer(
|
||||
CraftTMPacket(
|
||||
currentTm,
|
||||
handler.input.getStack(0),
|
||||
handler.input.getStack(1),
|
||||
handler.input.getStack(2)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
this.handler.syncState()
|
||||
}
|
||||
), "eject"
|
||||
)
|
||||
|
||||
addChild(
|
||||
ExitButton(
|
||||
pX = x + 228,
|
||||
pY = y + 185,
|
||||
onPress = {
|
||||
this.close()
|
||||
}
|
||||
), "exit"
|
||||
)
|
||||
|
||||
val startY = y + 13
|
||||
val offset = 28
|
||||
var iterations = 0
|
||||
CobblemonClient.storage.myParty.forEach { pokemon ->
|
||||
if (pokemon != null) {
|
||||
addChild(TMPartySlotWidget(
|
||||
pX = x - 23,
|
||||
pY = startY + (offset * iterations),
|
||||
pokemon = pokemon,
|
||||
onPress = {
|
||||
selectedPokemon = if (selectedPokemon == pokemon) null else pokemon
|
||||
}
|
||||
), "partyslot_${pokemon.uuid}")
|
||||
}
|
||||
iterations++
|
||||
}
|
||||
}
|
||||
|
||||
override fun drawForeground(context: DrawContext?, mouseX: Int, mouseY: Int) {
|
||||
//Text is usually drawn here, we dont want that
|
||||
this.drawMouseoverTooltip(context, mouseX - 158, mouseY - 28)
|
||||
//this.renderWithTooltip(context, mouseX, mouseY, 1F)
|
||||
}
|
||||
|
||||
override fun onSlotUpdate(handler: ScreenHandler?, slotId: Int, stack: ItemStack?) {
|
||||
|
||||
}
|
||||
|
||||
override fun close() {
|
||||
super.close()
|
||||
val inventory = handler.inventory
|
||||
|
||||
if (inventory is TMBlockEntity.TMBlockInventory) {
|
||||
inventory.tmBlockEntity.blockState.with(TMBlock.ON,false)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPropertyUpdate(handler: ScreenHandler?, property: Int, value: Int) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.cobblemon.mod.common.client.gui.tm
|
||||
|
||||
import com.cobblemon.mod.common.gui.TMMScreenHandler
|
||||
import com.cobblemon.mod.common.util.giveOrDropItemStack
|
||||
import net.minecraft.entity.player.PlayerEntity
|
||||
import net.minecraft.inventory.Inventory
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.item.Items
|
||||
import net.minecraft.screen.slot.Slot
|
||||
|
||||
class TMMOutputSlot(val screen: TMMScreenHandler, index: Int, x: Int, y: Int) : Slot(screen.playerInventory, index, x, y) {
|
||||
|
||||
override fun canInsert(stack: ItemStack?) = false
|
||||
|
||||
override fun onTakeItem(player: PlayerEntity, stack: ItemStack) {
|
||||
player.giveOrDropItemStack(stack, false)
|
||||
this.stack = Items.AIR.defaultStack
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.gui.tm
|
||||
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.api.text.text
|
||||
import com.cobblemon.mod.common.client.gui.drawProfilePokemon
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.math.fromEulerXYZDegrees
|
||||
import net.minecraft.client.gui.DrawContext
|
||||
import net.minecraft.client.gui.widget.ButtonWidget
|
||||
import net.minecraft.text.Text
|
||||
import org.joml.Quaternionf
|
||||
import org.joml.Vector3f
|
||||
|
||||
class TMPartySlotWidget(
|
||||
pX: Number,
|
||||
pY: Number,
|
||||
val pokemon: Pokemon?,
|
||||
onPress: PressAction
|
||||
) : ButtonWidget(pX.toInt(), pY.toInt(), WIDTH, HEIGHT, Text.literal("PartyMember"), onPress, NarrationSupplier { "".text() }) {
|
||||
|
||||
companion object {
|
||||
const val WIDTH = 46
|
||||
const val HEIGHT = 27
|
||||
private const val PORTRAIT_DIAMETER = 25
|
||||
|
||||
private val slotResource = cobblemonResource("textures/gui/tm/party_slot.png")
|
||||
val genderIconMale = cobblemonResource("textures/gui/party/party_gender_male.png")
|
||||
val genderIconFemale = cobblemonResource("textures/gui/party/party_gender_female.png")
|
||||
}
|
||||
private fun getSlotVOffset(pokemon: Pokemon?, isHovered: Boolean, isSelected: Boolean): Int {
|
||||
if (isHovered || isSelected) {
|
||||
if (pokemon == null) {
|
||||
return 0
|
||||
}
|
||||
return height
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
override fun renderButton(context: DrawContext, mouseX: Int, mouseY: Int, delta: Float) {
|
||||
hovered = mouseX >= x && mouseY >= y && mouseX < x + width && mouseY < y + height;
|
||||
val matrices = context.matrices
|
||||
|
||||
blitk(
|
||||
matrixStack = matrices,
|
||||
texture = slotResource,
|
||||
x = x,
|
||||
y = y,
|
||||
width = width,
|
||||
height = height,
|
||||
vOffset = getSlotVOffset(pokemon, isHovered, isSelected),
|
||||
textureHeight = height * 2,
|
||||
)
|
||||
|
||||
if (pokemon != null) {
|
||||
val halfScale = 0.5F
|
||||
|
||||
// Render Pokémon
|
||||
matrices.push()
|
||||
matrices.translate(x + (PORTRAIT_DIAMETER / 2.0) + 10, y - 1.0, 0.0)
|
||||
matrices.scale(2.5F, 2.5F, 1F)
|
||||
drawProfilePokemon(
|
||||
species = pokemon.species.resourceIdentifier,
|
||||
aspects = pokemon.aspects.toSet(),
|
||||
matrixStack = matrices,
|
||||
rotation = Quaternionf().fromEulerXYZDegrees(Vector3f(13F, 35F, 0F)),
|
||||
state = null,
|
||||
scale = 4.5F,
|
||||
partialTicks = delta
|
||||
)
|
||||
matrices.pop()
|
||||
|
||||
// Draw Name
|
||||
drawScaledText(
|
||||
context = context,
|
||||
text = pokemon.getDisplayName(),
|
||||
x = x + 16,
|
||||
y = y + 21.5,
|
||||
scale = halfScale
|
||||
)
|
||||
|
||||
val ballIcon = cobblemonResource("textures/gui/ball/" + pokemon.caughtBall.name.path + ".png")
|
||||
val ballHeight = 22
|
||||
blitk(
|
||||
matrixStack = matrices,
|
||||
texture = ballIcon,
|
||||
x = (x - 2) / halfScale,
|
||||
y = (y - 3) / halfScale,
|
||||
height = ballHeight,
|
||||
width = 18,
|
||||
textureHeight = ballHeight * 2,
|
||||
scale = halfScale
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
package com.cobblemon.mod.common.client.gui.tm
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.api.tms.TechnicalMachine
|
||||
import net.minecraft.client.MinecraftClient
|
||||
import net.minecraft.client.gui.DrawContext
|
||||
import net.minecraft.client.gui.widget.AlwaysSelectedEntryListWidget
|
||||
import net.minecraft.text.Text
|
||||
|
||||
class TMScrollingList(
|
||||
val x: Int,
|
||||
val y: Int,
|
||||
val parent: TMMHandledScreen
|
||||
) : AlwaysSelectedEntryListWidget<TMScrollingList.TMScrollingListEntry> (
|
||||
MinecraftClient.getInstance(),
|
||||
WIDTH, // width
|
||||
HEIGHT, // height
|
||||
0, // top
|
||||
HEIGHT, // bottom
|
||||
SLOT_HEIGHT// + SLOT_SPACING
|
||||
) {
|
||||
|
||||
companion object {
|
||||
const val WIDTH = 140
|
||||
const val HEIGHT = 78
|
||||
const val SLOT_WIDTH = 140
|
||||
const val SLOT_HEIGHT = 20
|
||||
const val SLOT_SPACING = 3
|
||||
const val SCALE = 0.5f
|
||||
}
|
||||
|
||||
private var scrolling = false
|
||||
|
||||
override fun getRowWidth() = SLOT_WIDTH
|
||||
|
||||
init {
|
||||
correctSize()
|
||||
setRenderHorizontalShadows(false)
|
||||
setRenderBackground(false)
|
||||
setRenderSelection(false)
|
||||
|
||||
parent.tmList.subscribeIncludingCurrent { tmList ->
|
||||
val currentEntries = children()
|
||||
val newTMs = tmList.filter { tm -> currentEntries.none { it.tm.id() == tm.id() } }
|
||||
val removedTMs = currentEntries.filter { entry -> tmList.none { it.id() == entry.tm.id() } }
|
||||
|
||||
removedTMs.forEach(this::removeEntry)
|
||||
newTMs.forEach { tm -> addEntry(TMScrollingListEntry(tm, parent)) }
|
||||
}
|
||||
}
|
||||
|
||||
override fun getScrollbarPositionX() = left + width - 3
|
||||
|
||||
private fun correctSize() {
|
||||
updateSize(
|
||||
WIDTH,
|
||||
HEIGHT, y - 2, (y + 2) + (HEIGHT - 2))
|
||||
setLeftPos(x)
|
||||
}
|
||||
|
||||
public override fun addEntry(entry: TMScrollingListEntry) = super.addEntry(entry)
|
||||
public override fun removeEntry(entry: TMScrollingListEntry) = super.removeEntry(entry)
|
||||
|
||||
override fun render(context: DrawContext, mouseX: Int, mouseY: Int, delta: Float) {
|
||||
correctSize()
|
||||
|
||||
context.enableScissor(
|
||||
left,
|
||||
top + 5,
|
||||
left + width,
|
||||
top + 1 + height
|
||||
)
|
||||
|
||||
super.render(context, mouseX, mouseY, delta)
|
||||
context.disableScissor()
|
||||
}
|
||||
|
||||
fun isHovered(mouseX: Double, mouseY: Double): Boolean {
|
||||
println(mouseX.toFloat() in (x.toFloat()..(x.toFloat() + WIDTH)) && mouseY.toFloat() in (y.toFloat()..(y.toFloat() + HEIGHT)))
|
||||
return mouseX.toFloat() in (x.toFloat()..(x.toFloat() + WIDTH)) && mouseY.toFloat() in (y.toFloat()..(y.toFloat() + HEIGHT))
|
||||
}
|
||||
|
||||
override fun mouseClicked(mouseX: Double, mouseY: Double, button: Int): Boolean {
|
||||
updateScrollingState(mouseX, mouseY)
|
||||
if (scrolling) {
|
||||
focused = getEntryAtPosition(mouseX, mouseY)
|
||||
isDragging = true
|
||||
}
|
||||
return super.mouseClicked(mouseX, mouseY, button)
|
||||
}
|
||||
|
||||
override fun mouseDragged(mouseX: Double, mouseY: Double, button: Int, deltaX: Double, deltaY: Double): Boolean {
|
||||
if (scrolling) {
|
||||
if (mouseY < top) {
|
||||
scrollAmount = 0.0
|
||||
} else if (mouseY > bottom) {
|
||||
scrollAmount = maxScroll.toDouble()
|
||||
} else {
|
||||
scrollAmount += deltaY
|
||||
}
|
||||
}
|
||||
return super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY)
|
||||
}
|
||||
|
||||
private fun updateScrollingState(mouseX: Double, mouseY: Double) {
|
||||
scrolling = mouseX >= this.scrollbarPositionX.toDouble()
|
||||
&& mouseX < (this.scrollbarPositionX + 3).toDouble()
|
||||
&& mouseY >= top
|
||||
&& mouseY < bottom
|
||||
}
|
||||
|
||||
class TMScrollingListEntry(val tm: TechnicalMachine, private val parent: TMMHandledScreen) : Entry<TMScrollingListEntry>() {
|
||||
|
||||
private val tmButton: TMListingButton = TMListingButton(
|
||||
pX = 0,
|
||||
pY = 0,
|
||||
onPress = {
|
||||
parent.selectedTM = tm
|
||||
parent.inventory.player.playSound(CobblemonSounds.GUI_CLICK, 1f, 1f)
|
||||
},
|
||||
tm = tm
|
||||
)
|
||||
override fun render(
|
||||
context: DrawContext,
|
||||
index: Int,
|
||||
rowTop: Int,
|
||||
rowLeft: Int,
|
||||
rowWidth: Int,
|
||||
rowHeight: Int,
|
||||
mouseX: Int,
|
||||
mouseY: Int,
|
||||
isHovered: Boolean,
|
||||
tickDelta: Float
|
||||
) {
|
||||
val x = rowLeft
|
||||
val y = rowTop
|
||||
val matrixStack = context.matrices
|
||||
|
||||
// Render just this TMListingButton
|
||||
tmButton.setPosition(x + 1, y)
|
||||
tmButton.render(context, mouseX, mouseY, tickDelta)
|
||||
}
|
||||
|
||||
override fun mouseClicked(mouseX: Double, mouseY: Double, delta: Int): Boolean {
|
||||
if (tmButton.isHovered(mouseX, mouseY)) {
|
||||
tmButton.onPress()
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
override fun getNarration(): Text {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package com.cobblemon.mod.common.client.gui.tm
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.api.types.ElementalType
|
||||
import com.cobblemon.mod.common.client.gui.TypeIcon
|
||||
import com.cobblemon.mod.common.client.gui.TypeReturnIcon
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.client.gui.DrawContext
|
||||
import net.minecraft.client.gui.widget.ButtonWidget
|
||||
import net.minecraft.client.sound.SoundInstance
|
||||
import net.minecraft.client.sound.SoundManager
|
||||
|
||||
class TypeButton(
|
||||
pX: Int, pY: Int,
|
||||
onPress: PressAction,
|
||||
val type: ElementalType?
|
||||
): ButtonWidget(pX, pY, WIDTH.toInt(), HEIGHT.toInt(), type?.displayName, onPress, DEFAULT_NARRATION_SUPPLIER) {
|
||||
|
||||
companion object {
|
||||
private const val WIDTH = 24F
|
||||
private const val HEIGHT = 24F
|
||||
val TYPE_BUTTON = cobblemonResource("textures/gui/tm/type_button.png")
|
||||
}
|
||||
|
||||
override fun renderButton(context: DrawContext, pMouseX: Int, pMouseY: Int, pPartialTicks: Float) {
|
||||
blitk(
|
||||
matrixStack = context.matrices,
|
||||
texture = TYPE_BUTTON,
|
||||
x = x,
|
||||
y = y,
|
||||
width = WIDTH,
|
||||
height = HEIGHT,
|
||||
vOffset = if (isHovered(pMouseX.toDouble(), pMouseY.toDouble())) HEIGHT else 0,
|
||||
textureHeight = HEIGHT * 2
|
||||
)
|
||||
|
||||
context.matrices.push()
|
||||
context.matrices.scale(2f, 2f, 2f)
|
||||
|
||||
if (type != null) {
|
||||
TypeIcon(
|
||||
x = (x + 12.125) / 2,
|
||||
y = (y + 3) / 2,
|
||||
type = type,
|
||||
centeredX = true,
|
||||
small = true
|
||||
).render(context)
|
||||
}
|
||||
else {
|
||||
TypeReturnIcon(
|
||||
x = (x + 12.125) / 2,
|
||||
y = (y + 3) / 2,
|
||||
centeredX = true,
|
||||
small = true
|
||||
).render(context)
|
||||
}
|
||||
|
||||
|
||||
context.matrices.pop()
|
||||
}
|
||||
|
||||
override fun playDownSound(soundManager: SoundManager) {
|
||||
|
||||
}
|
||||
fun isHovered(mouseX: Double, mouseY: Double) = mouseX.toFloat() in (x.toFloat()..(x.toFloat() + WIDTH)) && mouseY.toFloat() in (y.toFloat()..(y.toFloat() + HEIGHT))
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.cobblemon.mod.common.client.net.gui
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonItems
|
||||
import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.api.net.ServerNetworkPacketHandler
|
||||
import com.cobblemon.mod.common.gui.TMMScreenHandler
|
||||
import com.cobblemon.mod.common.net.messages.client.ui.CraftBlankTMPacket
|
||||
import com.cobblemon.mod.common.util.playSoundServer
|
||||
import net.minecraft.item.Items
|
||||
import net.minecraft.server.MinecraftServer
|
||||
import net.minecraft.server.network.ServerPlayerEntity
|
||||
import net.minecraft.sound.SoundCategory
|
||||
|
||||
object CraftBlankTMPacketHandler : ServerNetworkPacketHandler<CraftBlankTMPacket> {
|
||||
override fun handle(packet: CraftBlankTMPacket, server: MinecraftServer, player: ServerPlayerEntity) {
|
||||
val screen = player.currentScreenHandler as TMMScreenHandler
|
||||
val ingredientSlot = screen.input.getStack(2)
|
||||
|
||||
if (ingredientSlot.isOf(Items.AMETHYST_SHARD) && ingredientSlot.count >= 1) {
|
||||
screen.input.removeStack(2, 1)
|
||||
screen.result.setStack(0, CobblemonItems.BLANK_TM.defaultStack)
|
||||
|
||||
screen.input.markDirty()
|
||||
screen.result.markDirty()
|
||||
player.currentScreenHandler.syncState()
|
||||
|
||||
player.world.playSoundServer(player.pos, CobblemonSounds.TMM_CRAFT_BLANK, SoundCategory.BLOCKS)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package com.cobblemon.mod.common.client.net.gui
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonItems
|
||||
import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.api.net.ServerNetworkPacketHandler
|
||||
import com.cobblemon.mod.common.api.types.ElementalTypes
|
||||
import com.cobblemon.mod.common.gui.TMMScreenHandler
|
||||
import com.cobblemon.mod.common.item.TechnicalMachineItem
|
||||
import com.cobblemon.mod.common.net.messages.client.ui.CraftTMPacket
|
||||
import com.cobblemon.mod.common.util.playSoundServer
|
||||
import net.minecraft.item.Items
|
||||
import net.minecraft.registry.Registries
|
||||
import net.minecraft.server.MinecraftServer
|
||||
import net.minecraft.server.network.ServerPlayerEntity
|
||||
import net.minecraft.sound.SoundCategory
|
||||
|
||||
object CraftTMPacketHandler : ServerNetworkPacketHandler<CraftTMPacket> {
|
||||
override fun handle(packet: CraftTMPacket, server: MinecraftServer, player: ServerPlayerEntity) {
|
||||
val screen = player.currentScreenHandler as TMMScreenHandler
|
||||
val discSlot = screen.inventory?.getStack(0)
|
||||
val gemSlot = screen.inventory?.getStack(1)
|
||||
val ingredientSlot = screen.inventory?.getStack(2)
|
||||
val outputSlot = screen.result.getStack(0)
|
||||
val typeGem = Registries.ITEM.get(ElementalTypes.get(packet.tm.type)?.typeGem)
|
||||
|
||||
print("test")
|
||||
|
||||
if (!outputSlot.isEmpty) return
|
||||
if (discSlot != null) {
|
||||
if (!discSlot.isOf(CobblemonItems.BLANK_TM)) return
|
||||
}
|
||||
if (gemSlot != null) {
|
||||
if (!gemSlot.isOf(typeGem)) return
|
||||
}
|
||||
if (packet.tm.recipe != null) {
|
||||
if (ingredientSlot != null) {
|
||||
if (!ingredientSlot.isOf(Registries.ITEM.get(packet.tm.recipe.item))) return
|
||||
}
|
||||
if (ingredientSlot != null) {
|
||||
if (ingredientSlot.count < packet.tm.recipe.count) return
|
||||
}
|
||||
}
|
||||
|
||||
val item = CobblemonItems.TECHNICAL_MACHINE.defaultStack
|
||||
item.getOrCreateNbt().putString(TechnicalMachineItem.STORED_MOVE_KEY, packet.tm.id().toString())
|
||||
|
||||
screen.result.setStack(0, item)
|
||||
screen.inventory?.removeStack(0, 1)
|
||||
screen.inventory?.removeStack(1, 1)
|
||||
if (packet.tm.recipe != null) {
|
||||
screen.inventory?.removeStack(2, packet.tm.recipe.count)
|
||||
}
|
||||
|
||||
screen.input.markDirty()
|
||||
screen.result.markDirty()
|
||||
player.currentScreenHandler.syncState()
|
||||
|
||||
player.world.playSoundServer(player.pos, CobblemonSounds.TMM_CRAFT, SoundCategory.BLOCKS)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.cobblemon.mod.common.client.net.gui
|
||||
|
||||
import com.cobblemon.mod.common.api.net.ClientNetworkPacketHandler
|
||||
import com.cobblemon.mod.common.net.messages.client.ui.InteractPokemonUIPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.ui.OpenTMMPacket
|
||||
import net.minecraft.client.MinecraftClient
|
||||
|
||||
object OpenTMMPacketHandler : ClientNetworkPacketHandler<OpenTMMPacket>
|
||||
{
|
||||
override fun handle(packet: OpenTMMPacket, client: MinecraftClient) {
|
||||
//client.setScreen()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
package com.cobblemon.mod.common.client.render.block
|
||||
|
||||
import com.cobblemon.mod.common.api.text.blue
|
||||
import com.cobblemon.mod.common.api.text.green
|
||||
import com.cobblemon.mod.common.api.text.red
|
||||
import com.cobblemon.mod.common.api.tms.TechnicalMachines
|
||||
import com.cobblemon.mod.common.api.types.ElementalTypes
|
||||
import com.cobblemon.mod.common.block.TMBlock
|
||||
import com.cobblemon.mod.common.block.entity.TMBlockEntity
|
||||
import com.cobblemon.mod.common.client.CobblemonBakingOverrides
|
||||
import com.cobblemon.mod.common.client.render.layer.CobblemonRenderLayers
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.MiscModelRepository
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.setRotation
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.math.geometry.Axis
|
||||
import net.minecraft.client.MinecraftClient
|
||||
import net.minecraft.client.render.LightmapTextureManager
|
||||
import net.minecraft.client.render.OverlayTexture
|
||||
import net.minecraft.client.render.RenderLayer
|
||||
import net.minecraft.client.render.VertexConsumerProvider
|
||||
import net.minecraft.client.render.block.entity.BlockEntityRenderer
|
||||
import net.minecraft.client.render.block.entity.BlockEntityRendererFactory
|
||||
import net.minecraft.client.util.math.MatrixStack
|
||||
import net.minecraft.util.math.Direction
|
||||
import net.minecraft.util.math.RotationAxis
|
||||
import java.awt.Color
|
||||
import kotlin.math.sin
|
||||
|
||||
class TMBlockRenderer(context: BlockEntityRendererFactory.Context) : BlockEntityRenderer<TMBlockEntity> {
|
||||
//TODO Do the render optimizations that we do for berries and fossils
|
||||
override fun render(
|
||||
entity: TMBlockEntity,
|
||||
tickDelta: Float,
|
||||
matrices: MatrixStack,
|
||||
vertexConsumers: VertexConsumerProvider,
|
||||
light: Int,
|
||||
overlay: Int
|
||||
) {
|
||||
val diskModel = MiscModelRepository.modelOf(MODEL_ID)
|
||||
matrices.push()
|
||||
val tm = entity.tmmInventory.filterTM?.let {
|
||||
TechnicalMachines.getTechnicalMachineFromStack(
|
||||
it
|
||||
)
|
||||
}
|
||||
entity.partialTicks += tickDelta
|
||||
val color = tm?.let { Color(ElementalTypes.get(it.type)!!.hue) } ?: Color.WHITE
|
||||
when (entity.cachedState.get(TMBlock.FACING)) {
|
||||
Direction.SOUTH -> matrices.translate(15F / 16F, 5.5F / 16F, 1F / 16F)
|
||||
Direction.WEST -> matrices.translate(14F / 16F, 5.5F / 16F, 0F)
|
||||
Direction.EAST -> matrices.translate(1F, 5.5F / 16F, 0F)
|
||||
else -> matrices.translate(15F / 16F, 5.5F / 16F, -1F / 16F)
|
||||
}
|
||||
|
||||
matrices.translate(-7.0/16f, 0.0, 8.0/16f)
|
||||
matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees( entity.partialTicks / 0.5f))
|
||||
matrices.translate(7.0/16f, 0.0, -8.0/16f)
|
||||
|
||||
|
||||
val renderLayer = RenderLayer.getEntityCutout(cobblemonResource("textures/block/tm_machine.png"))
|
||||
diskModel?.render(
|
||||
matrices,
|
||||
vertexConsumers.getBuffer(renderLayer),
|
||||
light,
|
||||
overlay,
|
||||
color.red.toFloat() / 255F,
|
||||
color.green.toFloat() / 255F,
|
||||
color.blue.toFloat() / 255F,
|
||||
1.0F
|
||||
)
|
||||
matrices.pop()
|
||||
}
|
||||
|
||||
companion object {
|
||||
val MODEL_ID = cobblemonResource("tm_disk.geo")
|
||||
}
|
||||
|
||||
}
|
||||
@@ -40,6 +40,27 @@ object CobblemonRenderLayers {
|
||||
multiPhaseParameters
|
||||
)
|
||||
}
|
||||
val TM_BLOCK_LAYER = run {
|
||||
val multiPhaseParameters = RenderLayer.MultiPhaseParameters.builder()
|
||||
.lightmap(ENABLE_LIGHTMAP)
|
||||
.program(CUTOUT_PROGRAM)
|
||||
.texture(Texture(
|
||||
cobblemonResource("textures/misc/tm_machine"),
|
||||
false,
|
||||
true
|
||||
))
|
||||
.cull(DISABLE_CULLING)
|
||||
.build(true)
|
||||
RenderLayer.of(
|
||||
"tm_block",
|
||||
VertexFormats.POSITION_COLOR_TEXTURE_LIGHT_NORMAL,
|
||||
VertexFormat.DrawMode.QUADS,
|
||||
512,
|
||||
true,
|
||||
false,
|
||||
multiPhaseParameters
|
||||
)
|
||||
}
|
||||
|
||||
val ENTITY_TRANSLUCENT: BiFunction<Identifier, Boolean, RenderLayer> = Util.memoize { texture: Identifier, affectsOutline: kotlin.Boolean ->
|
||||
var multiPhaseParameters: RenderLayer.MultiPhaseParameters =
|
||||
|
||||
@@ -19,6 +19,9 @@ import com.cobblemon.mod.common.api.scheduling.ServerTaskTracker
|
||||
import com.cobblemon.mod.common.api.scheduling.taskBuilder
|
||||
import com.cobblemon.mod.common.api.text.green
|
||||
import com.cobblemon.mod.common.api.text.red
|
||||
import com.cobblemon.mod.common.api.text.text
|
||||
import com.cobblemon.mod.common.api.tms.TechnicalMachine
|
||||
import com.cobblemon.mod.common.api.tms.TechnicalMachines
|
||||
import com.cobblemon.mod.common.battles.BattleFormat
|
||||
import com.cobblemon.mod.common.battles.BattleRegistry
|
||||
import com.cobblemon.mod.common.battles.BattleSide
|
||||
@@ -60,7 +63,12 @@ object TestCommand {
|
||||
return Command.SINGLE_SUCCESS
|
||||
}
|
||||
|
||||
for (id in Cobblemon.playerData.get(context.source.playerOrThrow).tmSet) {
|
||||
context.source.player?.sendMessage(TechnicalMachines.tmMap[id]?.translatedMoveName())
|
||||
}
|
||||
|
||||
try {
|
||||
filter(context)
|
||||
// readBerryDataFromCSV()
|
||||
|
||||
// this.testClosestBattle(context)
|
||||
@@ -108,6 +116,12 @@ object TestCommand {
|
||||
var trade: ActiveTrade? = null
|
||||
var lastDebugId = 0
|
||||
|
||||
private fun filter(context: CommandContext<ServerCommandSource>) {
|
||||
val tms = TechnicalMachine.filterTms("fire", null, null)
|
||||
println(context.source.playerOrThrow.party().get(1)?.getDisplayName())
|
||||
tms.forEach { context.source.playerOrThrow.sendMessage(it.moveName.text()) }
|
||||
}
|
||||
|
||||
private fun testClosestBattle(context: CommandContext<ServerCommandSource>) {
|
||||
val player = context.source.playerOrThrow
|
||||
val cloneTeam = player.party().toBattleTeam(true)
|
||||
|
||||
@@ -29,6 +29,7 @@ import com.cobblemon.mod.common.api.pokemon.feature.SpeciesFeatures
|
||||
import com.cobblemon.mod.common.api.spawning.CobblemonSpawnPools
|
||||
import com.cobblemon.mod.common.api.spawning.CobblemonSpawnRules
|
||||
import com.cobblemon.mod.common.api.spawning.SpawnDetailPresets
|
||||
import com.cobblemon.mod.common.api.tms.TechnicalMachines
|
||||
import com.cobblemon.mod.common.battles.BagItems
|
||||
import com.cobblemon.mod.common.net.messages.client.data.UnlockReloadPacket
|
||||
import com.cobblemon.mod.common.platform.events.PlatformEvents
|
||||
@@ -75,6 +76,7 @@ object CobblemonDataProvider : DataProvider {
|
||||
|
||||
CobblemonSpawnPools.load()
|
||||
this.register(Berries)
|
||||
this.register(TechnicalMachines)
|
||||
|
||||
PlatformEvents.SERVER_PLAYER_LOGOUT.subscribe {
|
||||
synchronizedPlayerIds.remove(it.player.uuid)
|
||||
|
||||
@@ -9,7 +9,9 @@
|
||||
package com.cobblemon.mod.common.events
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.tms.TechnicalMachines
|
||||
import com.cobblemon.mod.common.battles.BattleRegistry
|
||||
import com.cobblemon.mod.common.item.TechnicalMachineItem
|
||||
import com.cobblemon.mod.common.util.party
|
||||
import net.minecraft.server.MinecraftServer
|
||||
|
||||
@@ -25,9 +27,21 @@ object ServerTickHandler {
|
||||
if (secondsTick == 20) {
|
||||
secondsTick = 0
|
||||
|
||||
// Party tick
|
||||
// Code to run every in-game second
|
||||
for (player in server.playerManager.playerList) {
|
||||
player.party().onSecondPassed(player)
|
||||
TechnicalMachines.checkPassives(player)
|
||||
|
||||
// Give player tm unlocks for tms they don't already have
|
||||
repeat(player.inventory.size()) {
|
||||
val stack = player.inventory.getStack(it)
|
||||
if (stack.item is TechnicalMachineItem) {
|
||||
val tm = TechnicalMachineItem.getMoveNbt(stack) ?: return@repeat
|
||||
if (!Cobblemon.playerData.get(player).tmSet.contains(tm.id())) {
|
||||
tm.unlock(player)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.cobblemon.mod.common.gui
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.mixin.invoker.ScreenHandlerTypeInvoker
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.registry.Registries
|
||||
import net.minecraft.resource.featuretoggle.FeatureFlags
|
||||
import net.minecraft.screen.ScreenHandlerType.Factory
|
||||
import net.minecraft.resource.featuretoggle.FeatureSet
|
||||
import net.minecraft.screen.ScreenHandler
|
||||
import net.minecraft.screen.ScreenHandlerType
|
||||
import net.minecraft.util.Identifier
|
||||
|
||||
object CobblemonScreenHandlers {
|
||||
val TMM_SCREEN = register(cobblemonResource("tmm_screen"), ::TMMScreenHandler)
|
||||
val MOD_STATION_SCREEN = register(cobblemonResource("mod_station_screen"), ::ModStationScreenHandler)
|
||||
|
||||
fun <T : ScreenHandler> register(identifier: Identifier, factory: Factory<T>): ScreenHandlerType<T> {
|
||||
|
||||
val result = ScreenHandlerTypeInvoker.`cobblemon$create`(factory, FeatureFlags.VANILLA_FEATURES)
|
||||
Cobblemon.implementation.registerScreenHandlerType(identifier, result)
|
||||
return result
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package com.cobblemon.mod.common.gui
|
||||
|
||||
import net.minecraft.entity.player.PlayerEntity
|
||||
import net.minecraft.entity.player.PlayerInventory
|
||||
import net.minecraft.inventory.*
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.screen.ScreenHandler
|
||||
import net.minecraft.screen.slot.CraftingResultSlot
|
||||
import net.minecraft.screen.slot.Slot
|
||||
|
||||
class ModStationScreenHandler(syncId: Int) : ScreenHandler(CobblemonScreenHandlers.MOD_STATION_SCREEN, syncId) {
|
||||
var playerInventory: PlayerInventory? = null
|
||||
var input: RecipeInputInventory = CraftingInventory(this, 2, 1)
|
||||
val result: CraftingResultInventory = CraftingResultInventory()
|
||||
var inventory: Inventory? = null
|
||||
|
||||
constructor(syncId: Int, playerInventory: PlayerInventory) : this(syncId, playerInventory, SimpleInventory(3))
|
||||
|
||||
constructor(syncId: Int, playerInventory: PlayerInventory, inventory: Inventory) : this(syncId) {
|
||||
val startX = 0 - 9
|
||||
val startY = 112
|
||||
val xLen = 18 // 18 is standard
|
||||
val yLen = 18 // 18 is standard
|
||||
this.playerInventory = playerInventory
|
||||
this.inventory = inventory
|
||||
|
||||
for (row in 0..2) {
|
||||
for (column in 0..8) {
|
||||
this.addSlot(Slot(playerInventory, 9 + (row * 9) + column, startX + (xLen * column), startY + (yLen * row)))
|
||||
}
|
||||
}
|
||||
for (column in 0..8) {
|
||||
this.addSlot(Slot(playerInventory, column, startX + (xLen * column), startY + 58))
|
||||
}
|
||||
|
||||
addSlot(CraftingResultSlot(
|
||||
playerInventory.player,
|
||||
input,
|
||||
result,
|
||||
0,
|
||||
startX,
|
||||
startY
|
||||
))
|
||||
|
||||
this.addSlot(Slot(this.inventory, 0, startX, startY - 20))
|
||||
this.addSlot(Slot(this.inventory, 1, startX, startY - 40))
|
||||
}
|
||||
|
||||
override fun quickMove(player: PlayerEntity?, slot: Int): ItemStack {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun canUse(player: PlayerEntity?): Boolean {
|
||||
return inventory?.canPlayerUse(player) ?: false
|
||||
}
|
||||
|
||||
override fun syncState() {
|
||||
super.syncState()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
package com.cobblemon.mod.common.gui
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonItems
|
||||
import com.cobblemon.mod.common.block.entity.TMBlockEntity
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.entity.player.PlayerEntity
|
||||
import net.minecraft.entity.player.PlayerInventory
|
||||
import net.minecraft.inventory.*
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.screen.ScreenHandler
|
||||
import net.minecraft.screen.slot.CraftingResultSlot
|
||||
import net.minecraft.screen.slot.Slot
|
||||
import net.minecraft.screen.slot.SlotActionType
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.world.World
|
||||
|
||||
class TMMScreenHandler(syncId: Int) : ScreenHandler(CobblemonScreenHandlers.TMM_SCREEN, syncId) {
|
||||
var playerInventory: PlayerInventory? = null
|
||||
|
||||
var input: RecipeInputInventory = CraftingInventory(this, 3, 1)
|
||||
val result: CraftingResultInventory = CraftingResultInventory()
|
||||
var tmmEntity: TMBlockEntity? = null
|
||||
var inventory: Inventory? = null
|
||||
|
||||
constructor(syncId: Int, playerInventory: PlayerInventory) : this(syncId, playerInventory, SimpleInventory(4), null) {
|
||||
}
|
||||
constructor(syncId: Int, playerInventory: PlayerInventory, inventory: Inventory, blockEntity: TMBlockEntity?) : this(syncId) {
|
||||
val startX = 0 - 9
|
||||
val startY = 112
|
||||
val xLen = 18 // 18 is standard
|
||||
val yLen = 18 // 18 is standard
|
||||
this.playerInventory = playerInventory
|
||||
this.inventory = inventory // as TMBlockEntity.TMBlockInventory) // this does grab the right inventory slots
|
||||
tmmEntity = blockEntity
|
||||
|
||||
if (inventory is TMBlockEntity.TMBlockInventory) {
|
||||
//inventory.tmBlockEntity
|
||||
|
||||
this.syncState()
|
||||
|
||||
/*this.inventory = inventory
|
||||
|
||||
this.tmmEntity = (inventory as TMBlockEntity.TMBlockInventory).tmBlockEntity
|
||||
|
||||
// sync the input slots with the TMM slots
|
||||
input.setStack(0, inventory.items!!.get(0))
|
||||
input.setStack(1, inventory.items!!.get(1))
|
||||
input.setStack(2, inventory.items!!.get(2))
|
||||
//inventory.items!![3] = result.getStack(0) // sync output of TMM with the crafted TM
|
||||
result.setStack(0, inventory.items!!.get(3))*/
|
||||
}
|
||||
|
||||
|
||||
for (row in 0..2) {
|
||||
for (column in 0..8) {
|
||||
this.addSlot(Slot(playerInventory, 9 + (row * 9) + column, startX + (xLen * column), startY + (yLen * row)))
|
||||
}
|
||||
}
|
||||
for (column in 0..8) {
|
||||
this.addSlot(Slot(playerInventory, column, startX + (xLen * column), startY + 58))
|
||||
}
|
||||
|
||||
this.addSlot(CraftingResultSlot(
|
||||
playerInventory.player,
|
||||
input,
|
||||
result,
|
||||
0,
|
||||
startX + 123,
|
||||
startY - 22
|
||||
))
|
||||
|
||||
this.addSlot(Slot(this.inventory, 0, startX + 167, startY + 9)) // material input slot 1
|
||||
this.addSlot(Slot(this.inventory, 1, startX + 185, startY + 9)) // material input slot 2
|
||||
this.addSlot(Slot(this.inventory, 2, startX + 203, startY + 9)) // material input slot 3
|
||||
|
||||
}
|
||||
override fun quickMove(player: PlayerEntity, slot: Int): ItemStack {
|
||||
return if (insertItem(getSlot(slot).stack, 0, SLOT_COUNT, true)) getSlot(slot).stack else ItemStack.EMPTY
|
||||
}
|
||||
|
||||
override fun canUse(player: PlayerEntity?): Boolean {
|
||||
return inventory?.canPlayerUse(player) ?: false
|
||||
}
|
||||
|
||||
// override fun onClosed(player: PlayerEntity) {
|
||||
//// for (i in 0..2) {
|
||||
//// if (!slots[i].stack.isEmpty) player.giveOrDropItemStack(slots[i].stack, false)
|
||||
//// }
|
||||
// super.onClosed(player)
|
||||
// }
|
||||
|
||||
override fun onSlotClick(slotIndex: Int, button: Int, actionType: SlotActionType?, player: PlayerEntity) {
|
||||
val type = if (actionType == SlotActionType.THROW) SlotActionType.PICKUP else actionType // todo issue might be inventory is not being clicked, but it is index 36 still
|
||||
|
||||
// if slot is the output slot then clear the TMM output slot
|
||||
if (slotIndex == 36) {
|
||||
this.inventory?.setStack(3, ItemStack.EMPTY)
|
||||
}
|
||||
|
||||
super.onSlotClick(slotIndex, button, type, player)
|
||||
}
|
||||
|
||||
override fun onClosed(player: PlayerEntity?) {
|
||||
super.onClosed(player)
|
||||
|
||||
tmmEntity?.stateManager?.closeContainer(player, tmmEntity!!.world, tmmEntity!!.blockPos, tmmEntity!!.blockState)
|
||||
|
||||
}
|
||||
|
||||
override fun syncState() {
|
||||
if (inventory is TMBlockEntity.TMBlockInventory) {
|
||||
//inventory.tmBlockEntity
|
||||
|
||||
// sync the input slots with the TMM slots
|
||||
input.setStack(0, (inventory as TMBlockEntity.TMBlockInventory).items!!.get(0))
|
||||
input.setStack(1, (inventory as TMBlockEntity.TMBlockInventory).items!!.get(1))
|
||||
input.setStack(2, (inventory as TMBlockEntity.TMBlockInventory).items!!.get(2))
|
||||
//inventory.items!![3] = result.getStack(0) // sync output of TMM with the crafted TM
|
||||
|
||||
// if there is something in the output slot of this.inventory then sync that with result
|
||||
if ((inventory as TMBlockEntity.TMBlockInventory).items?.get(3) != ItemStack.EMPTY) {
|
||||
if (ItemStack.areItemsEqual((inventory as TMBlockEntity.TMBlockInventory).items?.get(3), ItemStack(CobblemonItems.TECHNICAL_MACHINE, 1))
|
||||
|| ItemStack.areItemsEqual((inventory as TMBlockEntity.TMBlockInventory).items?.get(3), ItemStack(CobblemonItems.BLANK_TM, 1)))
|
||||
result.setStack(0, (inventory as TMBlockEntity.TMBlockInventory).items!!.get(3))
|
||||
}
|
||||
// if inventory is empty in the output slot then sync it to result
|
||||
else
|
||||
(inventory as TMBlockEntity.TMBlockInventory).items?.set(3, result.getStack(0))
|
||||
|
||||
}
|
||||
|
||||
super.syncState()
|
||||
}
|
||||
|
||||
companion object {
|
||||
val SLOT_COUNT = 3
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.item
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.api.moves.BenchedMove
|
||||
import com.cobblemon.mod.common.api.moves.Moves
|
||||
import com.cobblemon.mod.common.api.text.gray
|
||||
import com.cobblemon.mod.common.api.text.green
|
||||
import com.cobblemon.mod.common.api.tms.TechnicalMachine
|
||||
import com.cobblemon.mod.common.api.tms.TechnicalMachines
|
||||
import com.cobblemon.mod.common.api.types.ElementalTypes
|
||||
import com.cobblemon.mod.common.block.entity.TMBlockEntity
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
import com.cobblemon.mod.common.util.toBlockPos
|
||||
import net.minecraft.block.Block
|
||||
import net.minecraft.client.item.TooltipContext
|
||||
import net.minecraft.entity.LivingEntity
|
||||
import net.minecraft.entity.player.PlayerEntity
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.item.ItemUsageContext
|
||||
import net.minecraft.nbt.NbtString
|
||||
import net.minecraft.sound.SoundCategory
|
||||
import net.minecraft.text.MutableText
|
||||
import net.minecraft.text.Text
|
||||
import net.minecraft.util.ActionResult
|
||||
import net.minecraft.util.Hand
|
||||
import net.minecraft.util.Identifier
|
||||
import net.minecraft.world.World
|
||||
|
||||
class TechnicalMachineItem(settings: Settings): CobblemonItem(settings) {
|
||||
|
||||
companion object {
|
||||
val STORED_MOVE_KEY = "StoredMove"
|
||||
|
||||
fun getMoveNbt(stack: ItemStack): TechnicalMachine? {
|
||||
val nbtCompound = stack.nbt ?: return null
|
||||
|
||||
return TechnicalMachines.tmMap[Identifier.tryParse(nbtCompound.getString(STORED_MOVE_KEY))]
|
||||
}
|
||||
|
||||
fun getItemColor(stack: ItemStack, tint: Int): Int {
|
||||
val nbt = getMoveNbt(stack) ?: return ElementalTypes.NORMAL.primaryColor
|
||||
|
||||
if (nbt.primaryColor != null && tint == 0) return nbt.primaryColor
|
||||
if (nbt.secondaryColor != null && tint != 0) return nbt.secondaryColor
|
||||
|
||||
val type = ElementalTypes.getOrException(nbt.type)
|
||||
if (tint == 0) return type.primaryColor
|
||||
return type.secondaryColor
|
||||
}
|
||||
}
|
||||
|
||||
override fun hasGlint(stack: ItemStack?) = false
|
||||
|
||||
fun setNbt(stack: ItemStack, id: String): ItemStack {
|
||||
stack.getOrCreateNbt().put(STORED_MOVE_KEY, NbtString.of(id))
|
||||
return stack
|
||||
}
|
||||
|
||||
override fun appendTooltip(
|
||||
stack: ItemStack,
|
||||
world: World?,
|
||||
tooltip: MutableList<Text>,
|
||||
context: TooltipContext?
|
||||
) {
|
||||
val nbt = getMoveNbt(stack)
|
||||
val text: MutableText = if (nbt != null) {
|
||||
lang("move." + nbt.moveName)
|
||||
} else {
|
||||
lang("tms.unknown_move")
|
||||
}
|
||||
tooltip.add(text.gray())
|
||||
}
|
||||
|
||||
override fun useOnEntity(stack: ItemStack, user: PlayerEntity, entity: LivingEntity, hand: Hand): ActionResult {
|
||||
if (user.world.isClient) return ActionResult.FAIL
|
||||
if (entity !is PokemonEntity) return ActionResult.FAIL
|
||||
|
||||
val tm = getMoveNbt(stack) ?: return ActionResult.FAIL
|
||||
val move = Moves.getByName(tm.moveName) ?: return ActionResult.FAIL
|
||||
val pokemon = entity.pokemon
|
||||
|
||||
val tmLearnableMoves = pokemon.species.moves.tmLearnableMoves()
|
||||
|
||||
if (!tmLearnableMoves.contains(move)) {
|
||||
user.sendMessage(lang("tms.cannot_learn", pokemon.getDisplayName(), tm.translatedMoveName()))
|
||||
return ActionResult.FAIL
|
||||
}
|
||||
if (pokemon.allAccessibleMoves.contains(move)) {
|
||||
user.sendMessage(lang("tms.already_known", pokemon.getDisplayName(), tm.translatedMoveName()))
|
||||
return ActionResult.FAIL
|
||||
}
|
||||
|
||||
if (!user.isCreative) stack.decrement(1)
|
||||
if (pokemon.moveSet.hasSpace()) { pokemon.moveSet.add(move.create()) }
|
||||
else { pokemon.benchedMoves.add(BenchedMove(move, 0)) }
|
||||
|
||||
user.sendMessage(lang("tms.teach_move", pokemon.getDisplayName(), tm.translatedMoveName()).green())
|
||||
user.playSound(CobblemonSounds.TM_USE, SoundCategory.PLAYERS, 1.0f, 1.0f)
|
||||
entity.cry()
|
||||
return ActionResult.CONSUME
|
||||
}
|
||||
|
||||
override fun useOnBlock(context: ItemUsageContext): ActionResult {
|
||||
if (context.world.isClient) {
|
||||
context.player?.swingHand(context.hand)
|
||||
return ActionResult.FAIL
|
||||
}
|
||||
|
||||
//val TMM = context.world.getBlockState(context.hitPos.toBlockPos()).block
|
||||
val TMM = context.world.getBlockEntity(context.hitPos.toBlockPos())
|
||||
|
||||
if (TMM is TMBlockEntity
|
||||
&& (TMM.tmmInventory.filterTM == null
|
||||
|| TMM.tmmInventory.filterTM!!.nbt?.get("StoredMove") != context.stack.nbt?.get("StoredMove"))) {
|
||||
context.player?.playSound(CobblemonSounds.TMM_ON, SoundCategory.BLOCKS, 1.0f, 1.0f)
|
||||
context.player?.swingHand(context.hand)
|
||||
if (TMM.tmmInventory.filterTM != null) {
|
||||
if (!context.player?.isCreative!!) {
|
||||
context.player!!.giveItemStack(TMM.tmmInventory.filterTM!!)
|
||||
}
|
||||
}
|
||||
|
||||
// set filterTM equal to the item it corresponds to
|
||||
TMM.tmmInventory.filterTM = TechnicalMachines.getTechnicalMachineFromStack(context.stack)?.let { TechnicalMachines.getStackFromTechnicalMachine(it) }
|
||||
|
||||
|
||||
|
||||
/*// if materials are in the machine already
|
||||
if (TMM.tmmInventory.items?.isNotEmpty() == true) {
|
||||
TMM.tmmInventory.items?.forEach {
|
||||
// Get the direction the block is facing
|
||||
val facingDirection = TMM.blockState.get(Properties.FACING).opposite
|
||||
|
||||
// Calculate the center position of the block
|
||||
val frontOffset = 0.5 // Half block offset to the front
|
||||
val spawnX = TMM.blockPos.x + 0.5 + facingDirection.offsetX * frontOffset
|
||||
val spawnY = TMM.blockPos.y + 0.3 + facingDirection.offsetY * frontOffset
|
||||
val spawnZ = TMM.blockPos.z + 0.5 + facingDirection.offsetZ * frontOffset
|
||||
|
||||
// Create the ItemEntity at the center of the block
|
||||
val itemEntity = ItemEntity( context.world, spawnX, spawnY, spawnZ, it)
|
||||
|
||||
// Create the ItemEntity
|
||||
itemEntity.setVelocity(0.0, 0.0, 0.0)
|
||||
|
||||
// Add the ItemEntity to the world
|
||||
context.world.spawnEntity(itemEntity)
|
||||
}
|
||||
TMM.tmmInventory.items?.clear()
|
||||
}*/
|
||||
|
||||
// todo change the color of the disk in the TMM
|
||||
// todo remove 1 from the stack in the player's hand if not in creative
|
||||
if (!context.player?.isCreative!!) {
|
||||
context.player?.getStackInHand(context.hand)?.decrement(1)
|
||||
}
|
||||
|
||||
TMM.markDirty()
|
||||
TMM.world?.updateListeners(TMM.blockPos, TMM.cachedState, TMM.cachedState, Block.NOTIFY_LISTENERS)
|
||||
}
|
||||
|
||||
/*val type = ElementalTypes.getOrException(getMoveNbt(context.stack)!!.type)
|
||||
context.player!!.giveItemStack(Registries.ITEM.get(type.typeGem).defaultStack)*/
|
||||
return super.useOnBlock(context)
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,7 @@
|
||||
package com.cobblemon.mod.common.item.group
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonItems
|
||||
import com.cobblemon.mod.common.api.tms.TechnicalMachines
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.item.ItemConvertible
|
||||
import net.minecraft.item.ItemGroup
|
||||
@@ -35,6 +36,7 @@ object CobblemonItemGroups {
|
||||
@JvmStatic val CONSUMABLES_KEY = this.create("consumables", this::consumableEntries) { ItemStack(CobblemonItems.ROASTED_LEEK) }
|
||||
@JvmStatic val HELD_ITEMS_KEY = this.create("held_item", this::heldItemEntries) { ItemStack(CobblemonItems.EXP_SHARE) }
|
||||
@JvmStatic val EVOLUTION_ITEMS_KEY = this.create("evolution_item", this::evolutionItemEntries) { ItemStack(CobblemonItems.BLACK_AUGURITE) }
|
||||
@JvmStatic val TECHNICAL_MACHINES_KEY = this.create("technical_machines", this::technicalMachineEntries) { ItemStack(CobblemonItems.BLANK_TM) }
|
||||
|
||||
@JvmStatic val BLOCKS get() = Registries.ITEM_GROUP.get(BLOCKS_KEY)
|
||||
@JvmStatic val POKEBALLS get() = Registries.ITEM_GROUP.get(POKEBALLS_KEY)
|
||||
@@ -43,6 +45,7 @@ object CobblemonItemGroups {
|
||||
@JvmStatic val CONSUMABLES get() = Registries.ITEM_GROUP.get(CONSUMABLES_KEY)
|
||||
@JvmStatic val HELD_ITEMS get() = Registries.ITEM_GROUP.get(HELD_ITEMS_KEY)
|
||||
@JvmStatic val EVOLUTION_ITEMS get() = Registries.ITEM_GROUP.get(EVOLUTION_ITEMS_KEY)
|
||||
@JvmStatic val TECHNICAL_MACHINES get() = Registries.ITEM_GROUP.get(TECHNICAL_MACHINES_KEY)
|
||||
|
||||
@JvmStatic val FOOD_INJECTIONS = this.inject(RegistryKey.of(Registries.ITEM_GROUP.key, Identifier("food_and_drinks")), this::foodInjections)
|
||||
@JvmStatic val TOOLS_AND_UTILITIES_INJECTIONS = this.inject(RegistryKey.of(Registries.ITEM_GROUP.key, Identifier("tools_and_utilities")), this::toolsAndUtilitiesInjections)
|
||||
@@ -76,6 +79,16 @@ object CobblemonItemGroups {
|
||||
return consumer
|
||||
}
|
||||
|
||||
private fun technicalMachineEntries(displayContext: DisplayContext, entries: Entries) {
|
||||
entries.add(CobblemonItems.BLANK_TM)
|
||||
for (tm in TechnicalMachines.tmMap) {
|
||||
val item = CobblemonItems.TECHNICAL_MACHINE.setNbt(
|
||||
CobblemonItems.TECHNICAL_MACHINE.defaultStack,
|
||||
tm.key.toString())
|
||||
entries.add(item)
|
||||
}
|
||||
}
|
||||
|
||||
private fun agricultureEntries(displayContext: DisplayContext, entries: Entries) {
|
||||
entries.add(CobblemonItems.MEDICINAL_LEEK)
|
||||
entries.add(CobblemonItems.BIG_ROOT)
|
||||
@@ -217,8 +230,10 @@ object CobblemonItemGroups {
|
||||
entries.add(CobblemonItems.FOSSIL_ANALYZER)
|
||||
entries.add(CobblemonItems.MONITOR)
|
||||
entries.add(CobblemonItems.PC)
|
||||
entries.add(CobblemonItems.TM_MACHINE)
|
||||
entries.add(CobblemonItems.HEALING_MACHINE)
|
||||
entries.add(CobblemonItems.PASTURE)
|
||||
entries.add(CobblemonItems.MOD_STATION)
|
||||
|
||||
entries.add(CobblemonItems.GILDED_CHEST)
|
||||
entries.add(CobblemonItems.YELLOW_GILDED_CHEST)
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.cobblemon.mod.common.net.messages.client.ui
|
||||
|
||||
import com.cobblemon.mod.common.api.net.NetworkPacket
|
||||
import com.cobblemon.mod.common.api.tms.TechnicalMachine
|
||||
import com.cobblemon.mod.common.api.tms.TechnicalMachines
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.network.PacketByteBuf
|
||||
import java.util.UUID
|
||||
|
||||
/**
|
||||
* Tells the server to attempt crafting a Blank TM using the [TMBlock]
|
||||
*
|
||||
* Handled by [CraftBlankTMPacketHandler]
|
||||
*
|
||||
* @author whatsy
|
||||
*/
|
||||
class CraftBlankTMPacket(
|
||||
val ingredient: ItemStack
|
||||
): NetworkPacket<CraftBlankTMPacket> {
|
||||
override val id = ID
|
||||
|
||||
override fun encode(buffer: PacketByteBuf) {
|
||||
buffer.writeItemStack(ingredient)
|
||||
}
|
||||
|
||||
companion object {
|
||||
val ID = cobblemonResource("craft_blank_tm")
|
||||
|
||||
fun decode(buffer: PacketByteBuf) = CraftBlankTMPacket(
|
||||
buffer.readItemStack()
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.cobblemon.mod.common.net.messages.client.ui
|
||||
|
||||
import com.cobblemon.mod.common.api.net.NetworkPacket
|
||||
import com.cobblemon.mod.common.api.tms.TechnicalMachine
|
||||
import com.cobblemon.mod.common.api.tms.TechnicalMachines
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.network.PacketByteBuf
|
||||
import java.util.UUID
|
||||
|
||||
/**
|
||||
* Tells the server to attempt crafting a [TechnicalMachineItem] using the [TMBlock]
|
||||
*
|
||||
* Handled by [CraftTMPacketHandler]
|
||||
*
|
||||
* @author whatsy
|
||||
*/
|
||||
class CraftTMPacket(
|
||||
val tm: TechnicalMachine,
|
||||
val disc: ItemStack,
|
||||
val gem: ItemStack,
|
||||
val ingredient: ItemStack
|
||||
): NetworkPacket<CraftTMPacket> {
|
||||
override val id = ID
|
||||
|
||||
override fun encode(buffer: PacketByteBuf) {
|
||||
buffer.writeIdentifier(tm.id())
|
||||
buffer.writeItemStack(disc)
|
||||
buffer.writeItemStack(gem)
|
||||
buffer.writeItemStack(ingredient)
|
||||
}
|
||||
|
||||
companion object {
|
||||
val ID = cobblemonResource("craft_tm")
|
||||
|
||||
fun decode(buffer: PacketByteBuf) = CraftTMPacket(
|
||||
TechnicalMachines.tmMap[buffer.readIdentifier()]!!,
|
||||
buffer.readItemStack(), buffer.readItemStack(), buffer.readItemStack()
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.cobblemon.mod.common.net.messages.client.ui
|
||||
|
||||
import com.cobblemon.mod.common.api.net.NetworkPacket
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.network.PacketByteBuf
|
||||
import net.minecraft.util.Identifier
|
||||
|
||||
class OpenTMMPacket: NetworkPacket<OpenTMMPacket> {
|
||||
override val id = cobblemonResource("open_tm")
|
||||
|
||||
override fun encode(buffer: PacketByteBuf) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1398,11 +1398,18 @@ open class Pokemon : ShowdownIdentifiable {
|
||||
|
||||
val newLevelUpMoves = form.moves.getLevelUpMovesUpTo(newLevel)
|
||||
val differences = (newLevelUpMoves - previousLevelUpMoves).filter { this.moveSet.none { move -> move.template == it } }.toMutableSet()
|
||||
differences.forEach {
|
||||
if (moveSet.hasSpace()) {
|
||||
moveSet.add(it.create())
|
||||
}
|
||||
}
|
||||
// differences.forEach {
|
||||
// TechnicalMachines.tmsToCheckOnLevelUp.entries.filter { entry ->
|
||||
// entry.value.moveName == it.name
|
||||
// }.forEach { entry ->
|
||||
// val player = this.getOwnerPlayer() as PlayerEntity
|
||||
// Cobblemon.playerData.get(player).tmSet.add(entry.key)
|
||||
// player.sendMessage(lang("tms.unlock_tm", lang("move." + entry.value.moveName)))
|
||||
// }
|
||||
// if (moveSet.hasSpace()) {
|
||||
// moveSet.add(it.create())
|
||||
// }
|
||||
// }
|
||||
|
||||
CobblemonEvents.EXPERIENCE_GAINED_EVENT_POST.post(
|
||||
ExperienceGainedPostEvent(this, source, appliedXP, oldLevel, newLevel, differences),
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.cobblemon.mod.common.tms.obtain
|
||||
|
||||
import com.cobblemon.mod.common.api.tms.ObtainMethod
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.server.network.ServerPlayerEntity
|
||||
|
||||
/**
|
||||
* An [ObtainMethod] that never triggers.
|
||||
* Useful since the obtainMethods field in TM JSONs cannot be blank.
|
||||
*
|
||||
* @author whatsy
|
||||
*/
|
||||
class ImpossibleObtainMethod : ObtainMethod {
|
||||
|
||||
override val passive = false
|
||||
|
||||
companion object {
|
||||
val ID = cobblemonResource("impossible")
|
||||
}
|
||||
|
||||
override fun matches(player: ServerPlayerEntity) = false
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.cobblemon.mod.common.tms.obtain
|
||||
|
||||
import com.cobblemon.mod.common.api.tms.ObtainMethod
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.server.network.ServerPlayerEntity
|
||||
|
||||
/**
|
||||
* An [ObtainMethod] that unlocks immediately.
|
||||
* Used for TMs that aren't unlocked and are available immediately.
|
||||
* TMs with this [ObtainMethod] will not display an unlock text.
|
||||
*
|
||||
* @author whatsy
|
||||
*/
|
||||
class NoneObtainMethod : ObtainMethod {
|
||||
|
||||
override val passive = true
|
||||
|
||||
override fun matches(player: ServerPlayerEntity) = true
|
||||
|
||||
companion object {
|
||||
val ID = cobblemonResource("none")
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.cobblemon.mod.common.tms.obtain
|
||||
|
||||
import com.cobblemon.mod.common.api.tms.ObtainMethod
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.server.network.ServerPlayerEntity
|
||||
import net.minecraft.util.Identifier
|
||||
|
||||
/**
|
||||
* An [ObtainMethod] that triggers when the player has an advancement.
|
||||
*/
|
||||
class PlayerHasAdvancementObtainMethod : ObtainMethod {
|
||||
|
||||
companion object {
|
||||
val ID = cobblemonResource("advancement")
|
||||
}
|
||||
|
||||
override val passive = true
|
||||
val advancement: Identifier? = null
|
||||
|
||||
override fun matches(player: ServerPlayerEntity): Boolean {
|
||||
if (advancement == null) return false
|
||||
|
||||
for (entry in player.advancementTracker.progress) {
|
||||
if (entry.key.id == advancement && entry.value.isDone) return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.cobblemon.mod.common.tms.obtain
|
||||
|
||||
import com.cobblemon.mod.common.api.tms.ObtainMethod
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.server.network.ServerPlayerEntity
|
||||
|
||||
/**
|
||||
* An [ObtainMethod] that checks the player's Y level.
|
||||
*
|
||||
* @param yLevel The Y level to check for.
|
||||
* @param operator The operator to use. Can be "equals", "less", or "greater".
|
||||
* @author whatsy
|
||||
*/
|
||||
class PlayerYObtainMethod(val yLevel: Int, val operator: String) : ObtainMethod {
|
||||
|
||||
override val passive = true
|
||||
override fun matches(player: ServerPlayerEntity): Boolean {
|
||||
when (operator) {
|
||||
"equals" -> return (player.y.toInt() == yLevel)
|
||||
"less" -> return (yLevel < player.y)
|
||||
"greater" -> return (yLevel > player.y)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
companion object {
|
||||
val ID = cobblemonResource("y_level")
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.tms.obtain
|
||||
|
||||
import com.cobblemon.mod.common.api.moves.Moves
|
||||
import com.cobblemon.mod.common.api.tms.ObtainMethod
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.party
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import net.minecraft.server.network.ServerPlayerEntity
|
||||
|
||||
/**
|
||||
* An [ObtainMethod] that triggers when a [Pokemon] in the player's party knows a certain [Move]
|
||||
*
|
||||
* @author whatsy
|
||||
*/
|
||||
class PokemonHasMoveObtainMethod : ObtainMethod {
|
||||
|
||||
companion object {
|
||||
val ID = cobblemonResource("pokemon_knows")
|
||||
}
|
||||
|
||||
@SerializedName("move")
|
||||
val moveId: String = "splash"
|
||||
override val passive = true
|
||||
|
||||
override fun matches(player: ServerPlayerEntity): Boolean {
|
||||
player.party().forEach {
|
||||
it.allAccessibleMoves.forEach {
|
||||
if (it.equals(Moves.getByName(moveId))) return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.cobblemon.mod.common.util.adapters
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.tms.ObtainMethod
|
||||
import com.cobblemon.mod.common.api.tms.ObtainMethodAdapter
|
||||
import com.cobblemon.mod.common.tms.obtain.*
|
||||
import com.google.gson.JsonDeserializationContext
|
||||
import com.google.gson.JsonElement
|
||||
import com.google.gson.JsonSerializationContext
|
||||
import net.minecraft.util.Identifier
|
||||
import java.lang.reflect.Type
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
object CobblemonObtainMethodAdapter : ObtainMethodAdapter {
|
||||
private const val VARIANT = "variant"
|
||||
private val types = hashMapOf<String, KClass<out ObtainMethod>>()
|
||||
|
||||
init {
|
||||
this.register(PokemonHasMoveObtainMethod::class, PokemonHasMoveObtainMethod.ID)
|
||||
this.register(ImpossibleObtainMethod::class, ImpossibleObtainMethod.ID)
|
||||
this.register(PlayerHasAdvancementObtainMethod::class, PlayerHasAdvancementObtainMethod.ID)
|
||||
this.register(NoneObtainMethod::class, NoneObtainMethod.ID)
|
||||
this.register(PlayerYObtainMethod::class, PlayerYObtainMethod.ID)
|
||||
}
|
||||
|
||||
override fun register(type: KClass<out ObtainMethod>, identifier: Identifier) {
|
||||
val existing = this.types.put(identifier.toString(), type)
|
||||
if (existing != null) {
|
||||
Cobblemon.LOGGER.debug("Replaced {} under ID {} with {} in the {}", existing::class.qualifiedName, identifier.toString(), type.qualifiedName, this::class.qualifiedName)
|
||||
}
|
||||
}
|
||||
|
||||
override fun deserialize(jElement: JsonElement, type: Type, context: JsonDeserializationContext): ObtainMethod {
|
||||
val json = jElement.asJsonObject
|
||||
val variant = json.get(VARIANT).asString.lowercase()
|
||||
val registeredType = this.types[variant] ?: throw IllegalArgumentException("Cannot resolve type for variant $variant")
|
||||
return context.deserialize(json, registeredType.java)
|
||||
}
|
||||
|
||||
override fun serialize(method: ObtainMethod, type: Type, context: JsonSerializationContext): JsonElement {
|
||||
val json = context.serialize(method).asJsonObject
|
||||
val variant = this.types.entries.find { it.value == method::class }?.key ?: throw IllegalArgumentException("Cannot resolve variant for type ${method::class.qualifiedName}")
|
||||
json.addProperty(VARIANT, variant)
|
||||
return json
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"format_version": "1.12.0",
|
||||
"minecraft:geometry": [
|
||||
{
|
||||
"description": {
|
||||
"identifier": "geometry.unknown",
|
||||
"texture_width": 64,
|
||||
"texture_height": 64,
|
||||
"visible_bounds_width": 3,
|
||||
"visible_bounds_height": 1.5,
|
||||
"visible_bounds_offset": [0, 0.25, 0]
|
||||
},
|
||||
"bones": [
|
||||
{
|
||||
"name": "bb_main",
|
||||
"pivot": [0, 0, 0],
|
||||
"cubes": [
|
||||
{"origin": [-11, 0, 4], "size": [8, 0, 8], "uv": [37, 55]}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"variants": {
|
||||
"facing=south,on=false": {
|
||||
"model": "cobblemon:block/tm_machine"
|
||||
},
|
||||
"facing=west,on=false": {
|
||||
"model": "cobblemon:block/tm_machine",
|
||||
"y": 90
|
||||
},
|
||||
"facing=north,on=false": {
|
||||
"model": "cobblemon:block/tm_machine",
|
||||
"y": 180
|
||||
},
|
||||
"facing=east,on=false": {
|
||||
"model": "cobblemon:block/tm_machine",
|
||||
"y": 270
|
||||
},
|
||||
"facing=south,on=true": {
|
||||
"model": "cobblemon:block/tm_machine_on"
|
||||
},
|
||||
"facing=west,on=true": {
|
||||
"model": "cobblemon:block/tm_machine_on",
|
||||
"y": 90
|
||||
},
|
||||
"facing=north,on=true": {
|
||||
"model": "cobblemon:block/tm_machine_on",
|
||||
"y": 180
|
||||
},
|
||||
"facing=east,on=true": {
|
||||
"model": "cobblemon:block/tm_machine_on",
|
||||
"y": 270
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -109,6 +109,8 @@
|
||||
"item.cobblemon.sun_stone": "Sun Stone",
|
||||
"item.cobblemon.thunder_stone": "Thunder Stone",
|
||||
"item.cobblemon.water_stone": "Water Stone",
|
||||
"item.cobblemon.technical_machine": "Technical Machine",
|
||||
"item.cobblemon.blank_tm": "Blank TM",
|
||||
|
||||
"item.cobblemon.rare_candy": "Rare Candy",
|
||||
"item.cobblemon.exp_candy_xs": "Exp. Candy XS",
|
||||
@@ -402,11 +404,12 @@
|
||||
"cobblemon.fossilmachine.protected": "This fossil belongs to %s!",
|
||||
|
||||
"itemGroup.cobblemon.blocks": "Blocks",
|
||||
"itemGroup.cobblemon.pokeball": "Poké Balls",
|
||||
"itemGroup.cobblemon.pokeball": "Tools",
|
||||
"itemGroup.cobblemon.agriculture": "Agriculture",
|
||||
"itemGroup.cobblemon.consumables": "Consumables",
|
||||
"itemGroup.cobblemon.held_item": "Held Items",
|
||||
"itemGroup.cobblemon.evolution_item": "Evolution Items",
|
||||
"itemGroup.cobblemon.technical_machines": "Technical Machines",
|
||||
"itemGroup.cobblemon.archaeology": "Archaeology",
|
||||
|
||||
"block.cobblemon.apricorn_log": "Apricorn Log",
|
||||
@@ -458,6 +461,7 @@
|
||||
"block.cobblemon.green_gilded_chest": "Green Gilded Chest",
|
||||
"block.cobblemon.white_gilded_chest": "White Gilded Chest",
|
||||
"block.cobblemon.display_case": "Display Case",
|
||||
"block.cobblemon.tm_machine": "TM Machine",
|
||||
|
||||
"block.cobblemon.small_budding_tumblestone": "Small Tumblestone Bud",
|
||||
"block.cobblemon.medium_budding_tumblestone": "Medium Tumblestone Bud",
|
||||
@@ -505,6 +509,15 @@
|
||||
"cobblemon.ui.moves.switch": "Switch Move",
|
||||
"cobblemon.ui.moves.pp": "%1$sPP",
|
||||
|
||||
"cobblemon.tms.unknown_move": "Unknown Move",
|
||||
"cobblemon.tms.already_known": "%1$s already knows %2$s!",
|
||||
"cobblemon.tms.teach_move": "%1$s learned %2$s!",
|
||||
"cobblemon.tms.cannot_learn": "%1$s cannot learn %2$s!",
|
||||
"cobblemon.tms.unlock_tm": "You unlocked the %1$s TM!",
|
||||
|
||||
"cobblemon.ui.tms.material_cost": "Material Cost",
|
||||
"cobblemon.ui.tms.blank_tm_desc": "A blank disc used for crafting Technical Machines.",
|
||||
|
||||
"cobblemon.ui.stats": "Stats",
|
||||
"cobblemon.ui.stats.stat": "Stat",
|
||||
"cobblemon.ui.stats.base": "Base",
|
||||
@@ -542,6 +555,8 @@
|
||||
"cobblemon.ui.party": "Party",
|
||||
"cobblemon.ui.power": "Power",
|
||||
"cobblemon.ui.accuracy": "Accuracy",
|
||||
"cobblemon.ui.accuracy_short": "Acc.",
|
||||
"cobblemon.ui.pp": "PP",
|
||||
"cobblemon.ui.effect": "Effect",
|
||||
"cobblemon.ui.pokemon": "Pokémon",
|
||||
"cobblemon.ui.exit": "Exit",
|
||||
@@ -567,6 +582,13 @@
|
||||
"key.cobblemon.summary": "Open Summary",
|
||||
"key.cobblemon.categories.cobblemon": "Cobblemon",
|
||||
|
||||
"cobblemon.subtitle.capture_succeeded": "Capture Succeeded!",
|
||||
"cobblemon.subtitle.tm.use": "Technical Machine used",
|
||||
"cobblemon.subtitle.tmm.craft": "TM Machine prints TM",
|
||||
"cobblemon.subtitle.tmm.craft_blank": "TM Machine crafts blank TM",
|
||||
"cobblemon.subtitle.tmm.off": "TM Machine deactivates",
|
||||
"cobblemon.subtitle.tmm.on": "TM Machine activates",
|
||||
|
||||
"cobblemon.subtitle.poke_ball.capture_succeeded": "Poké Ball capture succeeds",
|
||||
"cobblemon.subtitle.fossilmachine.activate": "Restoration Machine activates",
|
||||
"cobblemon.subtitle.fossilmachine.active_loop": "Restoration Machine hums",
|
||||
|
||||
@@ -0,0 +1,199 @@
|
||||
{
|
||||
"credit": "Made with Blockbench",
|
||||
"texture_size": [64, 64],
|
||||
"textures": {
|
||||
"0": "cobblemon:block/tm_machine",
|
||||
"particle": "cobblemon:block/tm_machine"
|
||||
},
|
||||
"elements": [
|
||||
{
|
||||
"from": [0, 0, 1],
|
||||
"to": [16, 5, 16],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [8, 0, 8]},
|
||||
"faces": {
|
||||
"north": {"uv": [3.5, 7.75, 7.5, 9], "texture": "#0"},
|
||||
"east": {"uv": [7.5, 9.5, 11.25, 10.75], "texture": "#0"},
|
||||
"south": {"uv": [3.5, 9, 7.5, 10.25], "texture": "#0"},
|
||||
"west": {"uv": [10, 0, 13.75, 1.25], "texture": "#0"},
|
||||
"up": {"uv": [4, 3.75, 0, 0], "texture": "#0"},
|
||||
"down": {"uv": [4, 3.75, 0, 7.5], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [6, 5, 2],
|
||||
"to": [14, 13, 4],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [8, 0, 8]},
|
||||
"faces": {
|
||||
"north": {"uv": [0, 9.75, 2, 11.75], "texture": "#0"},
|
||||
"east": {"uv": [10.5, 10.75, 11, 12.75], "texture": "#0"},
|
||||
"south": {"uv": [10, 1.25, 12, 3.25], "texture": "#0"},
|
||||
"west": {"uv": [11, 10.75, 11.5, 12.75], "texture": "#0"},
|
||||
"up": {"uv": [13.25, 9.75, 11.25, 9.25], "texture": "#0"},
|
||||
"down": {"uv": [13.25, 9.75, 11.25, 10.25], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [14, 5, 1],
|
||||
"to": [16, 15, 4],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [8, 0, 8]},
|
||||
"faces": {
|
||||
"north": {"uv": [6.5, 10.25, 7, 12.75], "texture": "#0"},
|
||||
"east": {"uv": [3.5, 10.25, 4.25, 12.75], "texture": "#0"},
|
||||
"south": {"uv": [7, 10.25, 7.5, 12.75], "texture": "#0"},
|
||||
"west": {"uv": [4.25, 10.25, 5, 12.75], "texture": "#0"},
|
||||
"up": {"uv": [12.25, 5.75, 11.75, 5], "texture": "#0"},
|
||||
"down": {"uv": [12.5, 1.25, 12, 2], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [6, 13, 1],
|
||||
"to": [14, 15, 4],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [8, 0, 8]},
|
||||
"faces": {
|
||||
"north": {"uv": [11.25, 10.25, 13.25, 10.75], "texture": "#0"},
|
||||
"east": {"uv": [12, 2, 12.75, 2.5], "texture": "#0"},
|
||||
"south": {"uv": [7.5, 11.5, 9.5, 12], "texture": "#0"},
|
||||
"west": {"uv": [12, 2.5, 12.75, 3], "texture": "#0"},
|
||||
"up": {"uv": [12.25, 6.5, 10.25, 5.75], "texture": "#0"},
|
||||
"down": {"uv": [12.25, 6.5, 10.25, 7.25], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [0, 5, 1],
|
||||
"to": [6, 15, 4],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [8, 0, 8]},
|
||||
"faces": {
|
||||
"north": {"uv": [2, 9.75, 3.5, 12.25], "texture": "#0"},
|
||||
"east": {"uv": [5, 10.25, 5.75, 12.75], "texture": "#0"},
|
||||
"south": {"uv": [10.25, 3.25, 11.75, 5.75], "texture": "#0"},
|
||||
"west": {"uv": [5.75, 10.25, 6.5, 12.75], "texture": "#0"},
|
||||
"up": {"uv": [9, 11.5, 7.5, 10.75], "texture": "#0"},
|
||||
"down": {"uv": [10.5, 10.75, 9, 11.5], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [1, 5, 4],
|
||||
"to": [15, 14, 15],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [8, 14.25, 4]},
|
||||
"faces": {
|
||||
"north": {"uv": [4, 5.5, 7.5, 7.75], "texture": "#0"},
|
||||
"east": {"uv": [7.5, 5, 10.25, 7.25], "texture": "#0"},
|
||||
"south": {"uv": [0, 7.5, 3.5, 9.75], "texture": "#0"},
|
||||
"west": {"uv": [7.5, 7.25, 10.25, 9.5], "texture": "#0"},
|
||||
"up": {"uv": [7.5, 2.75, 4, 0], "texture": "#0"},
|
||||
"down": {"uv": [7.5, 2.75, 4, 5.5], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [14, 0, 6],
|
||||
"to": [14, 7, 8],
|
||||
"shade": false,
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [8, -5, 6]},
|
||||
"faces": {
|
||||
"north": {"uv": [0, 0, 0, 1.75], "texture": "#0"},
|
||||
"east": {"uv": [9.5, 11.5, 10, 13.25], "texture": "#0"},
|
||||
"south": {"uv": [0, 0, 0, 1.75], "texture": "#0"},
|
||||
"west": {"uv": [10, 11.5, 10.5, 13.25], "texture": "#0"},
|
||||
"up": {"uv": [0, 0.5, 0, 0], "texture": "#0"},
|
||||
"down": {"uv": [0, 0, 0, 0.5], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [2, 0, 6],
|
||||
"to": [2, 7, 8],
|
||||
"shade": false,
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [8, -5, 6]},
|
||||
"faces": {
|
||||
"north": {"uv": [0, 0, 0, 1.75], "texture": "#0"},
|
||||
"east": {"uv": [11.5, 10.75, 12, 12.5], "texture": "#0"},
|
||||
"south": {"uv": [0, 0, 0, 1.75], "texture": "#0"},
|
||||
"west": {"uv": [0, 11.75, 0.5, 13.5], "texture": "#0"},
|
||||
"up": {"uv": [0, 0.5, 0, 0], "texture": "#0"},
|
||||
"down": {"uv": [0, 0, 0, 0.5], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [2, 7, 6],
|
||||
"to": [14, 7, 8],
|
||||
"shade": false,
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [8, -5, 6]},
|
||||
"faces": {
|
||||
"north": {"uv": [0, 0, 3, 0], "texture": "#0"},
|
||||
"east": {"uv": [0, 0, 0.5, 0], "texture": "#0"},
|
||||
"south": {"uv": [0, 0, 3, 0], "texture": "#0"},
|
||||
"west": {"uv": [0, 0, 0.5, 0], "texture": "#0"},
|
||||
"up": {"uv": [13.25, 7.75, 10.25, 7.25], "texture": "#0"},
|
||||
"down": {"uv": [13.25, 7.75, 10.25, 8.25], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [14, 0, 10],
|
||||
"to": [14, 7, 12],
|
||||
"shade": false,
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [8, -5, 10]},
|
||||
"faces": {
|
||||
"north": {"uv": [0, 0, 0, 1.75], "texture": "#0"},
|
||||
"east": {"uv": [0.5, 11.75, 1, 13.5], "texture": "#0"},
|
||||
"south": {"uv": [0, 0, 0, 1.75], "texture": "#0"},
|
||||
"west": {"uv": [1, 11.75, 1.5, 13.5], "texture": "#0"},
|
||||
"up": {"uv": [0, 0.5, 0, 0], "texture": "#0"},
|
||||
"down": {"uv": [0, 0, 0, 0.5], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [2, 0, 10],
|
||||
"to": [2, 7, 12],
|
||||
"shade": false,
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [8, -5, 10]},
|
||||
"faces": {
|
||||
"north": {"uv": [0, 0, 0, 1.75], "texture": "#0"},
|
||||
"east": {"uv": [1.5, 11.75, 2, 13.5], "texture": "#0"},
|
||||
"south": {"uv": [0, 0, 0, 1.75], "texture": "#0"},
|
||||
"west": {"uv": [11.75, 3.25, 12.25, 5], "texture": "#0"},
|
||||
"up": {"uv": [0, 0.5, 0, 0], "texture": "#0"},
|
||||
"down": {"uv": [0, 0, 0, 0.5], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [2, 7, 10],
|
||||
"to": [14, 7, 12],
|
||||
"shade": false,
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [8, -5, 10]},
|
||||
"faces": {
|
||||
"north": {"uv": [0, 0, 3, 0], "texture": "#0"},
|
||||
"east": {"uv": [0, 0, 0.5, 0], "texture": "#0"},
|
||||
"south": {"uv": [0, 0, 3, 0], "texture": "#0"},
|
||||
"west": {"uv": [0, 0, 0.5, 0], "texture": "#0"},
|
||||
"up": {"uv": [13.25, 8.75, 10.25, 8.25], "texture": "#0"},
|
||||
"down": {"uv": [13.25, 8.75, 10.25, 9.25], "texture": "#0"}
|
||||
}
|
||||
}
|
||||
],
|
||||
"groups": [
|
||||
{
|
||||
"name": "tm_machine",
|
||||
"origin": [8, 8, 8],
|
||||
"color": 0,
|
||||
"children": [
|
||||
{
|
||||
"name": "machine",
|
||||
"origin": [8, 0, 8],
|
||||
"color": 0,
|
||||
"children": [0, 1, 2, 3, 4, 5]
|
||||
},
|
||||
{
|
||||
"name": "arm1",
|
||||
"origin": [8, -5, 8],
|
||||
"color": 0,
|
||||
"children": [6, 7, 8]
|
||||
},
|
||||
{
|
||||
"name": "arm2",
|
||||
"origin": [8, -5, 8],
|
||||
"color": 0,
|
||||
"children": [9, 10, 11]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,199 @@
|
||||
{
|
||||
"credit": "Made with Blockbench",
|
||||
"texture_size": [64, 64],
|
||||
"textures": {
|
||||
"0": "cobblemon:block/tm_machine_on",
|
||||
"particle": "cobblemon:block/tm_machine_on"
|
||||
},
|
||||
"elements": [
|
||||
{
|
||||
"from": [0, 0, 1],
|
||||
"to": [16, 5, 16],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [8, 0, 8]},
|
||||
"faces": {
|
||||
"north": {"uv": [3.5, 7.75, 7.5, 9], "texture": "#0"},
|
||||
"east": {"uv": [7.5, 9.5, 11.25, 10.75], "texture": "#0"},
|
||||
"south": {"uv": [3.5, 9, 7.5, 10.25], "texture": "#0"},
|
||||
"west": {"uv": [10, 0, 13.75, 1.25], "texture": "#0"},
|
||||
"up": {"uv": [4, 3.75, 0, 0], "texture": "#0"},
|
||||
"down": {"uv": [4, 3.75, 0, 7.5], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [6, 5, 2],
|
||||
"to": [14, 13, 4],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [8, 0, 8]},
|
||||
"faces": {
|
||||
"north": {"uv": [0, 9.75, 2, 11.75], "texture": "#0"},
|
||||
"east": {"uv": [10.5, 10.75, 11, 12.75], "texture": "#0"},
|
||||
"south": {"uv": [10, 1.25, 12, 3.25], "texture": "#0"},
|
||||
"west": {"uv": [11, 10.75, 11.5, 12.75], "texture": "#0"},
|
||||
"up": {"uv": [13.25, 9.75, 11.25, 9.25], "texture": "#0"},
|
||||
"down": {"uv": [13.25, 9.75, 11.25, 10.25], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [14, 5, 1],
|
||||
"to": [16, 15, 4],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [8, 0, 8]},
|
||||
"faces": {
|
||||
"north": {"uv": [6.5, 10.25, 7, 12.75], "texture": "#0"},
|
||||
"east": {"uv": [3.5, 10.25, 4.25, 12.75], "texture": "#0"},
|
||||
"south": {"uv": [7, 10.25, 7.5, 12.75], "texture": "#0"},
|
||||
"west": {"uv": [4.25, 10.25, 5, 12.75], "texture": "#0"},
|
||||
"up": {"uv": [12.25, 5.75, 11.75, 5], "texture": "#0"},
|
||||
"down": {"uv": [12.5, 1.25, 12, 2], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [6, 13, 1],
|
||||
"to": [14, 15, 4],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [8, 0, 8]},
|
||||
"faces": {
|
||||
"north": {"uv": [11.25, 10.25, 13.25, 10.75], "texture": "#0"},
|
||||
"east": {"uv": [12, 2, 12.75, 2.5], "texture": "#0"},
|
||||
"south": {"uv": [7.5, 11.5, 9.5, 12], "texture": "#0"},
|
||||
"west": {"uv": [12, 2.5, 12.75, 3], "texture": "#0"},
|
||||
"up": {"uv": [12.25, 6.5, 10.25, 5.75], "texture": "#0"},
|
||||
"down": {"uv": [12.25, 6.5, 10.25, 7.25], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [0, 5, 1],
|
||||
"to": [6, 15, 4],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [8, 0, 8]},
|
||||
"faces": {
|
||||
"north": {"uv": [2, 9.75, 3.5, 12.25], "texture": "#0"},
|
||||
"east": {"uv": [5, 10.25, 5.75, 12.75], "texture": "#0"},
|
||||
"south": {"uv": [10.25, 3.25, 11.75, 5.75], "texture": "#0"},
|
||||
"west": {"uv": [5.75, 10.25, 6.5, 12.75], "texture": "#0"},
|
||||
"up": {"uv": [9, 11.5, 7.5, 10.75], "texture": "#0"},
|
||||
"down": {"uv": [10.5, 10.75, 9, 11.5], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [1, 5, 4],
|
||||
"to": [15, 14, 15],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [8, 14.25, 4]},
|
||||
"faces": {
|
||||
"north": {"uv": [4, 5.5, 7.5, 7.75], "texture": "#0"},
|
||||
"east": {"uv": [7.5, 5, 10.25, 7.25], "texture": "#0"},
|
||||
"south": {"uv": [0, 7.5, 3.5, 9.75], "texture": "#0"},
|
||||
"west": {"uv": [7.5, 7.25, 10.25, 9.5], "texture": "#0"},
|
||||
"up": {"uv": [7.5, 2.75, 4, 0], "texture": "#0"},
|
||||
"down": {"uv": [7.5, 2.75, 4, 5.5], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [14, 0, 6],
|
||||
"to": [14, 7, 8],
|
||||
"shade": false,
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [8, -5, 6]},
|
||||
"faces": {
|
||||
"north": {"uv": [0, 0, 0, 1.75], "texture": "#0"},
|
||||
"east": {"uv": [9.5, 11.5, 10, 13.25], "texture": "#0"},
|
||||
"south": {"uv": [0, 0, 0, 1.75], "texture": "#0"},
|
||||
"west": {"uv": [10, 11.5, 10.5, 13.25], "texture": "#0"},
|
||||
"up": {"uv": [0, 0.5, 0, 0], "texture": "#0"},
|
||||
"down": {"uv": [0, 0, 0, 0.5], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [2, 0, 6],
|
||||
"to": [2, 7, 8],
|
||||
"shade": false,
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [8, -5, 6]},
|
||||
"faces": {
|
||||
"north": {"uv": [0, 0, 0, 1.75], "texture": "#0"},
|
||||
"east": {"uv": [11.5, 10.75, 12, 12.5], "texture": "#0"},
|
||||
"south": {"uv": [0, 0, 0, 1.75], "texture": "#0"},
|
||||
"west": {"uv": [0, 11.75, 0.5, 13.5], "texture": "#0"},
|
||||
"up": {"uv": [0, 0.5, 0, 0], "texture": "#0"},
|
||||
"down": {"uv": [0, 0, 0, 0.5], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [2, 7, 6],
|
||||
"to": [14, 7, 8],
|
||||
"shade": false,
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [8, -5, 6]},
|
||||
"faces": {
|
||||
"north": {"uv": [0, 0, 3, 0], "texture": "#0"},
|
||||
"east": {"uv": [0, 0, 0.5, 0], "texture": "#0"},
|
||||
"south": {"uv": [0, 0, 3, 0], "texture": "#0"},
|
||||
"west": {"uv": [0, 0, 0.5, 0], "texture": "#0"},
|
||||
"up": {"uv": [13.25, 7.75, 10.25, 7.25], "texture": "#0"},
|
||||
"down": {"uv": [13.25, 7.75, 10.25, 8.25], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [14, 0, 10],
|
||||
"to": [14, 7, 12],
|
||||
"shade": false,
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [8, -5, 10]},
|
||||
"faces": {
|
||||
"north": {"uv": [0, 0, 0, 1.75], "texture": "#0"},
|
||||
"east": {"uv": [0.5, 11.75, 1, 13.5], "texture": "#0"},
|
||||
"south": {"uv": [0, 0, 0, 1.75], "texture": "#0"},
|
||||
"west": {"uv": [1, 11.75, 1.5, 13.5], "texture": "#0"},
|
||||
"up": {"uv": [0, 0.5, 0, 0], "texture": "#0"},
|
||||
"down": {"uv": [0, 0, 0, 0.5], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [2, 0, 10],
|
||||
"to": [2, 7, 12],
|
||||
"shade": false,
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [8, -5, 10]},
|
||||
"faces": {
|
||||
"north": {"uv": [0, 0, 0, 1.75], "texture": "#0"},
|
||||
"east": {"uv": [1.5, 11.75, 2, 13.5], "texture": "#0"},
|
||||
"south": {"uv": [0, 0, 0, 1.75], "texture": "#0"},
|
||||
"west": {"uv": [11.75, 3.25, 12.25, 5], "texture": "#0"},
|
||||
"up": {"uv": [0, 0.5, 0, 0], "texture": "#0"},
|
||||
"down": {"uv": [0, 0, 0, 0.5], "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [2, 7, 10],
|
||||
"to": [14, 7, 12],
|
||||
"shade": false,
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [8, -5, 10]},
|
||||
"faces": {
|
||||
"north": {"uv": [0, 0, 3, 0], "texture": "#0"},
|
||||
"east": {"uv": [0, 0, 0.5, 0], "texture": "#0"},
|
||||
"south": {"uv": [0, 0, 3, 0], "texture": "#0"},
|
||||
"west": {"uv": [0, 0, 0.5, 0], "texture": "#0"},
|
||||
"up": {"uv": [13.25, 8.75, 10.25, 8.25], "texture": "#0"},
|
||||
"down": {"uv": [13.25, 8.75, 10.25, 9.25], "texture": "#0"}
|
||||
}
|
||||
}
|
||||
],
|
||||
"groups": [
|
||||
{
|
||||
"name": "tm_machine",
|
||||
"origin": [8, 8, 8],
|
||||
"color": 0,
|
||||
"children": [
|
||||
{
|
||||
"name": "machine",
|
||||
"origin": [8, 0, 8],
|
||||
"color": 0,
|
||||
"children": [0, 1, 2, 3, 4, 5]
|
||||
},
|
||||
{
|
||||
"name": "arm1",
|
||||
"origin": [8, -5, 8],
|
||||
"color": 0,
|
||||
"children": [6, 7, 8]
|
||||
},
|
||||
{
|
||||
"name": "arm2",
|
||||
"origin": [8, -5, 8],
|
||||
"color": 0,
|
||||
"children": [9, 10, 11]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "minecraft:item/generated",
|
||||
"textures": {
|
||||
"layer0": "cobblemon:item/tms/blank_disc"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"parent": "minecraft:item/generated",
|
||||
"textures": {
|
||||
"layer0": "cobblemon:item/tms/tm",
|
||||
"layer1": "cobblemon:item/tms/tm_overlay"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"parent": "cobblemon:block/tm_machine"
|
||||
}
|
||||
@@ -104,6 +104,26 @@
|
||||
"berry.eat": {
|
||||
"sounds": [ "cobblemon:berry_eat" ]
|
||||
},
|
||||
"tm.use": {
|
||||
"sounds": [ "cobblemon:tm/tm_use" ],
|
||||
"subtitle": "cobblemon.subtitle.tm.use"
|
||||
},
|
||||
"tmm.craft": {
|
||||
"sounds": [ "cobblemon:tm/tmm_craft" ],
|
||||
"subtitle": "cobblemon.subtitle.tmm.craft"
|
||||
},
|
||||
"tmm.craft_blank": {
|
||||
"sounds": [ "cobblemon:tm/tmm_craft_blank" ],
|
||||
"subtitle": "cobblemon.subtitle.tmm.craft_blank"
|
||||
},
|
||||
"tmm.off": {
|
||||
"sounds": [ "cobblemon:tm/tmm_off" ],
|
||||
"subtitle": "cobblemon.subtitle.tmm.off"
|
||||
},
|
||||
"tmm.on": {
|
||||
"sounds": [ "cobblemon:tm/tmm_on" ],
|
||||
"subtitle": "cobblemon.subtitle.tmm.on"
|
||||
},
|
||||
"fossilmachine.activate": {
|
||||
"subtitle": "cobblemon.subtitle.fossilmachine.activate",
|
||||
"sounds": [ "cobblemon:fossilmachine/activate" ]
|
||||
|
||||
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 962 B |
|
After Width: | Height: | Size: 345 B |
|
After Width: | Height: | Size: 310 B |
|
After Width: | Height: | Size: 354 B |
|
After Width: | Height: | Size: 226 B |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 706 B |
|
After Width: | Height: | Size: 412 B |
|
After Width: | Height: | Size: 423 B |
|
After Width: | Height: | Size: 3.5 KiB |
|
After Width: | Height: | Size: 3.3 KiB |
|
After Width: | Height: | Size: 3.6 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 7.4 KiB After Width: | Height: | Size: 7.8 KiB |
|
After Width: | Height: | Size: 299 B |
|
After Width: | Height: | Size: 474 B |
|
After Width: | Height: | Size: 299 B |
|
After Width: | Height: | Size: 281 B |
|
After Width: | Height: | Size: 340 B |
@@ -90,6 +90,8 @@ transitive-accessible method net/minecraft/client/texture/SpriteAtlasHolder getS
|
||||
transitive-accessible field net/minecraft/client/texture/SpriteAtlasHolder atlas Lnet/minecraft/client/texture/SpriteAtlasTexture;
|
||||
transitive-accessible field net/minecraft/client/texture/SpriteAtlasTexture width I
|
||||
transitive-accessible field net/minecraft/client/texture/SpriteAtlasTexture height I
|
||||
transitive-accessible class net/minecraft/screen/ScreenHandlerType$Factory
|
||||
transitive-accessible method net/minecraft/client/gui/screen/ingame/HandledScreens register (Lnet/minecraft/screen/ScreenHandlerType;Lnet/minecraft/client/gui/screen/ingame/HandledScreens$Provider;)V
|
||||
|
||||
transitive-accessible method net/minecraft/entity/ai/brain/Activity register (Ljava/lang/String;)Lnet/minecraft/entity/ai/brain/Activity;
|
||||
transitive-accessible field net/minecraft/client/model/ModelPart$Cuboid sides [Lnet/minecraft/client/model/ModelPart$Quad;
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"parent": "cobblemon:recipes/root",
|
||||
"rewards": {
|
||||
"recipes": [
|
||||
"cobblemon:tm_machine"
|
||||
]
|
||||
},
|
||||
"criteria": {
|
||||
"has_tm": {
|
||||
"trigger": "minecraft:inventory_changed",
|
||||
"conditions": {
|
||||
"items": [
|
||||
{
|
||||
"items": [
|
||||
"cobblemon:blank_tm"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"has_the_recipe": {
|
||||
"trigger": "minecraft:recipe_unlocked",
|
||||
"conditions": {
|
||||
"recipe": "cobblemon:tm_machine"
|
||||
}
|
||||
}
|
||||
},
|
||||
"requirements": [
|
||||
[
|
||||
"has_tm",
|
||||
"has_the_recipe"
|
||||
]
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"parent": "cobblemon:recipes/root",
|
||||
"rewards": {
|
||||
"recipes": [
|
||||
"cobblemon:blank_tm"
|
||||
]
|
||||
},
|
||||
"criteria": {
|
||||
"has_amethyst": {
|
||||
"trigger": "minecraft:inventory_changed",
|
||||
"conditions": {
|
||||
"items": [
|
||||
{
|
||||
"items": [
|
||||
"minecraft:amethyst_shard"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"has_the_recipe": {
|
||||
"trigger": "minecraft:recipe_unlocked",
|
||||
"conditions": {
|
||||
"recipe": "cobblemon:blank_tm"
|
||||
}
|
||||
}
|
||||
},
|
||||
"requirements": [
|
||||
[
|
||||
"has_amethyst",
|
||||
"has_the_recipe"
|
||||
]
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"type": "minecraft:crafting_shaped",
|
||||
"pattern": [
|
||||
"AG",
|
||||
"GA"
|
||||
],
|
||||
"key": {
|
||||
"G": {
|
||||
"item": "minecraft:glass"
|
||||
},
|
||||
"A": {
|
||||
"item": "minecraft:amethyst_shard"
|
||||
}
|
||||
},
|
||||
"result": {
|
||||
"item": "cobblemon:blank_tm",
|
||||
"count": 2
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"type": "minecraft:crafting_shaped",
|
||||
"pattern": [
|
||||
"GGI",
|
||||
"GTD",
|
||||
"IRI"
|
||||
],
|
||||
"key": {
|
||||
"G": {
|
||||
"item": "minecraft:glass"
|
||||
},
|
||||
"I": {
|
||||
"item": "minecraft:iron_ingot"
|
||||
},
|
||||
"T": {
|
||||
"item": "cobblemon:blank_tm"
|
||||
},
|
||||
"D": {
|
||||
"item": "minecraft:diamond"
|
||||
},
|
||||
"R": {
|
||||
"item": "minecraft:comparator"
|
||||
}
|
||||
},
|
||||
"result": {
|
||||
"item": "cobblemon:tm_machine"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"moveName": "bubblebeam",
|
||||
"obtainMethods": [
|
||||
{
|
||||
"variant": "cobblemon:advancement",
|
||||
"advancement": "cobblemon:craft_remedy"
|
||||
}
|
||||
],
|
||||
"type": "water"
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"moveName": "dazzlinggleam",
|
||||
"obtainMethods": [
|
||||
{
|
||||
"variant": "cobblemon:impossible"
|
||||
}
|
||||
],
|
||||
"type": "fairy"
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"moveName": "dragonrage",
|
||||
"obtainMethods": [
|
||||
{
|
||||
"variant": "cobblemon:impossible"
|
||||
}
|
||||
],
|
||||
"type": "dragon"
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"moveName": "earthquake",
|
||||
"obtainMethods": [
|
||||
{
|
||||
"variant": "cobblemon:impossible"
|
||||
}
|
||||
],
|
||||
"type": "ground"
|
||||
}
|
||||