mirror of
https://gitlab.com/cable-mc/cobblemon.git
synced 2026-10-27 04:26:27 -04:00
Compare commits
25
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bfa830b008 | ||
|
|
f944b1e533 | ||
|
|
f67e581256 | ||
|
|
6a3cd46dd2 | ||
|
|
e63c7b9faf | ||
|
|
6b5a6e1fc5 | ||
|
|
0306259d39 | ||
|
|
aaea445900 | ||
|
|
9919358443 | ||
|
|
8b2619c79b | ||
|
|
6e2d62ddb8 | ||
|
|
c575ade2dc | ||
|
|
b3cd548774 | ||
|
|
556293860f | ||
|
|
50b921f4a4 | ||
|
|
4de5f0d5ac | ||
|
|
90f6ad327d | ||
|
|
312e9e75ed | ||
|
|
41e80aad63 | ||
|
|
81fd09f6d8 | ||
|
|
990127a3f4 | ||
|
|
e0b165b35a | ||
|
|
7fa01e05a0 | ||
|
|
73040f9a31 | ||
|
|
81258abaeb |
@@ -0,0 +1,72 @@
|
|||||||
|
/*
|
||||||
|
* 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.mixin;
|
||||||
|
|
||||||
|
import com.cobblemon.mod.common.block.SaccharineLeafBlock;
|
||||||
|
import net.minecraft.block.*;
|
||||||
|
import net.minecraft.entity.EntityType;
|
||||||
|
import net.minecraft.entity.Flutterer;
|
||||||
|
import net.minecraft.entity.LivingEntity;
|
||||||
|
import net.minecraft.entity.mob.Angerable;
|
||||||
|
import net.minecraft.entity.mob.PathAwareEntity;
|
||||||
|
import net.minecraft.entity.passive.AnimalEntity;
|
||||||
|
import net.minecraft.entity.passive.BeeEntity;
|
||||||
|
import net.minecraft.server.world.ServerWorld;
|
||||||
|
import net.minecraft.sound.SoundEvents;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
import net.minecraft.world.WorldView;
|
||||||
|
import org.objectweb.asm.Opcodes;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.Unique;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Desc;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
import org.spongepowered.asm.mixin.injection.ModifyVariable;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Slice;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
|
||||||
|
|
||||||
|
|
||||||
|
@Mixin(targets="net.minecraft.entity.passive.BeeEntity$GrowCropsGoal")
|
||||||
|
public abstract class BeeEntityMixin {
|
||||||
|
|
||||||
|
@Unique
|
||||||
|
private BlockState cobblemon$result = null;
|
||||||
|
|
||||||
|
@Inject(method = "tick()V", at = @At(
|
||||||
|
value = "INVOKE",
|
||||||
|
target = "Lnet/minecraft/block/Fertilizable;grow(Lnet/minecraft/server/world/ServerWorld;Lnet/minecraft/util/math/random/Random;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/BlockState;)V",
|
||||||
|
shift = At.Shift.BY,
|
||||||
|
by = 2
|
||||||
|
),
|
||||||
|
locals = LocalCapture.CAPTURE_FAILHARD
|
||||||
|
)
|
||||||
|
private void injectCustomGrowth(CallbackInfo ci, int i, BlockPos blockPos, BlockState blockState, Block block) {
|
||||||
|
if (block instanceof SaccharineLeafBlock) {
|
||||||
|
|
||||||
|
int age = blockState.get(SaccharineLeafBlock.Companion.getAGE());
|
||||||
|
|
||||||
|
if (age < 2) {
|
||||||
|
this.cobblemon$result = blockState.with(SaccharineLeafBlock.Companion.getAGE(), age + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ModifyVariable(method = "tick", at = @At(value = "LOAD", ordinal = 0), index = 5)
|
||||||
|
private BlockState applyCustomBlockState(BlockState before) {
|
||||||
|
if(this.cobblemon$result != null && before == null) {
|
||||||
|
BlockState result = this.cobblemon$result;
|
||||||
|
this.cobblemon$result = null;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return before;
|
||||||
|
}
|
||||||
|
}
|
||||||
+16
@@ -0,0 +1,16 @@
|
|||||||
|
package com.cobblemon.mod.common.mixin.invoker;
|
||||||
|
|
||||||
|
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.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();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -83,4 +83,9 @@ object CobblemonBlockEntities : PlatformRegistry<Registry<BlockEntityType<*>>, R
|
|||||||
val DISPLAY_CASE: BlockEntityType<DisplayCaseBlockEntity> = this.create("display_case",
|
val DISPLAY_CASE: BlockEntityType<DisplayCaseBlockEntity> = this.create("display_case",
|
||||||
BlockEntityType.Builder.create(::DisplayCaseBlockEntity, CobblemonBlocks.DISPLAY_CASE).build(null)
|
BlockEntityType.Builder.create(::DisplayCaseBlockEntity, CobblemonBlocks.DISPLAY_CASE).build(null)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
val COOKING_POT: BlockEntityType<CookingPotBlockEntity> = this.create("cooking_pot",
|
||||||
|
BlockEntityType.Builder.create(::CookingPotBlockEntity, CobblemonBlocks.COOKING_POT).build(null)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import com.cobblemon.mod.common.block.sign.CobblemonSignBlock
|
|||||||
import com.cobblemon.mod.common.block.sign.CobblemonWallHangingSignBlock
|
import com.cobblemon.mod.common.block.sign.CobblemonWallHangingSignBlock
|
||||||
import com.cobblemon.mod.common.block.sign.CobblemonWallSignBlock
|
import com.cobblemon.mod.common.block.sign.CobblemonWallSignBlock
|
||||||
import net.minecraft.block.*
|
import net.minecraft.block.*
|
||||||
|
import net.minecraft.block.AbstractBlock.Settings
|
||||||
import net.minecraft.block.enums.Instrument
|
import net.minecraft.block.enums.Instrument
|
||||||
import net.minecraft.block.piston.PistonBehavior
|
import net.minecraft.block.piston.PistonBehavior
|
||||||
import net.minecraft.entity.effect.StatusEffects
|
import net.minecraft.entity.effect.StatusEffects
|
||||||
@@ -49,6 +50,8 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, RegistryKey<Registry<
|
|||||||
|
|
||||||
val APRICORN_BLOCK_SET_TYPE = BlockSetType("apricorn")
|
val APRICORN_BLOCK_SET_TYPE = BlockSetType("apricorn")
|
||||||
val APRICORN_WOOD_TYPE = WoodType.register(WoodType("apricorn", APRICORN_BLOCK_SET_TYPE))
|
val APRICORN_WOOD_TYPE = WoodType.register(WoodType("apricorn", APRICORN_BLOCK_SET_TYPE))
|
||||||
|
val SACCHARINE_BLOCK_SET_TYPE = BlockSetType("saccharine")
|
||||||
|
val SACCHARINE_WOOD_TYPE = WoodType.register(WoodType("saccharine", SACCHARINE_BLOCK_SET_TYPE))
|
||||||
|
|
||||||
// Evolution Ores
|
// Evolution Ores
|
||||||
@JvmField
|
@JvmField
|
||||||
@@ -153,9 +156,52 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, RegistryKey<Registry<
|
|||||||
@JvmField
|
@JvmField
|
||||||
val YELLOW_APRICORN_SAPLING = this.create("yellow_apricorn_sapling", ApricornSaplingBlock(PLANT_PROPERTIES, Apricorn.YELLOW))
|
val YELLOW_APRICORN_SAPLING = this.create("yellow_apricorn_sapling", ApricornSaplingBlock(PLANT_PROPERTIES, Apricorn.YELLOW))
|
||||||
|
|
||||||
|
// Saccharines
|
||||||
|
@JvmField
|
||||||
|
val SACCHARINE_LOG = log("saccharine_log", arg2 = MapColor.BLUE)
|
||||||
|
@JvmField
|
||||||
|
val STRIPPED_SACCHARINE_LOG = this.create("stripped_saccharine_log", SaccharineStrippedLogBlock(Settings.create().mapColor(MapColor.LIGHT_BLUE).instrument(Instrument.BASS).strength(2.0F).sounds(BlockSoundGroup.WOOD).burnable())) //log("stripped_saccharine_log")
|
||||||
|
@JvmField
|
||||||
|
val SACCHARINE_WOOD = log("saccharine_wood")
|
||||||
|
@JvmField
|
||||||
|
val STRIPPED_SACCHARINE_WOOD = this.create("stripped_saccharine_wood", SaccharineStrippedLogBlock(Settings.create().mapColor(MapColor.LIGHT_BLUE).instrument(Instrument.BASS).strength(2.0F).sounds(BlockSoundGroup.WOOD).burnable())) //log("stripped_saccharine_log")
|
||||||
|
//log("stripped_saccharine_wood")
|
||||||
|
@JvmField
|
||||||
|
val SACCHARINE_PLANKS = this.create("saccharine_planks", Block(AbstractBlock.Settings.create().mapColor(MapColor.LIGHT_BLUE).instrument(Instrument.BASS).strength(2.0f, 3.0f).sounds(BlockSoundGroup.WOOD)))
|
||||||
|
@JvmField
|
||||||
|
val SACCHARINE_LEAVES = this.create("saccharine_leaves", SaccharineLeafBlock(Settings.create().mapColor(MapColor.LIGHT_BLUE).strength(0.2F).ticksRandomly().sounds(BlockSoundGroup.GRASS).nonOpaque().allowsSpawning { _, _, _, _ -> false }))
|
||||||
|
@JvmField
|
||||||
|
val SACCHARINE_FENCE = this.create("saccharine_fence", FenceBlock(AbstractBlock.Settings.create().mapColor(SACCHARINE_PLANKS.defaultMapColor).instrument(Instrument.BASS).strength(2.0f, 3.0f).sounds(BlockSoundGroup.WOOD)))
|
||||||
|
@JvmField
|
||||||
|
val SACCHARINE_FENCE_GATE = this.create("saccharine_fence_gate", FenceGateBlock(AbstractBlock.Settings.create().mapColor(SACCHARINE_PLANKS.defaultMapColor).instrument(Instrument.BASS).strength(2.0f, 3.0f).sounds(BlockSoundGroup.WOOD), SACCHARINE_WOOD_TYPE))
|
||||||
|
@JvmField // Note At the time of 1.20.0 we don't need our own BlockSetType for SACCHARINE wood
|
||||||
|
val SACCHARINE_BUTTON = this.create("saccharine_button", BlocksInvoker.createWoodenButtonBlock(BlockSetType.OAK))
|
||||||
|
@JvmField
|
||||||
|
val SACCHARINE_PRESSURE_PLATE = this.create("saccharine_pressure_plate", PressurePlateBlockInvoker.`cobblemon$create`(PressurePlateBlock.ActivationRule.EVERYTHING, AbstractBlock.Settings.create().mapColor(SACCHARINE_PLANKS.defaultMapColor).instrument(Instrument.BASS).noCollision().strength(0.5f).sounds(BlockSoundGroup.WOOD), SACCHARINE_BLOCK_SET_TYPE))
|
||||||
|
@JvmField
|
||||||
|
val SACCHARINE_SIGN = this.create("saccharine_sign", CobblemonSignBlock(AbstractBlock.Settings.copy(Blocks.OAK_SIGN), SACCHARINE_WOOD_TYPE))
|
||||||
|
@JvmField
|
||||||
|
val SACCHARINE_WALL_SIGN = this.create("saccharine_wall_sign", CobblemonWallSignBlock(AbstractBlock.Settings.copy(Blocks.OAK_WALL_SIGN), SACCHARINE_WOOD_TYPE))
|
||||||
|
@JvmField
|
||||||
|
val SACCHARINE_HANGING_SIGN = this.create("saccharine_hanging_sign", CobblemonHangingSignBlock(AbstractBlock.Settings.copy(Blocks.OAK_WALL_HANGING_SIGN), SACCHARINE_WOOD_TYPE))
|
||||||
|
@JvmField
|
||||||
|
val SACCHARINE_WALL_HANGING_SIGN = this.create("saccharine_wall_hanging_sign", CobblemonWallHangingSignBlock(AbstractBlock.Settings.copy(Blocks.OAK_HANGING_SIGN), SACCHARINE_WOOD_TYPE))
|
||||||
|
@JvmField
|
||||||
|
val SACCHARINE_SLAB = this.create("saccharine_slab", SlabBlock(AbstractBlock.Settings.create().mapColor(MapColor.OAK_TAN).instrument(Instrument.BASS).strength(2.0f, 3.0f).sounds(BlockSoundGroup.WOOD)))
|
||||||
|
@JvmField
|
||||||
|
val SACCHARINE_STAIRS = this.create("saccharine_stairs", StairsBlockInvoker.`cobblemon$create`(SACCHARINE_PLANKS.defaultState, AbstractBlock.Settings.copy(SACCHARINE_PLANKS)))
|
||||||
|
@JvmField
|
||||||
|
val SACCHARINE_DOOR = this.create("saccharine_door", DoorBlockInvoker.`cobblemon$create`(AbstractBlock.Settings.create().mapColor(SACCHARINE_PLANKS.defaultMapColor).instrument(Instrument.BASS).strength(3.0F).sounds(BlockSoundGroup.WOOD).nonOpaque(), SACCHARINE_BLOCK_SET_TYPE))
|
||||||
|
@JvmField
|
||||||
|
val SACCHARINE_TRAPDOOR = this.create("saccharine_trapdoor", TrapdoorBlockInvoker.`cobblemon$create`(AbstractBlock.Settings.create().mapColor(MapColor.OAK_TAN).instrument(Instrument.BASS).strength(3.0F).sounds(BlockSoundGroup.WOOD).nonOpaque().allowsSpawning { _, _, _, _ -> false }, SACCHARINE_BLOCK_SET_TYPE))
|
||||||
|
@JvmField
|
||||||
|
val SACCHARINE_SAPLING = this.create("saccharine_sapling", SaccharineSaplingBlock(PLANT_PROPERTIES))
|
||||||
|
|
||||||
@JvmField
|
@JvmField
|
||||||
val MEDICINAL_LEEK = this.create("medicinal_leek", MedicinalLeekBlock(AbstractBlock.Settings.create().pistonBehavior(PistonBehavior.DESTROY).burnable().mapColor(MapColor.DULL_RED).noCollision().ticksRandomly().breakInstantly().sounds(CobblemonSounds.MEDICINAL_LEEK_SOUNDS)))
|
val MEDICINAL_LEEK = this.create("medicinal_leek", MedicinalLeekBlock(AbstractBlock.Settings.create().pistonBehavior(PistonBehavior.DESTROY).burnable().mapColor(MapColor.DULL_RED).noCollision().ticksRandomly().breakInstantly().sounds(CobblemonSounds.MEDICINAL_LEEK_SOUNDS)))
|
||||||
@JvmField
|
@JvmField
|
||||||
|
val BUGWORT = this.create("bugwort", BugwortBlock(AbstractBlock.Settings.create().pistonBehavior(PistonBehavior.DESTROY).burnable().mapColor(MapColor.PALE_PURPLE).noCollision().ticksRandomly().breakInstantly().sounds(CobblemonSounds.MEDICINAL_LEEK_SOUNDS)))
|
||||||
|
@JvmField
|
||||||
val ENERGY_ROOT = this.create("energy_root", EnergyRootBlock(AbstractBlock.Settings.create().pistonBehavior(PistonBehavior.DESTROY).burnable().mapColor(MapColor.DIRT_BROWN).noCollision().ticksRandomly().breakInstantly().sounds(CobblemonSounds.ENERGY_ROOT_SOUNDS)))
|
val ENERGY_ROOT = this.create("energy_root", EnergyRootBlock(AbstractBlock.Settings.create().pistonBehavior(PistonBehavior.DESTROY).burnable().mapColor(MapColor.DIRT_BROWN).noCollision().ticksRandomly().breakInstantly().sounds(CobblemonSounds.ENERGY_ROOT_SOUNDS)))
|
||||||
@JvmField
|
@JvmField
|
||||||
val BIG_ROOT = this.create("big_root", BigRootBlock(AbstractBlock.Settings.create().pistonBehavior(PistonBehavior.DESTROY).burnable().mapColor(MapColor.DARK_GREEN).noCollision().ticksRandomly().breakInstantly().sounds(CobblemonSounds.BIG_ROOT_SOUNDS)))
|
val BIG_ROOT = this.create("big_root", BigRootBlock(AbstractBlock.Settings.create().pistonBehavior(PistonBehavior.DESTROY).burnable().mapColor(MapColor.DARK_GREEN).noCollision().ticksRandomly().breakInstantly().sounds(CobblemonSounds.BIG_ROOT_SOUNDS)))
|
||||||
@@ -608,6 +654,32 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, RegistryKey<Registry<
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
val COOKING_POT = create(
|
||||||
|
"cooking_pot",
|
||||||
|
CookingPotBlock(
|
||||||
|
Settings.create()
|
||||||
|
.sounds(CobblemonSounds.DISPLAY_CASE_SOUNDS)
|
||||||
|
.nonOpaque()
|
||||||
|
.pistonBehavior(PistonBehavior.BLOCK)
|
||||||
|
.mapColor(MapColor.STONE_GRAY)
|
||||||
|
.strength(0.3f)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
val SWEET_INCENSE = create(
|
||||||
|
"sweet_incense",
|
||||||
|
SweetIncenseBlock(
|
||||||
|
AbstractBlock.Settings.create()
|
||||||
|
.sounds(CobblemonSounds.DISPLAY_CASE_SOUNDS)
|
||||||
|
.nonOpaque()
|
||||||
|
.pistonBehavior(PistonBehavior.BLOCK)
|
||||||
|
.mapColor(MapColor.STONE_GRAY)
|
||||||
|
.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)))
|
val RED_MINT = create("red_mint", MintBlock(MintType.RED, AbstractBlock.Settings.create().mapColor(MapColor.RED).noCollision().ticksRandomly().breakInstantly().sounds(CobblemonSounds.MINT_SOUNDS)))
|
||||||
@JvmField
|
@JvmField
|
||||||
val BLUE_MINT = create("blue_mint", MintBlock(MintType.BLUE, AbstractBlock.Settings.create().mapColor(MapColor.BLUE).noCollision().ticksRandomly().breakInstantly().sounds(CobblemonSounds.MINT_SOUNDS)))
|
val BLUE_MINT = create("blue_mint", MintBlock(MintType.BLUE, AbstractBlock.Settings.create().mapColor(MapColor.BLUE).noCollision().ticksRandomly().breakInstantly().sounds(CobblemonSounds.MINT_SOUNDS)))
|
||||||
@@ -648,7 +720,9 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, RegistryKey<Registry<
|
|||||||
*/
|
*/
|
||||||
fun strippedBlocks(): Map<Block, Block> = mapOf(
|
fun strippedBlocks(): Map<Block, Block> = mapOf(
|
||||||
APRICORN_WOOD to STRIPPED_APRICORN_WOOD,
|
APRICORN_WOOD to STRIPPED_APRICORN_WOOD,
|
||||||
APRICORN_LOG to STRIPPED_APRICORN_LOG
|
APRICORN_LOG to STRIPPED_APRICORN_LOG,
|
||||||
|
SACCHARINE_WOOD to STRIPPED_SACCHARINE_WOOD,
|
||||||
|
SACCHARINE_LOG to STRIPPED_SACCHARINE_LOG
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -800,4 +874,14 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, RegistryKey<Registry<
|
|||||||
val block = BlocksInvoker.createLeavesBlock(BlockSoundGroup.GRASS)
|
val block = BlocksInvoker.createLeavesBlock(BlockSoundGroup.GRASS)
|
||||||
return this.create(name, block)
|
return this.create(name, block)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper method for creating saccharine leaves
|
||||||
|
* similar to Vanilla
|
||||||
|
private fun saccharineLeaves(name: String): SaccharineLeafBlock {
|
||||||
|
val block = BlocksInvoker.createLeavesBlock(BlockSoundGroup.GRASS)
|
||||||
|
|
||||||
|
|
||||||
|
return this.create(name, block)
|
||||||
|
}*/
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import net.minecraft.registry.tag.TagKey
|
|||||||
import net.minecraft.resource.ResourceManager
|
import net.minecraft.resource.ResourceManager
|
||||||
import net.minecraft.resource.ResourceReloader
|
import net.minecraft.resource.ResourceReloader
|
||||||
import net.minecraft.resource.ResourceType
|
import net.minecraft.resource.ResourceType
|
||||||
|
import net.minecraft.screen.ScreenHandlerType
|
||||||
import net.minecraft.server.MinecraftServer
|
import net.minecraft.server.MinecraftServer
|
||||||
import net.minecraft.server.network.ServerPlayerEntity
|
import net.minecraft.server.network.ServerPlayerEntity
|
||||||
import net.minecraft.text.Text
|
import net.minecraft.text.Text
|
||||||
@@ -158,6 +159,8 @@ interface CobblemonImplementation {
|
|||||||
*/
|
*/
|
||||||
fun registerResourceReloader(identifier: Identifier, reloader: ResourceReloader, type: ResourceType, dependencies: Collection<Identifier>)
|
fun registerResourceReloader(identifier: Identifier, reloader: ResourceReloader, type: ResourceType, dependencies: Collection<Identifier>)
|
||||||
|
|
||||||
|
fun registerScreenHandlerType(identifier: Identifier, screenHandlerType: ScreenHandlerType<*>)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO
|
* TODO
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import com.cobblemon.mod.common.api.pokemon.Natures
|
|||||||
import com.cobblemon.mod.common.api.pokemon.stats.Stats
|
import com.cobblemon.mod.common.api.pokemon.stats.Stats
|
||||||
import com.cobblemon.mod.common.api.pokemon.status.Statuses
|
import com.cobblemon.mod.common.api.pokemon.status.Statuses
|
||||||
import com.cobblemon.mod.common.block.BerryBlock
|
import com.cobblemon.mod.common.block.BerryBlock
|
||||||
|
import com.cobblemon.mod.common.block.BugwortBlock
|
||||||
import com.cobblemon.mod.common.block.MintBlock
|
import com.cobblemon.mod.common.block.MintBlock
|
||||||
import com.cobblemon.mod.common.block.MintBlock.MintType
|
import com.cobblemon.mod.common.block.MintBlock.MintType
|
||||||
import com.cobblemon.mod.common.entity.boat.CobblemonBoatType
|
import com.cobblemon.mod.common.entity.boat.CobblemonBoatType
|
||||||
@@ -243,6 +244,57 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, RegistryKey<Registry<It
|
|||||||
@JvmField
|
@JvmField
|
||||||
val GIMMIGHOUL_CHEST = this.create("gimmighoul_chest", BlockItem(CobblemonBlocks.GIMMIGHOUL_CHEST, Item.Settings()))
|
val GIMMIGHOUL_CHEST = this.create("gimmighoul_chest", BlockItem(CobblemonBlocks.GIMMIGHOUL_CHEST, Item.Settings()))
|
||||||
|
|
||||||
|
// Saccharines
|
||||||
|
@JvmField
|
||||||
|
val SACCHARINE_LOG = blockItem("saccharine_log", CobblemonBlocks.SACCHARINE_LOG)
|
||||||
|
@JvmField
|
||||||
|
val STRIPPED_SACCHARINE_LOG = blockItem("stripped_saccharine_log", CobblemonBlocks.STRIPPED_SACCHARINE_LOG)
|
||||||
|
@JvmField
|
||||||
|
val SACCHARINE_WOOD = blockItem("saccharine_wood", CobblemonBlocks.SACCHARINE_WOOD)
|
||||||
|
@JvmField
|
||||||
|
val STRIPPED_SACCHARINE_WOOD = blockItem("stripped_saccharine_wood", CobblemonBlocks.STRIPPED_SACCHARINE_WOOD)
|
||||||
|
@JvmField
|
||||||
|
val SACCHARINE_PLANKS = blockItem("saccharine_planks", CobblemonBlocks.SACCHARINE_PLANKS)
|
||||||
|
@JvmField
|
||||||
|
val SACCHARINE_LEAVES = compostableBlockItem("saccharine_leaves", CobblemonBlocks.SACCHARINE_LEAVES)
|
||||||
|
@JvmField
|
||||||
|
val SACCHARINE_BOAT = create("saccharine_boat", CobblemonBoatItem(CobblemonBoatType.SACCHARINE, false, Item.Settings().maxCount(1)))
|
||||||
|
@JvmField
|
||||||
|
val SACCHARINE_CHEST_BOAT = create("saccharine_chest_boat", CobblemonBoatItem(CobblemonBoatType.SACCHARINE, true, Item.Settings().maxCount(1)))
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
val SACCHARINE_DOOR = blockItem("saccharine_door", CobblemonBlocks.SACCHARINE_DOOR)
|
||||||
|
@JvmField
|
||||||
|
val SACCHARINE_TRAPDOOR = blockItem("saccharine_trapdoor", CobblemonBlocks.SACCHARINE_TRAPDOOR)
|
||||||
|
@JvmField
|
||||||
|
val SACCHARINE_FENCE = blockItem("saccharine_fence", CobblemonBlocks.SACCHARINE_FENCE)
|
||||||
|
@JvmField
|
||||||
|
val SACCHARINE_FENCE_GATE = blockItem("saccharine_fence_gate", CobblemonBlocks.SACCHARINE_FENCE_GATE)
|
||||||
|
@JvmField
|
||||||
|
val SACCHARINE_BUTTON = blockItem("saccharine_button", CobblemonBlocks.SACCHARINE_BUTTON)
|
||||||
|
@JvmField
|
||||||
|
val SACCHARINE_PRESSURE_PLATE = blockItem("saccharine_pressure_plate", CobblemonBlocks.SACCHARINE_PRESSURE_PLATE)
|
||||||
|
@JvmField
|
||||||
|
val SACCHARINE_SLAB = blockItem("saccharine_slab", CobblemonBlocks.SACCHARINE_SLAB)
|
||||||
|
@JvmField
|
||||||
|
val SACCHARINE_STAIRS = blockItem("saccharine_stairs", CobblemonBlocks.SACCHARINE_STAIRS)
|
||||||
|
@JvmField
|
||||||
|
val SACCHARINE_SIGN = this.create("saccharine_sign", SignItem(Item.Settings().maxCount(16), CobblemonBlocks.SACCHARINE_SIGN, CobblemonBlocks.SACCHARINE_WALL_SIGN))
|
||||||
|
@JvmField
|
||||||
|
val SACCHARINE_HANGING_SIGN = this.create("saccharine_hanging_sign", HangingSignItem(CobblemonBlocks.SACCHARINE_HANGING_SIGN, CobblemonBlocks.SACCHARINE_WALL_HANGING_SIGN, Item.Settings().maxCount(16)))
|
||||||
|
@JvmField
|
||||||
|
val SACCHARINE_SAPLING = saccharineSaplingItem("saccharine_sapling", SaccharineSaplingItem(CobblemonBlocks.SACCHARINE_SAPLING))
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
val SWEET_SAP = noSettingsItem("sweet_sap")
|
||||||
|
@JvmField
|
||||||
|
val BUGWORT = bugwortItem("bugwort", BugwortItem(CobblemonBlocks.BUGWORT))
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
val SCATTER_BANG = this.create("scatter_bang", ScatterBangItem(Item.Settings()))
|
||||||
|
@JvmField
|
||||||
|
val STICKY_GLOB = this.create("sticky_glob", StickyGlobItem(Item.Settings()))
|
||||||
|
|
||||||
@JvmField
|
@JvmField
|
||||||
val RESTORATION_TANK = blockItem("restoration_tank", CobblemonBlocks.RESTORATION_TANK)
|
val RESTORATION_TANK = blockItem("restoration_tank", CobblemonBlocks.RESTORATION_TANK)
|
||||||
@JvmField
|
@JvmField
|
||||||
@@ -257,6 +309,10 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, RegistryKey<Registry<It
|
|||||||
val PASTURE = blockItem("pasture", CobblemonBlocks.PASTURE)
|
val PASTURE = blockItem("pasture", CobblemonBlocks.PASTURE)
|
||||||
@JvmField
|
@JvmField
|
||||||
val DISPLAY_CASE = blockItem("display_case", CobblemonBlocks.DISPLAY_CASE)
|
val DISPLAY_CASE = blockItem("display_case", CobblemonBlocks.DISPLAY_CASE)
|
||||||
|
@JvmField
|
||||||
|
val COOKING_POT = blockItem("cooking_pot", CobblemonBlocks.COOKING_POT)
|
||||||
|
@JvmField
|
||||||
|
val SWEET_INCENSE = blockItem("sweet_incense", CobblemonBlocks.SWEET_INCENSE)
|
||||||
|
|
||||||
// Evolution items
|
// Evolution items
|
||||||
@JvmField val LINK_CABLE = create("link_cable", LinkCableItem())
|
@JvmField val LINK_CABLE = create("link_cable", LinkCableItem())
|
||||||
@@ -1125,6 +1181,20 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, RegistryKey<Registry<It
|
|||||||
return item
|
return item
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun saccharineSaplingItem(name: String, saccharineSaplingItem: SaccharineSaplingItem): SaccharineSaplingItem {
|
||||||
|
val finalName = "saccharine_sapling"
|
||||||
|
val item = this.create(finalName, saccharineSaplingItem)
|
||||||
|
compostable(item, .65f)
|
||||||
|
return item
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun bugwortItem(name: String, bugwortItem: BugwortItem): BugwortItem {
|
||||||
|
val finalName = "bugwort"
|
||||||
|
val item = this.create(finalName, bugwortItem)
|
||||||
|
compostable(item, .65f)
|
||||||
|
return item
|
||||||
|
}
|
||||||
|
|
||||||
private fun mintSeed(name: String, mintBlock: MintBlock): Item {
|
private fun mintSeed(name: String, mintBlock: MintBlock): Item {
|
||||||
val finalName = "${name}_mint_seeds"
|
val finalName = "${name}_mint_seeds"
|
||||||
val item = this.blockItem(finalName, mintBlock)
|
val item = this.blockItem(finalName, mintBlock)
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ object CobblemonBlockTags {
|
|||||||
|
|
||||||
@JvmField val ALL_HANGING_SIGNS = createTag("all_hanging_signs")
|
@JvmField val ALL_HANGING_SIGNS = createTag("all_hanging_signs")
|
||||||
@JvmField val ALL_SIGNS = createTag("all_signs")
|
@JvmField val ALL_SIGNS = createTag("all_signs")
|
||||||
|
@JvmField val ALL_SAPLINGS = createTag("all_saplings")
|
||||||
@JvmField val APRICORN_LEAVES = createTag("apricorn_leaves")
|
@JvmField val APRICORN_LEAVES = createTag("apricorn_leaves")
|
||||||
@JvmField val APRICORN_LOGS = createTag("apricorn_logs")
|
@JvmField val APRICORN_LOGS = createTag("apricorn_logs")
|
||||||
@JvmField val APRICORN_SAPLINGS = createTag("apricorn_saplings")
|
@JvmField val APRICORN_SAPLINGS = createTag("apricorn_saplings")
|
||||||
@@ -37,6 +38,7 @@ object CobblemonBlockTags {
|
|||||||
@JvmField val DRIPSTONE_REPLACEABLES = createTag("dripstone_replaceables")
|
@JvmField val DRIPSTONE_REPLACEABLES = createTag("dripstone_replaceables")
|
||||||
@JvmField val FLOWERS = createTag("flowers")
|
@JvmField val FLOWERS = createTag("flowers")
|
||||||
@JvmField val MEDICINAL_LEEK_PLANTABLE = createTag("medicinal_leek_plantable")
|
@JvmField val MEDICINAL_LEEK_PLANTABLE = createTag("medicinal_leek_plantable")
|
||||||
|
@JvmField val BUGWORT_PLANTABLE = createTag("bugwort_plantable")
|
||||||
@JvmField val MINTS = createTag("mints")
|
@JvmField val MINTS = createTag("mints")
|
||||||
@JvmField val ROOTS_SPREADABLE = createTag("roots_spreadable")
|
@JvmField val ROOTS_SPREADABLE = createTag("roots_spreadable")
|
||||||
@JvmField val SIGNS = createTag("signs")
|
@JvmField val SIGNS = createTag("signs")
|
||||||
@@ -44,6 +46,9 @@ object CobblemonBlockTags {
|
|||||||
@JvmField val SEES_SKY = createTag("sees_sky")
|
@JvmField val SEES_SKY = createTag("sees_sky")
|
||||||
@JvmField val SNOW_BLOCK = createTag("snow_block")
|
@JvmField val SNOW_BLOCK = createTag("snow_block")
|
||||||
@JvmField val ROOTS = createTag("roots")
|
@JvmField val ROOTS = createTag("roots")
|
||||||
|
@JvmField val SACCHARINE_LEAVES = createTag("saccharine_leaves")
|
||||||
|
@JvmField val SACCHARINE_LOGS = createTag("saccharine_logs")
|
||||||
|
@JvmField val SACCHARINE_SAPLING = createTag("saccharine_sapling")
|
||||||
@JvmField val STANDING_SIGNS = createTag("standing_signs")
|
@JvmField val STANDING_SIGNS = createTag("standing_signs")
|
||||||
@JvmField val TUMBLESTONE_HEAT_SOURCE = createTag("tumblestone_heat_source")
|
@JvmField val TUMBLESTONE_HEAT_SOURCE = createTag("tumblestone_heat_source")
|
||||||
@JvmField val WALL_HANGING_SIGNS = createTag("wall_hanging_signs")
|
@JvmField val WALL_HANGING_SIGNS = createTag("wall_hanging_signs")
|
||||||
|
|||||||
@@ -0,0 +1,107 @@
|
|||||||
|
/*
|
||||||
|
* 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 net.minecraft.block.*
|
||||||
|
import net.minecraft.entity.player.PlayerEntity
|
||||||
|
import net.minecraft.item.ItemConvertible
|
||||||
|
import net.minecraft.item.ItemStack
|
||||||
|
import net.minecraft.server.world.ServerWorld
|
||||||
|
import net.minecraft.state.StateManager
|
||||||
|
import net.minecraft.state.property.IntProperty
|
||||||
|
import net.minecraft.state.property.Properties
|
||||||
|
import net.minecraft.util.ActionResult
|
||||||
|
import net.minecraft.util.Hand
|
||||||
|
import net.minecraft.util.ItemScatterer
|
||||||
|
import net.minecraft.util.hit.BlockHitResult
|
||||||
|
import net.minecraft.util.math.BlockPos
|
||||||
|
import net.minecraft.util.math.random.Random
|
||||||
|
import net.minecraft.util.shape.VoxelShape
|
||||||
|
import net.minecraft.world.BlockView
|
||||||
|
import net.minecraft.world.World
|
||||||
|
import net.minecraft.world.WorldView
|
||||||
|
|
||||||
|
@Suppress("OVERRIDE_DEPRECATION")
|
||||||
|
class BugwortBlock(settings: Settings) : CropBlock(settings), Fertilizable {
|
||||||
|
|
||||||
|
override fun getAgeProperty(): IntProperty = AGE
|
||||||
|
|
||||||
|
override fun getMaxAge(): Int = MATURE_AGE
|
||||||
|
|
||||||
|
override fun appendProperties(builder: StateManager.Builder<Block, BlockState>) {
|
||||||
|
builder.add(this.ageProperty)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getSeedsItem(): ItemConvertible = CobblemonItems.BUGWORT
|
||||||
|
|
||||||
|
override fun getOutlineShape(state: BlockState, world: BlockView, pos: BlockPos, context: ShapeContext): VoxelShape = AGE_TO_SHAPE[this.getAge(state)]
|
||||||
|
|
||||||
|
override fun randomTick(state: BlockState, world: ServerWorld, pos: BlockPos, random: Random) {
|
||||||
|
// This is specified as growing fast like sugar cane
|
||||||
|
// They have 15 age stages until they grow upwards, this is an attempt at a chance based but likely event
|
||||||
|
if (this.isMature(state) || random.nextInt(4) != 0) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.applyGrowth(world, pos, state)
|
||||||
|
}
|
||||||
|
|
||||||
|
// These 3 are still around for the sake of compatibility, vanilla won't trigger it but some mods might
|
||||||
|
// We implement applyGrowth & getGrowthAmount for them
|
||||||
|
override fun isFertilizable(world: WorldView?, pos: BlockPos?, state: BlockState?, isClient: Boolean): Boolean = !this.isMature(state)
|
||||||
|
|
||||||
|
override fun applyGrowth(world: World, pos: BlockPos, state: BlockState) {
|
||||||
|
world.setBlockState(pos, state.with(this.ageProperty, (this.getAge(state) + 1).coerceAtMost(this.maxAge)), NOTIFY_LISTENERS)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun canPlantOnTop(floor: BlockState, world: BlockView?, pos: BlockPos?): Boolean {
|
||||||
|
return floor.isOf(Blocks.GRASS_BLOCK) || floor.isOf(Blocks.DIRT) || floor.isOf(Blocks.FARMLAND)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun canPlaceAt(state: BlockState?, world: WorldView?, pos: BlockPos?): Boolean {
|
||||||
|
val blockPos = pos!!.down()
|
||||||
|
return canPlantOnTop(world!!.getBlockState(blockPos), world, blockPos)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onUse(
|
||||||
|
state: BlockState?,
|
||||||
|
world: World?,
|
||||||
|
pos: BlockPos?,
|
||||||
|
player: PlayerEntity?,
|
||||||
|
hand: Hand?,
|
||||||
|
hit: BlockHitResult?
|
||||||
|
): ActionResult {
|
||||||
|
if (state != null && world != null && pos != null) {
|
||||||
|
// if bugwort is at max age then revert age to 0 and drop items
|
||||||
|
if (state.get(AGE) == 3) {
|
||||||
|
|
||||||
|
world.setBlockState(pos, state.with(this.ageProperty, (0).coerceAtMost(this.maxAge)), NOTIFY_LISTENERS)
|
||||||
|
|
||||||
|
Block.dropStack(world, pos, ItemStack(CobblemonItems.BUGWORT, kotlin.random.Random.nextInt(2, 4)))
|
||||||
|
return ActionResult.SUCCESS
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return super.onUse(state, world, pos, player, hand, hit)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getGrowthAmount(world: World): Int = 1
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
const val MATURE_AGE = 3
|
||||||
|
val AGE: IntProperty = Properties.AGE_3
|
||||||
|
val AGE_TO_SHAPE = arrayOf(
|
||||||
|
createCuboidShape(0.0, 0.0, 0.0, 16.0, 2.0, 16.0),
|
||||||
|
createCuboidShape(0.0, 0.0, 0.0, 16.0, 5.0, 16.0),
|
||||||
|
createCuboidShape(0.0, 0.0, 0.0, 16.0, 8.0, 16.0),
|
||||||
|
createCuboidShape(0.0, 0.0, 0.0, 16.0, 11.0, 16.0)
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,314 @@
|
|||||||
|
/*
|
||||||
|
* 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.block.entity.CookingPotBlockEntity
|
||||||
|
import com.cobblemon.mod.common.gui.CookingPotScreenHandler
|
||||||
|
import net.minecraft.block.*
|
||||||
|
import net.minecraft.block.entity.BlockEntity
|
||||||
|
import net.minecraft.entity.ItemEntity
|
||||||
|
import net.minecraft.entity.ai.pathing.NavigationType
|
||||||
|
import net.minecraft.entity.player.PlayerEntity
|
||||||
|
import net.minecraft.entity.player.PlayerInventory
|
||||||
|
import net.minecraft.fluid.FluidState
|
||||||
|
import net.minecraft.fluid.Fluids
|
||||||
|
import net.minecraft.inventory.SidedInventory
|
||||||
|
import net.minecraft.item.ItemStack
|
||||||
|
import net.minecraft.screen.NamedScreenHandlerFactory
|
||||||
|
import net.minecraft.screen.ScreenHandlerContext
|
||||||
|
import net.minecraft.screen.SimpleNamedScreenHandlerFactory
|
||||||
|
import net.minecraft.server.world.ServerWorld
|
||||||
|
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 CookingPotBlock(settings: Settings?) : BlockWithEntity(settings), Waterloggable, InventoryProvider {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val COOKING: BooleanProperty = BooleanProperty.of("cooking")
|
||||||
|
val FACING = Properties.FACING
|
||||||
|
val TRIGGERED = Properties.TRIGGERED
|
||||||
|
val WATERLOGGED = Properties.WATERLOGGED
|
||||||
|
|
||||||
|
private val 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 val 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 val 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 val 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)
|
||||||
|
)
|
||||||
|
|
||||||
|
private val EMPTY_INVENTORY = object : SidedInventory {
|
||||||
|
override fun clear() {}
|
||||||
|
|
||||||
|
override fun size(): Int = 0
|
||||||
|
|
||||||
|
override fun isEmpty(): Boolean = true
|
||||||
|
|
||||||
|
override fun getStack(slot: Int) = ItemStack.EMPTY
|
||||||
|
|
||||||
|
override fun removeStack(slot: Int, amount: Int) = ItemStack.EMPTY
|
||||||
|
|
||||||
|
override fun removeStack(slot: Int) = ItemStack.EMPTY
|
||||||
|
|
||||||
|
override fun setStack(slot: Int, stack: ItemStack?) {}
|
||||||
|
|
||||||
|
override fun canPlayerUse(player: PlayerEntity?) = false
|
||||||
|
|
||||||
|
override fun getAvailableSlots(side: Direction?) = IntArray(0)
|
||||||
|
|
||||||
|
override fun canInsert(slot: Int, stack: ItemStack?, dir: Direction?) = false
|
||||||
|
|
||||||
|
override fun canExtract(slot: Int, stack: ItemStack?, dir: Direction?) = false
|
||||||
|
|
||||||
|
override fun markDirty() {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val TITLE: Text = Text.of("Campfire Pot")
|
||||||
|
|
||||||
|
init {
|
||||||
|
defaultState = this.stateManager.defaultState.with(FACING, Direction.NORTH)
|
||||||
|
.with(WATERLOGGED, false)
|
||||||
|
.with(COOKING, false)
|
||||||
|
.with(TRIGGERED, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deprecated("Deprecated in Java")
|
||||||
|
override fun onUse(
|
||||||
|
state: BlockState,
|
||||||
|
world: World,
|
||||||
|
pos: BlockPos,
|
||||||
|
player: PlayerEntity,
|
||||||
|
hand: Hand,
|
||||||
|
hit: BlockHitResult
|
||||||
|
): ActionResult {
|
||||||
|
if (world.isClient) {
|
||||||
|
return ActionResult.SUCCESS
|
||||||
|
}
|
||||||
|
player.openHandledScreen(state.createScreenHandlerFactory(world, pos))
|
||||||
|
player.incrementStat(Stats.INTERACT_WITH_CRAFTING_TABLE)
|
||||||
|
return ActionResult.CONSUME
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deprecated("Deprecated in Java")
|
||||||
|
override fun createScreenHandlerFactory(
|
||||||
|
state: BlockState,
|
||||||
|
world: World,
|
||||||
|
pos: BlockPos
|
||||||
|
): NamedScreenHandlerFactory {
|
||||||
|
return SimpleNamedScreenHandlerFactory({ syncId: Int, inventory: PlayerInventory, player: PlayerEntity ->
|
||||||
|
CookingPotScreenHandler(syncId, inventory, ScreenHandlerContext.create(world, pos))
|
||||||
|
}, TITLE)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun createBlockEntity(pos: BlockPos, state: BlockState): BlockEntity {
|
||||||
|
return CookingPotBlockEntity(pos, state)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getInventory(state: BlockState, world: WorldAccess, pos: BlockPos): SidedInventory {
|
||||||
|
val cookingPotBlockEntity = world.getBlockEntity(pos) as? CookingPotBlockEntity
|
||||||
|
?: return EMPTY_INVENTORY
|
||||||
|
return cookingPotBlockEntity.cookingPotInventory
|
||||||
|
}
|
||||||
|
|
||||||
|
@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
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun appendProperties(builder: StateManager.Builder<Block, BlockState>) {
|
||||||
|
builder.add(FACING, WATERLOGGED, COOKING, TRIGGERED)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deprecated("Deprecated in Java")
|
||||||
|
override fun rotate(blockState: BlockState, rotation: BlockRotation): BlockState {
|
||||||
|
return blockState.with(FACING, rotation.rotate(blockState[FACING]))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deprecated("Deprecated in Java")
|
||||||
|
override fun mirror(blockState: BlockState, mirror: BlockMirror): BlockState {
|
||||||
|
return blockState.rotate(mirror.getRotation(blockState[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 scheduledTick(state: BlockState?, world: ServerWorld?, pos: BlockPos?, random: net.minecraft.util.math.random.Random?) {
|
||||||
|
val inventory = (world!!.getBlockEntity(pos) as CookingPotBlockEntity).cookingPotInventory
|
||||||
|
val cookingPotEntity = (world.getBlockEntity(pos) as CookingPotBlockEntity)
|
||||||
|
|
||||||
|
if(world == null || pos == null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
//val tankEntity = world.getBlockEntity(pos) as MultiblockEntity
|
||||||
|
|
||||||
|
if (cookingPotEntity.blockState.get(COOKING)) {
|
||||||
|
//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)
|
||||||
|
cookingPotEntity.markDirty()
|
||||||
|
|
||||||
|
// Play sound for TM creation
|
||||||
|
world.playSoundServer(cookingPotEntity.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()
|
||||||
|
cookingPotEntity.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()
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
}override fun getRenderType(blockState: BlockState): BlockRenderType {
|
||||||
|
return BlockRenderType.MODEL
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getFluidState(state: BlockState): FluidState {
|
||||||
|
return if (state[WATERLOGGED]) {
|
||||||
|
Fluids.WATER.getStill(false)
|
||||||
|
} else super.getFluidState(state)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getOutlineShape(
|
||||||
|
state: BlockState,
|
||||||
|
world: BlockView,
|
||||||
|
pos: BlockPos,
|
||||||
|
context: ShapeContext
|
||||||
|
): VoxelShape {
|
||||||
|
return when (state[FACING]) {
|
||||||
|
Direction.NORTH -> NORTH_OUTLINE
|
||||||
|
Direction.SOUTH -> SOUTH_OUTLINE
|
||||||
|
Direction.WEST -> WEST_OUTLINE
|
||||||
|
else -> EAST_OUTLINE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,256 @@
|
|||||||
|
/*
|
||||||
|
* 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.api.tags.CobblemonItemTags
|
||||||
|
import com.cobblemon.mod.common.block.SaccharineStrippedLogBlock.Companion
|
||||||
|
import net.minecraft.block.*
|
||||||
|
import net.minecraft.block.BeehiveBlock.HONEY_LEVEL
|
||||||
|
import net.minecraft.entity.*
|
||||||
|
import net.minecraft.entity.ai.pathing.NavigationType
|
||||||
|
import net.minecraft.entity.attribute.DefaultAttributeContainer
|
||||||
|
import net.minecraft.entity.attribute.EntityAttributes
|
||||||
|
import net.minecraft.entity.player.PlayerEntity
|
||||||
|
import net.minecraft.fluid.Fluids
|
||||||
|
import net.minecraft.item.ItemPlacementContext
|
||||||
|
import net.minecraft.item.ItemStack
|
||||||
|
import net.minecraft.item.Items
|
||||||
|
import net.minecraft.particle.ParticleTypes
|
||||||
|
import net.minecraft.registry.tag.BlockTags
|
||||||
|
import net.minecraft.server.world.ServerWorld
|
||||||
|
import net.minecraft.state.StateManager
|
||||||
|
import net.minecraft.state.property.BooleanProperty
|
||||||
|
import net.minecraft.state.property.IntProperty
|
||||||
|
import net.minecraft.state.property.Properties
|
||||||
|
import net.minecraft.util.ActionResult
|
||||||
|
import net.minecraft.util.Arm
|
||||||
|
import net.minecraft.util.Hand
|
||||||
|
import net.minecraft.util.hit.BlockHitResult
|
||||||
|
import net.minecraft.util.hit.HitResult
|
||||||
|
import net.minecraft.util.math.BlockPos
|
||||||
|
import net.minecraft.util.math.Direction
|
||||||
|
import net.minecraft.util.math.MathHelper
|
||||||
|
import net.minecraft.util.math.Vec3d
|
||||||
|
import net.minecraft.util.math.random.Random
|
||||||
|
import net.minecraft.util.shape.VoxelShape
|
||||||
|
import net.minecraft.util.shape.VoxelShapes
|
||||||
|
import net.minecraft.world.*
|
||||||
|
|
||||||
|
@Suppress("DEPRECATION", "OVERRIDE_DEPRECATION")
|
||||||
|
class SaccharineLeafBlock(settings: Settings) : LeavesBlock(settings), Fertilizable {
|
||||||
|
|
||||||
|
init {
|
||||||
|
this.defaultState = this.stateManager.defaultState
|
||||||
|
.with(AGE, MIN_AGE)
|
||||||
|
.with(DISTANCE, DISTANCE_MAX)
|
||||||
|
.with(PERSISTENT, false)
|
||||||
|
.with(Properties.WATERLOGGED, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getPlacementState(ctx: ItemPlacementContext): BlockState? {
|
||||||
|
val blockState = defaultState
|
||||||
|
val worldView = ctx.world
|
||||||
|
val blockPos = ctx.blockPos
|
||||||
|
return if (blockState.canPlaceAt(worldView, blockPos)) {
|
||||||
|
blockState.with(PERSISTENT, true).with(Properties.WATERLOGGED, worldView.getFluidState(blockPos).isOf(Fluids.WATER))
|
||||||
|
} else null
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getStateForNeighborUpdate(state: BlockState, direction: Direction, neighborState: BlockState, world: WorldAccess, pos: BlockPos, neighborPos: BlockPos): BlockState? {
|
||||||
|
return if (!state.canPlaceAt(world, pos)) {
|
||||||
|
Blocks.AIR.defaultState
|
||||||
|
} else {
|
||||||
|
super.getStateForNeighborUpdate(state, direction, neighborState, world, pos, neighborPos)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hasRandomTicks(state: BlockState) = state.get(AGE) != 2
|
||||||
|
|
||||||
|
override fun randomTick(state: BlockState, world: ServerWorld, pos: BlockPos, random: Random) {
|
||||||
|
// todo if a honey soaked leaf block is the first block below this block then over time age that leaf block
|
||||||
|
if (random.nextInt(180) == 0) {
|
||||||
|
|
||||||
|
// todo if leaf block is within 10 blocks of a lead soaked block then age it
|
||||||
|
for (i in 1..10) {
|
||||||
|
|
||||||
|
val abovePos = pos.up(i)
|
||||||
|
val aboveState = world.getBlockState(abovePos)
|
||||||
|
val currentAge = state.get(AGE)
|
||||||
|
|
||||||
|
if (!aboveState.isAir) {
|
||||||
|
if ((aboveState.block is SaccharineLeafBlock && aboveState.get(AGE) > 0)/* ||
|
||||||
|
(aboveState.block is BeehiveBlock && aboveState.get(HONEY_LEVEL) == 5)*/) {
|
||||||
|
// todo -1 age from top block
|
||||||
|
world.setBlockState(abovePos, aboveState.with(AGE, aboveState.get(AGE) - 1), 2)
|
||||||
|
|
||||||
|
// todo +1 age the leaf bottom block
|
||||||
|
world.setBlockState(pos, state.with(AGE, currentAge + 1), 2)
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
super.randomTick(state, world, pos, random)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Deprecated("Deprecated in Java")
|
||||||
|
override fun getOutlineShape(state: BlockState, world: BlockView, pos: BlockPos, context: ShapeContext): VoxelShape {
|
||||||
|
return SHAPE
|
||||||
|
}
|
||||||
|
|
||||||
|
// todo make block
|
||||||
|
@Deprecated("Deprecated in Java")
|
||||||
|
override fun getCollisionShape(state: BlockState, world: BlockView, pos: BlockPos, context: ShapeContext): VoxelShape {
|
||||||
|
if (context is EntityShapeContext && (context.entity as? ItemEntity)?.stack?.isIn(CobblemonItemTags.APRICORNS) == true) {
|
||||||
|
return VoxelShapes.empty()
|
||||||
|
}
|
||||||
|
return super.getCollisionShape(state, world, pos, context)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isFertilizable(world: WorldView, pos: BlockPos, state: BlockState, isClient: Boolean) = false /*state.get(AGE) < MAX_AGE*/
|
||||||
|
|
||||||
|
override fun canGrow(world: World, random: Random, pos: BlockPos, state: BlockState) = true
|
||||||
|
|
||||||
|
override fun grow(world: ServerWorld, random: Random, pos: BlockPos, state: BlockState) {
|
||||||
|
world.setBlockState(pos, state.with(AGE, state.get(AGE) + 1), 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun appendProperties(builder: StateManager.Builder<Block, BlockState>) {
|
||||||
|
builder.add(AGE, DISTANCE, PERSISTENT, Properties.WATERLOGGED)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deprecated("Deprecated in Java")
|
||||||
|
override fun randomDisplayTick(state: BlockState, world: World, pos: BlockPos, random: Random) {
|
||||||
|
|
||||||
|
if (state.get(AGE) == 2) {
|
||||||
|
for (i in 0 until random.nextInt(1) + 1) {
|
||||||
|
this.spawnHoneyParticles(world, pos, state, .75f)
|
||||||
|
}
|
||||||
|
} else if (state.get(AGE) == 1) {
|
||||||
|
for (i in 0 until random.nextInt(1) + 1) {
|
||||||
|
this.spawnHoneyParticles(world, pos, state, .9f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// this code was for them aging as time goes on
|
||||||
|
/* if (world.random.nextInt(5) == 0) {
|
||||||
|
|
||||||
|
val currentAge = state.get(AGE)
|
||||||
|
if (currentAge < MAX_AGE) {
|
||||||
|
world.setBlockState(pos, state.with(AGE, currentAge + 1), 2)
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
|
||||||
|
/*@Deprecated("Deprecated in Java")
|
||||||
|
override fun canPlaceAt(state: BlockState, world: WorldView, pos: BlockPos): Boolean {
|
||||||
|
val blockState = world.getBlockState(pos.down())
|
||||||
|
return blockState.isIn(CobblemonBlockTags.SACCHARINE_LEAVES)
|
||||||
|
}*/
|
||||||
|
|
||||||
|
private fun spawnHoneyParticles(world: World, pos: BlockPos, state: BlockState, rate: Float) {
|
||||||
|
if (state.fluidState.isEmpty && !(world.random.nextFloat() < rate)) {
|
||||||
|
val voxelShape = state.getCollisionShape(world, pos)
|
||||||
|
val d = voxelShape.getMax(Direction.Axis.Y)
|
||||||
|
if (d >= 1.0 && !state.isIn(BlockTags.IMPERMEABLE)) {
|
||||||
|
val e = voxelShape.getMin(Direction.Axis.Y)
|
||||||
|
if (e > 0.0) {
|
||||||
|
this.addHoneyParticle(world, pos, voxelShape, pos.y.toDouble() + e - 0.05)
|
||||||
|
} else {
|
||||||
|
val blockPos = pos.down()
|
||||||
|
val blockState = world.getBlockState(blockPos)
|
||||||
|
val voxelShape2 = blockState.getCollisionShape(world, blockPos)
|
||||||
|
val f = voxelShape2.getMax(Direction.Axis.Y)
|
||||||
|
if ((f < 1.0 || !blockState.isFullCube(world, blockPos)) && blockState.fluidState.isEmpty) {
|
||||||
|
this.addHoneyParticle(world, pos, voxelShape, pos.y.toDouble() - 0.05)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun addHoneyParticle(world: World, pos: BlockPos, shape: VoxelShape, height: Double) {
|
||||||
|
this.addHoneyParticle(
|
||||||
|
world, pos.x.toDouble() + shape.getMin(Direction.Axis.X), pos.x.toDouble() + shape.getMax(
|
||||||
|
Direction.Axis.X
|
||||||
|
), pos.z.toDouble() + shape.getMin(Direction.Axis.Z), pos.z.toDouble() + shape.getMax(
|
||||||
|
Direction.Axis.Z
|
||||||
|
), height
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun addHoneyParticle(world: World, minX: Double, maxX: Double, minZ: Double, maxZ: Double, height: Double) {
|
||||||
|
world.addParticle(
|
||||||
|
ParticleTypes.DRIPPING_HONEY,
|
||||||
|
MathHelper.lerp(world.random.nextDouble(), minX, maxX),
|
||||||
|
height,
|
||||||
|
MathHelper.lerp(world.random.nextDouble(), minZ, maxZ),
|
||||||
|
0.0,
|
||||||
|
0.0,
|
||||||
|
0.0
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun canPathfindThrough(state: BlockState, world: BlockView, pos: BlockPos, type: NavigationType) = false
|
||||||
|
|
||||||
|
override fun onUse(state: BlockState, world: World, pos: BlockPos, player: PlayerEntity, hand: Hand, hit: BlockHitResult): ActionResult {
|
||||||
|
// todo if item in players hand is glass bottle and AGE is more than 0
|
||||||
|
if (player.getStackInHand(hand).isOf(Items.GLASS_BOTTLE) && state.get(AGE) > 0)
|
||||||
|
{
|
||||||
|
// decrement stack if not in creative mode
|
||||||
|
if (!player.isCreative)
|
||||||
|
player.getStackInHand(hand).decrement(1)
|
||||||
|
|
||||||
|
// give player honey bottle for now
|
||||||
|
player.giveItemStack(Items.HONEY_BOTTLE.defaultStack)
|
||||||
|
|
||||||
|
// todo reset AGE
|
||||||
|
world.setBlockState(pos, state.with(AGE, 0), 2)
|
||||||
|
|
||||||
|
val currentAge = state.get(AGE)
|
||||||
|
} else if (player.getStackInHand(hand).isOf(Items.HONEY_BOTTLE) && state.get(AGE) != 2) {
|
||||||
|
// decrement stack if not in creative mode
|
||||||
|
if (!player.isCreative)
|
||||||
|
player.getStackInHand(hand).decrement(1)
|
||||||
|
|
||||||
|
// todo set age to 2
|
||||||
|
world.setBlockState(pos, state.with(AGE, 2), 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state.get(AGE) != MAX_AGE) {
|
||||||
|
return super.onUse(state, world, pos, player, hand, hit)
|
||||||
|
}
|
||||||
|
|
||||||
|
//doHarvest(world, state, pos, player)
|
||||||
|
return ActionResult.SUCCESS
|
||||||
|
}
|
||||||
|
|
||||||
|
/*override fun onBlockBreakStart(state: BlockState, world: World, pos: BlockPos, player: PlayerEntity) {
|
||||||
|
if (state.get(AGE) != MAX_AGE) {
|
||||||
|
return super.onBlockBreakStart(state, world, pos, player)
|
||||||
|
}
|
||||||
|
|
||||||
|
//doHarvest(world, state, pos, player)
|
||||||
|
}*/
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
val AGE: IntProperty = Properties.AGE_2
|
||||||
|
val DISTANCE: IntProperty = Properties.DISTANCE_1_7
|
||||||
|
val PERSISTENT: BooleanProperty = Properties.PERSISTENT
|
||||||
|
const val MAX_AGE = Properties.AGE_2_MAX
|
||||||
|
const val MIN_AGE = 0
|
||||||
|
const val DISTANCE_MAX = 7
|
||||||
|
|
||||||
|
private val SHAPE: VoxelShape = Block.createCuboidShape(0.0, 0.0, 0.0, 16.0, 16.0, 16.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
/*
|
||||||
|
* 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.api.apricorn.Apricorn
|
||||||
|
import com.cobblemon.mod.common.block.grower.ApricornTreeGrower
|
||||||
|
import com.cobblemon.mod.common.block.grower.SaccharineTreeGrower
|
||||||
|
import net.minecraft.block.SaplingBlock
|
||||||
|
class SaccharineSaplingBlock(properties : Settings) : SaplingBlock(SaccharineTreeGrower(), properties)
|
||||||
@@ -0,0 +1,153 @@
|
|||||||
|
/*
|
||||||
|
* 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.api.tags.CobblemonItemTags
|
||||||
|
import net.minecraft.block.*
|
||||||
|
import net.minecraft.entity.ItemEntity
|
||||||
|
import net.minecraft.entity.LivingEntity
|
||||||
|
import net.minecraft.entity.ai.pathing.NavigationType
|
||||||
|
import net.minecraft.entity.player.PlayerEntity
|
||||||
|
import net.minecraft.item.ItemStack
|
||||||
|
import net.minecraft.item.Items
|
||||||
|
import net.minecraft.server.world.ServerWorld
|
||||||
|
import net.minecraft.state.StateManager
|
||||||
|
import net.minecraft.state.property.EnumProperty
|
||||||
|
import net.minecraft.state.property.IntProperty
|
||||||
|
import net.minecraft.state.property.Properties
|
||||||
|
import net.minecraft.util.ActionResult
|
||||||
|
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.math.Direction.Axis
|
||||||
|
import net.minecraft.util.math.random.Random
|
||||||
|
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
|
||||||
|
|
||||||
|
@Suppress("DEPRECATION", "OVERRIDE_DEPRECATION")
|
||||||
|
class SaccharineStrippedLogBlock(settings: Settings) : PillarBlock(settings) {
|
||||||
|
|
||||||
|
init {
|
||||||
|
this.defaultState = this.stateManager.defaultState
|
||||||
|
.with(AGE, MIN_AGE)
|
||||||
|
.with(AXIS, Axis.Y)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPlaced(world: World?, pos: BlockPos?, state: BlockState?, placer: LivingEntity?, itemStack: ItemStack?) {
|
||||||
|
owner = placer
|
||||||
|
super.onPlaced(world, pos, state, placer, itemStack)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hasRandomTicks(state: BlockState) = state.get(AGE) < MAX_AGE
|
||||||
|
|
||||||
|
@Deprecated("Deprecated in Java")
|
||||||
|
override fun randomTick(state: BlockState, world: ServerWorld, pos: BlockPos, random: Random) {
|
||||||
|
|
||||||
|
// todo make it so that it only ages when connected to enough natural-tagged Saccharine Leaves (so, generated or grown, not player placed)
|
||||||
|
|
||||||
|
// this code was for them aging as time goes on
|
||||||
|
if (world.random.nextInt(5) == 0 && owner == null) {
|
||||||
|
|
||||||
|
val currentAge = state.get(AGE)
|
||||||
|
if (currentAge < MAX_AGE) {
|
||||||
|
world.setBlockState(pos, state.with(AGE, currentAge + 1), 2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*@Deprecated("Deprecated in Java")
|
||||||
|
override fun canPlaceAt(state: BlockState, world: WorldView, pos: BlockPos): Boolean {
|
||||||
|
val blockState = world.getBlockState(pos.down())
|
||||||
|
return blockState.isIn(CobblemonBlockTags.SACCHARINE_LEAVES)
|
||||||
|
}*/
|
||||||
|
|
||||||
|
@Deprecated("Deprecated in Java")
|
||||||
|
override fun getOutlineShape(state: BlockState, world: BlockView, pos: BlockPos, context: ShapeContext): VoxelShape {
|
||||||
|
return SHAPE
|
||||||
|
}
|
||||||
|
|
||||||
|
// todo make block
|
||||||
|
@Deprecated("Deprecated in Java")
|
||||||
|
override fun getCollisionShape(state: BlockState, world: BlockView, pos: BlockPos, context: ShapeContext): VoxelShape {
|
||||||
|
if (context is EntityShapeContext && (context.entity as? ItemEntity)?.stack?.isIn(CobblemonItemTags.APRICORNS) == true) {
|
||||||
|
return VoxelShapes.empty()
|
||||||
|
}
|
||||||
|
return super.getCollisionShape(state, world, pos, context)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*override fun getPlacementState(ctx: ItemPlacementContext): BlockState? {
|
||||||
|
val blockState = defaultState
|
||||||
|
val worldView = ctx.world
|
||||||
|
val blockPos = ctx.blockPos
|
||||||
|
return defaultState.with(PillarBlock.AXIS, ctx.side.axis) as BlockState
|
||||||
|
return if (blockState.canPlaceAt(worldView, blockPos)) blockState else null
|
||||||
|
}*/
|
||||||
|
|
||||||
|
override fun getStateForNeighborUpdate(state: BlockState, direction: Direction, neighborState: BlockState, world: WorldAccess, pos: BlockPos, neighborPos: BlockPos): BlockState? {
|
||||||
|
return if (!state.canPlaceAt(world, pos)) Blocks.AIR.defaultState
|
||||||
|
else super.getStateForNeighborUpdate(state, direction, neighborState, world, pos, neighborPos)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun appendProperties(builder: StateManager.Builder<Block, BlockState>) {
|
||||||
|
builder.add(AGE, AXIS)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun canPathfindThrough(state: BlockState, world: BlockView, pos: BlockPos, type: NavigationType) = false
|
||||||
|
|
||||||
|
override fun onUse(state: BlockState, world: World, pos: BlockPos, player: PlayerEntity, hand: Hand, hit: BlockHitResult): ActionResult {
|
||||||
|
// todo if item in players hand is glass bottle and AGE is 1
|
||||||
|
if (player.getStackInHand(hand).isOf(Items.GLASS_BOTTLE) && state.get(AGE) == 1)
|
||||||
|
{
|
||||||
|
// decrement stack if not in creative mode
|
||||||
|
if (!player.isCreative)
|
||||||
|
player.getStackInHand(hand).decrement(1)
|
||||||
|
|
||||||
|
// todo give player Sweet Sap item
|
||||||
|
player.giveItemStack(CobblemonItems.SWEET_SAP.defaultStack)
|
||||||
|
|
||||||
|
// todo reset AGE
|
||||||
|
world.setBlockState(pos, state.with(AGE, 0), 2)
|
||||||
|
|
||||||
|
val currentAge = state.get(AGE)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state.get(AGE) != MAX_AGE) {
|
||||||
|
return super.onUse(state, world, pos, player, hand, hit)
|
||||||
|
}
|
||||||
|
|
||||||
|
//doHarvest(world, state, pos, player)
|
||||||
|
return ActionResult.SUCCESS
|
||||||
|
}
|
||||||
|
|
||||||
|
/*override fun onBlockBreakStart(state: BlockState, world: World, pos: BlockPos, player: PlayerEntity) {
|
||||||
|
if (state.get(AGE) != MAX_AGE) {
|
||||||
|
return super.onBlockBreakStart(state, world, pos, player)
|
||||||
|
}
|
||||||
|
|
||||||
|
//doHarvest(world, state, pos, player)
|
||||||
|
}*/
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
val AGE: IntProperty = Properties.AGE_1
|
||||||
|
val AXIS: EnumProperty<Axis> = Properties.AXIS
|
||||||
|
const val MAX_AGE = Properties.AGE_1_MAX
|
||||||
|
const val MIN_AGE = 0
|
||||||
|
var owner: LivingEntity? = null
|
||||||
|
|
||||||
|
|
||||||
|
private val SHAPE: VoxelShape = Block.createCuboidShape(0.0, 0.0, 0.0, 16.0, 16.0, 16.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,194 @@
|
|||||||
|
/*
|
||||||
|
* 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.block.entity.DisplayCaseBlockEntity
|
||||||
|
import net.minecraft.block.*
|
||||||
|
import net.minecraft.block.HorizontalFacingBlock.*
|
||||||
|
import net.minecraft.entity.ai.pathing.NavigationType
|
||||||
|
import net.minecraft.entity.player.PlayerEntity
|
||||||
|
import net.minecraft.item.ItemPlacementContext
|
||||||
|
import net.minecraft.item.Items
|
||||||
|
import net.minecraft.particle.ParticleTypes
|
||||||
|
import net.minecraft.sound.SoundCategory
|
||||||
|
import net.minecraft.sound.SoundEvents
|
||||||
|
import net.minecraft.state.StateManager
|
||||||
|
import net.minecraft.state.property.BooleanProperty
|
||||||
|
import net.minecraft.state.property.DirectionProperty
|
||||||
|
import net.minecraft.util.ActionResult
|
||||||
|
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.math.random.Random
|
||||||
|
import net.minecraft.world.BlockView
|
||||||
|
import net.minecraft.world.World
|
||||||
|
import net.minecraft.world.WorldAccess
|
||||||
|
|
||||||
|
@Suppress("OVERRIDE_DEPRECATION")
|
||||||
|
class SweetIncenseBlock(settings: Settings) : BlockWithEntity(settings), Waterloggable {
|
||||||
|
/*
|
||||||
|
This item, when placed, acts like a candle. It must be lit with a Flint n Steel or Fire Charge, and it can be “put out” by right-clicking on it. Small blue smoke particles will rise from the nub on the top of the block when lit.
|
||||||
|
|
||||||
|
This incense block has special effects on Pokémon spawns, but only when lit. When lit, Sweet Incense increases Pokémon spawn & despawn rates by 1.5x and raises spawn density by 25% in a 16 block radius (32 block diameter) (this number will need to be playtested).
|
||||||
|
|
||||||
|
This essentially means that the player will see a larger number of Pokémon at once, and a higher variety of Pokémon in a given span of time.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
init {
|
||||||
|
this.defaultState = this.stateManager.defaultState
|
||||||
|
.with(FACING, Direction.NORTH)
|
||||||
|
.with(ITEM_DIRECTION, Direction.NORTH)
|
||||||
|
.with(LIT,false)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val ITEM_DIRECTION = DirectionProperty.of("item_facing")
|
||||||
|
val LIT = BooleanProperty.of("false")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getPlacementState(ctx: ItemPlacementContext): BlockState? {
|
||||||
|
var blockState = defaultState
|
||||||
|
val worldView = ctx.world
|
||||||
|
val blockPos = ctx.blockPos
|
||||||
|
ctx.placementDirections.forEach { direction ->
|
||||||
|
if (direction.axis.isHorizontal) {
|
||||||
|
blockState = blockState
|
||||||
|
.with(FACING, direction)
|
||||||
|
.with(LIT, false)
|
||||||
|
.with(ITEM_DIRECTION, direction)
|
||||||
|
as BlockState
|
||||||
|
|
||||||
|
if (blockState.canPlaceAt(worldView, blockPos)) {
|
||||||
|
return blockState
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun appendProperties(builder: StateManager.Builder<Block, BlockState>) {
|
||||||
|
builder.add(FACING)
|
||||||
|
builder.add(ITEM_DIRECTION)
|
||||||
|
builder.add(LIT)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun createBlockEntity(pos: BlockPos, state: BlockState): DisplayCaseBlockEntity {
|
||||||
|
return DisplayCaseBlockEntity(pos, state)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getStateForNeighborUpdate(
|
||||||
|
state: BlockState,
|
||||||
|
direction: Direction,
|
||||||
|
neighborState: BlockState,
|
||||||
|
world: WorldAccess,
|
||||||
|
pos: BlockPos,
|
||||||
|
neighborPos: BlockPos
|
||||||
|
): BlockState {
|
||||||
|
return if (direction == state.get(FACING) && !state.canPlaceAt(world, pos)) Blocks.AIR.defaultState
|
||||||
|
else super.getStateForNeighborUpdate(state, direction, neighborState, world, pos, neighborPos)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onUse(
|
||||||
|
state: BlockState,
|
||||||
|
world: World,
|
||||||
|
pos: BlockPos,
|
||||||
|
player: PlayerEntity,
|
||||||
|
hand: Hand,
|
||||||
|
hit: BlockHitResult
|
||||||
|
): ActionResult {
|
||||||
|
// light the incense when flint and steel or fire charge is held
|
||||||
|
if (state.get(LIT) == false && (player.getStackInHand(hand).isOf(Items.FLINT_AND_STEEL.asItem()) ||
|
||||||
|
player.getStackInHand(hand).isOf(Items.FIRE_CHARGE.asItem()))) {
|
||||||
|
world.setBlockState(pos, state.with(LIT, true), 2)
|
||||||
|
return ActionResult.SUCCESS
|
||||||
|
}
|
||||||
|
|
||||||
|
// unlight the incense when used if it is on
|
||||||
|
if (state.get(LIT) == true && (player.getStackInHand(hand).isOf(Items.FLINT_AND_STEEL.asItem()) == false ||
|
||||||
|
player.getStackInHand(hand).isOf(Items.FIRE_CHARGE.asItem()) == false)) {
|
||||||
|
world.setBlockState(pos, state.with(LIT, false), 2)
|
||||||
|
return ActionResult.SUCCESS
|
||||||
|
}
|
||||||
|
|
||||||
|
return ActionResult.FAIL
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun randomDisplayTick(state: BlockState, world: World, pos: BlockPos, random: Random) {
|
||||||
|
if (state.get(LIT)) {
|
||||||
|
spawnSmokeParticle(world, pos, true, false)
|
||||||
|
|
||||||
|
if (random.nextInt(10) == 0) {
|
||||||
|
world.playSound(
|
||||||
|
pos.x.toDouble() + 0.5,
|
||||||
|
pos.y.toDouble() + 0.5,
|
||||||
|
pos.z.toDouble() + 0.5,
|
||||||
|
SoundEvents.BLOCK_CAMPFIRE_CRACKLE,
|
||||||
|
SoundCategory.BLOCKS,
|
||||||
|
0.2f + random.nextFloat(),
|
||||||
|
random.nextFloat() * 0.7f + 0.6f,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*if (random.nextInt(5) == 0) {
|
||||||
|
for (i in 0 until random.nextInt(1) + 1) {
|
||||||
|
world.addParticle(
|
||||||
|
ParticleTypes.LAVA, pos.x.toDouble() + 0.5, pos.y.toDouble() + 0.5, pos.z.toDouble() + 0.5,
|
||||||
|
(random.nextFloat() / 2.0f).toDouble(), 5.0E-5,
|
||||||
|
(random.nextFloat() / 2.0f).toDouble()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun spawnSmokeParticle(world: World, pos: BlockPos, isSignal: Boolean, lotsOfSmoke: Boolean) {
|
||||||
|
val random = world.getRandom()
|
||||||
|
val defaultParticleType =
|
||||||
|
if (isSignal) ParticleTypes.CAMPFIRE_SIGNAL_SMOKE else ParticleTypes.CAMPFIRE_COSY_SMOKE
|
||||||
|
world.addImportantParticle(
|
||||||
|
defaultParticleType,
|
||||||
|
true,
|
||||||
|
pos.x.toDouble() + 0.5 + random.nextDouble() / 3.0 * (if (random.nextBoolean()) 1 else -1).toDouble(),
|
||||||
|
pos.y.toDouble() + random.nextDouble() + random.nextDouble(),
|
||||||
|
pos.z.toDouble() + 0.5 + random.nextDouble() / 3.0 * (if (random.nextBoolean()) 1 else -1).toDouble(),
|
||||||
|
0.0,
|
||||||
|
0.07,
|
||||||
|
0.0
|
||||||
|
)
|
||||||
|
if (lotsOfSmoke) {
|
||||||
|
world.addParticle(
|
||||||
|
ParticleTypes.SMOKE,
|
||||||
|
pos.x.toDouble() + 0.5 + random.nextDouble() / 4.0 * (if (random.nextBoolean()) 1 else -1).toDouble(),
|
||||||
|
pos.y.toDouble() + 0.4,
|
||||||
|
pos.z.toDouble() + 0.5 + random.nextDouble() / 4.0 * (if (random.nextBoolean()) 1 else -1).toDouble(),
|
||||||
|
0.0,
|
||||||
|
0.005,
|
||||||
|
0.0
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBreak(world: World, pos: BlockPos, state: BlockState, player: PlayerEntity) {
|
||||||
|
/*val entity = world.getBlockEntity(pos) as DisplayCaseBlockEntity
|
||||||
|
if (!entity.getStack().isEmpty && !player.isCreative) {
|
||||||
|
ItemScatterer.spawn(world, pos, entity.inv)
|
||||||
|
}
|
||||||
|
super.onBreak(world, pos, state, player)*/
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getRenderType(state: BlockState?) = BlockRenderType.MODEL
|
||||||
|
|
||||||
|
override fun hasComparatorOutput(state: BlockState?) = true
|
||||||
|
|
||||||
|
override fun canPathfindThrough(state: BlockState, world: BlockView, pos: BlockPos, type: NavigationType) = false
|
||||||
|
|
||||||
|
}
|
||||||
+214
@@ -0,0 +1,214 @@
|
|||||||
|
package com.cobblemon.mod.common.block.entity
|
||||||
|
|
||||||
|
import com.cobblemon.mod.common.CobblemonBlockEntities
|
||||||
|
import com.cobblemon.mod.common.block.CookingPotBlock
|
||||||
|
import com.cobblemon.mod.common.gui.CookingPotScreenHandler
|
||||||
|
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.network.listener.ClientPlayPacketListener
|
||||||
|
import net.minecraft.network.packet.Packet
|
||||||
|
import net.minecraft.network.packet.s2c.play.BlockEntityUpdateS2CPacket
|
||||||
|
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 CookingPotBlockEntity(
|
||||||
|
val blockPos: BlockPos,
|
||||||
|
val blockState: BlockState
|
||||||
|
) : LockableContainerBlockEntity(CobblemonBlockEntities.COOKING_POT, blockPos, blockState) {
|
||||||
|
|
||||||
|
var cookingPotInventory = CookingPotBlockInventory(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@CookingPotBlockEntity.setOpen(state, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onContainerClose(world: World, pos: BlockPos, state: BlockState) {
|
||||||
|
this@CookingPotBlockEntity.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 CookingPotScreenHandler) {
|
||||||
|
val inventory = (player.currentScreenHandler as CookingPotScreenHandler).inventory
|
||||||
|
return inventory === this@CookingPotBlockEntity
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val AUTOMATION_DELAY = 4
|
||||||
|
const val FILTER_TM_NBT = "FilterTM"
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getPos(): BlockPos {
|
||||||
|
return blockPos
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getCachedState(): BlockState {
|
||||||
|
return blockState
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setOpen(state: BlockState, open: Boolean) {
|
||||||
|
world!!.setBlockState(pos, state.with(CookingPotBlock.COOKING, open), Block.NOTIFY_ALL)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun tick() {
|
||||||
|
if (!removed) {
|
||||||
|
stateManager.updateViewerCount(world, pos, cachedState)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun clear() {
|
||||||
|
cookingPotInventory.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun size(): Int {
|
||||||
|
return this.cookingPotInventory.size()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isEmpty(): Boolean {
|
||||||
|
return this.cookingPotInventory.isEmpty()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getStack(slot: Int): ItemStack {
|
||||||
|
return this.cookingPotInventory.getStack(slot)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun removeStack(slot: Int, amount: Int): ItemStack {
|
||||||
|
return this.cookingPotInventory.removeStack(slot, amount)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun removeStack(slot: Int): ItemStack {
|
||||||
|
return this.cookingPotInventory.removeStack(slot)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setStack(slot: Int, stack: ItemStack?) {
|
||||||
|
return this.cookingPotInventory.setStack(slot, stack)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun canPlayerUse(player: PlayerEntity?): Boolean {
|
||||||
|
return this.cookingPotInventory.canPlayerUse(player)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getContainerName(): Text {
|
||||||
|
return Text.translatable("container.brewing")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun createScreenHandler(syncId: Int, playerInventory: PlayerInventory?): ScreenHandler {
|
||||||
|
return CookingPotScreenHandler(syncId, playerInventory!!, this.cookingPotInventory, this)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toUpdatePacket(): Packet<ClientPlayPacketListener>? {
|
||||||
|
return BlockEntityUpdateS2CPacket.create(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
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 CookingPotBlockInventory(val cookingPotBlockEntity: CookingPotBlockEntity) : 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.cookingPotBlockEntity.pos
|
||||||
|
val entityState = this.cookingPotBlockEntity.cachedState
|
||||||
|
val entityWorld = this.cookingPotBlockEntity.world
|
||||||
|
|
||||||
|
var filterTM: ItemStack? = null
|
||||||
|
var items: DefaultedList<ItemStack?>? = DefaultedList.ofSize(4, ItemStack.EMPTY)
|
||||||
|
|
||||||
|
fun hasFilterTM(): Boolean {
|
||||||
|
return filterTM != null
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun clear() {
|
||||||
|
cookingPotBlockEntity.markDirty()
|
||||||
|
this.items?.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun size(): Int {
|
||||||
|
return this.items?.size ?: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
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 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
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun removeStack(slot: Int, amount: Int): ItemStack {
|
||||||
|
cookingPotBlockEntity.markDirty()
|
||||||
|
return Inventories.splitStack(items, slot, amount)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun removeStack(slot: Int): ItemStack {
|
||||||
|
val slotStack = items?.get(slot)
|
||||||
|
items?.set(slot, ItemStack.EMPTY)
|
||||||
|
cookingPotBlockEntity.markDirty()
|
||||||
|
return slotStack ?: ItemStack.EMPTY
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setStack(slot: Int, stack: ItemStack?) {
|
||||||
|
items?.set(slot, stack)
|
||||||
|
cookingPotBlockEntity.markDirty()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun markDirty() {
|
||||||
|
if (cookingPotBlockEntity.world != null)
|
||||||
|
cookingPotBlockEntity.markDirty()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun canPlayerUse(player: PlayerEntity?): Boolean {
|
||||||
|
return Inventory.canPlayerUse(this.cookingPotBlockEntity, player)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun canInsert(slot: Int, stack: ItemStack?, dir: Direction?): Boolean {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun canExtract(slot: Int, stack: ItemStack?, dir: Direction?): Boolean {
|
||||||
|
return dir == Direction.DOWN && slot == this.OUTPUT_SLOT_INDEX
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
/*
|
||||||
|
* 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.grower
|
||||||
|
|
||||||
|
import com.cobblemon.mod.common.api.apricorn.Apricorn
|
||||||
|
import com.cobblemon.mod.common.world.feature.CobblemonConfiguredFeatures
|
||||||
|
import net.minecraft.block.sapling.SaplingGenerator
|
||||||
|
import net.minecraft.util.math.random.Random
|
||||||
|
|
||||||
|
class SaccharineTreeGrower() : SaplingGenerator() {
|
||||||
|
override fun getTreeFeature(random: Random, bl: Boolean) = CobblemonConfiguredFeatures.SACCHARINE_TREE_KEY
|
||||||
|
}
|
||||||
@@ -50,10 +50,14 @@ import com.cobblemon.mod.common.item.PokeBallItem
|
|||||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.FossilModelRepository
|
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.GenericBedrockEntityModelRepository
|
||||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.MiscModelRepository
|
import com.cobblemon.mod.common.client.render.models.blockbench.repository.MiscModelRepository
|
||||||
|
import com.cobblemon.mod.common.gui.CobblemonScreenHandlers
|
||||||
|
import com.cobblemon.mod.common.gui.CobblemonScreenHandlers.COOKING_POT_SCREEN
|
||||||
|
import com.cobblemon.mod.common.gui.cooking.CookingPotHandledScreen
|
||||||
import com.cobblemon.mod.common.platform.events.PlatformEvents
|
import com.cobblemon.mod.common.platform.events.PlatformEvents
|
||||||
import com.cobblemon.mod.common.util.DataKeys
|
import com.cobblemon.mod.common.util.DataKeys
|
||||||
import com.cobblemon.mod.common.util.asTranslated
|
import com.cobblemon.mod.common.util.asTranslated
|
||||||
import net.minecraft.client.gui.DrawContext
|
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.RenderLayer
|
||||||
import net.minecraft.client.render.block.entity.HangingSignBlockEntityRenderer
|
import net.minecraft.client.render.block.entity.HangingSignBlockEntityRenderer
|
||||||
import net.minecraft.client.render.block.entity.SignBlockEntityRenderer
|
import net.minecraft.client.render.block.entity.SignBlockEntityRenderer
|
||||||
@@ -110,6 +114,7 @@ object CobblemonClient {
|
|||||||
//registerColors()
|
//registerColors()
|
||||||
registerFlywheelRenderers()
|
registerFlywheelRenderers()
|
||||||
this.registerEntityRenderers()
|
this.registerEntityRenderers()
|
||||||
|
registerHandledScreens()
|
||||||
Berries.observable.subscribe {
|
Berries.observable.subscribe {
|
||||||
BerryModelRepository.patchModels()
|
BerryModelRepository.patchModels()
|
||||||
}
|
}
|
||||||
@@ -221,7 +226,16 @@ object CobblemonClient {
|
|||||||
CobblemonBlocks.LARGE_BUDDING_SKY_TUMBLESTONE,
|
CobblemonBlocks.LARGE_BUDDING_SKY_TUMBLESTONE,
|
||||||
CobblemonBlocks.SKY_TUMBLESTONE_CLUSTER,
|
CobblemonBlocks.SKY_TUMBLESTONE_CLUSTER,
|
||||||
CobblemonBlocks.GIMMIGHOUL_CHEST,
|
CobblemonBlocks.GIMMIGHOUL_CHEST,
|
||||||
CobblemonBlocks.DISPLAY_CASE
|
CobblemonBlocks.DISPLAY_CASE,
|
||||||
|
CobblemonBlocks.COOKING_POT,
|
||||||
|
CobblemonBlocks.SACCHARINE_DOOR,
|
||||||
|
CobblemonBlocks.SACCHARINE_TRAPDOOR,
|
||||||
|
CobblemonBlocks.SACCHARINE_SIGN,
|
||||||
|
CobblemonBlocks.SACCHARINE_WALL_SIGN,
|
||||||
|
CobblemonBlocks.SACCHARINE_HANGING_SIGN,
|
||||||
|
CobblemonBlocks.SACCHARINE_WALL_HANGING_SIGN,
|
||||||
|
CobblemonBlocks.SACCHARINE_SAPLING,
|
||||||
|
CobblemonBlocks.BUGWORT
|
||||||
)
|
)
|
||||||
|
|
||||||
this.createBoatModelLayers()
|
this.createBoatModelLayers()
|
||||||
@@ -253,6 +267,7 @@ object CobblemonClient {
|
|||||||
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.RESTORATION_TANK, ::RestorationTankRenderer)
|
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.RESTORATION_TANK, ::RestorationTankRenderer)
|
||||||
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.GILDED_CHEST, ::GildedChestBlockRenderer)
|
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.GILDED_CHEST, ::GildedChestBlockRenderer)
|
||||||
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.DISPLAY_CASE, ::DisplayCaseRenderer)
|
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.DISPLAY_CASE, ::DisplayCaseRenderer)
|
||||||
|
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.COOKING_POT, ::CookingPotRenderer)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun registerEntityRenderers() {
|
private fun registerEntityRenderers() {
|
||||||
@@ -306,4 +321,11 @@ object CobblemonClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun registerHandledScreens() {
|
||||||
|
HandledScreens.register(
|
||||||
|
CobblemonScreenHandlers.COOKING_POT_SCREEN,
|
||||||
|
::CookingPotHandledScreen
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+166
@@ -0,0 +1,166 @@
|
|||||||
|
/*
|
||||||
|
* 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.render.block
|
||||||
|
|
||||||
|
import com.cobblemon.mod.common.CobblemonBlocks
|
||||||
|
import com.cobblemon.mod.common.CobblemonItems
|
||||||
|
import com.cobblemon.mod.common.block.DisplayCaseBlock
|
||||||
|
import com.cobblemon.mod.common.block.entity.CookingPotBlockEntity
|
||||||
|
import com.cobblemon.mod.common.block.entity.DisplayCaseBlockEntity
|
||||||
|
import com.cobblemon.mod.common.client.render.models.blockbench.repository.PokemonModelRepository
|
||||||
|
import com.cobblemon.mod.common.entity.PoseType
|
||||||
|
import com.cobblemon.mod.common.item.PokeBallItem
|
||||||
|
import com.cobblemon.mod.common.item.PokemonItem
|
||||||
|
import net.minecraft.client.MinecraftClient
|
||||||
|
import net.minecraft.client.render.OverlayTexture
|
||||||
|
import net.minecraft.client.render.VertexConsumer
|
||||||
|
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.render.model.json.ModelTransformationMode
|
||||||
|
import net.minecraft.client.util.math.MatrixStack
|
||||||
|
import net.minecraft.item.BannerItem
|
||||||
|
import net.minecraft.item.BedItem
|
||||||
|
import net.minecraft.item.Item
|
||||||
|
import net.minecraft.item.ItemStack
|
||||||
|
import net.minecraft.item.Items
|
||||||
|
import net.minecraft.nbt.NbtInt
|
||||||
|
import net.minecraft.util.math.Direction
|
||||||
|
import net.minecraft.util.math.RotationAxis
|
||||||
|
import net.minecraft.world.World
|
||||||
|
|
||||||
|
class CookingPotRenderer(ctx: BlockEntityRendererFactory.Context) : BlockEntityRenderer<CookingPotBlockEntity> {
|
||||||
|
//val coinPouchStack: ItemStack by lazy { ItemStack(CobblemonItems.RELIC_COIN_POUCH).also { it.setSubNbt("CustomModelData", NbtInt.of(1)) } }
|
||||||
|
override fun render(
|
||||||
|
entity: CookingPotBlockEntity,
|
||||||
|
tickDelta: Float,
|
||||||
|
matrices: MatrixStack,
|
||||||
|
vertexConsumers: VertexConsumerProvider,
|
||||||
|
light: Int,
|
||||||
|
overlay: Int
|
||||||
|
) {
|
||||||
|
/*val stack: ItemStack = if (entity.getStack().isOf(CobblemonItems.RELIC_COIN_POUCH)) {
|
||||||
|
coinPouchStack
|
||||||
|
} else {
|
||||||
|
entity.getStack()
|
||||||
|
}
|
||||||
|
val world = entity.world ?: return
|
||||||
|
val posType = getPositioningType(stack, world)
|
||||||
|
val blockState = if (entity.world != null) entity.cachedState
|
||||||
|
else (CobblemonBlocks.DISPLAY_CASE.defaultState.with(DisplayCaseBlock.ITEM_DIRECTION, Direction.NORTH))
|
||||||
|
val yRot = if (posType == PositioningType.ITEM_MODEL) blockState.get(DisplayCaseBlock.ITEM_DIRECTION).opposite.asRotation()
|
||||||
|
else blockState.get(DisplayCaseBlock.ITEM_DIRECTION).asRotation()
|
||||||
|
|
||||||
|
if (stack.item is PokemonItem) {
|
||||||
|
renderPokemon(
|
||||||
|
matrices,
|
||||||
|
vertexConsumers,
|
||||||
|
light,
|
||||||
|
stack,
|
||||||
|
yRot
|
||||||
|
)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
matrices.push()
|
||||||
|
matrices.translate(0.5f, 0.4f, 0.5f)
|
||||||
|
|
||||||
|
matrices.scale(posType.scaleX, posType.scaleY, posType.scaleZ)
|
||||||
|
matrices.translate(posType.transX, posType.transY, posType.transZ)
|
||||||
|
|
||||||
|
matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(-yRot))
|
||||||
|
matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(posType.rotY))
|
||||||
|
|
||||||
|
MinecraftClient.getInstance().itemRenderer.renderItem(
|
||||||
|
stack,
|
||||||
|
ModelTransformationMode.GROUND,
|
||||||
|
light,
|
||||||
|
overlay,
|
||||||
|
matrices,
|
||||||
|
vertexConsumers,
|
||||||
|
entity.world,
|
||||||
|
0
|
||||||
|
)
|
||||||
|
|
||||||
|
matrices.pop()*/
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun renderPokemon(
|
||||||
|
matrices: MatrixStack,
|
||||||
|
vertexConsumers: VertexConsumerProvider,
|
||||||
|
light: Int,
|
||||||
|
stack: ItemStack,
|
||||||
|
yRot: Float
|
||||||
|
) {
|
||||||
|
val item = stack.item as? PokemonItem ?: return
|
||||||
|
val pokemon = item.asPokemon(stack) ?: return
|
||||||
|
val model = PokemonModelRepository.getPoser(pokemon.species.resourceIdentifier, pokemon.aspects)
|
||||||
|
val renderLayer = model.getLayer(PokemonModelRepository.getTexture(pokemon.species.resourceIdentifier, pokemon.aspects, 0F))
|
||||||
|
val tint = item.tint(stack)
|
||||||
|
val vertexConsumer: VertexConsumer = vertexConsumers.getBuffer(renderLayer)
|
||||||
|
val scale = 0.25f
|
||||||
|
|
||||||
|
matrices.push()
|
||||||
|
matrices.scale(1f, -1f, -1f)
|
||||||
|
matrices.translate(0.5f, -0.69f, -0.5f)
|
||||||
|
matrices.scale(scale, scale, scale)
|
||||||
|
matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(yRot))
|
||||||
|
|
||||||
|
model.setupAnimStateless(PoseType.PROFILE)
|
||||||
|
|
||||||
|
model.withLayerContext(vertexConsumers, null, PokemonModelRepository.getLayers(pokemon.species.resourceIdentifier, pokemon.aspects)) {
|
||||||
|
model.render(matrices, vertexConsumer, light, OverlayTexture.DEFAULT_UV, tint.x, tint.y, tint.z, tint.w)
|
||||||
|
}
|
||||||
|
|
||||||
|
matrices.pop()
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val mobHeads = listOf<Item>(
|
||||||
|
Items.SKELETON_SKULL,
|
||||||
|
Items.WITHER_SKELETON_SKULL,
|
||||||
|
Items.ZOMBIE_HEAD,
|
||||||
|
Items.PIGLIN_HEAD,
|
||||||
|
Items.PLAYER_HEAD,
|
||||||
|
Items.DRAGON_HEAD,
|
||||||
|
Items.CREEPER_HEAD
|
||||||
|
)
|
||||||
|
|
||||||
|
private fun getPositioningType(stack: ItemStack, world: World) = when {
|
||||||
|
mobHeads.contains(stack.item) -> PositioningType.MOB_HEAD
|
||||||
|
stack.item is BedItem -> PositioningType.BED
|
||||||
|
stack.item is BannerItem -> PositioningType.BANNER
|
||||||
|
stack.item is PokeBallItem -> PositioningType.POKE_BALL
|
||||||
|
stack.item == CobblemonItems.RELIC_COIN_POUCH -> PositioningType.COIN_POUCH
|
||||||
|
stack.item == CobblemonItems.PASTURE -> PositioningType.PASTURE
|
||||||
|
stack.item == CobblemonItems.POKEMON_MODEL -> PositioningType.ITEM_MODEL
|
||||||
|
stack.item == Items.SHIELD -> PositioningType.SHIELD
|
||||||
|
stack.item == Items.DECORATED_POT -> PositioningType.MOB_HEAD
|
||||||
|
MinecraftClient.getInstance().itemRenderer.getModel(stack, world, null, 0).hasDepth() -> PositioningType.BLOCK_MODEL
|
||||||
|
else -> PositioningType.ITEM_MODEL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private enum class PositioningType(
|
||||||
|
val scaleX: Float, val scaleY: Float, val scaleZ: Float,
|
||||||
|
val transX: Float, val transY: Float, val transZ: Float,
|
||||||
|
val rotY: Float = 0f
|
||||||
|
) {
|
||||||
|
POKE_BALL(1f, 1f, 1f, 0f, 0.04f, 0f),
|
||||||
|
BLOCK_MODEL(1f, 1f, 1f, 0f, -0.15f, 0f),
|
||||||
|
ITEM_MODEL(1f, 1f, 1f, 0f, 0.04f, 0f),
|
||||||
|
BED(1f, 1f, 1f, 0f, -0.02f, 0f),
|
||||||
|
BANNER(1f, 1f, 1f, 0f, -0.02f, 0f, 180f),
|
||||||
|
MOB_HEAD(1f, 1f, 1f, 0f, -0.025f, 0f, 180f),
|
||||||
|
SHIELD(1f, 1f, 1f, 0f, -0.045f, 0f, 180f),
|
||||||
|
PASTURE(1f, 1f, 1f, 0f, 0.0375f, 0f),
|
||||||
|
COIN_POUCH(1f, 1f, 1f, 0f, 0.415f, 0f)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -21,13 +21,15 @@ import net.minecraft.util.StringIdentifiable
|
|||||||
*/
|
*/
|
||||||
enum class CobblemonBoatType(val mountedOffset: Double) : StringIdentifiable {
|
enum class CobblemonBoatType(val mountedOffset: Double) : StringIdentifiable {
|
||||||
|
|
||||||
APRICORN(-0.1);
|
APRICORN(-0.1),
|
||||||
|
SACCHARINE(-.01);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The base [Item] form of this [CobblemonBoatType].
|
* The base [Item] form of this [CobblemonBoatType].
|
||||||
*/
|
*/
|
||||||
val boatItem: Item get() = when (this) {
|
val boatItem: Item get() = when (this) {
|
||||||
APRICORN -> CobblemonItems.APRICORN_BOAT
|
APRICORN -> CobblemonItems.APRICORN_BOAT
|
||||||
|
SACCHARINE -> CobblemonItems.SACCHARINE_BOAT
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -35,6 +37,7 @@ enum class CobblemonBoatType(val mountedOffset: Double) : StringIdentifiable {
|
|||||||
*/
|
*/
|
||||||
val chestBoatItem: Item get() = when (this) {
|
val chestBoatItem: Item get() = when (this) {
|
||||||
APRICORN -> CobblemonItems.APRICORN_CHEST_BOAT
|
APRICORN -> CobblemonItems.APRICORN_CHEST_BOAT
|
||||||
|
SACCHARINE -> CobblemonItems.SACCHARINE_CHEST_BOAT
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -42,6 +45,7 @@ enum class CobblemonBoatType(val mountedOffset: Double) : StringIdentifiable {
|
|||||||
*/
|
*/
|
||||||
val baseBlock: Block get() = when (this) {
|
val baseBlock: Block get() = when (this) {
|
||||||
APRICORN -> CobblemonBlocks.APRICORN_PLANKS
|
APRICORN -> CobblemonBlocks.APRICORN_PLANKS
|
||||||
|
SACCHARINE -> CobblemonBlocks.SACCHARINE_PLANKS
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -49,6 +53,7 @@ enum class CobblemonBoatType(val mountedOffset: Double) : StringIdentifiable {
|
|||||||
*/
|
*/
|
||||||
val woodType: WoodType get() = when (this) {
|
val woodType: WoodType get() = when (this) {
|
||||||
APRICORN -> CobblemonBlocks.APRICORN_WOOD_TYPE
|
APRICORN -> CobblemonBlocks.APRICORN_WOOD_TYPE
|
||||||
|
SACCHARINE -> CobblemonBlocks.SACCHARINE_WOOD_TYPE
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun asString(): String = this.name.lowercase()
|
override fun asString(): String = this.name.lowercase()
|
||||||
|
|||||||
@@ -0,0 +1,86 @@
|
|||||||
|
package com.cobblemon.mod.common.entity.throwable
|
||||||
|
|
||||||
|
import net.minecraft.entity.EntityType
|
||||||
|
import net.minecraft.entity.LivingEntity
|
||||||
|
import net.minecraft.entity.mob.BlazeEntity
|
||||||
|
import net.minecraft.entity.player.PlayerEntity
|
||||||
|
import net.minecraft.entity.projectile.thrown.ThrownItemEntity
|
||||||
|
import net.minecraft.item.Item
|
||||||
|
import net.minecraft.item.Items
|
||||||
|
import net.minecraft.particle.ItemStackParticleEffect
|
||||||
|
import net.minecraft.particle.ParticleEffect
|
||||||
|
import net.minecraft.particle.ParticleTypes
|
||||||
|
import net.minecraft.sound.SoundCategory
|
||||||
|
import net.minecraft.sound.SoundEvents
|
||||||
|
import net.minecraft.util.hit.EntityHitResult
|
||||||
|
import net.minecraft.util.hit.HitResult
|
||||||
|
import net.minecraft.world.World
|
||||||
|
|
||||||
|
|
||||||
|
class ScatterBangEntity : ThrownItemEntity {
|
||||||
|
constructor(entityType: EntityType<out ScatterBangEntity?>?, world: World?) : super(entityType, world)
|
||||||
|
|
||||||
|
constructor(world: World?, owner: LivingEntity?) : super(EntityType.SNOWBALL, owner, world)
|
||||||
|
|
||||||
|
constructor(world: World?, x: Double, y: Double, z: Double) : super(EntityType.SNOWBALL, x, y, z, world)
|
||||||
|
|
||||||
|
override fun getDefaultItem(): Item {
|
||||||
|
return Items.SNOWBALL
|
||||||
|
}
|
||||||
|
|
||||||
|
private val particleParameters: ParticleEffect
|
||||||
|
get() {
|
||||||
|
val itemStack = this.item
|
||||||
|
return (if (itemStack.isEmpty) ParticleTypes.ITEM_SNOWBALL else ItemStackParticleEffect(
|
||||||
|
ParticleTypes.ITEM,
|
||||||
|
itemStack
|
||||||
|
)) as ParticleEffect
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun handleStatus(status: Byte) {
|
||||||
|
if (status.toInt() == 3) {
|
||||||
|
val particleEffect = this.particleParameters
|
||||||
|
|
||||||
|
for (i in 0..7) {
|
||||||
|
world.addParticle(particleEffect, this.x, this.y, this.z, 0.0, 0.0, 0.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onEntityHit(entityHitResult: EntityHitResult) {
|
||||||
|
world.playSound(
|
||||||
|
null as PlayerEntity?,
|
||||||
|
this.x,
|
||||||
|
this.y,
|
||||||
|
this.z,
|
||||||
|
SoundEvents.ENTITY_GENERIC_EXPLODE,
|
||||||
|
SoundCategory.NEUTRAL,
|
||||||
|
0.6f,
|
||||||
|
0.4f / (world.getRandom().nextFloat() * 0.4f + 0.8f)
|
||||||
|
)
|
||||||
|
|
||||||
|
super.onEntityHit(entityHitResult)
|
||||||
|
val entity = entityHitResult.entity
|
||||||
|
val i = if (entity is BlazeEntity) 3 else 0
|
||||||
|
entity.damage(this.damageSources.thrown(this, this.owner), i.toFloat())
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCollision(hitResult: HitResult) {
|
||||||
|
world.playSound(
|
||||||
|
null as PlayerEntity?,
|
||||||
|
this.x,
|
||||||
|
this.y,
|
||||||
|
this.z,
|
||||||
|
SoundEvents.ENTITY_GENERIC_EXPLODE,
|
||||||
|
SoundCategory.NEUTRAL,
|
||||||
|
0.6f,
|
||||||
|
0.4f / (world.getRandom().nextFloat() * 0.4f + 0.8f)
|
||||||
|
)
|
||||||
|
|
||||||
|
super.onCollision(hitResult)
|
||||||
|
if (!world.isClient) {
|
||||||
|
world.sendEntityStatus(this, 3.toByte())
|
||||||
|
this.discard()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
package com.cobblemon.mod.common.entity.throwable
|
||||||
|
|
||||||
|
import net.minecraft.entity.EntityType
|
||||||
|
import net.minecraft.entity.LivingEntity
|
||||||
|
import net.minecraft.entity.mob.BlazeEntity
|
||||||
|
import net.minecraft.entity.player.PlayerEntity
|
||||||
|
import net.minecraft.entity.projectile.thrown.ThrownItemEntity
|
||||||
|
import net.minecraft.item.Item
|
||||||
|
import net.minecraft.item.Items
|
||||||
|
import net.minecraft.particle.ItemStackParticleEffect
|
||||||
|
import net.minecraft.particle.ParticleEffect
|
||||||
|
import net.minecraft.particle.ParticleTypes
|
||||||
|
import net.minecraft.sound.SoundCategory
|
||||||
|
import net.minecraft.sound.SoundEvents
|
||||||
|
import net.minecraft.util.hit.EntityHitResult
|
||||||
|
import net.minecraft.util.hit.HitResult
|
||||||
|
import net.minecraft.world.World
|
||||||
|
|
||||||
|
|
||||||
|
class StickyGlobEntity : ThrownItemEntity {
|
||||||
|
constructor(entityType: EntityType<out StickyGlobEntity?>?, world: World?) : super(entityType, world)
|
||||||
|
|
||||||
|
constructor(world: World?, owner: LivingEntity?) : super(EntityType.SNOWBALL, owner, world)
|
||||||
|
|
||||||
|
constructor(world: World?, x: Double, y: Double, z: Double) : super(EntityType.SNOWBALL, x, y, z, world)
|
||||||
|
|
||||||
|
override fun getDefaultItem(): Item {
|
||||||
|
return Items.SNOWBALL
|
||||||
|
}
|
||||||
|
|
||||||
|
private val particleParameters: ParticleEffect
|
||||||
|
get() {
|
||||||
|
val itemStack = this.item
|
||||||
|
return (if (itemStack.isEmpty) ParticleTypes.ITEM_SNOWBALL else ItemStackParticleEffect(
|
||||||
|
ParticleTypes.ITEM,
|
||||||
|
itemStack
|
||||||
|
)) as ParticleEffect
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun handleStatus(status: Byte) {
|
||||||
|
if (status.toInt() == 3) {
|
||||||
|
val particleEffect = this.particleParameters
|
||||||
|
|
||||||
|
for (i in 0..7) {
|
||||||
|
world.addParticle(particleEffect, this.x, this.y, this.z, 0.0, 0.0, 0.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onEntityHit(entityHitResult: EntityHitResult) {
|
||||||
|
world.playSound(
|
||||||
|
null as PlayerEntity?,
|
||||||
|
this.x,
|
||||||
|
this.y,
|
||||||
|
this.z,
|
||||||
|
SoundEvents.ENTITY_SLIME_SQUISH,
|
||||||
|
SoundCategory.NEUTRAL,
|
||||||
|
0.6f,
|
||||||
|
0.4f / (world.getRandom().nextFloat() * 0.4f + 0.8f)
|
||||||
|
)
|
||||||
|
|
||||||
|
super.onEntityHit(entityHitResult)
|
||||||
|
val entity = entityHitResult.entity
|
||||||
|
val i = if (entity is BlazeEntity) 3 else 0
|
||||||
|
entity.damage(this.damageSources.thrown(this, this.owner), i.toFloat())
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCollision(hitResult: HitResult) {
|
||||||
|
world.playSound(
|
||||||
|
null as PlayerEntity?,
|
||||||
|
this.x,
|
||||||
|
this.y,
|
||||||
|
this.z,
|
||||||
|
SoundEvents.ENTITY_SLIME_SQUISH,
|
||||||
|
SoundCategory.NEUTRAL,
|
||||||
|
0.6f,
|
||||||
|
0.4f / (world.getRandom().nextFloat() * 0.4f + 0.8f)
|
||||||
|
)
|
||||||
|
|
||||||
|
super.onCollision(hitResult)
|
||||||
|
if (!world.isClient) {
|
||||||
|
world.sendEntityStatus(this, 3.toByte())
|
||||||
|
this.discard()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+201
@@ -0,0 +1,201 @@
|
|||||||
|
package com.cobblemon.mod.common.gui
|
||||||
|
|
||||||
|
import net.minecraft.entity.player.PlayerEntity
|
||||||
|
import net.minecraft.entity.player.PlayerInventory
|
||||||
|
import net.minecraft.inventory.Inventory
|
||||||
|
import net.minecraft.inventory.SimpleInventory
|
||||||
|
import net.minecraft.item.ItemStack
|
||||||
|
import net.minecraft.recipe.*
|
||||||
|
import net.minecraft.recipe.book.RecipeBookCategory
|
||||||
|
import net.minecraft.screen.AbstractRecipeScreenHandler
|
||||||
|
import net.minecraft.screen.ArrayPropertyDelegate
|
||||||
|
import net.minecraft.screen.PropertyDelegate
|
||||||
|
import net.minecraft.screen.ScreenHandlerType
|
||||||
|
import net.minecraft.screen.slot.FurnaceOutputSlot
|
||||||
|
import net.minecraft.screen.slot.Slot
|
||||||
|
import net.minecraft.world.World
|
||||||
|
|
||||||
|
abstract class AbstractCookingPotScreenHandler(
|
||||||
|
type: ScreenHandlerType<*>?,
|
||||||
|
private val recipeType: RecipeType<out AbstractCookingRecipe?>,
|
||||||
|
private val category: RecipeBookCategory,
|
||||||
|
syncId: Int,
|
||||||
|
playerInventory: PlayerInventory?,
|
||||||
|
inventory: Inventory? = SimpleInventory(3),
|
||||||
|
propertyDelegate: PropertyDelegate? = ArrayPropertyDelegate(
|
||||||
|
4
|
||||||
|
)
|
||||||
|
) :
|
||||||
|
AbstractRecipeScreenHandler<Inventory?>(type, syncId) {
|
||||||
|
lateinit var inventory: Inventory
|
||||||
|
lateinit var propertyDelegate: PropertyDelegate
|
||||||
|
lateinit var world: World
|
||||||
|
|
||||||
|
init {
|
||||||
|
checkSize(inventory, 3)
|
||||||
|
checkDataCount(propertyDelegate, 4)
|
||||||
|
if (inventory != null) {
|
||||||
|
this.inventory = inventory
|
||||||
|
}
|
||||||
|
if (propertyDelegate != null) {
|
||||||
|
this.propertyDelegate = propertyDelegate
|
||||||
|
}
|
||||||
|
if (playerInventory != null) {
|
||||||
|
this.world = playerInventory.player.world
|
||||||
|
}
|
||||||
|
this.addSlot(Slot(inventory, 0, 56, 17))
|
||||||
|
//this.addSlot(FurnaceFuelSlot(this, inventory, 1, 56, 53))
|
||||||
|
if (playerInventory != null) {
|
||||||
|
this.addSlot(FurnaceOutputSlot(playerInventory.player, inventory, 2, 116, 35))
|
||||||
|
}
|
||||||
|
var i = 0
|
||||||
|
while (i < 3) {
|
||||||
|
for (j in 0..8) {
|
||||||
|
this.addSlot(Slot(playerInventory, j + i * 9 + 9, 8 + j * 18, 84 + i * 18))
|
||||||
|
}
|
||||||
|
++i
|
||||||
|
}
|
||||||
|
|
||||||
|
i = 0
|
||||||
|
while (i < 9) {
|
||||||
|
this.addSlot(Slot(playerInventory, i, 8 + i * 18, 142))
|
||||||
|
++i
|
||||||
|
}
|
||||||
|
|
||||||
|
this.addProperties(propertyDelegate)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun populateRecipeFinder(finder: RecipeMatcher) {
|
||||||
|
if (inventory is RecipeInputProvider) {
|
||||||
|
(inventory as RecipeInputProvider).provideRecipeInputs(finder)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun clearCraftingSlots() {
|
||||||
|
getSlot(0).setStackNoCallbacks(ItemStack.EMPTY)
|
||||||
|
getSlot(2).setStackNoCallbacks(ItemStack.EMPTY)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun matches(recipe: Recipe<in Inventory?>): Boolean {
|
||||||
|
return recipe.matches(this.inventory, this.world)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getCraftingResultSlotIndex(): Int {
|
||||||
|
return 2
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getCraftingWidth(): Int {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getCraftingHeight(): Int {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getCraftingSlotCount(): Int {
|
||||||
|
return 3
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun canUse(player: PlayerEntity): Boolean {
|
||||||
|
return inventory.canPlayerUse(player)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun quickMove(player: PlayerEntity, slot: Int): ItemStack {
|
||||||
|
var itemStack = ItemStack.EMPTY
|
||||||
|
val slot2 = slots[slot]
|
||||||
|
if (slot2 != null && slot2.hasStack()) {
|
||||||
|
val itemStack2 = slot2.stack
|
||||||
|
itemStack = itemStack2.copy()
|
||||||
|
if (slot == 2) {
|
||||||
|
if (!this.insertItem(itemStack2, 3, 39, true)) {
|
||||||
|
return ItemStack.EMPTY
|
||||||
|
}
|
||||||
|
|
||||||
|
slot2.onQuickTransfer(itemStack2, itemStack)
|
||||||
|
} else if (slot != 1 && slot != 0) {
|
||||||
|
/*if (this.isSmeltable(itemStack2)) {
|
||||||
|
if (!this.insertItem(itemStack2, 0, 1, false)) {
|
||||||
|
return ItemStack.EMPTY
|
||||||
|
}
|
||||||
|
}*/ /*else if (this.isFuel(itemStack2)) {
|
||||||
|
if (!this.insertItem(itemStack2, 1, 2, false)) {
|
||||||
|
return ItemStack.EMPTY
|
||||||
|
}
|
||||||
|
}*/ if (slot >= 3 && slot < 30) {
|
||||||
|
if (!this.insertItem(itemStack2, 30, 39, false)) {
|
||||||
|
return ItemStack.EMPTY
|
||||||
|
}
|
||||||
|
} else if (slot >= 30 && slot < 39 && !this.insertItem(itemStack2, 3, 30, false)) {
|
||||||
|
return ItemStack.EMPTY
|
||||||
|
}
|
||||||
|
} else if (!this.insertItem(itemStack2, 3, 39, false)) {
|
||||||
|
return ItemStack.EMPTY
|
||||||
|
}
|
||||||
|
|
||||||
|
if (itemStack2.isEmpty) {
|
||||||
|
slot2.stack = ItemStack.EMPTY
|
||||||
|
} else {
|
||||||
|
slot2.markDirty()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (itemStack2.count == itemStack.count) {
|
||||||
|
return ItemStack.EMPTY
|
||||||
|
}
|
||||||
|
|
||||||
|
slot2.onTakeItem(player, itemStack2)
|
||||||
|
}
|
||||||
|
|
||||||
|
return itemStack
|
||||||
|
}
|
||||||
|
|
||||||
|
/*fun isSmeltable(itemStack: ItemStack): Boolean {
|
||||||
|
return world.recipeManager.getFirstMatch(
|
||||||
|
this.recipeType, SimpleInventory(*arrayOf(itemStack)),
|
||||||
|
this.world
|
||||||
|
).isPresent
|
||||||
|
}*/
|
||||||
|
|
||||||
|
/*protected fun isFuel(itemStack: ItemStack?): Boolean {
|
||||||
|
return AbstractFurnaceBlockEntity.canUseAsFuel(itemStack)
|
||||||
|
}*/
|
||||||
|
|
||||||
|
val cookProgress: Int
|
||||||
|
get() {
|
||||||
|
val i = propertyDelegate[2]
|
||||||
|
val j = propertyDelegate[3]
|
||||||
|
return if (j != 0 && i != 0) i * 24 / j else 0
|
||||||
|
}
|
||||||
|
|
||||||
|
val fuelProgress: Int
|
||||||
|
get() {
|
||||||
|
var i = propertyDelegate[1]
|
||||||
|
if (i == 0) {
|
||||||
|
i = 200
|
||||||
|
}
|
||||||
|
|
||||||
|
return propertyDelegate[0] * 13 / i
|
||||||
|
}
|
||||||
|
|
||||||
|
val isBurning: Boolean
|
||||||
|
get() = propertyDelegate[0] > 0
|
||||||
|
|
||||||
|
override fun getCategory(): RecipeBookCategory {
|
||||||
|
return this.category
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun canInsertIntoSlot(index: Int): Boolean {
|
||||||
|
return index != 1
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val field_30738: Int = 0
|
||||||
|
const val field_30739: Int = 1
|
||||||
|
const val field_30740: Int = 2
|
||||||
|
const val field_30741: Int = 3
|
||||||
|
const val field_30742: Int = 4
|
||||||
|
private const val field_30743 = 3
|
||||||
|
private const val field_30744 = 30
|
||||||
|
private const val field_30745 = 30
|
||||||
|
private const val field_30746 = 39
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
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.resource.featuretoggle.FeatureFlags
|
||||||
|
import net.minecraft.screen.ScreenHandlerType.Factory
|
||||||
|
import net.minecraft.screen.ScreenHandler
|
||||||
|
import net.minecraft.screen.ScreenHandlerContext
|
||||||
|
import net.minecraft.screen.ScreenHandlerType
|
||||||
|
import net.minecraft.text.Text
|
||||||
|
import net.minecraft.util.Identifier
|
||||||
|
|
||||||
|
object CobblemonScreenHandlers {
|
||||||
|
//val TMM_SCREEN = register(cobblemonResource("tmm_screen"), ::TMMScreenHandler)
|
||||||
|
val COOKING_POT_SCREEN = register(cobblemonResource("cooking_pot_screen")) { syncId, playerInventory ->
|
||||||
|
CookingPotScreenHandler(syncId, playerInventory, ScreenHandlerContext.EMPTY)
|
||||||
|
}
|
||||||
|
|
||||||
|
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,206 @@
|
|||||||
|
package com.cobblemon.mod.common.gui
|
||||||
|
|
||||||
|
import com.cobblemon.mod.common.CobblemonBlocks
|
||||||
|
import com.cobblemon.mod.common.block.entity.CookingPotBlockEntity
|
||||||
|
import net.minecraft.entity.player.PlayerEntity
|
||||||
|
import net.minecraft.entity.player.PlayerInventory
|
||||||
|
import net.minecraft.inventory.CraftingInventory
|
||||||
|
import net.minecraft.inventory.CraftingResultInventory
|
||||||
|
import net.minecraft.inventory.Inventory
|
||||||
|
import net.minecraft.inventory.RecipeInputInventory
|
||||||
|
import net.minecraft.item.ItemStack
|
||||||
|
import net.minecraft.network.packet.s2c.play.ScreenHandlerSlotUpdateS2CPacket
|
||||||
|
import net.minecraft.recipe.Recipe
|
||||||
|
import net.minecraft.recipe.RecipeMatcher
|
||||||
|
import net.minecraft.recipe.RecipeType
|
||||||
|
import net.minecraft.recipe.book.RecipeBookCategory
|
||||||
|
import net.minecraft.screen.AbstractRecipeScreenHandler
|
||||||
|
import net.minecraft.screen.ScreenHandler
|
||||||
|
import net.minecraft.screen.ScreenHandlerContext
|
||||||
|
import net.minecraft.screen.slot.CraftingResultSlot
|
||||||
|
import net.minecraft.screen.slot.Slot
|
||||||
|
import net.minecraft.server.network.ServerPlayerEntity
|
||||||
|
import net.minecraft.text.MutableText
|
||||||
|
import net.minecraft.world.World
|
||||||
|
|
||||||
|
class CookingPotScreenHandler : AbstractRecipeScreenHandler<RecipeInputInventory> {
|
||||||
|
val input: CraftingInventory
|
||||||
|
val result: CraftingResultInventory
|
||||||
|
val context: ScreenHandlerContext
|
||||||
|
val player: PlayerEntity
|
||||||
|
var inventory: Inventory? = null
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val RESULT_ID = 0
|
||||||
|
private const val INPUT_START = 1
|
||||||
|
private const val INPUT_END = 10
|
||||||
|
private const val INVENTORY_START = 10
|
||||||
|
private const val INVENTORY_END = 37
|
||||||
|
private const val HOTBAR_START = 37
|
||||||
|
private const val HOTBAR_END = 46
|
||||||
|
|
||||||
|
fun updateResult(
|
||||||
|
handler: ScreenHandler,
|
||||||
|
world: World,
|
||||||
|
player: PlayerEntity,
|
||||||
|
craftingInventory: RecipeInputInventory,
|
||||||
|
resultInventory: CraftingResultInventory
|
||||||
|
) {
|
||||||
|
if (world.isClient) return
|
||||||
|
val serverPlayerEntity = player as ServerPlayerEntity
|
||||||
|
var itemStack = ItemStack.EMPTY
|
||||||
|
val optional = world.server?.recipeManager?.getFirstMatch(
|
||||||
|
RecipeType.CRAFTING, craftingInventory, world
|
||||||
|
)
|
||||||
|
if (optional != null) {
|
||||||
|
if (optional.isPresent) {
|
||||||
|
val craftingRecipe = optional.get()
|
||||||
|
val itemStack2 = craftingRecipe.craft(craftingInventory, world.registryManager)
|
||||||
|
if (itemStack2.isItemEnabled(world.enabledFeatures)) {
|
||||||
|
itemStack = itemStack2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resultInventory.setStack(0, itemStack)
|
||||||
|
handler.setPreviousTrackedSlot(0, itemStack)
|
||||||
|
serverPlayerEntity.networkHandler.sendPacket(
|
||||||
|
ScreenHandlerSlotUpdateS2CPacket(handler.syncId, handler.nextRevision(), 0, itemStack)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(syncId: Int, playerInventory: PlayerInventory, context: ScreenHandlerContext) :
|
||||||
|
super(CobblemonScreenHandlers.COOKING_POT_SCREEN, syncId) {
|
||||||
|
this.context = context
|
||||||
|
this.player = playerInventory.player
|
||||||
|
this.input = CraftingInventory(this, 3, 3)
|
||||||
|
this.result = CraftingResultInventory()
|
||||||
|
initializeSlots(playerInventory)
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(syncId: Int, playerInventory: PlayerInventory, cookingPotInventory: CookingPotBlockEntity.CookingPotBlockInventory, cookingPotBlockEntity: CookingPotBlockEntity) :
|
||||||
|
super(CobblemonScreenHandlers.COOKING_POT_SCREEN, syncId) {
|
||||||
|
this.context = ScreenHandlerContext.EMPTY
|
||||||
|
this.player = playerInventory.player
|
||||||
|
this.input = CraftingInventory(this, 3, 3)
|
||||||
|
this.result = CraftingResultInventory()
|
||||||
|
this.inventory = cookingPotInventory
|
||||||
|
initializeSlots(playerInventory)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun initializeSlots(playerInventory: PlayerInventory) {
|
||||||
|
val craftingGridOffsetX = 14
|
||||||
|
val craftingGridOffsetY = 10
|
||||||
|
val craftingOutputOffsetX = 16
|
||||||
|
val craftingOutputOffsetY = 10
|
||||||
|
val playerInventoryOffsetX = 0
|
||||||
|
val playerInventoryOffsetY = 16
|
||||||
|
|
||||||
|
addSlot(CraftingResultSlot(playerInventory.player, input, result, 0, 124 + craftingOutputOffsetX, 35 + craftingOutputOffsetY))
|
||||||
|
|
||||||
|
|
||||||
|
for (i in 0..2) {
|
||||||
|
for (j in 0..2) {
|
||||||
|
addSlot(Slot(input, j + i * 3, 30 + craftingGridOffsetX + j * 18, 17 + craftingGridOffsetY + i * 18))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (i in 0..2) {
|
||||||
|
for (j in 0..8) {
|
||||||
|
addSlot(Slot(playerInventory, j + i * 9 + 9, 8 + playerInventoryOffsetX + j * 18, 84 + playerInventoryOffsetY+ i * 18))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (i in 0..8) {
|
||||||
|
addSlot(Slot(playerInventory, i, 8 + playerInventoryOffsetX + i * 18, 142 + playerInventoryOffsetY))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onContentChanged(inventory: Inventory) {
|
||||||
|
context.run { world, pos -> updateResult(this@CookingPotScreenHandler, world, player, input, result) }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun populateRecipeFinder(finder: RecipeMatcher) {
|
||||||
|
input.provideRecipeInputs(finder)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun clearCraftingSlots() {
|
||||||
|
input.clear()
|
||||||
|
result.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun matches(recipe: Recipe<in RecipeInputInventory>): Boolean {
|
||||||
|
return recipe.matches(input, player.world)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onClosed(player: PlayerEntity) {
|
||||||
|
super.onClosed(player)
|
||||||
|
context.run { world, pos -> dropInventory(player, input) }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun canUse(player: PlayerEntity): Boolean {
|
||||||
|
return canUse(context, player, CobblemonBlocks.COOKING_POT)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun quickMove(player: PlayerEntity, slot: Int): ItemStack {
|
||||||
|
var itemStack = ItemStack.EMPTY
|
||||||
|
val slot2 = slots[slot] as Slot
|
||||||
|
if (slot2.hasStack()) {
|
||||||
|
val itemStack2 = slot2.stack
|
||||||
|
itemStack = itemStack2.copy()
|
||||||
|
if (slot == 0) {
|
||||||
|
context.run { world, pos -> itemStack2.item.onCraft(itemStack2, world, player) }
|
||||||
|
if (!insertItem(itemStack2, 10, 46, true)) {
|
||||||
|
return ItemStack.EMPTY
|
||||||
|
}
|
||||||
|
slot2.onQuickTransfer(itemStack2, itemStack)
|
||||||
|
} else if (slot in 10 until 46) {
|
||||||
|
if (!insertItem(itemStack2, 1, 10, false) && (slot < 37 && !insertItem(itemStack2, 37, 46, false) || !insertItem(itemStack2, 10, 37, false))) {
|
||||||
|
return ItemStack.EMPTY
|
||||||
|
}
|
||||||
|
} else if (!insertItem(itemStack2, 10, 46, false)) {
|
||||||
|
return ItemStack.EMPTY
|
||||||
|
}
|
||||||
|
if (itemStack2.isEmpty) {
|
||||||
|
slot2.stack = ItemStack.EMPTY
|
||||||
|
} else {
|
||||||
|
slot2.markDirty()
|
||||||
|
}
|
||||||
|
if (itemStack2.count == itemStack.count) {
|
||||||
|
return ItemStack.EMPTY
|
||||||
|
}
|
||||||
|
slot2.onTakeItem(player, itemStack2)
|
||||||
|
if (slot == 0) {
|
||||||
|
player.dropItem(itemStack2, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return itemStack
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun canInsertIntoSlot(stack: ItemStack, slot: Slot): Boolean {
|
||||||
|
return slot.inventory !== result && super.canInsertIntoSlot(stack, slot)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getCraftingResultSlotIndex(): Int {
|
||||||
|
return RESULT_ID
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getCraftingWidth(): Int {
|
||||||
|
return input.width
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getCraftingHeight(): Int {
|
||||||
|
return input.height
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getCraftingSlotCount(): Int {
|
||||||
|
return 10
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getCategory(): RecipeBookCategory {
|
||||||
|
return RecipeBookCategory.CRAFTING
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun canInsertIntoSlot(index: Int): Boolean {
|
||||||
|
return index != craftingResultSlotIndex
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,120 @@
|
|||||||
|
package com.cobblemon.mod.common.gui.cooking
|
||||||
|
|
||||||
|
import com.google.common.collect.HashBasedTable
|
||||||
|
import com.google.common.collect.ImmutableList
|
||||||
|
import com.google.common.collect.ImmutableMap
|
||||||
|
import com.google.common.collect.Lists
|
||||||
|
import com.google.common.collect.Maps
|
||||||
|
import com.google.common.collect.Table
|
||||||
|
import com.mojang.logging.LogUtils
|
||||||
|
import net.fabricmc.api.EnvType
|
||||||
|
import net.fabricmc.api.Environment
|
||||||
|
import net.minecraft.client.gui.screen.recipebook.RecipeResultCollection
|
||||||
|
import net.minecraft.recipe.AbstractCookingRecipe
|
||||||
|
import net.minecraft.recipe.CraftingRecipe
|
||||||
|
import net.minecraft.recipe.Recipe
|
||||||
|
import net.minecraft.recipe.RecipeType
|
||||||
|
import net.minecraft.recipe.book.CookingRecipeCategory
|
||||||
|
import net.minecraft.recipe.book.CraftingRecipeCategory
|
||||||
|
import net.minecraft.recipe.book.RecipeBook
|
||||||
|
import net.minecraft.registry.DynamicRegistryManager
|
||||||
|
import net.minecraft.registry.Registries
|
||||||
|
import org.slf4j.Logger
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
@Environment(EnvType.CLIENT)
|
||||||
|
class ClientCookBook : RecipeBook() {
|
||||||
|
private val logger: Logger = LogUtils.getLogger()
|
||||||
|
private var resultsByGroup: Map<CookBookGroup, List<RecipeResultCollection>> = ImmutableMap.of()
|
||||||
|
private var orderedResults: List<RecipeResultCollection> = ImmutableList.of()
|
||||||
|
|
||||||
|
fun reload(recipes: Iterable<Recipe<*>>, registryManager: DynamicRegistryManager) {
|
||||||
|
val groupedMap = toGroupedMap(recipes)
|
||||||
|
val map2 = Maps.newHashMap<CookBookGroup, List<RecipeResultCollection>>()
|
||||||
|
val builder = ImmutableList.builder<RecipeResultCollection>()
|
||||||
|
groupedMap.forEach { (recipeBookGroup, list) ->
|
||||||
|
val var10002 = list.stream().map { recipes ->
|
||||||
|
RecipeResultCollection(registryManager, recipes)
|
||||||
|
}
|
||||||
|
map2[recipeBookGroup] = var10002.peek { builder.add(it) }.collect(ImmutableList.toImmutableList())
|
||||||
|
}
|
||||||
|
CookBookGroup.SEARCH_MAP.forEach { (group, searchGroups) ->
|
||||||
|
map2[group] = searchGroups.stream().flatMap { searchGroup ->
|
||||||
|
map2.getOrDefault(searchGroup, ImmutableList.of()).stream()
|
||||||
|
}.collect(ImmutableList.toImmutableList())
|
||||||
|
}
|
||||||
|
resultsByGroup = ImmutableMap.copyOf(map2)
|
||||||
|
orderedResults = builder.build()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun toGroupedMap(recipes: Iterable<Recipe<*>>): Map<CookBookGroup, List<List<Recipe<*>>>> {
|
||||||
|
val map = Maps.newHashMap<CookBookGroup, MutableList<List<Recipe<*>>>>()
|
||||||
|
val table: Table<CookBookGroup, String, MutableList<Recipe<*>>> = HashBasedTable.create()
|
||||||
|
for (recipe in recipes) {
|
||||||
|
if (!recipe.isIgnoredInRecipeBook && !recipe.isEmpty) {
|
||||||
|
val recipeBookGroup = getGroupForRecipe(recipe)
|
||||||
|
val group = recipe.group
|
||||||
|
if (group.isEmpty()) {
|
||||||
|
map.computeIfAbsent(recipeBookGroup) { Lists.newArrayList() }.add(ImmutableList.of(recipe))
|
||||||
|
} else {
|
||||||
|
val list = table.get(recipeBookGroup, group) ?: Lists.newArrayList<Recipe<*>>().also { newList ->
|
||||||
|
table.put(recipeBookGroup, group, newList)
|
||||||
|
map.computeIfAbsent(recipeBookGroup) { Lists.newArrayList() }.add(newList)
|
||||||
|
}
|
||||||
|
list.add(recipe)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return map
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getGroupForRecipe(recipe: Recipe<*>): CookBookGroup {
|
||||||
|
return when {
|
||||||
|
recipe is CraftingRecipe -> {
|
||||||
|
when (recipe.category) {
|
||||||
|
CraftingRecipeCategory.BUILDING -> CookBookGroup.CRAFTING_BUILDING_BLOCKS
|
||||||
|
CraftingRecipeCategory.EQUIPMENT -> CookBookGroup.CRAFTING_EQUIPMENT
|
||||||
|
CraftingRecipeCategory.REDSTONE -> CookBookGroup.CRAFTING_REDSTONE
|
||||||
|
CraftingRecipeCategory.MISC -> CookBookGroup.CRAFTING_MISC
|
||||||
|
else -> throw IncompatibleClassChangeError()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
recipe is AbstractCookingRecipe -> {
|
||||||
|
val cookingRecipeCategory = recipe.category
|
||||||
|
when (recipe.type) {
|
||||||
|
RecipeType.SMELTING -> {
|
||||||
|
when (cookingRecipeCategory) {
|
||||||
|
CookingRecipeCategory.BLOCKS -> CookBookGroup.FURNACE_BLOCKS
|
||||||
|
CookingRecipeCategory.FOOD -> CookBookGroup.FURNACE_FOOD
|
||||||
|
CookingRecipeCategory.MISC -> CookBookGroup.FURNACE_MISC
|
||||||
|
else -> throw IncompatibleClassChangeError()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
RecipeType.BLASTING -> {
|
||||||
|
if (cookingRecipeCategory == CookingRecipeCategory.BLOCKS) CookBookGroup.BLAST_FURNACE_BLOCKS else CookBookGroup.BLAST_FURNACE_MISC
|
||||||
|
}
|
||||||
|
RecipeType.SMOKING -> CookBookGroup.SMOKER_FOOD
|
||||||
|
RecipeType.CAMPFIRE_COOKING -> CookBookGroup.CAMPFIRE
|
||||||
|
else -> {
|
||||||
|
logger.warn("Unknown recipe category: {}/{}", LogUtils.defer { Registries.RECIPE_TYPE.getId(recipe.type) }, LogUtils.defer { recipe.id })
|
||||||
|
CookBookGroup.UNKNOWN
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
recipe.type == RecipeType.STONECUTTING -> CookBookGroup.STONECUTTER
|
||||||
|
recipe.type == RecipeType.SMITHING -> CookBookGroup.SMITHING
|
||||||
|
else -> {
|
||||||
|
logger.warn("Unknown recipe category: {}/{}", LogUtils.defer { Registries.RECIPE_TYPE.getId(recipe.type) }, LogUtils.defer { recipe.id })
|
||||||
|
CookBookGroup.UNKNOWN
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getOrderedResults(): List<RecipeResultCollection> {
|
||||||
|
return orderedResults
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getResultsForGroup(category: CookBookGroup): List<RecipeResultCollection> {
|
||||||
|
return resultsByGroup.getOrDefault(category, Collections.emptyList())
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
package com.cobblemon.mod.common.gui.cooking
|
||||||
|
|
||||||
|
import com.google.common.collect.Sets
|
||||||
|
import net.minecraft.recipe.Recipe
|
||||||
|
import net.minecraft.recipe.book.RecipeBook
|
||||||
|
import net.minecraft.recipe.book.RecipeBookCategory
|
||||||
|
import net.minecraft.recipe.book.RecipeBookOptions
|
||||||
|
import net.minecraft.screen.AbstractRecipeScreenHandler
|
||||||
|
import net.minecraft.util.Identifier
|
||||||
|
import org.jetbrains.annotations.Nullable
|
||||||
|
|
||||||
|
class CookBook : RecipeBook() {
|
||||||
|
protected val recipes: MutableSet<Identifier> = Sets.newHashSet()
|
||||||
|
protected val toBeDisplayed: MutableSet<Identifier> = Sets.newHashSet()
|
||||||
|
private val options = RecipeBookOptions()
|
||||||
|
|
||||||
|
fun copyFrom(book: CookBook) {
|
||||||
|
recipes.clear()
|
||||||
|
toBeDisplayed.clear()
|
||||||
|
options.copyFrom(book.options)
|
||||||
|
recipes.addAll(book.recipes)
|
||||||
|
toBeDisplayed.addAll(book.toBeDisplayed)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun add(recipe: Recipe<*>) {
|
||||||
|
if (!recipe.isIgnoredInRecipeBook) {
|
||||||
|
add(recipe.id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun add(id: Identifier) {
|
||||||
|
recipes.add(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun contains(@Nullable recipe: Recipe<*>?): Boolean {
|
||||||
|
return recipe?.let { recipes.contains(it.id) } ?: false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun contains(id: Identifier): Boolean {
|
||||||
|
return recipes.contains(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun remove(recipe: Recipe<*>) {
|
||||||
|
remove(recipe.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun remove(id: Identifier) {
|
||||||
|
recipes.remove(id)
|
||||||
|
toBeDisplayed.remove(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun shouldDisplay(recipe: Recipe<*>): Boolean {
|
||||||
|
return toBeDisplayed.contains(recipe.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onRecipeDisplayed(recipe: Recipe<*>) {
|
||||||
|
toBeDisplayed.remove(recipe.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun display(recipe: Recipe<*>) {
|
||||||
|
display(recipe.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun display(id: Identifier) {
|
||||||
|
toBeDisplayed.add(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isGuiOpen(category: RecipeBookCategory): Boolean {
|
||||||
|
return options.isGuiOpen(category)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setGuiOpen(category: RecipeBookCategory, open: Boolean) {
|
||||||
|
options.setGuiOpen(category, open)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isFilteringCraftable(handler: AbstractRecipeScreenHandler<*>): Boolean {
|
||||||
|
return isFilteringCraftable(handler.category)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isFilteringCraftable(category: RecipeBookCategory): Boolean {
|
||||||
|
return options.isFilteringCraftable(category)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setFilteringCraftable(category: RecipeBookCategory, filteringCraftable: Boolean) {
|
||||||
|
options.setFilteringCraftable(category, filteringCraftable)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setOptions(options: RecipeBookOptions) {
|
||||||
|
this.options.copyFrom(options)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getOptions(): RecipeBookOptions {
|
||||||
|
return options.copy()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setCategoryOptions(category: RecipeBookCategory, guiOpen: Boolean, filteringCraftable: Boolean) {
|
||||||
|
options.setGuiOpen(category, guiOpen)
|
||||||
|
options.setFilteringCraftable(category, filteringCraftable)
|
||||||
|
}
|
||||||
|
}
|
||||||
+136
@@ -0,0 +1,136 @@
|
|||||||
|
package com.cobblemon.mod.common.gui.cooking
|
||||||
|
|
||||||
|
import com.google.common.collect.Lists
|
||||||
|
import net.fabricmc.api.EnvType
|
||||||
|
import net.fabricmc.api.Environment
|
||||||
|
import net.minecraft.client.MinecraftClient
|
||||||
|
import net.minecraft.client.gui.DrawContext
|
||||||
|
import net.minecraft.client.gui.screen.Screen
|
||||||
|
import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder
|
||||||
|
import net.minecraft.client.gui.screen.narration.NarrationPart
|
||||||
|
import net.minecraft.client.gui.screen.recipebook.RecipeBookResults
|
||||||
|
import net.minecraft.client.gui.screen.recipebook.RecipeResultCollection
|
||||||
|
import net.minecraft.client.gui.tooltip.Tooltip
|
||||||
|
import net.minecraft.client.gui.widget.ClickableWidget
|
||||||
|
import net.minecraft.item.ItemStack
|
||||||
|
import net.minecraft.recipe.Recipe
|
||||||
|
import net.minecraft.recipe.book.RecipeBook
|
||||||
|
import net.minecraft.screen.AbstractRecipeScreenHandler
|
||||||
|
import net.minecraft.screen.ScreenTexts
|
||||||
|
import net.minecraft.text.Text
|
||||||
|
import net.minecraft.util.Identifier
|
||||||
|
import net.minecraft.util.math.MathHelper
|
||||||
|
|
||||||
|
@Environment(EnvType.CLIENT)
|
||||||
|
class CookBookAnimatedResultButton : ClickableWidget(0, 0, 25, 25, ScreenTexts.EMPTY) {
|
||||||
|
val BACKGROUND_TEXTURE = Identifier("textures/gui/recipe_book.png")
|
||||||
|
val field_32414 = 15.0f
|
||||||
|
val field_32415 = 25
|
||||||
|
val field_32413 = 30
|
||||||
|
val MORE_RECIPES_TEXT = Text.translatable("gui.recipebook.moreRecipes")
|
||||||
|
lateinit var craftingScreenHandler: AbstractRecipeScreenHandler<*>
|
||||||
|
lateinit var recipeBook: RecipeBook
|
||||||
|
lateinit var resultCollection: RecipeResultCollection
|
||||||
|
var time = 0f
|
||||||
|
var bounce = 0f
|
||||||
|
var currentResultIndex = 0
|
||||||
|
|
||||||
|
fun showResultCollection(resultCollection: RecipeResultCollection, results: CookBookResults) {
|
||||||
|
this.resultCollection = resultCollection
|
||||||
|
this.craftingScreenHandler = results.getClientValue().player?.currentScreenHandler as AbstractRecipeScreenHandler<*>
|
||||||
|
this.recipeBook = results.getCookBookValue()
|
||||||
|
val list = resultCollection.getResults(this.recipeBook.isFilteringCraftable(this.craftingScreenHandler))
|
||||||
|
for (recipe in list) {
|
||||||
|
if (this.recipeBook.shouldDisplay(recipe)) {
|
||||||
|
results.onRecipesDisplayed(list)
|
||||||
|
this.bounce = 15.0f
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getResultCollectionValue(): RecipeResultCollection {
|
||||||
|
return this.resultCollection
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun renderButton(context: DrawContext, mouseX: Int, mouseY: Int, delta: Float) {
|
||||||
|
if (!Screen.hasControlDown()) {
|
||||||
|
this.time += delta
|
||||||
|
}
|
||||||
|
val minecraftClient = MinecraftClient.getInstance()
|
||||||
|
var i = 29
|
||||||
|
if (!this.resultCollection.hasCraftableRecipes()) {
|
||||||
|
i += 25
|
||||||
|
}
|
||||||
|
var j = 206
|
||||||
|
if (this.resultCollection.getResults(this.recipeBook.isFilteringCraftable(this.craftingScreenHandler)).size > 1) {
|
||||||
|
j += 25
|
||||||
|
}
|
||||||
|
val bl = this.bounce > 0.0f
|
||||||
|
if (bl) {
|
||||||
|
val f = 1.0f + 0.1f * Math.sin((this.bounce / 15.0f * Math.PI).toDouble()).toFloat()
|
||||||
|
context.matrices.push()
|
||||||
|
context.matrices.translate((this.x + 8).toFloat(), (this.y + 12).toFloat(), 0.0f)
|
||||||
|
context.matrices.scale(f, f, 1.0f)
|
||||||
|
context.matrices.translate(-(this.x + 8).toFloat(), -(this.y + 12).toFloat(), 0.0f)
|
||||||
|
this.bounce -= delta
|
||||||
|
}
|
||||||
|
context.drawTexture(BACKGROUND_TEXTURE, this.x, this.y, i, j, this.width, this.height)
|
||||||
|
val list = this.results
|
||||||
|
this.currentResultIndex = MathHelper.floor(this.time / 30.0f) % list.size
|
||||||
|
val itemStack = list[this.currentResultIndex].getOutput(this.resultCollection.registryManager)
|
||||||
|
var k = 4
|
||||||
|
if (this.resultCollection.hasSingleOutput() && this.results.size > 1) {
|
||||||
|
context.drawItem(itemStack, this.x + k + 1, this.y + k + 1, 0, 10)
|
||||||
|
k--
|
||||||
|
}
|
||||||
|
context.drawItemWithoutEntity(itemStack, this.x + k, this.y + k)
|
||||||
|
if (bl) {
|
||||||
|
context.matrices.pop()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val results: List<Recipe<*>>
|
||||||
|
get() {
|
||||||
|
val list = this.resultCollection.getRecipes(true)
|
||||||
|
if (!this.recipeBook.isFilteringCraftable(this.craftingScreenHandler)) {
|
||||||
|
list.addAll(this.resultCollection.getRecipes(false))
|
||||||
|
}
|
||||||
|
return list
|
||||||
|
}
|
||||||
|
|
||||||
|
fun hasResults(): Boolean {
|
||||||
|
return this.results.size == 1
|
||||||
|
}
|
||||||
|
|
||||||
|
fun currentRecipe(): Recipe<*> {
|
||||||
|
return this.results[this.currentResultIndex]
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getRecipeTooltip(): List<Text> {
|
||||||
|
val itemStack = this.results[this.currentResultIndex].getOutput(this.resultCollection.registryManager)
|
||||||
|
val list = Lists.newArrayList(Screen.getTooltipFromItem(MinecraftClient.getInstance(), itemStack))
|
||||||
|
if (this.resultCollection.getResults(this.recipeBook.isFilteringCraftable(this.craftingScreenHandler)).size > 1) {
|
||||||
|
list.add(MORE_RECIPES_TEXT)
|
||||||
|
}
|
||||||
|
return list
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun appendClickableNarrations(builder: NarrationMessageBuilder) {
|
||||||
|
val itemStack = this.results[this.currentResultIndex].getOutput(this.resultCollection.registryManager)
|
||||||
|
builder.put(NarrationPart.TITLE, Text.translatable("narration.recipe", itemStack.name))
|
||||||
|
if (this.resultCollection.getResults(this.recipeBook.isFilteringCraftable(this.craftingScreenHandler)).size > 1) {
|
||||||
|
builder.put(NarrationPart.USAGE, Text.translatable("narration.button.usage.hovered"), Text.translatable("narration.recipe.usage.more"))
|
||||||
|
} else {
|
||||||
|
builder.put(NarrationPart.USAGE, Text.translatable("narration.button.usage.hovered"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getWidth(): Int {
|
||||||
|
return 25
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isValidClickButton(button: Int): Boolean {
|
||||||
|
return button == 0 || button == 1
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
package com.cobblemon.mod.common.gui.cooking
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList
|
||||||
|
import com.google.common.collect.ImmutableMap
|
||||||
|
import net.fabricmc.api.EnvType
|
||||||
|
import net.fabricmc.api.Environment
|
||||||
|
import net.minecraft.block.Blocks
|
||||||
|
import net.minecraft.item.ItemStack
|
||||||
|
import net.minecraft.item.Items
|
||||||
|
import net.minecraft.recipe.book.RecipeBookCategory
|
||||||
|
|
||||||
|
@Environment(EnvType.CLIENT)
|
||||||
|
enum class CookBookGroup(vararg entries: ItemStack) {
|
||||||
|
CRAFTING_SEARCH(ItemStack(Items.COMPASS)),
|
||||||
|
CRAFTING_BUILDING_BLOCKS(ItemStack(Blocks.BRICKS)),
|
||||||
|
CRAFTING_REDSTONE(ItemStack(Items.REDSTONE)),
|
||||||
|
CRAFTING_EQUIPMENT(ItemStack(Items.IRON_AXE), ItemStack(Items.GOLDEN_SWORD)),
|
||||||
|
CRAFTING_MISC(ItemStack(Items.LAVA_BUCKET), ItemStack(Items.APPLE)),
|
||||||
|
FURNACE_SEARCH(ItemStack(Items.COMPASS)),
|
||||||
|
FURNACE_FOOD(ItemStack(Items.PORKCHOP)),
|
||||||
|
FURNACE_BLOCKS(ItemStack(Blocks.STONE)),
|
||||||
|
FURNACE_MISC(ItemStack(Items.LAVA_BUCKET), ItemStack(Items.EMERALD)),
|
||||||
|
BLAST_FURNACE_SEARCH(ItemStack(Items.COMPASS)),
|
||||||
|
BLAST_FURNACE_BLOCKS(ItemStack(Blocks.REDSTONE_ORE)),
|
||||||
|
BLAST_FURNACE_MISC(ItemStack(Items.IRON_SHOVEL), ItemStack(Items.GOLDEN_LEGGINGS)),
|
||||||
|
SMOKER_SEARCH(ItemStack(Items.COMPASS)),
|
||||||
|
SMOKER_FOOD(ItemStack(Items.PORKCHOP)),
|
||||||
|
STONECUTTER(ItemStack(Items.CHISELED_STONE_BRICKS)),
|
||||||
|
SMITHING(ItemStack(Items.NETHERITE_CHESTPLATE)),
|
||||||
|
CAMPFIRE(ItemStack(Items.PORKCHOP)),
|
||||||
|
UNKNOWN(ItemStack(Items.BARRIER));
|
||||||
|
|
||||||
|
val icons: List<ItemStack> = ImmutableList.copyOf(entries)
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val SMOKER: List<CookBookGroup> = ImmutableList.of(SMOKER_SEARCH, SMOKER_FOOD)
|
||||||
|
val BLAST_FURNACE: List<CookBookGroup> = ImmutableList.of(BLAST_FURNACE_SEARCH, BLAST_FURNACE_BLOCKS, BLAST_FURNACE_MISC)
|
||||||
|
val FURNACE: List<CookBookGroup> = ImmutableList.of(FURNACE_SEARCH, FURNACE_FOOD, FURNACE_BLOCKS, FURNACE_MISC)
|
||||||
|
val CRAFTING: List<CookBookGroup> = ImmutableList.of(CRAFTING_SEARCH, CRAFTING_EQUIPMENT, CRAFTING_BUILDING_BLOCKS, CRAFTING_MISC, CRAFTING_REDSTONE)
|
||||||
|
val SEARCH_MAP: Map<CookBookGroup, List<CookBookGroup>> = ImmutableMap.of(
|
||||||
|
CRAFTING_SEARCH, ImmutableList.of(CRAFTING_EQUIPMENT, CRAFTING_BUILDING_BLOCKS, CRAFTING_MISC, CRAFTING_REDSTONE),
|
||||||
|
FURNACE_SEARCH, ImmutableList.of(FURNACE_FOOD, FURNACE_BLOCKS, FURNACE_MISC),
|
||||||
|
BLAST_FURNACE_SEARCH, ImmutableList.of(BLAST_FURNACE_BLOCKS, BLAST_FURNACE_MISC),
|
||||||
|
SMOKER_SEARCH, ImmutableList.of(SMOKER_FOOD)
|
||||||
|
)
|
||||||
|
|
||||||
|
fun getGroups(category: RecipeBookCategory): List<CookBookGroup> {
|
||||||
|
return when (category) {
|
||||||
|
RecipeBookCategory.CRAFTING -> CRAFTING
|
||||||
|
RecipeBookCategory.FURNACE -> FURNACE
|
||||||
|
RecipeBookCategory.BLAST_FURNACE -> BLAST_FURNACE
|
||||||
|
RecipeBookCategory.SMOKER -> SMOKER
|
||||||
|
else -> throw IncompatibleClassChangeError()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getIconsValue(): List<ItemStack> {
|
||||||
|
return this.icons
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package com.cobblemon.mod.common.gui.cooking;
|
||||||
|
|
||||||
|
import net.fabricmc.api.EnvType
|
||||||
|
import net.fabricmc.api.Environment
|
||||||
|
import net.minecraft.client.gui.screen.recipebook.RecipeBookWidget
|
||||||
|
|
||||||
|
@Environment(EnvType.CLIENT)
|
||||||
|
interface CookBookProvider {
|
||||||
|
fun refreshCookBook()
|
||||||
|
|
||||||
|
fun getCookBookWidget(): CookBookWidget
|
||||||
|
}
|
||||||
@@ -0,0 +1,193 @@
|
|||||||
|
package com.cobblemon.mod.common.gui.cooking
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList
|
||||||
|
import com.google.common.collect.Lists
|
||||||
|
import net.fabricmc.api.EnvType
|
||||||
|
import net.fabricmc.api.Environment
|
||||||
|
import net.minecraft.client.MinecraftClient
|
||||||
|
import net.minecraft.client.gui.DrawContext
|
||||||
|
import net.minecraft.client.gui.screen.recipebook.AnimatedResultButton
|
||||||
|
import net.minecraft.client.gui.screen.recipebook.RecipeAlternativesWidget
|
||||||
|
import net.minecraft.client.gui.screen.recipebook.RecipeDisplayListener
|
||||||
|
import net.minecraft.client.gui.screen.recipebook.RecipeResultCollection
|
||||||
|
import net.minecraft.client.gui.widget.ClickableWidget
|
||||||
|
import net.minecraft.client.gui.widget.ToggleButtonWidget
|
||||||
|
import net.minecraft.recipe.Recipe
|
||||||
|
import net.minecraft.recipe.book.RecipeBook
|
||||||
|
import org.jetbrains.annotations.Nullable
|
||||||
|
import java.util.function.Consumer
|
||||||
|
|
||||||
|
@Environment(EnvType.CLIENT)
|
||||||
|
class CookBookResults {
|
||||||
|
val resultButtons = Lists.newArrayListWithCapacity<CookBookAnimatedResultButton>(20)
|
||||||
|
@Nullable
|
||||||
|
var hoveredResultButton: CookBookAnimatedResultButton? = null
|
||||||
|
val alternatesWidget = RecipeAlternativesWidget()
|
||||||
|
lateinit var client: MinecraftClient
|
||||||
|
val recipeDisplayListeners = Lists.newArrayList<RecipeDisplayListener>()
|
||||||
|
var resultCollections = ImmutableList.of<RecipeResultCollection>()
|
||||||
|
lateinit var nextPageButton: ToggleButtonWidget
|
||||||
|
lateinit var prevPageButton: ToggleButtonWidget
|
||||||
|
var pageCount = 0
|
||||||
|
var currentPage = 0
|
||||||
|
lateinit var recipeBook: RecipeBook
|
||||||
|
@Nullable
|
||||||
|
var lastClickedRecipe: Recipe<*>? = null
|
||||||
|
@Nullable
|
||||||
|
var resultCollection: RecipeResultCollection? = null
|
||||||
|
|
||||||
|
init {
|
||||||
|
for (i in 0 until 20) {
|
||||||
|
resultButtons.add(CookBookAnimatedResultButton())
|
||||||
|
/*resultButtons.add(CookBookAnimatedResultButton().apply {
|
||||||
|
// Initialize resultCollection with a default or dummy value if possible
|
||||||
|
this.resultCollection = RecipeResultCollection()
|
||||||
|
})*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun initialize(client: MinecraftClient, parentLeft: Int, parentTop: Int) {
|
||||||
|
this.client = client
|
||||||
|
this.recipeBook = client.player?.recipeBook ?: return
|
||||||
|
|
||||||
|
for (i in resultButtons.indices) {
|
||||||
|
resultButtons[i].setPosition(parentLeft + 11 + 25 * (i % 5), parentTop + 31 + 25 * (i / 5))
|
||||||
|
}
|
||||||
|
|
||||||
|
nextPageButton = ToggleButtonWidget(parentLeft + 93, parentTop + 137, 12, 17, false)
|
||||||
|
nextPageButton.setTextureUV(1, 208, 13, 18, CookBookWidget.TEXTURE)
|
||||||
|
prevPageButton = ToggleButtonWidget(parentLeft + 38, parentTop + 137, 12, 17, true)
|
||||||
|
prevPageButton.setTextureUV(1, 208, 13, 18, CookBookWidget.TEXTURE)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setGui(widget: CookBookWidget) {
|
||||||
|
recipeDisplayListeners.remove(widget)
|
||||||
|
recipeDisplayListeners.add(widget)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setResults(resultCollections: List<RecipeResultCollection>, resetCurrentPage: Boolean) {
|
||||||
|
this.resultCollections = ImmutableList.copyOf(resultCollections)
|
||||||
|
this.pageCount = Math.ceil(resultCollections.size / 20.0).toInt()
|
||||||
|
if (this.pageCount <= this.currentPage || resetCurrentPage) {
|
||||||
|
this.currentPage = 0
|
||||||
|
}
|
||||||
|
refreshResultButtons()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun refreshResultButtons() {
|
||||||
|
val i = 20 * this.currentPage
|
||||||
|
for (j in resultButtons.indices) {
|
||||||
|
val animatedResultButton = resultButtons[j]
|
||||||
|
if (i + j < resultCollections.size) {
|
||||||
|
val recipeResultCollection = resultCollections[i + j]
|
||||||
|
animatedResultButton.showResultCollection(recipeResultCollection, this)
|
||||||
|
animatedResultButton.visible = true
|
||||||
|
} else {
|
||||||
|
animatedResultButton.visible = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
hideShowPageButtons()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun hideShowPageButtons() {
|
||||||
|
nextPageButton.visible = pageCount > 1 && currentPage < pageCount - 1
|
||||||
|
prevPageButton.visible = pageCount > 1 && currentPage > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
fun draw(context: DrawContext, x: Int, y: Int, mouseX: Int, mouseY: Int, delta: Float) {
|
||||||
|
if (pageCount > 1) {
|
||||||
|
val string = "${currentPage + 1}/$pageCount"
|
||||||
|
val i = client.textRenderer.getWidth(string)
|
||||||
|
context.drawText(client.textRenderer, string, x - i / 2 + 73, y + 141, -1, false)
|
||||||
|
}
|
||||||
|
hoveredResultButton = null
|
||||||
|
for (animatedResultButton in resultButtons) {
|
||||||
|
animatedResultButton.render(context, mouseX, mouseY, delta)
|
||||||
|
if (animatedResultButton.visible && animatedResultButton.isSelected()) {
|
||||||
|
hoveredResultButton = animatedResultButton
|
||||||
|
}
|
||||||
|
}
|
||||||
|
prevPageButton.render(context, mouseX, mouseY, delta)
|
||||||
|
nextPageButton.render(context, mouseX, mouseY, delta)
|
||||||
|
alternatesWidget.render(context, mouseX, mouseY, delta)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun drawTooltip(context: DrawContext, x: Int, y: Int) {
|
||||||
|
if (client.currentScreen != null && hoveredResultButton != null && !alternatesWidget.isVisible()) {
|
||||||
|
context.drawTooltip(client.textRenderer, hoveredResultButton!!.getRecipeTooltip(), x, y)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
fun getLastClickedRecipeValue(): Recipe<*>? {
|
||||||
|
return lastClickedRecipe
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
fun getLastClickedResults(): RecipeResultCollection? {
|
||||||
|
return resultCollection
|
||||||
|
}
|
||||||
|
|
||||||
|
fun hideAlternates() {
|
||||||
|
alternatesWidget.isVisible = false
|
||||||
|
}
|
||||||
|
|
||||||
|
fun mouseClicked(mouseX: Double, mouseY: Double, button: Int, areaLeft: Int, areaTop: Int, areaWidth: Int, areaHeight: Int): Boolean {
|
||||||
|
lastClickedRecipe = null
|
||||||
|
resultCollection = null
|
||||||
|
if (alternatesWidget.isVisible()) {
|
||||||
|
if (alternatesWidget.mouseClicked(mouseX, mouseY, button)) {
|
||||||
|
lastClickedRecipe = alternatesWidget.getLastClickedRecipe()
|
||||||
|
resultCollection = alternatesWidget.getResults()
|
||||||
|
} else {
|
||||||
|
alternatesWidget.isVisible = false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
} else if (nextPageButton.mouseClicked(mouseX, mouseY, button)) {
|
||||||
|
currentPage++
|
||||||
|
refreshResultButtons()
|
||||||
|
return true
|
||||||
|
} else if (prevPageButton.mouseClicked(mouseX, mouseY, button)) {
|
||||||
|
currentPage--
|
||||||
|
refreshResultButtons()
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
for (animatedResultButton in resultButtons) {
|
||||||
|
if (animatedResultButton.mouseClicked(mouseX, mouseY, button)) {
|
||||||
|
if (button == 0) {
|
||||||
|
lastClickedRecipe = animatedResultButton.currentRecipe()
|
||||||
|
resultCollection = animatedResultButton.getResultCollectionValue()
|
||||||
|
} else if (button == 1 && !alternatesWidget.isVisible() && !animatedResultButton.hasResults()) {
|
||||||
|
alternatesWidget.showAlternativesForResult(client, animatedResultButton.getResultCollectionValue(), animatedResultButton.x, animatedResultButton.y, areaLeft + areaWidth / 2, areaTop + 13 + areaHeight / 2, animatedResultButton.width.toFloat())
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onRecipesDisplayed(recipes: List<Recipe<*>>) {
|
||||||
|
for (recipeDisplayListener in recipeDisplayListeners) {
|
||||||
|
recipeDisplayListener.onRecipesDisplayed(recipes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getClientValue(): MinecraftClient {
|
||||||
|
return client
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getCookBookValue(): RecipeBook {
|
||||||
|
return recipeBook
|
||||||
|
}
|
||||||
|
|
||||||
|
fun forEachButton(consumer: Consumer<ClickableWidget>) {
|
||||||
|
consumer.accept(nextPageButton)
|
||||||
|
consumer.accept(prevPageButton)
|
||||||
|
resultButtons.forEach(consumer)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val field_32411 = 20
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,499 @@
|
|||||||
|
package com.cobblemon.mod.common.gui.cooking
|
||||||
|
|
||||||
|
import com.google.common.collect.Lists
|
||||||
|
import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet
|
||||||
|
import it.unimi.dsi.fastutil.objects.ObjectSet
|
||||||
|
import net.fabricmc.api.EnvType
|
||||||
|
import net.fabricmc.api.Environment
|
||||||
|
import net.minecraft.client.MinecraftClient
|
||||||
|
import net.minecraft.client.font.TextRenderer
|
||||||
|
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.Selectable.SelectionType
|
||||||
|
import net.minecraft.client.gui.screen.Screen
|
||||||
|
import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder
|
||||||
|
import net.minecraft.client.gui.screen.recipebook.RecipeBookGhostSlots
|
||||||
|
import net.minecraft.client.gui.screen.recipebook.RecipeDisplayListener
|
||||||
|
import net.minecraft.client.gui.screen.recipebook.RecipeGroupButtonWidget
|
||||||
|
import net.minecraft.client.gui.tooltip.Tooltip
|
||||||
|
import net.minecraft.client.gui.widget.TextFieldWidget
|
||||||
|
import net.minecraft.client.gui.widget.ToggleButtonWidget
|
||||||
|
import net.minecraft.client.recipebook.ClientRecipeBook
|
||||||
|
import net.minecraft.client.recipebook.RecipeBookGroup
|
||||||
|
import net.minecraft.client.resource.language.LanguageDefinition
|
||||||
|
import net.minecraft.client.resource.language.LanguageManager
|
||||||
|
import net.minecraft.client.search.SearchManager
|
||||||
|
import net.minecraft.item.ItemStack
|
||||||
|
import net.minecraft.network.packet.c2s.play.RecipeCategoryOptionsC2SPacket
|
||||||
|
import net.minecraft.recipe.Ingredient
|
||||||
|
import net.minecraft.recipe.Recipe
|
||||||
|
import net.minecraft.recipe.RecipeGridAligner
|
||||||
|
import net.minecraft.recipe.RecipeMatcher
|
||||||
|
import net.minecraft.recipe.book.RecipeBookCategory
|
||||||
|
import net.minecraft.screen.AbstractRecipeScreenHandler
|
||||||
|
import net.minecraft.screen.slot.Slot
|
||||||
|
import net.minecraft.text.Text
|
||||||
|
import net.minecraft.util.Formatting
|
||||||
|
import net.minecraft.util.Identifier
|
||||||
|
import org.jetbrains.annotations.Nullable
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
@Environment(EnvType.CLIENT)
|
||||||
|
class CookBookWidget : RecipeGridAligner<Ingredient>, Drawable, Element, Selectable, RecipeDisplayListener {
|
||||||
|
//val SEARCH_HINT_TEXT: Text
|
||||||
|
val field_32408 = 147
|
||||||
|
val field_32409 = 166
|
||||||
|
val field_32410 = 86
|
||||||
|
//val TOGGLE_CRAFTABLE_RECIPES_TEXT: Text
|
||||||
|
//val TOGGLE_ALL_RECIPES_TEXT: Text
|
||||||
|
var leftOffset = 0
|
||||||
|
var parentWidth = 0
|
||||||
|
var parentHeight = 0
|
||||||
|
val ghostSlots = RecipeBookGhostSlots()
|
||||||
|
val tabButtons: ArrayList<CookingRecipeGroupButtonWidget> = Lists.newArrayList<CookingRecipeGroupButtonWidget>()
|
||||||
|
@Nullable
|
||||||
|
var currentTab: CookingRecipeGroupButtonWidget? = null
|
||||||
|
lateinit var toggleCraftableButton: ToggleButtonWidget
|
||||||
|
lateinit var craftingScreenHandler: AbstractRecipeScreenHandler<*>
|
||||||
|
lateinit var client: MinecraftClient
|
||||||
|
@Nullable
|
||||||
|
var searchField: TextFieldWidget? = null
|
||||||
|
var searchText = ""
|
||||||
|
lateinit var recipeBook: ClientRecipeBook
|
||||||
|
val recipesArea = CookBookResults()
|
||||||
|
val recipeFinder = RecipeMatcher()
|
||||||
|
var cachedInvChangeCount = 0
|
||||||
|
var searching = false
|
||||||
|
var open = false
|
||||||
|
var narrow = false
|
||||||
|
|
||||||
|
fun initialize(parentWidth: Int, parentHeight: Int, client: MinecraftClient?, narrow: Boolean, craftingScreenHandler: AbstractRecipeScreenHandler<*>) {
|
||||||
|
if (client != null) {
|
||||||
|
this.client = client
|
||||||
|
}
|
||||||
|
this.parentWidth = parentWidth
|
||||||
|
this.parentHeight = parentHeight
|
||||||
|
this.craftingScreenHandler = craftingScreenHandler
|
||||||
|
this.narrow = narrow
|
||||||
|
client?.player?.currentScreenHandler = craftingScreenHandler
|
||||||
|
this.recipeBook = client?.player?.recipeBook ?: return
|
||||||
|
this.cachedInvChangeCount = client?.player?.inventory?.changeCount ?: 0
|
||||||
|
this.open = isGuiOpen()
|
||||||
|
if (this.open) {
|
||||||
|
reset()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun reset() {
|
||||||
|
leftOffset = if (narrow) 0 else 86
|
||||||
|
val i = (parentWidth - 147) / 2 - leftOffset
|
||||||
|
val j = (parentHeight - 166) / 2
|
||||||
|
recipeFinder.clear()
|
||||||
|
client.player?.inventory?.populateRecipeFinder(recipeFinder)
|
||||||
|
craftingScreenHandler.populateRecipeFinder(recipeFinder)
|
||||||
|
val string = searchField?.text ?: ""
|
||||||
|
val var10003 = client.textRenderer
|
||||||
|
val var10004 = i + 26
|
||||||
|
val var10005 = j + 14
|
||||||
|
Objects.requireNonNull(client.textRenderer)
|
||||||
|
searchField = TextFieldWidget(var10003, var10004, var10005, 79, 9 + 3, Text.translatable("itemGroup.search"))
|
||||||
|
searchField?.setMaxLength(50)
|
||||||
|
searchField?.isVisible = true
|
||||||
|
searchField?.setEditableColor(16777215)
|
||||||
|
searchField?.text = string
|
||||||
|
searchField?.setPlaceholder(SEARCH_HINT_TEXT)
|
||||||
|
recipesArea.initialize(client, i, j)
|
||||||
|
recipesArea.setGui(this)
|
||||||
|
toggleCraftableButton = ToggleButtonWidget(i + 110, j + 12, 26, 16, recipeBook.isFilteringCraftable(craftingScreenHandler))
|
||||||
|
updateTooltip()
|
||||||
|
setBookButtonTexture()
|
||||||
|
tabButtons.clear()
|
||||||
|
val var4 = RecipeBookGroup.getGroups(craftingScreenHandler.category).iterator()
|
||||||
|
while (var4.hasNext()) {
|
||||||
|
val recipeBookGroup = var4.next() as RecipeBookGroup
|
||||||
|
tabButtons.add(CookingRecipeGroupButtonWidget(recipeBookGroup))
|
||||||
|
}
|
||||||
|
if (currentTab != null) {
|
||||||
|
currentTab = tabButtons.stream().filter { button ->
|
||||||
|
button.category == currentTab?.getCategoryValue()
|
||||||
|
}.findFirst().orElse(null)
|
||||||
|
}
|
||||||
|
if (currentTab == null) {
|
||||||
|
currentTab = tabButtons[0]
|
||||||
|
}
|
||||||
|
currentTab?.setToggled(true)
|
||||||
|
refreshResults(false)
|
||||||
|
refreshTabButtons()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateTooltip() {
|
||||||
|
toggleCraftableButton.setTooltip(if (toggleCraftableButton.isToggled) Tooltip.of(getToggleCraftableButtonText()) else Tooltip.of(TOGGLE_ALL_RECIPES_TEXT))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setBookButtonTexture() {
|
||||||
|
toggleCraftableButton.setTextureUV(152, 41, 28, 18, TEXTURE)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun findLeftEdge(width: Int, backgroundWidth: Int): Int {
|
||||||
|
return if (isOpen() && !narrow) {
|
||||||
|
177 + (width - backgroundWidth - 200) / 2
|
||||||
|
} else {
|
||||||
|
(width - backgroundWidth) / 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun toggleOpen() {
|
||||||
|
setOpenValue(!isOpen())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isOpen(): Boolean {
|
||||||
|
return open
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isGuiOpen(): Boolean {
|
||||||
|
return recipeBook.isGuiOpen(craftingScreenHandler.category)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setOpenValue(opened: Boolean) {
|
||||||
|
if (opened) {
|
||||||
|
reset()
|
||||||
|
}
|
||||||
|
open = opened
|
||||||
|
recipeBook.setGuiOpen(craftingScreenHandler.category, opened)
|
||||||
|
if (!opened) {
|
||||||
|
recipesArea.hideAlternates()
|
||||||
|
}
|
||||||
|
sendBookDataPacket()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun slotClicked(@Nullable slot: Slot?) {
|
||||||
|
if (slot != null && slot.id < craftingScreenHandler.craftingSlotCount) {
|
||||||
|
ghostSlots.reset()
|
||||||
|
if (isOpen()) {
|
||||||
|
refreshInputs()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun refreshResults(resetCurrentPage: Boolean) {
|
||||||
|
val list = recipeBook.getResultsForGroup(currentTab?.category ?: return)
|
||||||
|
list.forEach { resultCollection ->
|
||||||
|
resultCollection.computeCraftables(recipeFinder, craftingScreenHandler.craftingWidth, craftingScreenHandler.craftingHeight, recipeBook)
|
||||||
|
}
|
||||||
|
val list2 = Lists.newArrayList(list)
|
||||||
|
list2.removeIf { !it.isInitialized }
|
||||||
|
list2.removeIf { !it.hasFittingRecipes() }
|
||||||
|
val string = searchField?.text ?: ""
|
||||||
|
if (string.isNotEmpty()) {
|
||||||
|
val objectSet = ObjectLinkedOpenHashSet(client.getSearchProvider(SearchManager.RECIPE_OUTPUT).findAll(string.lowercase(Locale.ROOT)))
|
||||||
|
list2.removeIf { !objectSet.contains(it) }
|
||||||
|
}
|
||||||
|
if (recipeBook.isFilteringCraftable(craftingScreenHandler)) {
|
||||||
|
list2.removeIf { !it.hasCraftableRecipes() }
|
||||||
|
}
|
||||||
|
recipesArea.setResults(list2, resetCurrentPage)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun refreshTabButtons() {
|
||||||
|
val i = (parentWidth - 147) / 2 - leftOffset - 30
|
||||||
|
val j = (parentHeight - 166) / 2 + 3
|
||||||
|
var l = 0
|
||||||
|
val var5 = tabButtons.iterator()
|
||||||
|
while (true) {
|
||||||
|
while (var5.hasNext()) {
|
||||||
|
val recipeGroupButtonWidget = var5.next()
|
||||||
|
val recipeBookGroup = recipeGroupButtonWidget.category
|
||||||
|
if (recipeBookGroup != RecipeBookGroup.CRAFTING_SEARCH && recipeBookGroup != RecipeBookGroup.FURNACE_SEARCH) {
|
||||||
|
if (recipeGroupButtonWidget.hasKnownRecipes(recipeBook)) {
|
||||||
|
recipeGroupButtonWidget.setPosition(i, j + 27 * l++)
|
||||||
|
recipeGroupButtonWidget.checkForNewRecipes(client)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
recipeGroupButtonWidget.visible = true
|
||||||
|
recipeGroupButtonWidget.setPosition(i, j + 27 * l++)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun update() {
|
||||||
|
val bl = isGuiOpen()
|
||||||
|
if (isOpen() != bl) {
|
||||||
|
setOpenValue(bl)
|
||||||
|
}
|
||||||
|
if (isOpen()) {
|
||||||
|
if (cachedInvChangeCount != client.player?.inventory?.changeCount) {
|
||||||
|
refreshInputs()
|
||||||
|
cachedInvChangeCount = client.player?.inventory?.changeCount ?: 0
|
||||||
|
}
|
||||||
|
searchField?.tick()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun refreshInputs() {
|
||||||
|
recipeFinder.clear()
|
||||||
|
client.player?.inventory?.populateRecipeFinder(recipeFinder)
|
||||||
|
craftingScreenHandler.populateRecipeFinder(recipeFinder)
|
||||||
|
refreshResults(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun render(context: DrawContext, mouseX: Int, mouseY: Int, delta: Float) {
|
||||||
|
if (isOpen()) {
|
||||||
|
context.matrices.push()
|
||||||
|
context.matrices.translate(0.0F, 0.0F, 100.0F)
|
||||||
|
val i = (parentWidth - 147) / 2 - leftOffset
|
||||||
|
val j = (parentHeight - 166) / 2
|
||||||
|
context.drawTexture(TEXTURE, i, j, 1, 1, 147, 166)
|
||||||
|
searchField?.render(context, mouseX, mouseY, delta)
|
||||||
|
for (recipeGroupButtonWidget in tabButtons) {
|
||||||
|
recipeGroupButtonWidget.render(context, mouseX, mouseY, delta)
|
||||||
|
}
|
||||||
|
toggleCraftableButton.render(context, mouseX, mouseY, delta)
|
||||||
|
recipesArea.draw(context, i, j, mouseX, mouseY, delta)
|
||||||
|
context.matrices.pop()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun drawTooltip(context: DrawContext, x: Int, y: Int, mouseX: Int, mouseY: Int) {
|
||||||
|
if (isOpen()) {
|
||||||
|
recipesArea.drawTooltip(context, mouseX, mouseY)
|
||||||
|
drawGhostSlotTooltip(context, x, y, mouseX, mouseY)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getToggleCraftableButtonText(): Text {
|
||||||
|
return TOGGLE_CRAFTABLE_RECIPES_TEXT
|
||||||
|
}
|
||||||
|
|
||||||
|
fun drawGhostSlotTooltip(context: DrawContext, x: Int, y: Int, mouseX: Int, mouseY: Int) {
|
||||||
|
var itemStack: ItemStack? = null
|
||||||
|
for (i in 0 until ghostSlots.slotCount) {
|
||||||
|
val ghostInputSlot = ghostSlots.getSlot(i)
|
||||||
|
val j = ghostInputSlot.x + x
|
||||||
|
val k = ghostInputSlot.y + y
|
||||||
|
if (mouseX >= j && mouseY >= k && mouseX < j + 16 && mouseY < k + 16) {
|
||||||
|
itemStack = ghostInputSlot.currentItemStack
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (itemStack != null && client.currentScreen != null) {
|
||||||
|
context.drawTooltip(client.textRenderer, Screen.getTooltipFromItem(client, itemStack), mouseX, mouseY)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun drawGhostSlots(context: DrawContext, x: Int, y: Int, notInventory: Boolean, delta: Float) {
|
||||||
|
ghostSlots.draw(context, client, x, y, notInventory, delta)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun mouseClicked(mouseX: Double, mouseY: Double, button: Int): Boolean {
|
||||||
|
if (isOpen() && !client.player?.isSpectator()!!) {
|
||||||
|
if (recipesArea.mouseClicked(mouseX, mouseY, button, (parentWidth - 147) / 2 - leftOffset, (parentHeight - 166) / 2, 147, 166)) {
|
||||||
|
val recipe = recipesArea.getLastClickedRecipeValue()
|
||||||
|
val recipeResultCollection = recipesArea.getLastClickedResults()
|
||||||
|
if (recipe != null && recipeResultCollection != null) {
|
||||||
|
if (!recipeResultCollection.isCraftable(recipe) && ghostSlots.recipe == recipe) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
ghostSlots.reset()
|
||||||
|
client.interactionManager?.clickRecipe(client.player?.currentScreenHandler?.syncId ?: 0, recipe, Screen.hasShiftDown())
|
||||||
|
if (!isWide()) {
|
||||||
|
setOpenValue(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
} else if (searchField?.mouseClicked(mouseX, mouseY, button) == true) {
|
||||||
|
searchField?.setFocused(true)
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
searchField?.setFocused(false)
|
||||||
|
if (toggleCraftableButton.mouseClicked(mouseX, mouseY, button)) {
|
||||||
|
val bl = toggleFilteringCraftable()
|
||||||
|
toggleCraftableButton.setToggled(bl)
|
||||||
|
updateTooltip()
|
||||||
|
sendBookDataPacket()
|
||||||
|
refreshResults(false)
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
for (recipeGroupButtonWidget in tabButtons) {
|
||||||
|
if (recipeGroupButtonWidget.mouseClicked(mouseX, mouseY, button)) {
|
||||||
|
if (currentTab != recipeGroupButtonWidget) {
|
||||||
|
currentTab?.setToggled(false)
|
||||||
|
currentTab = recipeGroupButtonWidget
|
||||||
|
currentTab?.setToggled(true)
|
||||||
|
refreshResults(true)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun toggleFilteringCraftable(): Boolean {
|
||||||
|
val recipeBookCategory = craftingScreenHandler.category
|
||||||
|
val bl = !recipeBook.isFilteringCraftable(recipeBookCategory)
|
||||||
|
recipeBook.setFilteringCraftable(recipeBookCategory, bl)
|
||||||
|
return bl
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isClickOutsideBounds(mouseX: Double, mouseY: Double, x: Int, y: Int, backgroundWidth: Int, backgroundHeight: Int, button: Int): Boolean {
|
||||||
|
return if (!isOpen()) {
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
val bl = mouseX < x.toDouble() || mouseY < y.toDouble() || mouseX >= (x + backgroundWidth).toDouble() || mouseY >= (y + backgroundHeight).toDouble()
|
||||||
|
val bl2 = (x - 147).toDouble() < mouseX && mouseX < x.toDouble() && y.toDouble() < mouseY && mouseY < (y + backgroundHeight).toDouble()
|
||||||
|
bl && !bl2 && !currentTab?.isSelected()!!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun keyPressed(keyCode: Int, scanCode: Int, modifiers: Int): Boolean {
|
||||||
|
searching = false
|
||||||
|
if (isOpen() && !client.player?.isSpectator()!!) {
|
||||||
|
return if (keyCode == 256 && !isWide()) {
|
||||||
|
setOpenValue(false)
|
||||||
|
true
|
||||||
|
} else if (searchField?.keyPressed(keyCode, scanCode, modifiers) == true) {
|
||||||
|
refreshSearchResults()
|
||||||
|
true
|
||||||
|
} else if (searchField?.isFocused == true && searchField?.isVisible == true && keyCode != 256) {
|
||||||
|
true
|
||||||
|
} else if (client.options.chatKey.matchesKey(keyCode, scanCode) && searchField?.isFocused == false) {
|
||||||
|
searching = true
|
||||||
|
searchField?.setFocused(true)
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun keyReleased(keyCode: Int, scanCode: Int, modifiers: Int): Boolean {
|
||||||
|
searching = false
|
||||||
|
return super.keyReleased(keyCode, scanCode, modifiers)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun charTyped(chr: Char, modifiers: Int): Boolean {
|
||||||
|
return if (searching) {
|
||||||
|
false
|
||||||
|
} else if (isOpen() && !client.player?.isSpectator()!!) {
|
||||||
|
if (searchField?.charTyped(chr, modifiers) == true) {
|
||||||
|
refreshSearchResults()
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
super.charTyped(chr, modifiers)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isMouseOver(mouseX: Double, mouseY: Double): Boolean {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setFocused(focused: Boolean) {}
|
||||||
|
|
||||||
|
override fun isFocused(): Boolean {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
fun refreshSearchResults() {
|
||||||
|
val string = searchField?.text?.lowercase(Locale.ROOT) ?: ""
|
||||||
|
triggerPirateSpeakEasterEgg(string)
|
||||||
|
if (string != searchText) {
|
||||||
|
refreshResults(false)
|
||||||
|
searchText = string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun triggerPirateSpeakEasterEgg(search: String) {
|
||||||
|
if ("excitedze" == search) {
|
||||||
|
val languageManager = client.languageManager
|
||||||
|
val string = "en_pt"
|
||||||
|
val languageDefinition = languageManager.getLanguage("en_pt")
|
||||||
|
if (languageDefinition == null || languageManager.language == "en_pt") {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
languageManager.language = "en_pt"
|
||||||
|
client.options.language = "en_pt"
|
||||||
|
client.reloadResources()
|
||||||
|
client.options.write()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isWide(): Boolean {
|
||||||
|
return leftOffset == 86
|
||||||
|
}
|
||||||
|
|
||||||
|
fun refresh() {
|
||||||
|
refreshTabButtons()
|
||||||
|
if (isOpen()) {
|
||||||
|
refreshResults(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onRecipesDisplayed(recipes: List<Recipe<*>>) {
|
||||||
|
for (recipe in recipes) {
|
||||||
|
client.player?.onRecipeDisplayed(recipe)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun showGhostRecipe(recipe: Recipe<*>, slots: List<Slot>) {
|
||||||
|
val itemStack = recipe.getOutput(client.world?.registryManager)
|
||||||
|
ghostSlots.setRecipe(recipe)
|
||||||
|
ghostSlots.addSlot(Ingredient.ofStacks(itemStack), slots[0].x, slots[0].y)
|
||||||
|
alignRecipeToGrid(craftingScreenHandler.craftingWidth, craftingScreenHandler.craftingHeight, craftingScreenHandler.craftingResultSlotIndex, recipe, recipe.ingredients.iterator(), 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun acceptAlignedInput(inputs: Iterator<Ingredient>, slot: Int, amount: Int, gridX: Int, gridY: Int) {
|
||||||
|
val ingredient = inputs.next()
|
||||||
|
if (!ingredient.isEmpty) {
|
||||||
|
val slot2 = craftingScreenHandler.slots[slot]
|
||||||
|
ghostSlots.addSlot(ingredient, slot2.x, slot2.y)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun sendBookDataPacket() {
|
||||||
|
if (client.networkHandler != null) {
|
||||||
|
val recipeBookCategory = craftingScreenHandler.category
|
||||||
|
val bl = recipeBook.options.isGuiOpen(recipeBookCategory)
|
||||||
|
val bl2 = recipeBook.options.isFilteringCraftable(recipeBookCategory)
|
||||||
|
client.networkHandler?.sendPacket(RecipeCategoryOptionsC2SPacket(recipeBookCategory, bl, bl2))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getType(): SelectionType {
|
||||||
|
return if (open) SelectionType.HOVERED else SelectionType.NONE
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun appendNarrations(builder: NarrationMessageBuilder) {
|
||||||
|
val list = Lists.newArrayList<Selectable>()
|
||||||
|
recipesArea.forEachButton { button ->
|
||||||
|
if (button.isNarratable) {
|
||||||
|
list.add(button)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
searchField?.let { list.add(it) } // not sure if this is the right way
|
||||||
|
list.add(toggleCraftableButton)
|
||||||
|
list.addAll(tabButtons)
|
||||||
|
val selectedElementNarrationData = Screen.findSelectedElementData(list, null)
|
||||||
|
selectedElementNarrationData?.selectable?.appendNarrations(builder.nextMessage())
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val TEXTURE = Identifier("textures/gui/recipe_book.png")
|
||||||
|
val SEARCH_HINT_TEXT: Text = Text.translatable("gui.recipebook.search_hint").formatted(Formatting.ITALIC).formatted(Formatting.GRAY)
|
||||||
|
val TOGGLE_CRAFTABLE_RECIPES_TEXT: Text = Text.translatable("gui.recipebook.toggleRecipes.craftable")
|
||||||
|
val TOGGLE_ALL_RECIPES_TEXT: Text = Text.translatable("gui.recipebook.toggleRecipes.all")
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
+125
@@ -0,0 +1,125 @@
|
|||||||
|
package com.cobblemon.mod.common.gui.cooking
|
||||||
|
|
||||||
|
import com.cobblemon.mod.common.api.gui.blitk
|
||||||
|
import com.cobblemon.mod.common.api.text.text
|
||||||
|
import com.cobblemon.mod.common.gui.CookingPotScreenHandler
|
||||||
|
import com.cobblemon.mod.common.util.cobblemonResource
|
||||||
|
import net.minecraft.client.gui.DrawContext
|
||||||
|
import net.minecraft.client.gui.screen.ingame.HandledScreen
|
||||||
|
import net.minecraft.client.gui.screen.recipebook.RecipeBookProvider
|
||||||
|
import net.minecraft.client.gui.screen.recipebook.RecipeBookWidget
|
||||||
|
import net.minecraft.client.gui.widget.TexturedButtonWidget
|
||||||
|
import net.minecraft.entity.player.PlayerInventory
|
||||||
|
import net.minecraft.screen.AbstractRecipeScreenHandler
|
||||||
|
import net.minecraft.screen.slot.Slot
|
||||||
|
import net.minecraft.screen.slot.SlotActionType
|
||||||
|
import net.minecraft.text.Text
|
||||||
|
import net.minecraft.util.Identifier
|
||||||
|
|
||||||
|
class CookingPotHandledScreen(
|
||||||
|
handler: CookingPotScreenHandler,
|
||||||
|
inventory: PlayerInventory,
|
||||||
|
title: Text?
|
||||||
|
) : HandledScreen<CookingPotScreenHandler>(handler, inventory, title), CookBookProvider {
|
||||||
|
|
||||||
|
private val recipeBook = CookBookWidget()
|
||||||
|
private var narrow = false
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
//private val TEXTURE = Identifier("textures/gui/container/crafting_table.png")
|
||||||
|
val TEXTURE = cobblemonResource("textures/gui/cooking/cooking_pot.png")
|
||||||
|
private val RECIPE_BUTTON_TEXTURE = Identifier("textures/gui/recipe_button.png")
|
||||||
|
val TEXTURE_HEIGHT = 198
|
||||||
|
val TEXTURE_WIDTH = 176
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun init() {
|
||||||
|
super.init()
|
||||||
|
narrow = width < 379
|
||||||
|
val recipeBookOffsetX = 12
|
||||||
|
val recipeBookOffsetY = 40
|
||||||
|
recipeBook.initialize(width, height, client, narrow, handler as AbstractRecipeScreenHandler<*>)
|
||||||
|
x = recipeBook.findLeftEdge(width, TEXTURE_WIDTH)
|
||||||
|
addDrawableChild(
|
||||||
|
TexturedButtonWidget(x + recipeBookOffsetX, height / 2 - recipeBookOffsetY, 20, 18, 0, 0, 19, RECIPE_BUTTON_TEXTURE) {
|
||||||
|
recipeBook.toggleOpen()
|
||||||
|
x = recipeBook.findLeftEdge(width, TEXTURE_WIDTH)
|
||||||
|
it.setPosition(x + recipeBookOffsetX, height / 2 - recipeBookOffsetY)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
addSelectableChild(recipeBook)
|
||||||
|
setInitialFocus(recipeBook)
|
||||||
|
titleX = 39
|
||||||
|
titleY = -10
|
||||||
|
playerInventoryTitleX = 8
|
||||||
|
playerInventoryTitleY = 88
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun handledScreenTick() {
|
||||||
|
super.handledScreenTick()
|
||||||
|
recipeBook.update()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun render(context: DrawContext, mouseX: Int, mouseY: Int, delta: Float) {
|
||||||
|
renderBackground(context)
|
||||||
|
if (recipeBook.isOpen() && narrow) {
|
||||||
|
drawBackground(context, delta, mouseX, mouseY)
|
||||||
|
recipeBook.render(context, mouseX, mouseY, delta)
|
||||||
|
} else {
|
||||||
|
recipeBook.render(context, mouseX, mouseY, delta)
|
||||||
|
super.render(context, mouseX, mouseY, delta)
|
||||||
|
recipeBook.drawGhostSlots(context, x, y, true, delta)
|
||||||
|
}
|
||||||
|
drawMouseoverTooltip(context, mouseX, mouseY)
|
||||||
|
recipeBook.drawTooltip(context, x, y, mouseX, mouseY)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun drawBackground(context: DrawContext, delta: Float, mouseX: Int, mouseY: Int) {
|
||||||
|
val i = x
|
||||||
|
val j = (height - TEXTURE_HEIGHT) / 2
|
||||||
|
|
||||||
|
blitk(
|
||||||
|
matrixStack = context.matrices,
|
||||||
|
texture = TEXTURE,
|
||||||
|
x = x, // horizontal placement of GUI
|
||||||
|
y = (height - TEXTURE_HEIGHT) / 2, // vertical placement of GUI
|
||||||
|
|
||||||
|
width = TEXTURE_WIDTH * 1.0, // scale of the GUI width
|
||||||
|
height = TEXTURE_HEIGHT * 1.0 // scale of the GUI height
|
||||||
|
)
|
||||||
|
|
||||||
|
//context.drawTexture(TEXTURE, i, j, 0, 0, TEXTURE_WIDTH, TEXTURE_HEIGHT)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isPointWithinBounds(x: Int, y: Int, width: Int, height: Int, pointX: Double, pointY: Double): Boolean {
|
||||||
|
return (!narrow || !recipeBook.isOpen()) && super.isPointWithinBounds(x, y, width, height, pointX, pointY)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun mouseClicked(mouseX: Double, mouseY: Double, button: Int): Boolean {
|
||||||
|
if (recipeBook.mouseClicked(mouseX, mouseY, button)) {
|
||||||
|
focused = recipeBook
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return if (narrow && recipeBook.isOpen()) {
|
||||||
|
true
|
||||||
|
} else super.mouseClicked(mouseX, mouseY, button)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isClickOutsideBounds(mouseX: Double, mouseY: Double, left: Int, top: Int, button: Int): Boolean {
|
||||||
|
val bl = mouseX < left.toDouble() || mouseY < top.toDouble() || mouseX >= (left + backgroundWidth).toDouble() || mouseY >= (top + backgroundHeight).toDouble()
|
||||||
|
return recipeBook.isClickOutsideBounds(mouseX, mouseY, x, y, backgroundWidth, backgroundHeight, button) && bl
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onMouseClick(slot: Slot?, slotId: Int, button: Int, actionType: SlotActionType?) {
|
||||||
|
super.onMouseClick(slot, slotId, button, actionType)
|
||||||
|
recipeBook.slotClicked(slot)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun refreshCookBook() {
|
||||||
|
recipeBook.refresh()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getCookBookWidget(): CookBookWidget {
|
||||||
|
return recipeBook
|
||||||
|
}
|
||||||
|
}
|
||||||
+102
@@ -0,0 +1,102 @@
|
|||||||
|
package com.cobblemon.mod.common.gui.cooking
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.systems.RenderSystem
|
||||||
|
import net.fabricmc.api.EnvType
|
||||||
|
import net.fabricmc.api.Environment
|
||||||
|
import net.minecraft.client.MinecraftClient
|
||||||
|
import net.minecraft.client.gui.DrawContext
|
||||||
|
import net.minecraft.client.gui.screen.recipebook.RecipeBookWidget
|
||||||
|
import net.minecraft.client.gui.widget.ToggleButtonWidget
|
||||||
|
import net.minecraft.client.recipebook.ClientRecipeBook
|
||||||
|
import net.minecraft.client.recipebook.RecipeBookGroup
|
||||||
|
import net.minecraft.client.render.item.ItemRenderer
|
||||||
|
import net.minecraft.item.ItemStack
|
||||||
|
import net.minecraft.recipe.Recipe
|
||||||
|
import net.minecraft.screen.AbstractRecipeScreenHandler
|
||||||
|
|
||||||
|
@Environment(EnvType.CLIENT)
|
||||||
|
class CookingRecipeGroupButtonWidget(val category: RecipeBookGroup) : ToggleButtonWidget(0, 0, 35, 27, false) {
|
||||||
|
private var bounce = 0f
|
||||||
|
|
||||||
|
init {
|
||||||
|
setTextureUV(153, 2, 35, 0, CookBookWidget.TEXTURE)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun checkForNewRecipes(client: MinecraftClient) {
|
||||||
|
val clientRecipeBook = client.player?.recipeBook ?: return
|
||||||
|
val list = clientRecipeBook.getResultsForGroup(this.category)
|
||||||
|
if (client.player?.currentScreenHandler is AbstractRecipeScreenHandler<*>) {
|
||||||
|
for (recipeResultCollection in list) {
|
||||||
|
for (recipe in recipeResultCollection.getResults(clientRecipeBook.isFilteringCraftable(client.player!!.currentScreenHandler as AbstractRecipeScreenHandler<*>))) {
|
||||||
|
if (clientRecipeBook.shouldDisplay(recipe)) {
|
||||||
|
this.bounce = 15.0f
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun renderButton(context: DrawContext, mouseX: Int, mouseY: Int, delta: Float) {
|
||||||
|
if (this.bounce > 0.0f) {
|
||||||
|
val f = 1.0f + 0.1f * Math.sin((this.bounce / 15.0f * Math.PI).toDouble()).toFloat()
|
||||||
|
context.matrices.push()
|
||||||
|
context.matrices.translate((this.x + 8).toFloat(), (this.y + 12).toFloat(), 0.0f)
|
||||||
|
context.matrices.scale(1.0f, f, 1.0f)
|
||||||
|
context.matrices.translate(-(this.x + 8).toFloat(), -(this.y + 12).toFloat(), 0.0f)
|
||||||
|
}
|
||||||
|
|
||||||
|
val minecraftClient = MinecraftClient.getInstance()
|
||||||
|
RenderSystem.disableDepthTest()
|
||||||
|
var i = this.u
|
||||||
|
var j = this.v
|
||||||
|
if (this.toggled) {
|
||||||
|
i += this.pressedUOffset
|
||||||
|
}
|
||||||
|
if (this.isSelected) {
|
||||||
|
j += this.hoverVOffset
|
||||||
|
}
|
||||||
|
|
||||||
|
var k = this.x
|
||||||
|
if (this.toggled) {
|
||||||
|
k -= 2
|
||||||
|
}
|
||||||
|
|
||||||
|
context.drawTexture(this.texture, k, this.y, i, j, this.width, this.height)
|
||||||
|
RenderSystem.enableDepthTest()
|
||||||
|
this.renderIcons(context, minecraftClient.itemRenderer)
|
||||||
|
if (this.bounce > 0.0f) {
|
||||||
|
context.matrices.pop()
|
||||||
|
this.bounce -= delta
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun renderIcons(context: DrawContext, itemRenderer: ItemRenderer) {
|
||||||
|
val list = this.category.getIcons()
|
||||||
|
val i = if (this.toggled) -2 else 0
|
||||||
|
if (list.size == 1) {
|
||||||
|
context.drawItemWithoutEntity(list[0], this.x + 9 + i, this.y + 5)
|
||||||
|
} else if (list.size == 2) {
|
||||||
|
context.drawItemWithoutEntity(list[0], this.x + 3 + i, this.y + 5)
|
||||||
|
context.drawItemWithoutEntity(list[1], this.x + 14 + i, this.y + 5)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getCategoryValue(): RecipeBookGroup {
|
||||||
|
return this.category
|
||||||
|
}
|
||||||
|
|
||||||
|
fun hasKnownRecipes(recipeBook: ClientRecipeBook): Boolean {
|
||||||
|
val list = recipeBook.getResultsForGroup(this.category)
|
||||||
|
this.visible = false
|
||||||
|
if (list != null) {
|
||||||
|
for (recipeResultCollection in list) {
|
||||||
|
if (recipeResultCollection.isInitialized && recipeResultCollection.hasFittingRecipes()) {
|
||||||
|
this.visible = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this.visible
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
* 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.block.BugwortBlock
|
||||||
|
import com.cobblemon.mod.common.block.SaccharineSaplingBlock
|
||||||
|
import net.minecraft.block.BlockState
|
||||||
|
import net.minecraft.item.AliasedBlockItem
|
||||||
|
import net.minecraft.item.ItemPlacementContext
|
||||||
|
|
||||||
|
class BugwortItem(block: BugwortBlock) : AliasedBlockItem(block, Settings()) {
|
||||||
|
|
||||||
|
override fun getPlacementState(context: ItemPlacementContext): BlockState? {
|
||||||
|
|
||||||
|
return super.getPlacementState(context)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
* 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.block.SaccharineSaplingBlock
|
||||||
|
import net.minecraft.block.BlockState
|
||||||
|
import net.minecraft.item.AliasedBlockItem
|
||||||
|
import net.minecraft.item.ItemPlacementContext
|
||||||
|
|
||||||
|
class SaccharineSaplingItem(block: SaccharineSaplingBlock) : AliasedBlockItem(block, Settings()) {
|
||||||
|
|
||||||
|
override fun getPlacementState(context: ItemPlacementContext): BlockState? {
|
||||||
|
|
||||||
|
return super.getPlacementState(context)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* 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.entity.throwable.ScatterBangEntity
|
||||||
|
import net.minecraft.entity.player.PlayerEntity
|
||||||
|
import net.minecraft.entity.projectile.thrown.SnowballEntity
|
||||||
|
import net.minecraft.item.Item
|
||||||
|
import net.minecraft.item.ItemStack
|
||||||
|
import net.minecraft.sound.SoundCategory
|
||||||
|
import net.minecraft.sound.SoundEvents
|
||||||
|
import net.minecraft.stat.Stats
|
||||||
|
import net.minecraft.util.Hand
|
||||||
|
import net.minecraft.util.TypedActionResult
|
||||||
|
import net.minecraft.world.World
|
||||||
|
|
||||||
|
|
||||||
|
class ScatterBangItem(settings: Settings?) : Item(settings) {
|
||||||
|
override fun use(world: World, user: PlayerEntity, hand: Hand): TypedActionResult<ItemStack> {
|
||||||
|
val itemStack = user.getStackInHand(hand)
|
||||||
|
world.playSound(
|
||||||
|
null as PlayerEntity?,
|
||||||
|
user.x,
|
||||||
|
user.y,
|
||||||
|
user.z,
|
||||||
|
SoundEvents.ENTITY_SNOWBALL_THROW,
|
||||||
|
SoundCategory.NEUTRAL,
|
||||||
|
0.5f,
|
||||||
|
0.4f / (world.getRandom().nextFloat() * 0.4f + 0.8f)
|
||||||
|
)
|
||||||
|
if (!world.isClient) {
|
||||||
|
val scatterBangEntity = ScatterBangEntity(world, user)
|
||||||
|
scatterBangEntity.setItem(itemStack)
|
||||||
|
scatterBangEntity.setVelocity(user, user.pitch, user.yaw, 0.0f, 1.5f, 1.0f)
|
||||||
|
world.spawnEntity(scatterBangEntity)
|
||||||
|
}
|
||||||
|
|
||||||
|
user.incrementStat(Stats.USED.getOrCreateStat(this))
|
||||||
|
if (!user.abilities.creativeMode) {
|
||||||
|
itemStack.decrement(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return TypedActionResult.success(itemStack, world.isClient())
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* 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.entity.throwable.ScatterBangEntity
|
||||||
|
import com.cobblemon.mod.common.entity.throwable.StickyGlobEntity
|
||||||
|
import net.minecraft.entity.player.PlayerEntity
|
||||||
|
import net.minecraft.entity.projectile.thrown.SnowballEntity
|
||||||
|
import net.minecraft.item.Item
|
||||||
|
import net.minecraft.item.ItemStack
|
||||||
|
import net.minecraft.sound.SoundCategory
|
||||||
|
import net.minecraft.sound.SoundEvents
|
||||||
|
import net.minecraft.stat.Stats
|
||||||
|
import net.minecraft.util.Hand
|
||||||
|
import net.minecraft.util.TypedActionResult
|
||||||
|
import net.minecraft.world.World
|
||||||
|
|
||||||
|
|
||||||
|
class StickyGlobItem(settings: Settings?) : Item(settings) {
|
||||||
|
override fun use(world: World, user: PlayerEntity, hand: Hand): TypedActionResult<ItemStack> {
|
||||||
|
val itemStack = user.getStackInHand(hand)
|
||||||
|
world.playSound(
|
||||||
|
null as PlayerEntity?,
|
||||||
|
user.x,
|
||||||
|
user.y,
|
||||||
|
user.z,
|
||||||
|
SoundEvents.ENTITY_SNOWBALL_THROW,
|
||||||
|
SoundCategory.NEUTRAL,
|
||||||
|
0.5f,
|
||||||
|
0.4f / (world.getRandom().nextFloat() * 0.4f + 0.8f)
|
||||||
|
)
|
||||||
|
if (!world.isClient) {
|
||||||
|
val stickyGlobEntity = StickyGlobEntity(world, user)
|
||||||
|
stickyGlobEntity.setItem(itemStack)
|
||||||
|
stickyGlobEntity.setVelocity(user, user.pitch, user.yaw, 0.0f, 1.5f, 1.0f)
|
||||||
|
world.spawnEntity(stickyGlobEntity)
|
||||||
|
}
|
||||||
|
|
||||||
|
user.incrementStat(Stats.USED.getOrCreateStat(this))
|
||||||
|
if (!user.abilities.creativeMode) {
|
||||||
|
itemStack.decrement(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return TypedActionResult.success(itemStack, world.isClient())
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -89,6 +89,11 @@ object CobblemonItemGroups {
|
|||||||
entries.add(CobblemonItems.VIVICHOKE)
|
entries.add(CobblemonItems.VIVICHOKE)
|
||||||
entries.add(CobblemonItems.VIVICHOKE_SEEDS)
|
entries.add(CobblemonItems.VIVICHOKE_SEEDS)
|
||||||
|
|
||||||
|
entries.add(CobblemonItems.SWEET_SAP)
|
||||||
|
entries.add(CobblemonItems.BUGWORT)
|
||||||
|
entries.add(CobblemonItems.SCATTER_BANG)
|
||||||
|
entries.add(CobblemonItems.STICKY_GLOB)
|
||||||
|
|
||||||
entries.add(CobblemonItems.RED_APRICORN)
|
entries.add(CobblemonItems.RED_APRICORN)
|
||||||
entries.add(CobblemonItems.YELLOW_APRICORN)
|
entries.add(CobblemonItems.YELLOW_APRICORN)
|
||||||
entries.add(CobblemonItems.GREEN_APRICORN)
|
entries.add(CobblemonItems.GREEN_APRICORN)
|
||||||
@@ -104,6 +109,8 @@ object CobblemonItemGroups {
|
|||||||
entries.add(CobblemonItems.BLACK_APRICORN_SEED)
|
entries.add(CobblemonItems.BLACK_APRICORN_SEED)
|
||||||
entries.add(CobblemonItems.WHITE_APRICORN_SEED)
|
entries.add(CobblemonItems.WHITE_APRICORN_SEED)
|
||||||
|
|
||||||
|
entries.add(CobblemonItems.SACCHARINE_SAPLING)
|
||||||
|
|
||||||
entries.add(CobblemonItems.RED_MINT_SEEDS)
|
entries.add(CobblemonItems.RED_MINT_SEEDS)
|
||||||
entries.add(CobblemonItems.RED_MINT_LEAF)
|
entries.add(CobblemonItems.RED_MINT_LEAF)
|
||||||
entries.add(CobblemonItems.BLUE_MINT_SEEDS)
|
entries.add(CobblemonItems.BLUE_MINT_SEEDS)
|
||||||
@@ -231,6 +238,8 @@ object CobblemonItemGroups {
|
|||||||
entries.add(CobblemonItems.RELIC_COIN_POUCH)
|
entries.add(CobblemonItems.RELIC_COIN_POUCH)
|
||||||
entries.add(CobblemonItems.RELIC_COIN_SACK)
|
entries.add(CobblemonItems.RELIC_COIN_SACK)
|
||||||
|
|
||||||
|
entries.add(CobblemonItems.COOKING_POT)
|
||||||
|
entries.add(CobblemonItems.SWEET_INCENSE)
|
||||||
entries.add(CobblemonItems.DISPLAY_CASE)
|
entries.add(CobblemonItems.DISPLAY_CASE)
|
||||||
entries.add(CobblemonItems.APRICORN_LOG)
|
entries.add(CobblemonItems.APRICORN_LOG)
|
||||||
entries.add(CobblemonItems.APRICORN_WOOD)
|
entries.add(CobblemonItems.APRICORN_WOOD)
|
||||||
@@ -249,6 +258,23 @@ object CobblemonItemGroups {
|
|||||||
entries.add(CobblemonItems.APRICORN_HANGING_SIGN)
|
entries.add(CobblemonItems.APRICORN_HANGING_SIGN)
|
||||||
entries.add(CobblemonItems.APRICORN_LEAVES)
|
entries.add(CobblemonItems.APRICORN_LEAVES)
|
||||||
|
|
||||||
|
entries.add(CobblemonItems.SACCHARINE_LOG)
|
||||||
|
entries.add(CobblemonItems.SACCHARINE_WOOD)
|
||||||
|
entries.add(CobblemonItems.STRIPPED_SACCHARINE_LOG)
|
||||||
|
entries.add(CobblemonItems.STRIPPED_SACCHARINE_WOOD)
|
||||||
|
entries.add(CobblemonItems.SACCHARINE_PLANKS)
|
||||||
|
entries.add(CobblemonItems.SACCHARINE_STAIRS)
|
||||||
|
entries.add(CobblemonItems.SACCHARINE_SLAB)
|
||||||
|
entries.add(CobblemonItems.SACCHARINE_FENCE)
|
||||||
|
entries.add(CobblemonItems.SACCHARINE_FENCE_GATE)
|
||||||
|
entries.add(CobblemonItems.SACCHARINE_DOOR)
|
||||||
|
entries.add(CobblemonItems.SACCHARINE_TRAPDOOR)
|
||||||
|
entries.add(CobblemonItems.SACCHARINE_BUTTON)
|
||||||
|
entries.add(CobblemonItems.SACCHARINE_PRESSURE_PLATE)
|
||||||
|
entries.add(CobblemonItems.SACCHARINE_SIGN)
|
||||||
|
entries.add(CobblemonItems.SACCHARINE_HANGING_SIGN)
|
||||||
|
entries.add(CobblemonItems.SACCHARINE_LEAVES)
|
||||||
|
|
||||||
entries.add(CobblemonItems.TUMBLESTONE_BLOCK)
|
entries.add(CobblemonItems.TUMBLESTONE_BLOCK)
|
||||||
entries.add(CobblemonItems.BLACK_TUMBLESTONE_BLOCK)
|
entries.add(CobblemonItems.BLACK_TUMBLESTONE_BLOCK)
|
||||||
entries.add(CobblemonItems.SKY_TUMBLESTONE_BLOCK)
|
entries.add(CobblemonItems.SKY_TUMBLESTONE_BLOCK)
|
||||||
|
|||||||
+3
@@ -30,6 +30,9 @@ object CobblemonConfiguredFeatures {
|
|||||||
@JvmField
|
@JvmField
|
||||||
val YELLOW_APRICORN_TREE_KEY = of("yellow_apricorn_tree")
|
val YELLOW_APRICORN_TREE_KEY = of("yellow_apricorn_tree")
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
val SACCHARINE_TREE_KEY = of("saccharine_tree")
|
||||||
|
|
||||||
@JvmField
|
@JvmField
|
||||||
val MINTS_KEY = of("mints")
|
val MINTS_KEY = of("mints")
|
||||||
@JvmField
|
@JvmField
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ object CobblemonFeatures : PlatformRegistry<Registry<Feature<*>>, RegistryKey<Re
|
|||||||
@JvmField
|
@JvmField
|
||||||
val APRICORN_TREE_FEATURE = create("apricorn_tree", ApricornTreeFeature())
|
val APRICORN_TREE_FEATURE = create("apricorn_tree", ApricornTreeFeature())
|
||||||
@JvmField
|
@JvmField
|
||||||
|
val SACCHARINE_TREE_FEATURE = create("saccharine_tree", SaccharineTreeFeature())
|
||||||
|
@JvmField
|
||||||
val MINT_FEATURE = create("mint", MintBlockFeature())
|
val MINT_FEATURE = create("mint", MintBlockFeature())
|
||||||
@JvmField
|
@JvmField
|
||||||
val BERRY_GROVE_FEATURE = CobblemonFeatures.create("berry_grove", BerryGroveFeature())
|
val BERRY_GROVE_FEATURE = CobblemonFeatures.create("berry_grove", BerryGroveFeature())
|
||||||
|
|||||||
+2
@@ -29,6 +29,7 @@ object CobblemonPlacedFeatures {
|
|||||||
|
|
||||||
|
|
||||||
val APRICORN_TREES = of("apricorn_trees")
|
val APRICORN_TREES = of("apricorn_trees")
|
||||||
|
val SACCHARINE_TREE = of("saccharine_tree")
|
||||||
|
|
||||||
val MINTS = of("mints")
|
val MINTS = of("mints")
|
||||||
|
|
||||||
@@ -42,6 +43,7 @@ object CobblemonPlacedFeatures {
|
|||||||
fun register() {
|
fun register() {
|
||||||
// We don't need to pass in any tags, the feature implementation handles it, while not a perfect system it works
|
// We don't need to pass in any tags, the feature implementation handles it, while not a perfect system it works
|
||||||
Cobblemon.implementation.addFeatureToWorldGen(APRICORN_TREES, GenerationStep.Feature.VEGETAL_DECORATION, null)
|
Cobblemon.implementation.addFeatureToWorldGen(APRICORN_TREES, GenerationStep.Feature.VEGETAL_DECORATION, null)
|
||||||
|
Cobblemon.implementation.addFeatureToWorldGen(SACCHARINE_TREE, GenerationStep.Feature.VEGETAL_DECORATION, null)
|
||||||
Cobblemon.implementation.addFeatureToWorldGen(MINTS, GenerationStep.Feature.VEGETAL_DECORATION, null)
|
Cobblemon.implementation.addFeatureToWorldGen(MINTS, GenerationStep.Feature.VEGETAL_DECORATION, null)
|
||||||
Cobblemon.implementation.addFeatureToWorldGen(MEDICINAL_LEEK, GenerationStep.Feature.VEGETAL_DECORATION, null)
|
Cobblemon.implementation.addFeatureToWorldGen(MEDICINAL_LEEK, GenerationStep.Feature.VEGETAL_DECORATION, null)
|
||||||
Cobblemon.implementation.addFeatureToWorldGen(BIG_ROOT, GenerationStep.Feature.VEGETAL_DECORATION, BiomeTags.IS_OVERWORLD)
|
Cobblemon.implementation.addFeatureToWorldGen(BIG_ROOT, GenerationStep.Feature.VEGETAL_DECORATION, BiomeTags.IS_OVERWORLD)
|
||||||
|
|||||||
+287
@@ -0,0 +1,287 @@
|
|||||||
|
/*
|
||||||
|
* 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.world.feature
|
||||||
|
|
||||||
|
import com.cobblemon.mod.common.Cobblemon
|
||||||
|
import com.cobblemon.mod.common.CobblemonBlocks
|
||||||
|
import com.cobblemon.mod.common.api.tags.CobblemonBiomeTags
|
||||||
|
import com.cobblemon.mod.common.block.SaccharineLeafBlock
|
||||||
|
import com.cobblemon.mod.common.util.randomNoCopy
|
||||||
|
import com.google.common.collect.Lists
|
||||||
|
import kotlin.random.Random
|
||||||
|
import net.minecraft.block.BlockState
|
||||||
|
import net.minecraft.block.Blocks
|
||||||
|
import net.minecraft.block.HorizontalFacingBlock
|
||||||
|
import net.minecraft.block.LeavesBlock
|
||||||
|
import net.minecraft.registry.tag.BlockTags
|
||||||
|
import net.minecraft.util.math.BlockPos
|
||||||
|
import net.minecraft.util.math.Direction
|
||||||
|
import net.minecraft.util.math.Direction.*
|
||||||
|
import net.minecraft.world.StructureWorldAccess
|
||||||
|
import net.minecraft.world.TestableWorld
|
||||||
|
import net.minecraft.world.chunk.ChunkStatus
|
||||||
|
import net.minecraft.world.gen.feature.Feature
|
||||||
|
import net.minecraft.world.gen.feature.SingleStateFeatureConfig
|
||||||
|
import net.minecraft.world.gen.feature.TreeFeature
|
||||||
|
import net.minecraft.world.gen.feature.util.FeatureContext
|
||||||
|
|
||||||
|
class SaccharineTreeFeature : Feature<SingleStateFeatureConfig>(SingleStateFeatureConfig.CODEC) {
|
||||||
|
|
||||||
|
override fun generate(context: FeatureContext<SingleStateFeatureConfig>): Boolean {
|
||||||
|
val worldGenLevel: StructureWorldAccess = context.world
|
||||||
|
val random = context.random
|
||||||
|
val origin = context.origin
|
||||||
|
|
||||||
|
val isGenerating = worldGenLevel.getChunk(origin).status != ChunkStatus.FULL
|
||||||
|
|
||||||
|
if (isGenerating) {
|
||||||
|
val biome = worldGenLevel.getBiome(origin)
|
||||||
|
val multiplier = if (biome.isIn(CobblemonBiomeTags.HAS_APRICORNS_SPARSE)) {
|
||||||
|
0.1F
|
||||||
|
} else if (biome.isIn(CobblemonBiomeTags.HAS_APRICORNS_DENSE)) {
|
||||||
|
10F
|
||||||
|
} else if (biome.isIn(CobblemonBiomeTags.HAS_APRICORNS_NORMAL)) {
|
||||||
|
1.0F
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (random.nextFloat() > multiplier * Cobblemon.config.baseApricornTreeGenerationChance) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!worldGenLevel.getBlockState(origin.down()).isIn(BlockTags.DIRT)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
val potentialBeehivePositions = mutableListOf<BlockPos>()
|
||||||
|
|
||||||
|
// Create trunk (1 or 2 blocks tall)
|
||||||
|
val logState = CobblemonBlocks.SACCHARINE_LOG.defaultState
|
||||||
|
val trunkHeight = if (random.nextBoolean()) 1 else 2
|
||||||
|
for (y in 0 until trunkHeight) {
|
||||||
|
val logPos = origin.offset(UP, y)
|
||||||
|
worldGenLevel.setBlockState(logPos, logState, 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
val saccharineLeaf = CobblemonBlocks.SACCHARINE_LEAVES.defaultState // SaccharineLeafBlock
|
||||||
|
var currentHeight = trunkHeight
|
||||||
|
|
||||||
|
// Top Trunk Pattern
|
||||||
|
placeTopTrunkPattern(worldGenLevel, origin.offset(UP, currentHeight), logState, potentialBeehivePositions)
|
||||||
|
currentHeight++
|
||||||
|
|
||||||
|
// Leaf Start Pattern
|
||||||
|
placeLeafStartPattern(worldGenLevel, origin.offset(UP, currentHeight), logState, CobblemonBlocks.SACCHARINE_LEAVES.defaultState, potentialBeehivePositions, Random)
|
||||||
|
currentHeight++
|
||||||
|
|
||||||
|
// Big Leaf Pattern
|
||||||
|
placeBigLeafPattern(worldGenLevel, origin.offset(UP, currentHeight), logState, CobblemonBlocks.SACCHARINE_LEAVES.defaultState)
|
||||||
|
currentHeight++
|
||||||
|
|
||||||
|
// Small Leaf Pattern
|
||||||
|
placeSmallLeafPattern(worldGenLevel, origin.offset(UP, currentHeight), logState, CobblemonBlocks.SACCHARINE_LEAVES.defaultState, Blocks.AIR.defaultState, Random)
|
||||||
|
currentHeight++
|
||||||
|
|
||||||
|
// Big Leaf Pattern
|
||||||
|
placeBigLeafPattern(worldGenLevel, origin.offset(UP, currentHeight), logState, CobblemonBlocks.SACCHARINE_LEAVES.defaultState)
|
||||||
|
currentHeight++
|
||||||
|
|
||||||
|
// Random extension or Leaf Topper Pattern
|
||||||
|
if (random.nextBoolean()) {
|
||||||
|
placeLeafTopperPattern(worldGenLevel, origin.offset(UP, currentHeight), CobblemonBlocks.SACCHARINE_LEAVES.defaultState, CobblemonBlocks.SACCHARINE_LEAVES.defaultState, Random)
|
||||||
|
} else {
|
||||||
|
// Small Leaf Pattern
|
||||||
|
placeSmallLeafPattern(worldGenLevel, origin.offset(UP, currentHeight), logState, CobblemonBlocks.SACCHARINE_LEAVES.defaultState, Blocks.AIR.defaultState, Random)
|
||||||
|
currentHeight++
|
||||||
|
|
||||||
|
// Big Leaf Pattern
|
||||||
|
placeBigLeafPattern(worldGenLevel, origin.offset(UP, currentHeight), logState, CobblemonBlocks.SACCHARINE_LEAVES.defaultState)
|
||||||
|
currentHeight++
|
||||||
|
|
||||||
|
// Leaf Topper Pattern
|
||||||
|
placeLeafTopperPattern(worldGenLevel, origin.offset(UP, currentHeight), CobblemonBlocks.SACCHARINE_LEAVES.defaultState, CobblemonBlocks.SACCHARINE_LEAVES.defaultState, Random)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for flowers within a 5-block radius to place a beehive
|
||||||
|
if (isFlowerNearby(worldGenLevel, origin)) {
|
||||||
|
placeBeehive(worldGenLevel, Random, potentialBeehivePositions)
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun placeBigLeafPattern(worldGenLevel: StructureWorldAccess, origin: BlockPos, logBlock: BlockState, leafBlock: BlockState) {
|
||||||
|
val positions = listOf(
|
||||||
|
origin.add(-2, 0, 0),
|
||||||
|
origin.add(2, 0, 0),
|
||||||
|
origin.add(0, 0, -2),
|
||||||
|
origin.add(0, 0, 2),
|
||||||
|
origin.add(-1, 0, -2),
|
||||||
|
origin.add(1, 0, -2),
|
||||||
|
origin.add(-1, 0, 2),
|
||||||
|
origin.add(1, 0, 2),
|
||||||
|
origin.add(-2, 0, -1),
|
||||||
|
origin.add(-2, 0, 1),
|
||||||
|
origin.add(2, 0, -1),
|
||||||
|
origin.add(2, 0, 1),
|
||||||
|
origin.add(-1, 0, -1),
|
||||||
|
origin.add(1, 0, 1),
|
||||||
|
origin.add(-1, 0, 1),
|
||||||
|
origin.add(1, 0, -1),
|
||||||
|
origin.add(0, 0, 0), // Add center position
|
||||||
|
origin.add(1, 0, 0),
|
||||||
|
origin.add(-1, 0, 0),
|
||||||
|
origin.add(0, 0, 1),
|
||||||
|
origin.add(0, 0, -1),
|
||||||
|
origin.add(0, 0, 0)
|
||||||
|
)
|
||||||
|
|
||||||
|
for (pos in positions) {
|
||||||
|
setBlockIfClear(worldGenLevel, pos, leafBlock.with(LeavesBlock.DISTANCE, 2))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Center trunk
|
||||||
|
worldGenLevel.setBlockState(origin, logBlock, 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun placeSmallLeafPattern(worldGenLevel: StructureWorldAccess, origin: BlockPos, logBlock: BlockState, leafBlock: BlockState, specialBlock: BlockState, random: Random) {
|
||||||
|
val positions = listOf(
|
||||||
|
origin.add(-1, 0, 0),
|
||||||
|
origin.add(1, 0, 0),
|
||||||
|
origin.add(0, 0, -1),
|
||||||
|
origin.add(0, 0, 1)
|
||||||
|
)
|
||||||
|
|
||||||
|
for (pos in positions) {
|
||||||
|
setBlockIfClear(worldGenLevel, pos, leafBlock.with(LeavesBlock.DISTANCE, 2))
|
||||||
|
}
|
||||||
|
|
||||||
|
val specialPositions = listOf(
|
||||||
|
origin.add(-1, 0, -1),
|
||||||
|
origin.add(1, 0, 1),
|
||||||
|
origin.add(-1, 0, 1),
|
||||||
|
origin.add(1, 0, -1)
|
||||||
|
)
|
||||||
|
|
||||||
|
for (pos in specialPositions) {
|
||||||
|
if (random.nextFloat() < 0.25f) {
|
||||||
|
setBlockIfClear(worldGenLevel, pos, specialBlock)
|
||||||
|
} else {
|
||||||
|
setBlockIfClear(worldGenLevel, pos, leafBlock.with(LeavesBlock.DISTANCE, 2))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Center trunk
|
||||||
|
worldGenLevel.setBlockState(origin, logBlock, 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun placeLeafTopperPattern(worldGenLevel: StructureWorldAccess, origin: BlockPos, leafBlock: BlockState, specialBlock: BlockState, random: Random) {
|
||||||
|
val positions = listOf(
|
||||||
|
origin.add(-1, 0, 0),
|
||||||
|
origin.add(1, 0, 0),
|
||||||
|
origin.add(0, 0, -1),
|
||||||
|
origin.add(0, 0, 1),
|
||||||
|
origin.add(-1, 0, -1),
|
||||||
|
origin.add(1, 0, 1),
|
||||||
|
origin.add(-1, 0, 1),
|
||||||
|
origin.add(1, 0, -1)
|
||||||
|
)
|
||||||
|
|
||||||
|
for (pos in positions) {
|
||||||
|
if (random.nextFloat() < 0.25f) {
|
||||||
|
setBlockIfClear(worldGenLevel, pos, specialBlock)
|
||||||
|
} else {
|
||||||
|
setBlockIfClear(worldGenLevel, pos, leafBlock.with(LeavesBlock.DISTANCE, 2))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Center leaf
|
||||||
|
setBlockIfClear(worldGenLevel, origin, leafBlock.with(LeavesBlock.DISTANCE, 2))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun placeLeafStartPattern(worldGenLevel: StructureWorldAccess, origin: BlockPos, logBlock: BlockState, leafBlock: BlockState, potentialBeehivePositions: MutableList<BlockPos>, random: Random) {
|
||||||
|
val positions = listOf(
|
||||||
|
origin.add(-1, 0, 0),
|
||||||
|
origin.add(1, 0, 0),
|
||||||
|
origin.add(0, 0, -1),
|
||||||
|
origin.add(0, 0, 1),
|
||||||
|
origin.add(-1, 0, -1),
|
||||||
|
origin.add(1, 0, 1),
|
||||||
|
origin.add(-1, 0, 1),
|
||||||
|
origin.add(1, 0, -1)
|
||||||
|
)
|
||||||
|
|
||||||
|
for (pos in positions) {
|
||||||
|
if (random.nextFloat() < 0.25f) {
|
||||||
|
potentialBeehivePositions.add(pos)
|
||||||
|
} else {
|
||||||
|
setBlockIfClear(worldGenLevel, pos, leafBlock.with(LeavesBlock.DISTANCE, 2))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Center trunk
|
||||||
|
worldGenLevel.setBlockState(origin, logBlock, 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun placeTopTrunkPattern(worldGenLevel: StructureWorldAccess, origin: BlockPos, logBlock: BlockState, potentialBeehivePositions: MutableList<BlockPos>) {
|
||||||
|
val positions = listOf(
|
||||||
|
origin.add(-1, 0, 0),
|
||||||
|
origin.add(1, 0, 0),
|
||||||
|
origin.add(0, 0, -1),
|
||||||
|
origin.add(0, 0, 1)
|
||||||
|
)
|
||||||
|
|
||||||
|
for (pos in positions) {
|
||||||
|
potentialBeehivePositions.add(pos)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Center trunk
|
||||||
|
worldGenLevel.setBlockState(origin, logBlock, 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isFlowerNearby(worldGenLevel: StructureWorldAccess, origin: BlockPos): Boolean {
|
||||||
|
for (dx in -5..5) {
|
||||||
|
for (dz in -5..5) {
|
||||||
|
for (dy in -5..5) {
|
||||||
|
val pos = origin.add(dx, dy, dz)
|
||||||
|
if (worldGenLevel.getBlockState(pos).isIn(BlockTags.FLOWERS)) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun placeBeehive(worldGenLevel: StructureWorldAccess, random: Random, potentialBeehivePositions: MutableList<BlockPos>) {
|
||||||
|
if (potentialBeehivePositions.isNotEmpty()) {
|
||||||
|
val hivePos = potentialBeehivePositions[random.nextInt(potentialBeehivePositions.size)]
|
||||||
|
setBlockIfClear(worldGenLevel, hivePos, Blocks.BEE_NEST.defaultState)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setBlockIfClear(worldGenLevel: StructureWorldAccess, blockPos: BlockPos, blockState: BlockState) {
|
||||||
|
if (!TreeFeature.isAirOrLeaves(worldGenLevel, blockPos)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
worldGenLevel.setBlockState(blockPos, blockState, 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isAir(testableWorld: TestableWorld, blockPos: BlockPos?): Boolean {
|
||||||
|
return testableWorld.testBlockState(
|
||||||
|
blockPos
|
||||||
|
) { blockState: BlockState ->
|
||||||
|
blockState.isOf(
|
||||||
|
Blocks.AIR
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"variants": {
|
||||||
|
"age=0": { "model": "cobblemon:block/bugwort_stage_0" },
|
||||||
|
"age=1": { "model": "cobblemon:block/bugwort_stage_1" },
|
||||||
|
"age=2": { "model": "cobblemon:block/bugwort_stage_2" },
|
||||||
|
"age=3": { "model": "cobblemon:block/bugwort_stage_3" }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,118 @@
|
|||||||
|
{
|
||||||
|
"variants": {
|
||||||
|
"face=ceiling,facing=east,powered=false": {
|
||||||
|
"model": "cobblemon:block/saccharine_button",
|
||||||
|
"y": 270,
|
||||||
|
"x": 180
|
||||||
|
},
|
||||||
|
"face=ceiling,facing=east,powered=true": {
|
||||||
|
"model": "cobblemon:block/saccharine_button_pressed",
|
||||||
|
"y": 270,
|
||||||
|
"x": 180
|
||||||
|
},
|
||||||
|
"face=ceiling,facing=north,powered=false": {
|
||||||
|
"model": "cobblemon:block/saccharine_button",
|
||||||
|
"y": 180,
|
||||||
|
"x": 180
|
||||||
|
},
|
||||||
|
"face=ceiling,facing=north,powered=true": {
|
||||||
|
"model": "cobblemon:block/saccharine_button_pressed",
|
||||||
|
"y": 180,
|
||||||
|
"x": 180
|
||||||
|
},
|
||||||
|
"face=ceiling,facing=south,powered=false": {
|
||||||
|
"model": "cobblemon:block/saccharine_button",
|
||||||
|
"x": 180
|
||||||
|
},
|
||||||
|
"face=ceiling,facing=south,powered=true": {
|
||||||
|
"model": "cobblemon:block/saccharine_button_pressed",
|
||||||
|
"x": 180
|
||||||
|
},
|
||||||
|
"face=ceiling,facing=west,powered=false": {
|
||||||
|
"model": "cobblemon:block/saccharine_button",
|
||||||
|
"y": 90,
|
||||||
|
"x": 180
|
||||||
|
},
|
||||||
|
"face=ceiling,facing=west,powered=true": {
|
||||||
|
"model": "cobblemon:block/saccharine_button_pressed",
|
||||||
|
"y": 90,
|
||||||
|
"x": 180
|
||||||
|
},
|
||||||
|
"face=floor,facing=east,powered=false": {
|
||||||
|
"model": "cobblemon:block/saccharine_button",
|
||||||
|
"y": 90
|
||||||
|
},
|
||||||
|
"face=floor,facing=east,powered=true": {
|
||||||
|
"model": "cobblemon:block/saccharine_button_pressed",
|
||||||
|
"y": 90
|
||||||
|
},
|
||||||
|
"face=floor,facing=north,powered=false": {
|
||||||
|
"model": "cobblemon:block/saccharine_button"
|
||||||
|
},
|
||||||
|
"face=floor,facing=north,powered=true": {
|
||||||
|
"model": "cobblemon:block/saccharine_button_pressed"
|
||||||
|
},
|
||||||
|
"face=floor,facing=south,powered=false": {
|
||||||
|
"model": "cobblemon:block/saccharine_button",
|
||||||
|
"y": 180
|
||||||
|
},
|
||||||
|
"face=floor,facing=south,powered=true": {
|
||||||
|
"model": "cobblemon:block/saccharine_button_pressed",
|
||||||
|
"y": 180
|
||||||
|
},
|
||||||
|
"face=floor,facing=west,powered=false": {
|
||||||
|
"model": "cobblemon:block/saccharine_button",
|
||||||
|
"y": 270
|
||||||
|
},
|
||||||
|
"face=floor,facing=west,powered=true": {
|
||||||
|
"model": "cobblemon:block/saccharine_button_pressed",
|
||||||
|
"y": 270
|
||||||
|
},
|
||||||
|
"face=wall,facing=east,powered=false": {
|
||||||
|
"model": "cobblemon:block/saccharine_button",
|
||||||
|
"y": 90,
|
||||||
|
"x": 90,
|
||||||
|
"uvlock": true
|
||||||
|
},
|
||||||
|
"face=wall,facing=east,powered=true": {
|
||||||
|
"model": "cobblemon:block/saccharine_button_pressed",
|
||||||
|
"y": 90,
|
||||||
|
"x": 90,
|
||||||
|
"uvlock": true
|
||||||
|
},
|
||||||
|
"face=wall,facing=north,powered=false": {
|
||||||
|
"model": "cobblemon:block/saccharine_button",
|
||||||
|
"x": 90,
|
||||||
|
"uvlock": true
|
||||||
|
},
|
||||||
|
"face=wall,facing=north,powered=true": {
|
||||||
|
"model": "cobblemon:block/saccharine_button_pressed",
|
||||||
|
"x": 90,
|
||||||
|
"uvlock": true
|
||||||
|
},
|
||||||
|
"face=wall,facing=south,powered=false": {
|
||||||
|
"model": "cobblemon:block/saccharine_button",
|
||||||
|
"y": 180,
|
||||||
|
"x": 90,
|
||||||
|
"uvlock": true
|
||||||
|
},
|
||||||
|
"face=wall,facing=south,powered=true": {
|
||||||
|
"model": "cobblemon:block/saccharine_button_pressed",
|
||||||
|
"y": 180,
|
||||||
|
"x": 90,
|
||||||
|
"uvlock": true
|
||||||
|
},
|
||||||
|
"face=wall,facing=west,powered=false": {
|
||||||
|
"model": "cobblemon:block/saccharine_button",
|
||||||
|
"y": 270,
|
||||||
|
"x": 90,
|
||||||
|
"uvlock": true
|
||||||
|
},
|
||||||
|
"face=wall,facing=west,powered=true": {
|
||||||
|
"model": "cobblemon:block/saccharine_button_pressed",
|
||||||
|
"y": 270,
|
||||||
|
"x": 90,
|
||||||
|
"uvlock": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,124 @@
|
|||||||
|
{
|
||||||
|
"variants": {
|
||||||
|
"facing=east,half=lower,hinge=left,open=false": {
|
||||||
|
"model": "cobblemon:block/saccharine_door_bottom_left"
|
||||||
|
},
|
||||||
|
"facing=east,half=lower,hinge=left,open=true": {
|
||||||
|
"model": "cobblemon:block/saccharine_door_bottom_left_open",
|
||||||
|
"y": 90
|
||||||
|
},
|
||||||
|
"facing=east,half=lower,hinge=right,open=false": {
|
||||||
|
"model": "cobblemon:block/saccharine_door_bottom_right"
|
||||||
|
},
|
||||||
|
"facing=east,half=lower,hinge=right,open=true": {
|
||||||
|
"model": "cobblemon:block/saccharine_door_bottom_right_open",
|
||||||
|
"y": 270
|
||||||
|
},
|
||||||
|
"facing=east,half=upper,hinge=left,open=false": {
|
||||||
|
"model": "cobblemon:block/saccharine_door_top_left"
|
||||||
|
},
|
||||||
|
"facing=east,half=upper,hinge=left,open=true": {
|
||||||
|
"model": "cobblemon:block/saccharine_door_top_left_open",
|
||||||
|
"y": 90
|
||||||
|
},
|
||||||
|
"facing=east,half=upper,hinge=right,open=false": {
|
||||||
|
"model": "cobblemon:block/saccharine_door_top_right"
|
||||||
|
},
|
||||||
|
"facing=east,half=upper,hinge=right,open=true": {
|
||||||
|
"model": "cobblemon:block/saccharine_door_top_right_open",
|
||||||
|
"y": 270
|
||||||
|
},
|
||||||
|
"facing=north,half=lower,hinge=left,open=false": {
|
||||||
|
"model": "cobblemon:block/saccharine_door_bottom_left",
|
||||||
|
"y": 270
|
||||||
|
},
|
||||||
|
"facing=north,half=lower,hinge=left,open=true": {
|
||||||
|
"model": "cobblemon:block/saccharine_door_bottom_left_open"
|
||||||
|
},
|
||||||
|
"facing=north,half=lower,hinge=right,open=false": {
|
||||||
|
"model": "cobblemon:block/saccharine_door_bottom_right",
|
||||||
|
"y": 270
|
||||||
|
},
|
||||||
|
"facing=north,half=lower,hinge=right,open=true": {
|
||||||
|
"model": "cobblemon:block/saccharine_door_bottom_right_open",
|
||||||
|
"y": 180
|
||||||
|
},
|
||||||
|
"facing=north,half=upper,hinge=left,open=false": {
|
||||||
|
"model": "cobblemon:block/saccharine_door_top_left",
|
||||||
|
"y": 270
|
||||||
|
},
|
||||||
|
"facing=north,half=upper,hinge=left,open=true": {
|
||||||
|
"model": "cobblemon:block/saccharine_door_top_left_open"
|
||||||
|
},
|
||||||
|
"facing=north,half=upper,hinge=right,open=false": {
|
||||||
|
"model": "cobblemon:block/saccharine_door_top_right",
|
||||||
|
"y": 270
|
||||||
|
},
|
||||||
|
"facing=north,half=upper,hinge=right,open=true": {
|
||||||
|
"model": "cobblemon:block/saccharine_door_top_right_open",
|
||||||
|
"y": 180
|
||||||
|
},
|
||||||
|
"facing=south,half=lower,hinge=left,open=false": {
|
||||||
|
"model": "cobblemon:block/saccharine_door_bottom_left",
|
||||||
|
"y": 90
|
||||||
|
},
|
||||||
|
"facing=south,half=lower,hinge=left,open=true": {
|
||||||
|
"model": "cobblemon:block/saccharine_door_bottom_left_open",
|
||||||
|
"y": 180
|
||||||
|
},
|
||||||
|
"facing=south,half=lower,hinge=right,open=false": {
|
||||||
|
"model": "cobblemon:block/saccharine_door_bottom_right",
|
||||||
|
"y": 90
|
||||||
|
},
|
||||||
|
"facing=south,half=lower,hinge=right,open=true": {
|
||||||
|
"model": "cobblemon:block/saccharine_door_bottom_right_open"
|
||||||
|
},
|
||||||
|
"facing=south,half=upper,hinge=left,open=false": {
|
||||||
|
"model": "cobblemon:block/saccharine_door_top_left",
|
||||||
|
"y": 90
|
||||||
|
},
|
||||||
|
"facing=south,half=upper,hinge=left,open=true": {
|
||||||
|
"model": "cobblemon:block/saccharine_door_top_left_open",
|
||||||
|
"y": 180
|
||||||
|
},
|
||||||
|
"facing=south,half=upper,hinge=right,open=false": {
|
||||||
|
"model": "cobblemon:block/saccharine_door_top_right",
|
||||||
|
"y": 90
|
||||||
|
},
|
||||||
|
"facing=south,half=upper,hinge=right,open=true": {
|
||||||
|
"model": "cobblemon:block/saccharine_door_top_right_open"
|
||||||
|
},
|
||||||
|
"facing=west,half=lower,hinge=left,open=false": {
|
||||||
|
"model": "cobblemon:block/saccharine_door_bottom_left",
|
||||||
|
"y": 180
|
||||||
|
},
|
||||||
|
"facing=west,half=lower,hinge=left,open=true": {
|
||||||
|
"model": "cobblemon:block/saccharine_door_bottom_left_open",
|
||||||
|
"y": 270
|
||||||
|
},
|
||||||
|
"facing=west,half=lower,hinge=right,open=false": {
|
||||||
|
"model": "cobblemon:block/saccharine_door_bottom_right",
|
||||||
|
"y": 180
|
||||||
|
},
|
||||||
|
"facing=west,half=lower,hinge=right,open=true": {
|
||||||
|
"model": "cobblemon:block/saccharine_door_bottom_right_open",
|
||||||
|
"y": 90
|
||||||
|
},
|
||||||
|
"facing=west,half=upper,hinge=left,open=false": {
|
||||||
|
"model": "cobblemon:block/saccharine_door_top_left",
|
||||||
|
"y": 180
|
||||||
|
},
|
||||||
|
"facing=west,half=upper,hinge=left,open=true": {
|
||||||
|
"model": "cobblemon:block/saccharine_door_top_left_open",
|
||||||
|
"y": 270
|
||||||
|
},
|
||||||
|
"facing=west,half=upper,hinge=right,open=false": {
|
||||||
|
"model": "cobblemon:block/saccharine_door_top_right",
|
||||||
|
"y": 180
|
||||||
|
},
|
||||||
|
"facing=west,half=upper,hinge=right,open=true": {
|
||||||
|
"model": "cobblemon:block/saccharine_door_top_right_open",
|
||||||
|
"y": 90
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
{
|
||||||
|
"multipart": [
|
||||||
|
{
|
||||||
|
"apply": {
|
||||||
|
"model": "cobblemon:block/saccharine_fence_post"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"when": {
|
||||||
|
"north": "true"
|
||||||
|
},
|
||||||
|
"apply": {
|
||||||
|
"model": "cobblemon:block/saccharine_fence_side",
|
||||||
|
"uvlock": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"when": {
|
||||||
|
"east": "true"
|
||||||
|
},
|
||||||
|
"apply": {
|
||||||
|
"model": "cobblemon:block/saccharine_fence_side",
|
||||||
|
"y": 90,
|
||||||
|
"uvlock": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"when": {
|
||||||
|
"south": "true"
|
||||||
|
},
|
||||||
|
"apply": {
|
||||||
|
"model": "cobblemon:block/saccharine_fence_side",
|
||||||
|
"y": 180,
|
||||||
|
"uvlock": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"when": {
|
||||||
|
"west": "true"
|
||||||
|
},
|
||||||
|
"apply": {
|
||||||
|
"model": "cobblemon:block/saccharine_fence_side",
|
||||||
|
"y": 270,
|
||||||
|
"uvlock": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
{
|
||||||
|
"variants": {
|
||||||
|
"facing=east,in_wall=false,open=false": {
|
||||||
|
"uvlock": true,
|
||||||
|
"y": 270,
|
||||||
|
"model": "cobblemon:block/saccharine_fence_gate"
|
||||||
|
},
|
||||||
|
"facing=east,in_wall=false,open=true": {
|
||||||
|
"uvlock": true,
|
||||||
|
"y": 270,
|
||||||
|
"model": "cobblemon:block/saccharine_fence_gate_open"
|
||||||
|
},
|
||||||
|
"facing=east,in_wall=true,open=false": {
|
||||||
|
"uvlock": true,
|
||||||
|
"y": 270,
|
||||||
|
"model": "cobblemon:block/saccharine_fence_gate_wall"
|
||||||
|
},
|
||||||
|
"facing=east,in_wall=true,open=true": {
|
||||||
|
"uvlock": true,
|
||||||
|
"y": 270,
|
||||||
|
"model": "cobblemon:block/saccharine_fence_gate_wall_open"
|
||||||
|
},
|
||||||
|
"facing=north,in_wall=false,open=false": {
|
||||||
|
"uvlock": true,
|
||||||
|
"y": 180,
|
||||||
|
"model": "cobblemon:block/saccharine_fence_gate"
|
||||||
|
},
|
||||||
|
"facing=north,in_wall=false,open=true": {
|
||||||
|
"uvlock": true,
|
||||||
|
"y": 180,
|
||||||
|
"model": "cobblemon:block/saccharine_fence_gate_open"
|
||||||
|
},
|
||||||
|
"facing=north,in_wall=true,open=false": {
|
||||||
|
"uvlock": true,
|
||||||
|
"y": 180,
|
||||||
|
"model": "cobblemon:block/saccharine_fence_gate_wall"
|
||||||
|
},
|
||||||
|
"facing=north,in_wall=true,open=true": {
|
||||||
|
"uvlock": true,
|
||||||
|
"y": 180,
|
||||||
|
"model": "cobblemon:block/saccharine_fence_gate_wall_open"
|
||||||
|
},
|
||||||
|
"facing=south,in_wall=false,open=false": {
|
||||||
|
"uvlock": true,
|
||||||
|
"model": "cobblemon:block/saccharine_fence_gate"
|
||||||
|
},
|
||||||
|
"facing=south,in_wall=false,open=true": {
|
||||||
|
"uvlock": true,
|
||||||
|
"model": "cobblemon:block/saccharine_fence_gate_open"
|
||||||
|
},
|
||||||
|
"facing=south,in_wall=true,open=false": {
|
||||||
|
"uvlock": true,
|
||||||
|
"model": "cobblemon:block/saccharine_fence_gate_wall"
|
||||||
|
},
|
||||||
|
"facing=south,in_wall=true,open=true": {
|
||||||
|
"uvlock": true,
|
||||||
|
"model": "cobblemon:block/saccharine_fence_gate_wall_open"
|
||||||
|
},
|
||||||
|
"facing=west,in_wall=false,open=false": {
|
||||||
|
"uvlock": true,
|
||||||
|
"y": 90,
|
||||||
|
"model": "cobblemon:block/saccharine_fence_gate"
|
||||||
|
},
|
||||||
|
"facing=west,in_wall=false,open=true": {
|
||||||
|
"uvlock": true,
|
||||||
|
"y": 90,
|
||||||
|
"model": "cobblemon:block/saccharine_fence_gate_open"
|
||||||
|
},
|
||||||
|
"facing=west,in_wall=true,open=false": {
|
||||||
|
"uvlock": true,
|
||||||
|
"y": 90,
|
||||||
|
"model": "cobblemon:block/saccharine_fence_gate_wall"
|
||||||
|
},
|
||||||
|
"facing=west,in_wall=true,open=true": {
|
||||||
|
"uvlock": true,
|
||||||
|
"y": 90,
|
||||||
|
"model": "cobblemon:block/saccharine_fence_gate_wall_open"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"variants": {
|
||||||
|
"": {
|
||||||
|
"model": "cobblemon:block/saccharine_hanging_sign"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"variants": {
|
||||||
|
"age=0": {
|
||||||
|
"model": "cobblemon:block/saccharine_leaves"
|
||||||
|
},
|
||||||
|
"age=1": {
|
||||||
|
"model": "cobblemon:block/saccharine_sticky_leaves"
|
||||||
|
},
|
||||||
|
"age=2": {
|
||||||
|
"model": "cobblemon:block/saccharine_glistening_leaves"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"variants": {
|
||||||
|
"axis=x": {
|
||||||
|
"model": "cobblemon:block/saccharine_log_horizontal",
|
||||||
|
"x": 90,
|
||||||
|
"y": 90
|
||||||
|
},
|
||||||
|
"axis=y": {
|
||||||
|
"model": "cobblemon:block/saccharine_log"
|
||||||
|
},
|
||||||
|
"axis=z": {
|
||||||
|
"model": "cobblemon:block/saccharine_log_horizontal",
|
||||||
|
"x": 90
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"variants": {
|
||||||
|
"": {
|
||||||
|
"model": "cobblemon:block/saccharine_planks"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"variants": {
|
||||||
|
"powered=false": {
|
||||||
|
"model": "cobblemon:block/saccharine_pressure_plate"
|
||||||
|
},
|
||||||
|
"powered=true": {
|
||||||
|
"model": "cobblemon:block/saccharine_pressure_plate_down"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"variants": {
|
||||||
|
"": {
|
||||||
|
"model": "cobblemon:block/saccharine_sapling"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"variants": {
|
||||||
|
"": {
|
||||||
|
"model": "cobblemon:block/saccharine_sign"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"variants": {
|
||||||
|
"type=bottom": {
|
||||||
|
"model": "cobblemon:block/saccharine_slab"
|
||||||
|
},
|
||||||
|
"type=double": {
|
||||||
|
"model": "cobblemon:block/saccharine_planks"
|
||||||
|
},
|
||||||
|
"type=top": {
|
||||||
|
"model": "cobblemon:block/saccharine_slab_top"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,209 @@
|
|||||||
|
{
|
||||||
|
"variants": {
|
||||||
|
"facing=east,half=bottom,shape=inner_left": {
|
||||||
|
"model": "cobblemon:block/saccharine_stairs_inner",
|
||||||
|
"y": 270,
|
||||||
|
"uvlock": true
|
||||||
|
},
|
||||||
|
"facing=east,half=bottom,shape=inner_right": {
|
||||||
|
"model": "cobblemon:block/saccharine_stairs_inner"
|
||||||
|
},
|
||||||
|
"facing=east,half=bottom,shape=outer_left": {
|
||||||
|
"model": "cobblemon:block/saccharine_stairs_outer",
|
||||||
|
"y": 270,
|
||||||
|
"uvlock": true
|
||||||
|
},
|
||||||
|
"facing=east,half=bottom,shape=outer_right": {
|
||||||
|
"model": "cobblemon:block/saccharine_stairs_outer"
|
||||||
|
},
|
||||||
|
"facing=east,half=bottom,shape=straight": {
|
||||||
|
"model": "cobblemon:block/saccharine_stairs"
|
||||||
|
},
|
||||||
|
"facing=east,half=top,shape=inner_left": {
|
||||||
|
"model": "cobblemon:block/saccharine_stairs_inner",
|
||||||
|
"x": 180,
|
||||||
|
"uvlock": true
|
||||||
|
},
|
||||||
|
"facing=east,half=top,shape=inner_right": {
|
||||||
|
"model": "cobblemon:block/saccharine_stairs_inner",
|
||||||
|
"x": 180,
|
||||||
|
"y": 90,
|
||||||
|
"uvlock": true
|
||||||
|
},
|
||||||
|
"facing=east,half=top,shape=outer_left": {
|
||||||
|
"model": "cobblemon:block/saccharine_stairs_outer",
|
||||||
|
"x": 180,
|
||||||
|
"uvlock": true
|
||||||
|
},
|
||||||
|
"facing=east,half=top,shape=outer_right": {
|
||||||
|
"model": "cobblemon:block/saccharine_stairs_outer",
|
||||||
|
"x": 180,
|
||||||
|
"y": 90,
|
||||||
|
"uvlock": true
|
||||||
|
},
|
||||||
|
"facing=east,half=top,shape=straight": {
|
||||||
|
"model": "cobblemon:block/saccharine_stairs",
|
||||||
|
"x": 180,
|
||||||
|
"uvlock": true
|
||||||
|
},
|
||||||
|
"facing=north,half=bottom,shape=inner_left": {
|
||||||
|
"model": "cobblemon:block/saccharine_stairs_inner",
|
||||||
|
"y": 180,
|
||||||
|
"uvlock": true
|
||||||
|
},
|
||||||
|
"facing=north,half=bottom,shape=inner_right": {
|
||||||
|
"model": "cobblemon:block/saccharine_stairs_inner",
|
||||||
|
"y": 270,
|
||||||
|
"uvlock": true
|
||||||
|
},
|
||||||
|
"facing=north,half=bottom,shape=outer_left": {
|
||||||
|
"model": "cobblemon:block/saccharine_stairs_outer",
|
||||||
|
"y": 180,
|
||||||
|
"uvlock": true
|
||||||
|
},
|
||||||
|
"facing=north,half=bottom,shape=outer_right": {
|
||||||
|
"model": "cobblemon:block/saccharine_stairs_outer",
|
||||||
|
"y": 270,
|
||||||
|
"uvlock": true
|
||||||
|
},
|
||||||
|
"facing=north,half=bottom,shape=straight": {
|
||||||
|
"model": "cobblemon:block/saccharine_stairs",
|
||||||
|
"y": 270,
|
||||||
|
"uvlock": true
|
||||||
|
},
|
||||||
|
"facing=north,half=top,shape=inner_left": {
|
||||||
|
"model": "cobblemon:block/saccharine_stairs_inner",
|
||||||
|
"x": 180,
|
||||||
|
"y": 270,
|
||||||
|
"uvlock": true
|
||||||
|
},
|
||||||
|
"facing=north,half=top,shape=inner_right": {
|
||||||
|
"model": "cobblemon:block/saccharine_stairs_inner",
|
||||||
|
"x": 180,
|
||||||
|
"uvlock": true
|
||||||
|
},
|
||||||
|
"facing=north,half=top,shape=outer_left": {
|
||||||
|
"model": "cobblemon:block/saccharine_stairs_outer",
|
||||||
|
"x": 180,
|
||||||
|
"y": 270,
|
||||||
|
"uvlock": true
|
||||||
|
},
|
||||||
|
"facing=north,half=top,shape=outer_right": {
|
||||||
|
"model": "cobblemon:block/saccharine_stairs_outer",
|
||||||
|
"x": 180,
|
||||||
|
"uvlock": true
|
||||||
|
},
|
||||||
|
"facing=north,half=top,shape=straight": {
|
||||||
|
"model": "cobblemon:block/saccharine_stairs",
|
||||||
|
"x": 180,
|
||||||
|
"y": 270,
|
||||||
|
"uvlock": true
|
||||||
|
},
|
||||||
|
"facing=south,half=bottom,shape=inner_left": {
|
||||||
|
"model": "cobblemon:block/saccharine_stairs_inner"
|
||||||
|
},
|
||||||
|
"facing=south,half=bottom,shape=inner_right": {
|
||||||
|
"model": "cobblemon:block/saccharine_stairs_inner",
|
||||||
|
"y": 90,
|
||||||
|
"uvlock": true
|
||||||
|
},
|
||||||
|
"facing=south,half=bottom,shape=outer_left": {
|
||||||
|
"model": "cobblemon:block/saccharine_stairs_outer"
|
||||||
|
},
|
||||||
|
"facing=south,half=bottom,shape=outer_right": {
|
||||||
|
"model": "cobblemon:block/saccharine_stairs_outer",
|
||||||
|
"y": 90,
|
||||||
|
"uvlock": true
|
||||||
|
},
|
||||||
|
"facing=south,half=bottom,shape=straight": {
|
||||||
|
"model": "cobblemon:block/saccharine_stairs",
|
||||||
|
"y": 90,
|
||||||
|
"uvlock": true
|
||||||
|
},
|
||||||
|
"facing=south,half=top,shape=inner_left": {
|
||||||
|
"model": "cobblemon:block/saccharine_stairs_inner",
|
||||||
|
"x": 180,
|
||||||
|
"y": 90,
|
||||||
|
"uvlock": true
|
||||||
|
},
|
||||||
|
"facing=south,half=top,shape=inner_right": {
|
||||||
|
"model": "cobblemon:block/saccharine_stairs_inner",
|
||||||
|
"x": 180,
|
||||||
|
"y": 180,
|
||||||
|
"uvlock": true
|
||||||
|
},
|
||||||
|
"facing=south,half=top,shape=outer_left": {
|
||||||
|
"model": "cobblemon:block/saccharine_stairs_outer",
|
||||||
|
"x": 180,
|
||||||
|
"y": 90,
|
||||||
|
"uvlock": true
|
||||||
|
},
|
||||||
|
"facing=south,half=top,shape=outer_right": {
|
||||||
|
"model": "cobblemon:block/saccharine_stairs_outer",
|
||||||
|
"x": 180,
|
||||||
|
"y": 180,
|
||||||
|
"uvlock": true
|
||||||
|
},
|
||||||
|
"facing=south,half=top,shape=straight": {
|
||||||
|
"model": "cobblemon:block/saccharine_stairs",
|
||||||
|
"x": 180,
|
||||||
|
"y": 90,
|
||||||
|
"uvlock": true
|
||||||
|
},
|
||||||
|
"facing=west,half=bottom,shape=inner_left": {
|
||||||
|
"model": "cobblemon:block/saccharine_stairs_inner",
|
||||||
|
"y": 90,
|
||||||
|
"uvlock": true
|
||||||
|
},
|
||||||
|
"facing=west,half=bottom,shape=inner_right": {
|
||||||
|
"model": "cobblemon:block/saccharine_stairs_inner",
|
||||||
|
"y": 180,
|
||||||
|
"uvlock": true
|
||||||
|
},
|
||||||
|
"facing=west,half=bottom,shape=outer_left": {
|
||||||
|
"model": "cobblemon:block/saccharine_stairs_outer",
|
||||||
|
"y": 90,
|
||||||
|
"uvlock": true
|
||||||
|
},
|
||||||
|
"facing=west,half=bottom,shape=outer_right": {
|
||||||
|
"model": "cobblemon:block/saccharine_stairs_outer",
|
||||||
|
"y": 180,
|
||||||
|
"uvlock": true
|
||||||
|
},
|
||||||
|
"facing=west,half=bottom,shape=straight": {
|
||||||
|
"model": "cobblemon:block/saccharine_stairs",
|
||||||
|
"y": 180,
|
||||||
|
"uvlock": true
|
||||||
|
},
|
||||||
|
"facing=west,half=top,shape=inner_left": {
|
||||||
|
"model": "cobblemon:block/saccharine_stairs_inner",
|
||||||
|
"x": 180,
|
||||||
|
"y": 180,
|
||||||
|
"uvlock": true
|
||||||
|
},
|
||||||
|
"facing=west,half=top,shape=inner_right": {
|
||||||
|
"model": "cobblemon:block/saccharine_stairs_inner",
|
||||||
|
"x": 180,
|
||||||
|
"y": 270,
|
||||||
|
"uvlock": true
|
||||||
|
},
|
||||||
|
"facing=west,half=top,shape=outer_left": {
|
||||||
|
"model": "cobblemon:block/saccharine_stairs_outer",
|
||||||
|
"x": 180,
|
||||||
|
"y": 180,
|
||||||
|
"uvlock": true
|
||||||
|
},
|
||||||
|
"facing=west,half=top,shape=outer_right": {
|
||||||
|
"model": "cobblemon:block/saccharine_stairs_outer",
|
||||||
|
"x": 180,
|
||||||
|
"y": 270,
|
||||||
|
"uvlock": true
|
||||||
|
},
|
||||||
|
"facing=west,half=top,shape=straight": {
|
||||||
|
"model": "cobblemon:block/saccharine_stairs",
|
||||||
|
"x": 180,
|
||||||
|
"y": 180,
|
||||||
|
"uvlock": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
{
|
||||||
|
"variants": {
|
||||||
|
"facing=east,half=bottom,open=false": {
|
||||||
|
"model": "cobblemon:block/saccharine_trapdoor_bottom",
|
||||||
|
"y": 90
|
||||||
|
},
|
||||||
|
"facing=east,half=bottom,open=true": {
|
||||||
|
"model": "cobblemon:block/saccharine_trapdoor_open",
|
||||||
|
"y": 90
|
||||||
|
},
|
||||||
|
"facing=east,half=top,open=false": {
|
||||||
|
"model": "cobblemon:block/saccharine_trapdoor_top",
|
||||||
|
"y": 90
|
||||||
|
},
|
||||||
|
"facing=east,half=top,open=true": {
|
||||||
|
"model": "cobblemon:block/saccharine_trapdoor_open",
|
||||||
|
"x": 180,
|
||||||
|
"y": 270
|
||||||
|
},
|
||||||
|
"facing=north,half=bottom,open=false": {
|
||||||
|
"model": "cobblemon:block/saccharine_trapdoor_bottom"
|
||||||
|
},
|
||||||
|
"facing=north,half=bottom,open=true": {
|
||||||
|
"model": "cobblemon:block/saccharine_trapdoor_open"
|
||||||
|
},
|
||||||
|
"facing=north,half=top,open=false": {
|
||||||
|
"model": "cobblemon:block/saccharine_trapdoor_top"
|
||||||
|
},
|
||||||
|
"facing=north,half=top,open=true": {
|
||||||
|
"model": "cobblemon:block/saccharine_trapdoor_open",
|
||||||
|
"x": 180,
|
||||||
|
"y": 180
|
||||||
|
},
|
||||||
|
"facing=south,half=bottom,open=false": {
|
||||||
|
"model": "cobblemon:block/saccharine_trapdoor_bottom",
|
||||||
|
"y": 180
|
||||||
|
},
|
||||||
|
"facing=south,half=bottom,open=true": {
|
||||||
|
"model": "cobblemon:block/saccharine_trapdoor_open",
|
||||||
|
"y": 180
|
||||||
|
},
|
||||||
|
"facing=south,half=top,open=false": {
|
||||||
|
"model": "cobblemon:block/saccharine_trapdoor_top",
|
||||||
|
"y": 180
|
||||||
|
},
|
||||||
|
"facing=south,half=top,open=true": {
|
||||||
|
"model": "cobblemon:block/saccharine_trapdoor_open",
|
||||||
|
"x": 180,
|
||||||
|
"y": 0
|
||||||
|
},
|
||||||
|
"facing=west,half=bottom,open=false": {
|
||||||
|
"model": "cobblemon:block/saccharine_trapdoor_bottom",
|
||||||
|
"y": 270
|
||||||
|
},
|
||||||
|
"facing=west,half=bottom,open=true": {
|
||||||
|
"model": "cobblemon:block/saccharine_trapdoor_open",
|
||||||
|
"y": 270
|
||||||
|
},
|
||||||
|
"facing=west,half=top,open=false": {
|
||||||
|
"model": "cobblemon:block/saccharine_trapdoor_top",
|
||||||
|
"y": 270
|
||||||
|
},
|
||||||
|
"facing=west,half=top,open=true": {
|
||||||
|
"model": "cobblemon:block/saccharine_trapdoor_open",
|
||||||
|
"x": 180,
|
||||||
|
"y": 90
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"variants": {
|
||||||
|
"": {
|
||||||
|
"model": "cobblemon:block/saccharine_hanging_sign"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"variants": {
|
||||||
|
"": {
|
||||||
|
"model": "cobblemon:block/saccharine_sign"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"variants": {
|
||||||
|
"axis=x": {
|
||||||
|
"model": "cobblemon:block/saccharine_wood",
|
||||||
|
"x": 90,
|
||||||
|
"y": 90
|
||||||
|
},
|
||||||
|
"axis=y": {
|
||||||
|
"model": "cobblemon:block/saccharine_wood"
|
||||||
|
},
|
||||||
|
"axis=z": {
|
||||||
|
"model": "cobblemon:block/saccharine_wood",
|
||||||
|
"x": 90
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
{
|
||||||
|
"variants": {
|
||||||
|
"age=0,axis=x": {
|
||||||
|
"model": "cobblemon:block/stripped_saccharine_log_horizontal",
|
||||||
|
"x": 90,
|
||||||
|
"y": 90
|
||||||
|
},
|
||||||
|
"age=0,axis=y": {
|
||||||
|
"model": "cobblemon:block/stripped_saccharine_log"
|
||||||
|
},
|
||||||
|
"age=0,axis=z": {
|
||||||
|
"model": "cobblemon:block/stripped_saccharine_log_horizontal",
|
||||||
|
"x": 90
|
||||||
|
},
|
||||||
|
"age=1,axis=x": {
|
||||||
|
"model": "cobblemon:block/syrupy_stripped_saccharine_log_horizontal",
|
||||||
|
"x": 90,
|
||||||
|
"y": 90
|
||||||
|
},
|
||||||
|
"age=1,axis=y": {
|
||||||
|
"model": "cobblemon:block/syrupy_stripped_saccharine_log"
|
||||||
|
},
|
||||||
|
"age=1,axis=z": {
|
||||||
|
"model": "cobblemon:block/syrupy_stripped_saccharine_log_horizontal",
|
||||||
|
"x": 90
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"variants": {
|
||||||
|
"age=0": {
|
||||||
|
"model": "cobblemon:block/stripped_saccharine_wood"
|
||||||
|
},
|
||||||
|
"age=1": {
|
||||||
|
"model": "cobblemon:block/syrupy_stripped_saccharine_wood"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"variants": {
|
||||||
|
"lit=false": {
|
||||||
|
"model": "cobblemon:block/sweet_incense_unlit"
|
||||||
|
},
|
||||||
|
"lit=true": {
|
||||||
|
"model": "cobblemon:block/sweet_incense_lit"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"parent": "minecraft:block/cross",
|
||||||
|
"textures": {
|
||||||
|
"cross": "cobblemon:block/bugwort_stage_0"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"parent": "minecraft:block/cross",
|
||||||
|
"textures": {
|
||||||
|
"cross": "cobblemon:block/bugwort_stage_1"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"parent": "minecraft:block/cross",
|
||||||
|
"textures": {
|
||||||
|
"cross": "cobblemon:block/bugwort_stage_2"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"parent": "minecraft:block/cross",
|
||||||
|
"textures": {
|
||||||
|
"cross": "cobblemon:block/bugwort_stage_3"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
{
|
||||||
|
"format_version": "1.12.0",
|
||||||
|
"minecraft:geometry": [
|
||||||
|
{
|
||||||
|
"description": {
|
||||||
|
"identifier": "geometry.unknown",
|
||||||
|
"texture_width": 64,
|
||||||
|
"texture_height": 64,
|
||||||
|
"visible_bounds_width": 2,
|
||||||
|
"visible_bounds_height": 2.5,
|
||||||
|
"visible_bounds_offset": [0, 0.75, 0]
|
||||||
|
},
|
||||||
|
"bones": [
|
||||||
|
{
|
||||||
|
"name": "bb_main",
|
||||||
|
"pivot": [0, 0, 0],
|
||||||
|
"cubes": [
|
||||||
|
{
|
||||||
|
"origin": [-6, 0, -6],
|
||||||
|
"size": [12, 3, 12],
|
||||||
|
"uv": {
|
||||||
|
"north": {"uv": [10, 28], "uv_size": [12, 3]},
|
||||||
|
"east": {"uv": [28, 18], "uv_size": [12, 3]},
|
||||||
|
"south": {"uv": [28, 21], "uv_size": [12, 3]},
|
||||||
|
"west": {"uv": [22, 28], "uv_size": [12, 3]},
|
||||||
|
"up": {"uv": [0, 0], "uv_size": [12, 12]},
|
||||||
|
"down": {"uv": [0, 24], "uv_size": [12, -12]}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"origin": [-5, 3, -5],
|
||||||
|
"size": [10, 6, 10],
|
||||||
|
"uv": {
|
||||||
|
"north": {"uv": [22, 0], "uv_size": [10, 6]},
|
||||||
|
"east": {"uv": [22, 6], "uv_size": [10, 6]},
|
||||||
|
"south": {"uv": [22, 12], "uv_size": [10, 6]},
|
||||||
|
"west": {"uv": [0, 24], "uv_size": [10, 6]},
|
||||||
|
"up": {"uv": [12, 0], "uv_size": [10, 10]},
|
||||||
|
"down": {"uv": [12, 20], "uv_size": [10, -10]}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"origin": [-4, 9, -4],
|
||||||
|
"size": [8, 1, 8],
|
||||||
|
"uv": {
|
||||||
|
"north": {"uv": [28, 24], "uv_size": [8, 1]},
|
||||||
|
"east": {"uv": [28, 25], "uv_size": [8, 1]},
|
||||||
|
"south": {"uv": [28, 26], "uv_size": [8, 1]},
|
||||||
|
"west": {"uv": [28, 27], "uv_size": [8, 1]},
|
||||||
|
"up": {"uv": [12, 20], "uv_size": [8, 8]},
|
||||||
|
"down": {"uv": [20, 28], "uv_size": [8, -8]}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"origin": [-1, 10, -1],
|
||||||
|
"size": [2, 1, 2],
|
||||||
|
"uv": {
|
||||||
|
"north": {"uv": [24, 18], "uv_size": [2, 1]},
|
||||||
|
"east": {"uv": [24, 19], "uv_size": [2, 1]},
|
||||||
|
"south": {"uv": [10, 26], "uv_size": [2, 1]},
|
||||||
|
"west": {"uv": [26, 18], "uv_size": [2, 1]},
|
||||||
|
"up": {"uv": [22, 18], "uv_size": [2, 2]},
|
||||||
|
"down": {"uv": [10, 26], "uv_size": [2, -2]}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"parent": "minecraft:block/button",
|
||||||
|
"textures": {
|
||||||
|
"texture": "cobblemon:block/saccharine_planks"
|
||||||
|
}
|
||||||
|
}
|
||||||
+6
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"parent": "minecraft:block/button_inventory",
|
||||||
|
"textures": {
|
||||||
|
"texture": "cobblemon:block/saccharine_planks"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"parent": "minecraft:block/button_pressed",
|
||||||
|
"textures": {
|
||||||
|
"texture": "cobblemon:block/saccharine_planks"
|
||||||
|
}
|
||||||
|
}
|
||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"parent": "minecraft:block/door_bottom_left",
|
||||||
|
"textures": {
|
||||||
|
"bottom": "cobblemon:block/saccharine_door_bottom",
|
||||||
|
"top": "cobblemon:block/saccharine_door_top"
|
||||||
|
}
|
||||||
|
}
|
||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"parent": "minecraft:block/door_bottom_left_open",
|
||||||
|
"textures": {
|
||||||
|
"bottom": "cobblemon:block/saccharine_door_bottom",
|
||||||
|
"top": "cobblemon:block/saccharine_door_top"
|
||||||
|
}
|
||||||
|
}
|
||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"parent": "minecraft:block/door_bottom_right",
|
||||||
|
"textures": {
|
||||||
|
"bottom": "cobblemon:block/saccharine_door_bottom",
|
||||||
|
"top": "cobblemon:block/saccharine_door_top"
|
||||||
|
}
|
||||||
|
}
|
||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"parent": "minecraft:block/door_bottom_right_open",
|
||||||
|
"textures": {
|
||||||
|
"bottom": "cobblemon:block/saccharine_door_bottom",
|
||||||
|
"top": "cobblemon:block/saccharine_door_top"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"parent": "minecraft:block/door_top_left",
|
||||||
|
"textures": {
|
||||||
|
"bottom": "cobblemon:block/saccharine_door_bottom",
|
||||||
|
"top": "cobblemon:block/saccharine_door_top"
|
||||||
|
}
|
||||||
|
}
|
||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"parent": "minecraft:block/door_top_left_open",
|
||||||
|
"textures": {
|
||||||
|
"bottom": "cobblemon:block/saccharine_door_bottom",
|
||||||
|
"top": "cobblemon:block/saccharine_door_top"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"parent": "minecraft:block/door_top_right",
|
||||||
|
"textures": {
|
||||||
|
"bottom": "cobblemon:block/saccharine_door_bottom",
|
||||||
|
"top": "cobblemon:block/saccharine_door_top"
|
||||||
|
}
|
||||||
|
}
|
||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"parent": "minecraft:block/door_top_right_open",
|
||||||
|
"textures": {
|
||||||
|
"bottom": "cobblemon:block/saccharine_door_bottom",
|
||||||
|
"top": "cobblemon:block/saccharine_door_top"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"parent": "minecraft:block/template_fence_gate",
|
||||||
|
"textures": {
|
||||||
|
"texture": "cobblemon:block/saccharine_planks"
|
||||||
|
}
|
||||||
|
}
|
||||||
+6
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"parent": "minecraft:block/template_fence_gate_open",
|
||||||
|
"textures": {
|
||||||
|
"texture": "cobblemon:block/saccharine_planks"
|
||||||
|
}
|
||||||
|
}
|
||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
|
||||||
|
{
|
||||||
|
"parent": "minecraft:block/template_fence_gate_wall",
|
||||||
|
"textures": {
|
||||||
|
"texture": "cobblemon:block/saccharine_planks"
|
||||||
|
}
|
||||||
|
}
|
||||||
+6
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"parent": "minecraft:block/template_fence_gate_wall_open",
|
||||||
|
"textures": {
|
||||||
|
"texture": "cobblemon:block/saccharine_planks"
|
||||||
|
}
|
||||||
|
}
|
||||||
+6
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"parent": "minecraft:block/fence_inventory",
|
||||||
|
"textures": {
|
||||||
|
"texture": "cobblemon:block/saccharine_planks"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"parent": "minecraft:block/fence_post",
|
||||||
|
"textures": {
|
||||||
|
"texture": "cobblemon:block/saccharine_planks"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"parent": "minecraft:block/fence_side",
|
||||||
|
"textures": {
|
||||||
|
"texture": "cobblemon:block/saccharine_planks"
|
||||||
|
}
|
||||||
|
}
|
||||||
+6
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"parent": "minecraft:block/cube_all",
|
||||||
|
"textures": {
|
||||||
|
"all": "cobblemon:block/saccharine_glistening_leaves"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"textures": {
|
||||||
|
"particle": "cobblemon:block/stripped_saccharine_log"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"parent": "minecraft:block/cube_all",
|
||||||
|
"textures": {
|
||||||
|
"all": "cobblemon:block/saccharine_leaves"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"parent": "minecraft:block/cube_column",
|
||||||
|
"textures": {
|
||||||
|
"end": "cobblemon:block/saccharine_log_top",
|
||||||
|
"side": "cobblemon:block/saccharine_log"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"parent": "minecraft:block/cube_column_horizontal",
|
||||||
|
"textures": {
|
||||||
|
"end": "cobblemon:block/saccharine_log_top",
|
||||||
|
"side": "cobblemon:block/saccharine_log"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"parent": "minecraft:block/cube_all",
|
||||||
|
"textures": {
|
||||||
|
"all": "cobblemon:block/saccharine_planks"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"parent": "minecraft:block/pressure_plate_up",
|
||||||
|
"textures": {
|
||||||
|
"texture": "cobblemon:block/saccharine_planks"
|
||||||
|
}
|
||||||
|
}
|
||||||
+6
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"parent": "minecraft:block/pressure_plate_down",
|
||||||
|
"textures": {
|
||||||
|
"texture": "cobblemon:block/saccharine_planks"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"parent": "minecraft:block/cross",
|
||||||
|
"textures": {
|
||||||
|
"cross": "cobblemon:block/saccharine_sapling"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"textures": {
|
||||||
|
"particle": "cobblemon:block/saccharine_planks"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"parent": "minecraft:block/slab",
|
||||||
|
"textures": {
|
||||||
|
"bottom": "cobblemon:block/saccharine_planks",
|
||||||
|
"top": "cobblemon:block/saccharine_planks",
|
||||||
|
"side": "cobblemon:block/saccharine_planks"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"parent": "minecraft:block/slab_top",
|
||||||
|
"textures": {
|
||||||
|
"bottom": "cobblemon:block/saccharine_planks",
|
||||||
|
"top": "cobblemon:block/saccharine_planks",
|
||||||
|
"side": "cobblemon:block/saccharine_planks"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"parent": "minecraft:block/stairs",
|
||||||
|
"textures": {
|
||||||
|
"bottom": "cobblemon:block/saccharine_planks",
|
||||||
|
"top": "cobblemon:block/saccharine_planks",
|
||||||
|
"side": "cobblemon:block/saccharine_planks"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"parent": "minecraft:block/inner_stairs",
|
||||||
|
"textures": {
|
||||||
|
"bottom": "cobblemon:block/saccharine_planks",
|
||||||
|
"top": "cobblemon:block/saccharine_planks",
|
||||||
|
"side": "cobblemon:block/saccharine_planks"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"parent": "minecraft:block/outer_stairs",
|
||||||
|
"textures": {
|
||||||
|
"bottom": "cobblemon:block/saccharine_planks",
|
||||||
|
"top": "cobblemon:block/saccharine_planks",
|
||||||
|
"side": "cobblemon:block/saccharine_planks"
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user