forked from mirrors/cobblemon
Compare commits
13
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
86d48df9fe | ||
|
|
3401ba9cbb | ||
|
|
dac9ccb461 | ||
|
|
191a62f693 | ||
|
|
d8d410e539 | ||
|
|
b7c6e1ea77 | ||
|
|
186812d6fd | ||
|
|
1c0bdc766a | ||
|
|
c697bcd2e9 | ||
|
|
9d6ff01d80 | ||
|
|
1691853a19 | ||
|
|
4e9a4e1e5a | ||
|
|
6450255a0b |
@@ -1,3 +0,0 @@
|
||||
### Additions
|
||||
|
||||
- Added the ability to ride Pokémon by shift-right clicking and selecting the ride option.
|
||||
+1
-16
@@ -6,10 +6,6 @@
|
||||
- Added `/cobblemonconfig reload` command to reload `main.json` configuration. **Note:** Some settings require a server restart to take effect; use this command cautiously.
|
||||
- Added `blacklisted_items_to_hold` and `whitelisted_items_to_hold` tags to allow for controlling which items players can give to their Pokémon. If the whitelist is empty, it will consider all item as allowed (unless they are in the blacklist).
|
||||
- Pokémon now follow the mouse cursor on the Summary screen, with an option to disable this in the settings.
|
||||
- Pokémon's held items can now be rendered, with a visibility toggle in the Summary screen.
|
||||
- Added cosmetic item functionality for Pokémon. Certain cosmetic items can be given to applicable Pokémon via the interact menu.
|
||||
- Added the various log blocks as cosmetic items for Timburr and Komala.
|
||||
- Added `visibility/hidden`, `visibility/hat` and `visibility/face` tags to control where and how certain items are rendered.
|
||||
|
||||
### Changes
|
||||
- Renamed `chargeGainedPerTick` config to `secondsToChargeHealingMachine`.
|
||||
@@ -25,15 +21,6 @@
|
||||
- Fixed fling not using Item Names for minecraft held items that substitute Pokémon items
|
||||
- Fixed evolutions sometimes preventing players from logging in to servers
|
||||
- Fixed rendering of shoulder-mounted Pokémon desyncing between clients
|
||||
- Fixed apricorn chest boats forgetting their inventories when being unloaded
|
||||
- Fixed moves not updating correctly between form changes resulting in illegal movesets
|
||||
- Fixed crash sometimes occurring with the "Oritech" mod
|
||||
- Fixed crashes due to an incorrect Java version handing out an obscure crash.
|
||||
- Fixed some berries being able to rarely get too many berries and cause a crash.
|
||||
- Fixed status curing berries not playing the berry eating sound, same for healing berries used mid-battle.
|
||||
- Fixed owned Pokémon sometimes being un-interactable after the player relogs fast
|
||||
- Fixed field name in evolution requirements for Spewpa Pokeball.
|
||||
- Fixed LevelUpCriterion logic to correctly check that the Pokémon is a preEvo.
|
||||
|
||||
### Developer
|
||||
- A finished battle now has winners and losers set inside of `PokemonBattle` instead of them always being empty.
|
||||
@@ -47,13 +34,11 @@
|
||||
|
||||
### Changes
|
||||
- When using the `cobblemon` or `generation_9` capture calculators a critical capture with a single shake will always play for successful captures when you've already registered the Pokémon as caught in your Pokédex.
|
||||
|
||||
### MoLang & Datapacks
|
||||
- The following usages for item predicates can now use item conditions like advancements do, you can learn about them in the [Minecraft wiki](https://minecraft.wiki/w/Advancement_definition#minecraft:filled_bucket)
|
||||
- The `requiredContext` for an item interaction evolution
|
||||
- The `itemCondition` for a held item evolution requirement
|
||||
- The `fossils` for a fossil entry
|
||||
- Added MoLang flows for `poke_ball_capture_calculated`, `evolution_tested`, `evolution_accepted`, `evolution_completed`
|
||||
|
||||
## [1.6.1 (January 26th, 2025)](#1-6-1)
|
||||
|
||||
@@ -2174,4 +2159,4 @@ Thank you so much to all of our community translators that bring the mod to the
|
||||
- Added species, ability, and move translations for `ko_ko`, `jp_jp`, `fr_fr`, `es_es`, `it_it`, and `zh_cn`.
|
||||
|
||||
## [1.0.0 (November 12th, 2022)](#1-0-0)
|
||||
- Initial release.
|
||||
- Initial release.
|
||||
@@ -1,124 +0,0 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import net.minecraft.util.Mth;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.joml.Matrix3f;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
public interface Rollable {
|
||||
|
||||
// From Minecraft's Camera
|
||||
Vector3f FORWARDS = new Vector3f(0.0F, 0.0F, -1.0F);
|
||||
Vector3f UP = new Vector3f(0.0F, 1.0F, 0.0F);
|
||||
Vector3f LEFT = new Vector3f(-1.0F, 0.0F, 0.0F);
|
||||
|
||||
@Nullable Matrix3f getOrientation();
|
||||
|
||||
Rollable updateOrientation(Function<Matrix3f, Matrix3f> update);
|
||||
|
||||
/**
|
||||
* @return The forward vector (0, 0, -1) after the rotation matrix is applied.
|
||||
*/
|
||||
default Vector3f getForwardVector() {
|
||||
if (getOrientation() == null) return new Vector3f(FORWARDS);
|
||||
return getOrientation().transform(FORWARDS, new Vector3f());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The left vector (-1, 0, 0) after the rotation matrix is applied.
|
||||
*/
|
||||
default Vector3f getLeftVector() {
|
||||
if (getOrientation() == null) return new Vector3f(LEFT);
|
||||
return getOrientation().transform(LEFT, new Vector3f());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The up vector (0, 1, 0) after the rotation matrix is applied.
|
||||
*/
|
||||
default Vector3f getUpVector() {
|
||||
if (getOrientation() == null) return new Vector3f(UP);
|
||||
return getOrientation().transform(UP, new Vector3f());
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param yaw change in degrees
|
||||
* @return The Rollable object this method was called on
|
||||
*/
|
||||
|
||||
default Rollable rotateYaw(float yaw) {
|
||||
return updateOrientation(prev -> prev.rotateY((float) Math.toRadians(-yaw)));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param pitch change in degrees
|
||||
* @return The Rollable object this method was called on
|
||||
*/
|
||||
|
||||
default Rollable rotatePitch(float pitch) {
|
||||
return updateOrientation(prev -> prev.rotateX((float) Math.toRadians(-pitch)));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param roll change in degrees
|
||||
* @return The Rollable object this method was called on
|
||||
*/
|
||||
default Rollable rotateRoll(float roll) {
|
||||
return updateOrientation(prev -> prev.rotateZ((float) Math.toRadians(-roll)));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Order matters when rotating an object. If you need a different order, individually call rotateYaw, rotatePitch, and rotateRoll
|
||||
*
|
||||
* @param yaw change in degrees
|
||||
* @param pitch change in degrees
|
||||
* @param roll change in degrees
|
||||
* @return The Rollable object this method was called on
|
||||
*/
|
||||
default Rollable rotate(float yaw, float pitch, float roll) {
|
||||
return rotateYaw(yaw).rotatePitch(pitch).rotateRoll(roll);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The pitch angle in degrees as a float.
|
||||
* Value is between [-180, 180] with 0 being South, 90 being West, 180/-180 being North, and -90 being East
|
||||
*/
|
||||
default float getYaw() {
|
||||
return (float) Mth.wrapDegrees(-Math.toDegrees(FORWARDS.angleSigned(getForwardVector(), UP)) + 180);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The yaw angle in degrees as a float.
|
||||
* Value is between [-90, 90] with 0 being straight forward, 90 being straight down, and -90 being straight up
|
||||
*/
|
||||
default float getPitch() {
|
||||
return (float) Mth.wrapDegrees(-Math.toDegrees(Math.asin(getForwardVector().y)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The roll angle in degrees as a float.
|
||||
* Value is between [-180, 180] with 0 being no roll (normal), 90 being 90 degrees CW, 180/-180 being 180 degrees CW/CCW, and -90 being 90 degrees CCW
|
||||
*/
|
||||
default float getRoll() {
|
||||
//Cobblemon.LOGGER.info("{}", (float) Math.toDegrees(getUpVector().angleSigned(UP, getForwardVector())));
|
||||
return (float) Mth.wrapDegrees(-Math.toDegrees(getUpVector().angleSigned(UP, getForwardVector())));
|
||||
}
|
||||
|
||||
boolean shouldRoll();
|
||||
|
||||
void clearRotation();
|
||||
|
||||
}
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin.client;
|
||||
package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.api.scheduling.ClientTaskTracker;
|
||||
import net.minecraft.client.DeltaTracker;
|
||||
+1
-15
@@ -6,22 +6,18 @@
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin.client;
|
||||
package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.Rollable;
|
||||
import com.cobblemon.mod.common.item.PokedexItem;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.player.AbstractClientPlayer;
|
||||
import net.minecraft.client.renderer.ItemInHandRenderer;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import org.joml.Quaternionf;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(ItemInHandRenderer.class)
|
||||
@@ -31,15 +27,5 @@ public class ItemInHandRendererMixin {
|
||||
if (abstractClientPlayer.isUsingItem() && abstractClientPlayer.getUseItem().getItem() instanceof PokedexItem) {
|
||||
ci.cancel();
|
||||
}
|
||||
else if (abstractClientPlayer instanceof Rollable rollable && rollable.shouldRoll()) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Redirect(method = "renderHandsWithItems", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/vertex/PoseStack;mulPose(Lorg/joml/Quaternionf;)V", ordinal = 1))
|
||||
private void cobblemon$renderHandswithItems(PoseStack instance, Quaternionf quaternion) {
|
||||
if (!(Minecraft.getInstance().player instanceof Rollable rollable && rollable.shouldRoll())) {
|
||||
instance.mulPose(quaternion);
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-3
@@ -6,7 +6,7 @@
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin.client;
|
||||
package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon;
|
||||
import com.cobblemon.mod.common.ModAPI;
|
||||
@@ -40,8 +40,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
*/
|
||||
@Mixin(ItemRenderer.class)
|
||||
public abstract class ItemRendererMixin {
|
||||
// ignore the hint saying implmentation is never null, if something crashes then it is null and causes red herrings
|
||||
@Unique private final String MODEL_PATH = (Cobblemon.implementation != null && Cobblemon.implementation.getModAPI() == ModAPI.FABRIC) ? "fabric_resource" : "standalone";
|
||||
@Unique private final String MODEL_PATH = Cobblemon.implementation.getModAPI() == ModAPI.FABRIC ? "fabric_resource" : "standalone";
|
||||
|
||||
@Shadow @Final private ItemModelShaper itemModelShaper;
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin.client;
|
||||
package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.client.CobblemonBakingOverrides;
|
||||
import java.util.List;
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin.client;
|
||||
package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pose.Bone;
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.RenderContext;
|
||||
+6
-31
@@ -6,9 +6,8 @@
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin.client;
|
||||
package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.Rollable;
|
||||
import com.cobblemon.mod.common.client.CobblemonClient;
|
||||
import com.cobblemon.mod.common.client.keybind.keybinds.PartySendBinding;
|
||||
import com.cobblemon.mod.common.pokedex.scanner.PokedexUsageContext;
|
||||
@@ -23,18 +22,16 @@ import org.objectweb.asm.Opcodes;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(MouseHandler.class)
|
||||
public class MouseHandlerMixin {
|
||||
@Shadow private double accumulatedScrollY;
|
||||
@Shadow @Final private Minecraft minecraft;
|
||||
@Shadow
|
||||
private double accumulatedScrollY;
|
||||
|
||||
@Unique SmoothDouble pitchSmoother = new SmoothDouble();
|
||||
@Unique SmoothDouble rollSmoother = new SmoothDouble();
|
||||
@Shadow @Final private Minecraft minecraft;
|
||||
|
||||
@Shadow @Final private SmoothDouble smoothTurnY;
|
||||
|
||||
@@ -96,6 +93,7 @@ public class MouseHandlerMixin {
|
||||
)
|
||||
)
|
||||
public boolean cobblemon$modifyRotation(LocalPlayer player, double cursorDeltaX, double cursorDeltaY, @Local(argsOnly = true) double d) {
|
||||
// I know this technically doesn't need to be a WrapWithCondition, but it'll make things easier later for riding.
|
||||
PokedexUsageContext usageContext = CobblemonClient.INSTANCE.getPokedexUsageContext();
|
||||
if (usageContext.getScanningGuiOpen()) {
|
||||
this.smoothTurnY.reset();
|
||||
@@ -107,30 +105,7 @@ public class MouseHandlerMixin {
|
||||
player.turn(this.accumulatedDX * sensitivity, (this.accumulatedDY * sensitivity));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(player instanceof Rollable rollable)) return true;
|
||||
if (!rollable.shouldRoll()) {
|
||||
pitchSmoother.reset();
|
||||
rollSmoother.reset();
|
||||
return true;
|
||||
}
|
||||
|
||||
var pitch = pitchSmoother.getNewDeltaValue(cursorDeltaY * 0.15f, d);
|
||||
var roll = rollSmoother.getNewDeltaValue(cursorDeltaX * 0.15f, d);
|
||||
rollable.rotate(0.0F, (float)pitch, (float)roll);
|
||||
return false;
|
||||
}
|
||||
|
||||
@Inject(method = "handleAccumulatedMovement", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/MouseHandler;isMouseGrabbed()Z", ordinal = 0))
|
||||
private void cobblemon$maintainMovementWhenInScreens(CallbackInfo ci, @Local(ordinal = 1) double e) {
|
||||
if (minecraft.player == null) return;
|
||||
if (!(minecraft.player instanceof Rollable rollable)) return;
|
||||
if (!rollable.shouldRoll()) return;
|
||||
if (minecraft.isPaused()) return;
|
||||
|
||||
var pitch = pitchSmoother.getNewDeltaValue(0, e);
|
||||
var roll = rollSmoother.getNewDeltaValue(0, e);
|
||||
rollable.rotate(0.0F, (float)pitch, (float)roll);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -10,15 +10,12 @@ package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon;
|
||||
import com.cobblemon.mod.common.CobblemonItems;
|
||||
import com.cobblemon.mod.common.Rollable;
|
||||
import com.cobblemon.mod.common.api.events.CobblemonEvents;
|
||||
import com.cobblemon.mod.common.api.events.item.LeftoversCreatedEvent;
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonSpecies;
|
||||
import com.cobblemon.mod.common.api.riding.Rideable;
|
||||
import com.cobblemon.mod.common.api.storage.party.PartyStore;
|
||||
import com.cobblemon.mod.common.api.storage.party.PlayerPartyStore;
|
||||
import com.cobblemon.mod.common.api.tags.CobblemonItemTags;
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
|
||||
import com.cobblemon.mod.common.pokedex.scanner.PokedexEntityData;
|
||||
import com.cobblemon.mod.common.pokedex.scanner.ScannableEntity;
|
||||
import com.cobblemon.mod.common.pokemon.FormData;
|
||||
@@ -29,10 +26,6 @@ import com.cobblemon.mod.common.util.CompoundTagExtensionsKt;
|
||||
import com.cobblemon.mod.common.util.CompoundTagUtilities;
|
||||
import com.cobblemon.mod.common.util.DataKeys;
|
||||
import com.cobblemon.mod.common.world.gamerules.CobblemonGameRules;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.player.LocalPlayer;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import net.minecraft.network.chat.Component;
|
||||
@@ -45,10 +38,8 @@ import net.minecraft.world.entity.item.ItemEntity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.food.FoodProperties;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.Items;
|
||||
import net.minecraft.world.level.Level;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.joml.Matrix3f;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
@@ -62,11 +53,10 @@ import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Mixin(Player.class)
|
||||
public abstract class PlayerMixin extends LivingEntity implements Rollable, ScannableEntity {
|
||||
public abstract class PlayerMixin extends LivingEntity implements ScannableEntity {
|
||||
|
||||
@Shadow public abstract CompoundTag getShoulderEntityLeft();
|
||||
|
||||
@@ -84,7 +74,6 @@ public abstract class PlayerMixin extends LivingEntity implements Rollable, Scan
|
||||
|
||||
@Shadow public abstract void displayClientMessage(Component message, boolean overlay);
|
||||
|
||||
@Unique private Matrix3f orientation = null;
|
||||
|
||||
protected PlayerMixin(EntityType<? extends LivingEntity> p_20966_, Level p_20967_) {
|
||||
super(p_20966_, p_20967_);
|
||||
@@ -178,7 +167,8 @@ public abstract class PlayerMixin extends LivingEntity implements Rollable, Scan
|
||||
|
||||
@Inject(method = "isInvulnerableTo", at = @At("HEAD"), cancellable = true)
|
||||
public void isInvulnerableTo(DamageSource source, CallbackInfoReturnable<Boolean> ci) {
|
||||
if (!level().isClientSide && (Object) this instanceof ServerPlayer player) {
|
||||
if (!level().isClientSide) {
|
||||
ServerPlayer player = (ServerPlayer)(Object)this;
|
||||
boolean invulnerableInBattle = this.level().getGameRules().getBoolean(CobblemonGameRules.BATTLE_INVULNERABILITY);
|
||||
boolean inBattle = Cobblemon.INSTANCE.getBattleRegistry().getBattleByParticipatingPlayer(player) != null;
|
||||
if (invulnerableInBattle && inBattle) {
|
||||
@@ -235,81 +225,4 @@ public abstract class PlayerMixin extends LivingEntity implements Rollable, Scan
|
||||
public LivingEntity resolveEntityScan() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void absMoveTo(double x, double y, double z, float yaw, float pitch) {
|
||||
if (shouldRoll()) {
|
||||
this.absMoveTo(x, y, z);
|
||||
this.setYRot(yaw % 360.0f);
|
||||
this.setXRot(pitch % 360.0f);
|
||||
this.yRotO = this.getYRot();
|
||||
this.xRotO = this.getXRot();
|
||||
}
|
||||
else {
|
||||
this.absMoveTo(x, y, z);
|
||||
this.absRotateTo(yaw, pitch);
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "tick", at = @At("HEAD"))
|
||||
public void tick(CallbackInfo ci) {
|
||||
if (this.shouldRoll()) {
|
||||
// Proof of concept for yaw movement
|
||||
if (this.getMainHandItem().is(Items.STICK)) {
|
||||
this.rotateYaw(2);
|
||||
}
|
||||
else if (this.getMainHandItem().is(Items.BLAZE_ROD)) {
|
||||
this.rotateYaw(-2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Matrix3f getOrientation() {
|
||||
return orientation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Rollable updateOrientation(Function<Matrix3f, Matrix3f> update) {
|
||||
if (!shouldRoll()) return this;
|
||||
|
||||
if (this.orientation == null) {
|
||||
this.orientation = new Matrix3f();
|
||||
this.rotate(getYRot() - 180, getXRot(), 0);
|
||||
}
|
||||
this.orientation = update.apply(this.orientation);
|
||||
setYRot(this.getYaw());
|
||||
setXRot(this.getPitch());
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldRoll() {
|
||||
LocalPlayer player = Minecraft.getInstance().player;
|
||||
if (!this.equals(player)) return false;
|
||||
if (player.isHolding(Items.DIAMOND)) return true;
|
||||
|
||||
var playerVehicle = player.getVehicle();
|
||||
if (playerVehicle == null) return false;
|
||||
if (!(playerVehicle instanceof PokemonEntity pokemonEntity)) return false;
|
||||
|
||||
return pokemonEntity.getRiding().shouldRoll(pokemonEntity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearRotation() {
|
||||
this.orientation = null;
|
||||
}
|
||||
|
||||
@WrapOperation(
|
||||
method = "rideTick()V",
|
||||
at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;wantsToStopRiding()Z")
|
||||
)
|
||||
public boolean delegateDismountToController(Player instance, Operation<Boolean> original) {
|
||||
if (this.getVehicle() instanceof Rideable vehicle) {
|
||||
return vehicle.getRiding().dismountOnShift() && original.call(instance);
|
||||
}
|
||||
return original.call(instance);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* 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.client.render.ClientPlayerIcon;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import net.minecraft.client.player.AbstractClientPlayer;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.client.renderer.entity.player.PlayerRenderer;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(PlayerRenderer.class)
|
||||
public class PlayerRendererMixin {
|
||||
|
||||
@Inject(method = "render", at = @At(value = "TAIL"))
|
||||
public void renderPlayer(AbstractClientPlayer player, float f, float g, PoseStack poseStack, MultiBufferSource multiBufferSource, int i, CallbackInfo ci) {
|
||||
ClientPlayerIcon.Companion.onRenderPlayer(player);
|
||||
}
|
||||
}
|
||||
@@ -1,151 +0,0 @@
|
||||
/*
|
||||
* 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.client;
|
||||
|
||||
import com.cobblemon.mod.common.Rollable;
|
||||
import com.cobblemon.mod.common.api.riding.Rideable;
|
||||
import com.cobblemon.mod.common.api.riding.Seat;
|
||||
import com.cobblemon.mod.common.client.entity.PokemonClientDelegate;
|
||||
import com.cobblemon.mod.common.client.render.MatrixWrapper;
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
|
||||
import net.minecraft.client.Camera;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.joml.Matrix3f;
|
||||
import org.joml.Quaternionf;
|
||||
import org.joml.Vector3f;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(Camera.class)
|
||||
public abstract class CameraMixin {
|
||||
@Shadow @Final private static float DEFAULT_CAMERA_DISTANCE;
|
||||
|
||||
@Shadow private Entity entity;
|
||||
@Shadow @Final private Quaternionf rotation;
|
||||
@Shadow @Final private Vector3f forwards;
|
||||
@Shadow @Final private Vector3f up;
|
||||
@Shadow @Final private Vector3f left;
|
||||
@Shadow private float xRot;
|
||||
@Shadow private float yRot;
|
||||
|
||||
@Shadow public abstract float getXRot();
|
||||
@Shadow public abstract float getYRot();
|
||||
|
||||
@Shadow private Vec3 position;
|
||||
@Shadow private float eyeHeight;
|
||||
@Shadow private float eyeHeightOld;
|
||||
|
||||
@Unique private float returnTimer = 0;
|
||||
@Unique private float rollAngleStart = 0;
|
||||
@Unique Minecraft minecraft = Minecraft.getInstance();
|
||||
|
||||
@Unique boolean disableRollableCameraDebug = false;
|
||||
|
||||
@Inject(method = "setRotation", at = @At("HEAD"), cancellable = true)
|
||||
public void open_camera$setRotation(float f, float g, CallbackInfo ci) {
|
||||
if (!(this.entity instanceof Rollable rollable) || disableRollableCameraDebug) return;
|
||||
if (!rollable.shouldRoll() && rollable.getOrientation() != null) {
|
||||
if(this.returnTimer < 1) {
|
||||
//Rotation is taken from entity since we no longer handle mouse ourselves
|
||||
//Stops a period of time when you can't input anything.
|
||||
rollable.getOrientation().set(
|
||||
new Matrix3f()
|
||||
.rotateY((float) Math.toRadians(180 - this.entity.getYRot()))
|
||||
.rotateX((float) Math.toRadians(-this.entity.getXRot()))
|
||||
);
|
||||
if(rollAngleStart == 0){
|
||||
this.returnTimer = 1;
|
||||
rollable.clearRotation();
|
||||
return;
|
||||
}
|
||||
rollable.getOrientation().rotateZ((float) Math.toRadians(-rollAngleStart*(1-returnTimer)));
|
||||
applyRotation();
|
||||
this.returnTimer += .05F;
|
||||
ci.cancel();
|
||||
} else {
|
||||
this.returnTimer = 1;
|
||||
rollable.clearRotation();
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (rollable.getOrientation() == null) return;
|
||||
applyRotation();
|
||||
|
||||
this.returnTimer = 0;
|
||||
this.rollAngleStart = rollable.getRoll();
|
||||
ci.cancel();
|
||||
}
|
||||
|
||||
//If you want to move this to a delagate you need an AW for position
|
||||
@WrapOperation(method = "setup", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/Camera;setPosition(DDD)V"))
|
||||
public void positionCamera(Camera instance, double x, double y, double z, Operation<Void> original){
|
||||
Entity entity = instance.getEntity();
|
||||
Entity vehicle = entity.getVehicle();
|
||||
|
||||
if(vehicle instanceof Rideable){
|
||||
//RidingCameraDelagate.INSTANCE.positionCamera(instance, x, y, z, original);
|
||||
if(!(vehicle instanceof PokemonEntity)){
|
||||
original.call(instance, x, y, z);
|
||||
return;
|
||||
}
|
||||
PokemonEntity pokemon = (PokemonEntity) vehicle;
|
||||
|
||||
int seatIndex = pokemon.getPassengers().indexOf(entity);
|
||||
Seat seat = pokemon.getSeats().get(seatIndex);
|
||||
PokemonClientDelegate delegate = (PokemonClientDelegate) pokemon.getDelegate();
|
||||
MatrixWrapper locator = delegate.getLocatorStates().get(seat.getLocator());
|
||||
if(locator == null){
|
||||
original.call(instance, x, y, z);
|
||||
return;
|
||||
}
|
||||
|
||||
Vec3 locatorOffset = new Vec3(locator.getMatrix().getTranslation(new Vector3f()));
|
||||
|
||||
Vec3 entityPos = new Vec3(
|
||||
Mth.lerp(instance.getPartialTickTime(), pokemon.xOld, pokemon.getX()),
|
||||
Mth.lerp(instance.getPartialTickTime(), pokemon.yOld, pokemon.getY()),
|
||||
Mth.lerp(instance.getPartialTickTime(), pokemon.zOld, pokemon.getZ())
|
||||
);
|
||||
|
||||
Rollable rollable = (Rollable) entity;
|
||||
float currEyeHeight = Mth.lerp(instance.getPartialTickTime(), eyeHeightOld, eyeHeight);
|
||||
Matrix3f orientation = rollable.shouldRoll() && rollable.getOrientation() != null ? rollable.getOrientation() : new Matrix3f();
|
||||
Vec3 rotatedEyeHeight = new Vec3(orientation.transform(new Vector3f(0f, currEyeHeight, 0f)));
|
||||
|
||||
position = locatorOffset.add(entityPos).add(rotatedEyeHeight);
|
||||
} else {
|
||||
original.call(instance, x, y, z);
|
||||
}
|
||||
}
|
||||
|
||||
@Unique
|
||||
private void applyRotation(){
|
||||
if (!(this.entity instanceof Rollable rollable) || rollable.getOrientation() == null) return;
|
||||
var newRotation = rollable.getOrientation().normal(new Matrix3f()).getNormalizedRotation(new Quaternionf());
|
||||
if (this.minecraft.options.getCameraType().isMirrored()) {
|
||||
newRotation.rotateY((float)Math.toRadians(180));
|
||||
}
|
||||
this.rotation.set(newRotation);
|
||||
this.xRot = rollable.getPitch();
|
||||
this.yRot = rollable.getYaw();
|
||||
this.forwards.set(rollable.getForwardVector());
|
||||
this.up.set(rollable.getUpVector());
|
||||
this.left.set(rollable.getLeftVector());
|
||||
}
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
/*
|
||||
* 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.client;
|
||||
|
||||
import com.cobblemon.mod.common.client.render.player.MountedPlayerRenderer;
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
|
||||
import net.minecraft.client.model.HumanoidModel;
|
||||
import net.minecraft.client.model.geom.ModelPart;
|
||||
import net.minecraft.client.player.AbstractClientPlayer;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
@Mixin(HumanoidModel.class)
|
||||
public class HumanoidModelMixin {
|
||||
@Unique HashMap<String, ModelPart> relevantPartsByName = new HashMap<>();
|
||||
|
||||
@Shadow @Final
|
||||
public ModelPart head;
|
||||
@Shadow @Final
|
||||
public ModelPart rightArm;
|
||||
@Shadow @Final
|
||||
public ModelPart leftArm;
|
||||
@Shadow @Final
|
||||
public ModelPart rightLeg;
|
||||
@Shadow @Final
|
||||
public ModelPart leftLeg;
|
||||
|
||||
@Inject(method = "setupAnim*", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/model/geom/ModelPart;copyFrom(Lnet/minecraft/client/model/geom/ModelPart;)V", shift = At.Shift.BEFORE))
|
||||
public void cobblemon$animateRiders(
|
||||
LivingEntity entity,
|
||||
float limbSwing,
|
||||
float limbSwingAmount,
|
||||
float ageInTicks,
|
||||
float netHeadYaw,
|
||||
float headPitch,
|
||||
CallbackInfo ci
|
||||
) {
|
||||
if (relevantPartsByName.isEmpty()) {
|
||||
relevantPartsByName.put("arm_left", leftArm);
|
||||
relevantPartsByName.put("arm_right", rightArm);
|
||||
relevantPartsByName.put("leg_left", leftLeg);
|
||||
relevantPartsByName.put("leg_right", rightLeg);
|
||||
relevantPartsByName.put("head", head);
|
||||
}
|
||||
|
||||
Entity vehicle = entity.getVehicle();
|
||||
if (vehicle instanceof PokemonEntity && entity instanceof AbstractClientPlayer) {
|
||||
MountedPlayerRenderer.INSTANCE.animate((PokemonEntity) vehicle, (AbstractClientPlayer) entity, relevantPartsByName, netHeadYaw, headPitch, ageInTicks, limbSwing, limbSwingAmount);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
/*
|
||||
* 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.client;
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonNetwork;
|
||||
import com.cobblemon.mod.common.Rollable;
|
||||
import com.cobblemon.mod.common.net.messages.server.orientation.C2SUpdateOrientationPacket;
|
||||
import net.minecraft.client.player.LocalPlayer;
|
||||
import org.joml.Matrix3f;
|
||||
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.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(LocalPlayer.class)
|
||||
public class LocalPlayerMixin {
|
||||
|
||||
@Unique Matrix3f cobblemon$lastOrientation;
|
||||
|
||||
@Inject(method = "sendPosition", at = @At("TAIL"))
|
||||
private void cobblemon_updateRotationMatrix(CallbackInfo ci) {
|
||||
if (!(this instanceof Rollable rollable)) return;
|
||||
if (rollable.getOrientation() == cobblemon$lastOrientation) return;
|
||||
cobblemon$lastOrientation = rollable.getOrientation() != null ? new Matrix3f(rollable.getOrientation()) : null;
|
||||
CobblemonNetwork.INSTANCE.sendToServer(new C2SUpdateOrientationPacket(rollable.getOrientation()));
|
||||
}
|
||||
|
||||
@Inject(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/multiplayer/ClientPacketListener;send(Lnet/minecraft/network/protocol/Packet;)V"))
|
||||
private void cobblemon_updateRotationMatrixPassenger(CallbackInfo ci) {
|
||||
if (!(this instanceof Rollable rollable)) return;
|
||||
if (rollable.getOrientation() == cobblemon$lastOrientation) return;
|
||||
cobblemon$lastOrientation = rollable.getOrientation() != null ? new Matrix3f(rollable.getOrientation()) : null;
|
||||
CobblemonNetwork.INSTANCE.sendToServer(new C2SUpdateOrientationPacket(rollable.getOrientation()));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
/*
|
||||
* 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.client;
|
||||
import com.cobblemon.mod.common.api.riding.Rideable;
|
||||
import com.cobblemon.mod.common.api.riding.RidingManager;
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
|
||||
import net.minecraft.client.model.PlayerModel;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(PlayerModel.class)
|
||||
public class PlayerModelMixin {
|
||||
@Inject(method = "setupAnim(Lnet/minecraft/world/entity/LivingEntity;FFFFF)V", at = @At(value = "HEAD"))
|
||||
private void cobblemon$setHeadRotation(LivingEntity entity, float limbSwing, float limbSwingAmount, float ageInTicks, float netHeadYaw, float headPitch, CallbackInfo ci){
|
||||
if (!(entity instanceof Player)) return;
|
||||
Entity vehicle = entity.getVehicle();
|
||||
|
||||
if (!(vehicle instanceof PokemonEntity)) return;
|
||||
RidingManager ridingManager = ((Rideable) vehicle).getRiding();
|
||||
if (ridingManager.shouldRotatePlayerHead((PokemonEntity) vehicle)) return;
|
||||
|
||||
netHeadYaw = 0f;
|
||||
headPitch = 0f;
|
||||
}
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
/*
|
||||
* 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.client;
|
||||
|
||||
import com.cobblemon.mod.common.client.render.ClientPlayerIcon;
|
||||
import com.cobblemon.mod.common.client.render.player.MountedPlayerRenderer;
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import net.minecraft.client.player.AbstractClientPlayer;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.client.renderer.entity.player.PlayerRenderer;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(PlayerRenderer.class)
|
||||
public class PlayerRendererMixin {
|
||||
@Inject(method = "render(Lnet/minecraft/world/entity/LivingEntity;FFLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;I)V", at = @At(value = "TAIL"))
|
||||
public void cobblemon$clientPlayerIcon(LivingEntity entity, float entityYaw, float partialTicks, PoseStack poseStack, MultiBufferSource buffer, int packedLight, CallbackInfo ci) {
|
||||
ClientPlayerIcon.Companion.onRenderPlayer((Player) entity);
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "setupRotations(Lnet/minecraft/client/player/AbstractClientPlayer;Lcom/mojang/blaze3d/vertex/PoseStack;FFFF)V",
|
||||
at = @At("HEAD")
|
||||
)
|
||||
private void cobblemon$modifyRoll(AbstractClientPlayer player, PoseStack poseStack, float a, float b, float partialTicks, float i, CallbackInfo ci) {
|
||||
if (player.isPassenger()) {
|
||||
var vehicle = player.getVehicle();
|
||||
if (vehicle instanceof PokemonEntity entity) {
|
||||
MountedPlayerRenderer.INSTANCE.render(player, entity, poseStack, a, b, partialTicks, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
/*
|
||||
* 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.entity;
|
||||
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(Entity.class)
|
||||
public abstract class EntityMixin {
|
||||
|
||||
@Shadow @Nullable public abstract Entity getVehicle();
|
||||
|
||||
@Inject(method = "updateInWaterStateAndDoWaterCurrentPushing", at = @At(value = "FIELD", target = "Lnet/minecraft/world/entity/Entity;wasTouchingWater:Z", ordinal = 1), cancellable = true)
|
||||
public void cobblemon$verifyActuallyTouchingWater(CallbackInfo ci) {
|
||||
if(this.getVehicle() instanceof PokemonEntity) {
|
||||
ci.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
/*
|
||||
* 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.riding;
|
||||
|
||||
import net.minecraft.client.player.LocalPlayer;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
|
||||
|
||||
@Mixin(LocalPlayer.class)
|
||||
public class JetMixin {
|
||||
|
||||
@Shadow private int jumpRidingTicks;
|
||||
@Shadow private float jumpRidingScale;
|
||||
|
||||
private float jetStrength;
|
||||
|
||||
// @Redirect(method = "tickMovement", at = @At(target = "Lnet/minecraft/entity/JumpingMount;getJumpCooldown()I", value = "INVOKE"))
|
||||
// public int cobblemon$tryHandlingJet(JumpingMount mount) {
|
||||
// if(mount instanceof PokemonEntity pokemon) {
|
||||
//// if(pokemon.getDataTracker().get(PokemonEntity.MOVING)) {
|
||||
//// ++this.field_3938;
|
||||
//// if (this.field_3938 < 11) {
|
||||
//// this.jetStrength = (float) this.field_3938 * 0.1F;
|
||||
//// } else {
|
||||
// this.mountJumpStrength = 0.8F + 2.0F / (float) (this.field_3938 - 9) * 0.1F;
|
||||
//// }
|
||||
//// } else {
|
||||
//// this.field_3938 = 0;
|
||||
//// this.jetStrength = 0;
|
||||
//// }
|
||||
//
|
||||
//// return -1;
|
||||
// }
|
||||
//
|
||||
// return 0;
|
||||
// }
|
||||
|
||||
@Inject(
|
||||
method = "aiStep",
|
||||
at = @At(
|
||||
target = "Lnet/minecraft/client/player/LocalPlayer;jumpRidingScale:F",
|
||||
value = "FIELD",
|
||||
ordinal = 4,
|
||||
shift = At.Shift.AFTER
|
||||
),
|
||||
locals = LocalCapture.CAPTURE_FAILSOFT
|
||||
)
|
||||
public void cobblemon$applyCachedJumpStrength(CallbackInfo ci) {
|
||||
this.jumpRidingScale = this.jetStrength;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -80,7 +80,6 @@ import com.cobblemon.mod.common.net.messages.client.settings.ServerSettingsPacke
|
||||
import com.cobblemon.mod.common.permission.LaxPermissionValidator
|
||||
import com.cobblemon.mod.common.platform.events.PlatformEvents
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.pokemon.aspects.COSMETIC_SLOT_ASPECT
|
||||
import com.cobblemon.mod.common.pokemon.aspects.GENDER_ASPECT
|
||||
import com.cobblemon.mod.common.pokemon.aspects.SHINY_ASPECT
|
||||
import com.cobblemon.mod.common.pokemon.evolution.variants.BlockClickEvolution
|
||||
@@ -279,7 +278,6 @@ object Cobblemon {
|
||||
|
||||
SHINY_ASPECT.register()
|
||||
GENDER_ASPECT.register()
|
||||
COSMETIC_SLOT_ASPECT.register()
|
||||
|
||||
SpeciesFeatures.types["choice"] = ChoiceSpeciesFeatureProvider::class.java
|
||||
SpeciesFeatures.types["flag"] = FlagSpeciesFeatureProvider::class.java
|
||||
|
||||
@@ -36,6 +36,9 @@ object CobblemonBlockEntities : PlatformRegistry<Registry<BlockEntityType<*>>, R
|
||||
@JvmField
|
||||
val PC: BlockEntityType<PCBlockEntity> = this.create("pc", BlockEntityType.Builder.of(::PCBlockEntity, CobblemonBlocks.PC).build(null))
|
||||
|
||||
@JvmField
|
||||
val STADIUM: BlockEntityType<StadiumBlockEntity> = this.create("stadium_terminal", BlockEntityType.Builder.of(::StadiumBlockEntity, CobblemonBlocks.STADIUM).build(null))
|
||||
|
||||
@JvmField
|
||||
val LECTERN: BlockEntityType<LecternBlockEntity> = this.create("lectern", BlockEntityType.Builder.of(::LecternBlockEntity, CobblemonBlocks.LECTERN).build(null))
|
||||
|
||||
|
||||
@@ -354,6 +354,9 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
@JvmField
|
||||
val PC = create("pc", PCBlock(BlockBehaviour.Properties.of().mapColor(MapColor.METAL).sound(SoundType.METAL).pushReaction(PushReaction.BLOCK).strength(2F).noOcclusion().lightLevel { if ((it.getValue(PCBlock.ON) as Boolean) && (it.getValue(PCBlock.PART) == PCBlock.PCPart.TOP)) 10 else 0 }))
|
||||
|
||||
@JvmField
|
||||
val STADIUM = create("stadium_terminal", StadiumBlock(BlockBehaviour.Properties.of().mapColor(MapColor.METAL).sound(SoundType.METAL).pushReaction(PushReaction.BLOCK).strength(2F)))
|
||||
|
||||
@JvmField
|
||||
val LECTERN = create("lectern", LecternBlock(BlockBehaviour.Properties.of().mapColor(MapColor.WOOD).instrument(NoteBlockInstrument.BASS).sound(SoundType.WOOD).strength(2.5F).ignitedByLava()))
|
||||
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
import com.cobblemon.mod.common.api.conditional.RegistryLikeCondition
|
||||
import com.cobblemon.mod.common.api.data.JsonDataRegistry
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
|
||||
import com.cobblemon.mod.common.api.reactive.SimpleObservable
|
||||
import com.cobblemon.mod.common.net.messages.client.data.CosmeticItemAssignmentSyncPacket
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.pokemon.cosmetic.CosmeticItemAssignment
|
||||
import com.cobblemon.mod.common.util.adapters.IdentifierAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.ItemLikeConditionAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.PokemonPropertiesAdapter
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.google.gson.GsonBuilder
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import net.minecraft.core.RegistryAccess
|
||||
import net.minecraft.core.registries.Registries
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.server.packs.PackType
|
||||
import net.minecraft.world.item.Item
|
||||
import net.minecraft.world.item.ItemStack
|
||||
|
||||
object CobblemonCosmeticItems : JsonDataRegistry<CosmeticItemAssignment> {
|
||||
override val id = cobblemonResource("cosmetic_items")
|
||||
override val type = PackType.SERVER_DATA
|
||||
override val observable = SimpleObservable<CobblemonCosmeticItems>()
|
||||
override val typeToken = TypeToken.get(CosmeticItemAssignment::class.java)
|
||||
override val resourcePath = "cosmetic_items"
|
||||
|
||||
override val gson = GsonBuilder()
|
||||
.setPrettyPrinting()
|
||||
.registerTypeAdapter(PokemonProperties::class.java, PokemonPropertiesAdapter(saveLong = false))
|
||||
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Item::class.java).type, ItemLikeConditionAdapter)
|
||||
.registerTypeAdapter(ResourceLocation::class.java, IdentifierAdapter)
|
||||
.create()
|
||||
|
||||
val cosmeticItems = mutableListOf<CosmeticItemAssignment>()
|
||||
|
||||
override fun reload(data: Map<ResourceLocation, CosmeticItemAssignment>) {
|
||||
cosmeticItems.clear()
|
||||
data.entries.forEach { (id, value) -> value.id = id }
|
||||
cosmeticItems.addAll(data.values)
|
||||
}
|
||||
|
||||
override fun sync(player: ServerPlayer) {
|
||||
CosmeticItemAssignmentSyncPacket(cosmeticItems).sendToPlayer(player)
|
||||
}
|
||||
|
||||
fun findValidForPokemon(pokemon: Pokemon) = cosmeticItems.filter { it.pokemon.any { it.matches(pokemon) } }
|
||||
fun findValidCosmeticForPokemonAndItem(registryAccess: RegistryAccess, pokemon: Pokemon, itemStack: ItemStack) = cosmeticItems
|
||||
.filter { it.pokemon.any { it.matches(pokemon) } }
|
||||
.flatMap { it.cosmeticItems }
|
||||
.firstOrNull { it.consumedItem.fits(itemStack.item, registryAccess.registryOrThrow(Registries.ITEM)) }
|
||||
}
|
||||
@@ -9,7 +9,6 @@
|
||||
package com.cobblemon.mod.common
|
||||
|
||||
import com.bedrockk.molang.runtime.MoLangRuntime
|
||||
import com.bedrockk.molang.runtime.MoParams
|
||||
import com.bedrockk.molang.runtime.value.MoValue
|
||||
import com.cobblemon.mod.common.CobblemonNetwork.sendPacket
|
||||
import com.cobblemon.mod.common.api.data.DataRegistry
|
||||
@@ -87,20 +86,13 @@ object CobblemonFlows : DataRegistry {
|
||||
observable.emit(this)
|
||||
}
|
||||
|
||||
fun run(
|
||||
eventResourceLocation: ResourceLocation,
|
||||
context: Map<String, MoValue>,
|
||||
functions: Map<String, (MoParams) -> Any> = emptyMap(),
|
||||
cancelable: Cancelable? = null
|
||||
) {
|
||||
fun run(eventResourceLocation: ResourceLocation, context: Map<String, MoValue>, cancelable: Cancelable? = null) {
|
||||
if (cancelable == null) {
|
||||
runtime.environment.query.functions.remove("cancel")
|
||||
} else {
|
||||
runtime.environment.query.addFunction("cancel") { cancelable }
|
||||
}
|
||||
|
||||
functions.forEach { (name, function) -> runtime.environment.query.addFunction(name, function) }
|
||||
|
||||
flows[eventResourceLocation]?.forEach {
|
||||
if (cancelable != null && cancelable.isCanceled) {
|
||||
return
|
||||
|
||||
@@ -272,6 +272,8 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val PC = blockItem("pc", CobblemonBlocks.PC)
|
||||
@JvmField
|
||||
val STADIUM = blockItem("stadium_terminal", CobblemonBlocks.STADIUM)
|
||||
@JvmField
|
||||
val PASTURE = blockItem("pasture", CobblemonBlocks.PASTURE)
|
||||
@JvmField
|
||||
val DISPLAY_CASE = blockItem("display_case", CobblemonBlocks.DISPLAY_CASE)
|
||||
|
||||
@@ -47,14 +47,7 @@ import com.cobblemon.mod.common.client.net.storage.party.SetPartyPokemonHandler
|
||||
import com.cobblemon.mod.common.client.net.storage.party.SetPartyReferenceHandler
|
||||
import com.cobblemon.mod.common.client.net.storage.pc.*
|
||||
import com.cobblemon.mod.common.client.net.toast.ToastPacketHandler
|
||||
import com.cobblemon.mod.common.client.net.trade.TradeAcceptanceChangedHandler
|
||||
import com.cobblemon.mod.common.client.net.trade.TradeCancelledHandler
|
||||
import com.cobblemon.mod.common.client.net.trade.TradeCompletedHandler
|
||||
import com.cobblemon.mod.common.client.net.trade.TradeOfferExpiredHandler
|
||||
import com.cobblemon.mod.common.client.net.trade.TradeOfferNotificationHandler
|
||||
import com.cobblemon.mod.common.client.net.trade.TradeProcessStartedHandler
|
||||
import com.cobblemon.mod.common.client.net.trade.TradeStartedHandler
|
||||
import com.cobblemon.mod.common.client.net.trade.TradeUpdatedHandler
|
||||
import com.cobblemon.mod.common.client.net.trade.*
|
||||
import com.cobblemon.mod.common.net.PacketRegisterInfo
|
||||
import com.cobblemon.mod.common.net.messages.client.PlayerInteractOptionsPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.SetClientPlayerDataPacket
|
||||
@@ -94,41 +87,17 @@ import com.cobblemon.mod.common.net.messages.client.storage.party.InitializePart
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.party.MoveClientPartyPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.party.SetPartyPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.party.SetPartyReferencePacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.ClosePCPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.InitializePCPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.MoveClientPCPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.OpenPCPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.RenamePCBoxPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.SetPCBoxPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.SetPCPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.*
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.wallpaper.ChangePCBoxWallpaperPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.wallpaper.RequestPCBoxWallpapersPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.wallpaper.SetPCBoxWallpapersPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.toast.ToastPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.TradeAcceptanceChangedPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.TradeCancelledPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.TradeCompletedPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.TradeOfferExpiredPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.TradeOfferNotificationPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.TradeProcessStartedPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.TradeStartedPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.TradeUpdatedPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.*
|
||||
import com.cobblemon.mod.common.net.messages.client.ui.InteractPokemonUIPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.ui.PokedexUIPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.ui.SummaryUIPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.BattleChallengePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.BattleChallengeResponsePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.BenchMovePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.RequestMoveSwapPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.RequestPlayerInteractionsPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.SelectStarterPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.SendOutPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.battle.BattleSelectActionsPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.battle.BattleTeamLeavePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.battle.BattleTeamRequestPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.battle.BattleTeamResponsePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.battle.RemoveSpectatorPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.battle.SpectateBattlePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.*
|
||||
import com.cobblemon.mod.common.net.messages.server.battle.*
|
||||
import com.cobblemon.mod.common.net.messages.server.block.AdjustBlockEntityViewerCountPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.callback.move.MoveSelectCancelledPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.callback.move.MoveSelectedPacket
|
||||
@@ -139,14 +108,12 @@ import com.cobblemon.mod.common.net.messages.server.callback.partymove.PartyPoke
|
||||
import com.cobblemon.mod.common.net.messages.server.dialogue.EscapeDialoguePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.dialogue.InputToDialoguePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.npc.SaveNPCPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.orientation.C2SUpdateOrientationPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pasture.PasturePokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pasture.UnpastureAllPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pasture.UnpasturePokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pokedex.scanner.FinishScanningPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pokedex.scanner.StartScanningPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pokemon.interact.InteractPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pokemon.update.SetItemHiddenPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pokemon.update.SetNicknamePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pokemon.update.evolution.AcceptEvolutionPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.starter.RequestStarterScreenPacket
|
||||
@@ -154,22 +121,19 @@ import com.cobblemon.mod.common.net.messages.server.storage.SwapPCPartyPokemonPa
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.party.MovePartyPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.party.ReleasePartyPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.party.SwapPartyPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.pc.*
|
||||
import com.cobblemon.mod.common.net.messages.server.trade.AcceptTradeRequestPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.trade.CancelTradePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.trade.ChangeTradeAcceptancePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.trade.OfferTradePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.trade.PerformTradePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.trade.UpdateTradeOfferPacket
|
||||
import com.cobblemon.mod.common.net.serverhandling.ChallengeHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.ChallengeResponseHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.RequestInteractionsHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.battle.BattleSelectActionsHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.battle.RemoveSpectatorHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.battle.SpectateBattleHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.battle.TeamLeaveHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.battle.TeamRequestHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.battle.TeamRequestResponseHandler
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.pc.MovePCPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.pc.MovePCPokemonToPartyPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.pc.MovePartyPokemonToPCPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.pc.PCBoxWallpapersPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.pc.ReleasePCPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.pc.RequestChangePCBoxWallpaperPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.pc.RequestRenamePCBoxPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.pc.SortPCBoxPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.pc.SwapPCPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.pc.UnlinkPlayerFromPCPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.trade.*
|
||||
import com.cobblemon.mod.common.net.serverhandling.*
|
||||
import com.cobblemon.mod.common.net.serverhandling.battle.*
|
||||
import com.cobblemon.mod.common.net.serverhandling.block.AdjustBlockEntityViewerCountHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.callback.move.MoveSelectCancelledHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.callback.move.MoveSelectedHandler
|
||||
@@ -181,14 +145,12 @@ import com.cobblemon.mod.common.net.serverhandling.dialogue.EscapeDialogueHandle
|
||||
import com.cobblemon.mod.common.net.serverhandling.dialogue.InputToDialogueHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.evolution.AcceptEvolutionHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.npc.SaveNPCHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.orientation.OrientationPacketHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.pasture.PasturePokemonHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.pasture.UnpastureAllPokemonHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.pasture.UnpasturePokemonHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.pokedex.scanner.FinishScanningHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.pokedex.scanner.StartScanningHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.pokemon.interact.InteractPokemonHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.pokemon.update.SetItemHiddenHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.pokemon.update.SetNicknameHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.starter.RequestStarterScreenHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.starter.SelectStarterPacketHandler
|
||||
@@ -200,12 +162,7 @@ import com.cobblemon.mod.common.net.serverhandling.storage.party.MovePartyPokemo
|
||||
import com.cobblemon.mod.common.net.serverhandling.storage.party.ReleasePCPokemonHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.storage.party.SwapPartyPokemonHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.storage.pc.*
|
||||
import com.cobblemon.mod.common.net.serverhandling.trade.AcceptTradeRequestHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.trade.CancelTradeHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.trade.ChangeTradeAcceptanceHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.trade.OfferTradeHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.trade.PerformTradeHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.trade.UpdateTradeOfferHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.trade.*
|
||||
import com.cobblemon.mod.common.util.server
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
|
||||
@@ -218,11 +175,13 @@ import net.minecraft.server.level.ServerPlayer
|
||||
* @since November 27th, 2021
|
||||
*/
|
||||
object CobblemonNetwork {
|
||||
//private val logger = LogUtils.getLogger()
|
||||
|
||||
fun ServerPlayer.sendPacket(packet: NetworkPacket<*>) {
|
||||
sendPacketToPlayer(this, packet)
|
||||
}
|
||||
fun sendToServer(packet: NetworkPacket<*>) {
|
||||
//logger.info("[C->S] ${packet.type()}")
|
||||
Cobblemon.implementation.networkManager.sendToServer(packet)
|
||||
}
|
||||
fun sendToAllPlayers(packet: NetworkPacket<*>) = sendPacketToPlayers(server()!!.playerList.players, packet)
|
||||
@@ -261,7 +220,6 @@ object CobblemonNetwork {
|
||||
list.add(PacketRegisterInfo(TeraTypeUpdatePacket.ID, TeraTypeUpdatePacket::decode, PokemonUpdatePacketHandler()))
|
||||
list.add(PacketRegisterInfo(DmaxLevelUpdatePacket.ID, DmaxLevelUpdatePacket::decode, PokemonUpdatePacketHandler()))
|
||||
list.add(PacketRegisterInfo(GmaxFactorUpdatePacket.ID, GmaxFactorUpdatePacket::decode, PokemonUpdatePacketHandler()))
|
||||
list.add(PacketRegisterInfo(CosmeticItemUpdatePacket.ID, CosmeticItemUpdatePacket::decode, PokemonUpdatePacketHandler()))
|
||||
|
||||
// Evolution start
|
||||
list.add(PacketRegisterInfo(AddEvolutionPacket.ID, AddEvolutionPacket::decode, PokemonUpdatePacketHandler()))
|
||||
@@ -352,7 +310,6 @@ object CobblemonNetwork {
|
||||
list.add(PacketRegisterInfo(DexEntrySyncPacket.ID, DexEntrySyncPacket::decode, DataRegistrySyncPacketHandler()))
|
||||
list.add(PacketRegisterInfo(FishingBaitRegistrySyncPacket.ID, FishingBaitRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
|
||||
list.add(PacketRegisterInfo(FlowRegistrySyncPacket.ID, FlowRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
|
||||
list.add(PacketRegisterInfo(CosmeticItemAssignmentSyncPacket.ID, CosmeticItemAssignmentSyncPacket::decode, DataRegistrySyncPacketHandler()))
|
||||
|
||||
// Effects
|
||||
list.add(PacketRegisterInfo(SpawnSnowstormParticlePacket.ID, SpawnSnowstormParticlePacket::decode, SpawnSnowstormParticleHandler))
|
||||
@@ -412,7 +369,6 @@ object CobblemonNetwork {
|
||||
val list = mutableListOf<PacketRegisterInfo<*>>()
|
||||
// Pokemon Update Packets
|
||||
list.add(PacketRegisterInfo(SetNicknamePacket.ID, SetNicknamePacket::decode, SetNicknameHandler))
|
||||
list.add(PacketRegisterInfo(SetItemHiddenPacket.ID, SetItemHiddenPacket::decode, SetItemHiddenHandler))
|
||||
|
||||
// Evolution Packets
|
||||
list.add(PacketRegisterInfo(AcceptEvolutionPacket.ID, AcceptEvolutionPacket::decode, AcceptEvolutionHandler))
|
||||
@@ -499,13 +455,11 @@ object CobblemonNetwork {
|
||||
// NPC packets
|
||||
list.add(PacketRegisterInfo(SaveNPCPacket.ID, SaveNPCPacket::decode, SaveNPCHandler))
|
||||
|
||||
// Orientation packet(s)
|
||||
list.add(PacketRegisterInfo(C2SUpdateOrientationPacket.ID, C2SUpdateOrientationPacket::decode, OrientationPacketHandler))
|
||||
|
||||
return list
|
||||
}
|
||||
|
||||
fun sendPacketToPlayer(player: ServerPlayer, packet: NetworkPacket<*>) {
|
||||
//logger.info("[S->C] ${packet.type()}")
|
||||
Cobblemon.implementation.networkManager.sendPacketToPlayer(player, packet)
|
||||
}
|
||||
}
|
||||
}
|
||||
+25
-1
@@ -33,7 +33,7 @@ class LevelUpCriterion(
|
||||
}
|
||||
|
||||
override fun matches(player: ServerPlayer, context: LevelUpContext): Boolean {
|
||||
val preEvo = context.pokemon.preEvolution != null
|
||||
val preEvo = context.pokemon.preEvolution == null
|
||||
val hasEvolution = !context.pokemon.evolutions.none()
|
||||
var evolutionCheck = true
|
||||
if (preEvo || hasEvolution) {
|
||||
@@ -43,3 +43,27 @@ class LevelUpCriterion(
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*class LevelUpCriterionCondition(id: Identifier, entity: LootContextPredicate) : SimpleCriterionCondition<LevelUpContext>(id, entity) {
|
||||
var level = 0
|
||||
var evolved = true
|
||||
override fun toJson(json: JsonObject) {
|
||||
json.addProperty("level", level)
|
||||
json.addProperty("has_evolved", evolved)
|
||||
}
|
||||
|
||||
override fun fromJson(json: JsonObject) {
|
||||
level = json.get("level")?.asInt ?: 0
|
||||
evolved = json.get("has_evolved")?.asBoolean ?: true
|
||||
}
|
||||
|
||||
override fun matches(player: ServerPlayer, context: LevelUpContext): Boolean {
|
||||
val preEvo = context.pokemon.preEvolution == null
|
||||
val hasEvolution = !context.pokemon.evolutions.none()
|
||||
var evolutionCheck = true
|
||||
if (preEvo || hasEvolution) {
|
||||
evolutionCheck = !(preEvo == hasEvolution)
|
||||
}
|
||||
return level == context.level && evolutionCheck == evolved
|
||||
}
|
||||
}*/
|
||||
-10
@@ -8,9 +8,6 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.battles.interpreter
|
||||
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.bedrockk.molang.runtime.value.StringValue
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.queryStructOf
|
||||
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
|
||||
|
||||
/**
|
||||
@@ -33,13 +30,6 @@ interface BattleContext {
|
||||
/** The [BattlePokemon] that directly or indirectly caused this [BattleContext]. */
|
||||
val origin: BattlePokemon?
|
||||
|
||||
fun getStruct() = queryStructOf(
|
||||
"type" to { StringValue(type.name) },
|
||||
"origin" to { origin?.struct ?: DoubleValue(0.0) },
|
||||
"id" to { StringValue(id) },
|
||||
"turn_created" to { DoubleValue(turn.toDouble()) }
|
||||
)
|
||||
|
||||
/**
|
||||
* The type of [BattleContext].
|
||||
*
|
||||
|
||||
@@ -99,6 +99,7 @@ class Berry(
|
||||
val weight: Float,
|
||||
val boneMealChance: Float
|
||||
) {
|
||||
|
||||
@Transient
|
||||
var identifier: ResourceLocation = identifier
|
||||
internal set
|
||||
@@ -158,7 +159,7 @@ class Berry(
|
||||
* Calculates the yield for a berry tree being planted or replanted after a life cycle.
|
||||
* Triggers [BerryYieldCalculationEvent].
|
||||
*
|
||||
* @param world The [Level] the tree is present in.
|
||||
* @param world The [World] the tree is present in.
|
||||
* @param state The [BlockState] of the tree.
|
||||
* @param pos The [BlockPos] of the tree.
|
||||
* @param placer The [LivingEntity] tending to the tree, if any.
|
||||
@@ -172,10 +173,9 @@ class Berry(
|
||||
if (BerryBlock.getMulch(treeEntity) == MulchVariant.RICH) {
|
||||
//I hope the upper bound isnt exclusive, especially when there's a method called nextBetweenExclusive
|
||||
// update: it was meant to be exclusive, which caused #1124. I've lowered the upper bound from 3 to 2.
|
||||
yield += world.random.nextIntBetweenInclusive(RICH_MULCH_MIN, RICH_MULCH_MAX)
|
||||
yield += world.random.nextIntBetweenInclusive(1, 2)
|
||||
treeEntity.decrementMulchDuration(world, pos, state)
|
||||
}
|
||||
yield = yield.coerceAtMost(growthPoints.size)
|
||||
val event = BerryYieldCalculationEvent(this, world, state, pos, placer, yield, bonus.second)
|
||||
CobblemonEvents.BERRY_YIELD.post(event) { yield = it.yield }
|
||||
return yield
|
||||
@@ -193,7 +193,7 @@ class Berry(
|
||||
*
|
||||
* @return The maximum possible yield.
|
||||
*/
|
||||
fun maxYield() = this.baseYield.last + this.growthFactors.sumOf { it.maxYield() } + RICH_MULCH_MAX
|
||||
fun maxYield() = this.baseYield.last + this.growthFactors.sumOf { it.maxYield() }
|
||||
|
||||
/**
|
||||
* Checks if this berry can mutate with the given [partner].
|
||||
@@ -231,7 +231,6 @@ class Berry(
|
||||
}
|
||||
|
||||
// A cheat since gson doesn't invoke init block
|
||||
// well I actually suspect it does but
|
||||
internal fun validate() {
|
||||
if (this.baseYield.first < 0 || this.baseYield.last < 0) {
|
||||
throw IllegalArgumentException("A berry base yield must be a positive range")
|
||||
@@ -248,6 +247,10 @@ class Berry(
|
||||
}
|
||||
*/
|
||||
this.growthFactors.forEach { it.validateArguments() }
|
||||
val maxYield = this.maxYield()
|
||||
if (this.growthPoints.size < maxYield) {
|
||||
throw IllegalArgumentException("Anchor points must have enough elements for the max possible yield of $maxYield you've provided ${this.growthPoints.size} points")
|
||||
}
|
||||
this.shapedFlower = hashMapOf()
|
||||
this.shapedFruit = hashMapOf()
|
||||
this.sproutShape = this.createAndUniteShapes(this.sproutShapeBoxes)
|
||||
@@ -336,8 +339,6 @@ class Berry(
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val RICH_MULCH_MIN = 1
|
||||
const val RICH_MULCH_MAX = 2
|
||||
|
||||
internal fun decode(buffer: RegistryFriendlyByteBuf): Berry {
|
||||
val identifier = buffer.readIdentifier()
|
||||
|
||||
@@ -15,10 +15,12 @@ package com.cobblemon.mod.common.api.berry
|
||||
* @author Licious
|
||||
* @since November 28th, 2022
|
||||
*/
|
||||
enum class Flavor(val colour: Int) {
|
||||
SPICY(0x00FF00),
|
||||
DRY(0xFF0000),
|
||||
SWEET(0x0000FF),
|
||||
BITTER(0xFFFF00),
|
||||
SOUR(0xFF00FF);
|
||||
enum class Flavor {
|
||||
|
||||
SPICY,
|
||||
DRY,
|
||||
SWEET,
|
||||
BITTER,
|
||||
SOUR
|
||||
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.conditional
|
||||
|
||||
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
|
||||
import com.cobblemon.mod.common.util.codec.CodecUtils
|
||||
import com.mojang.serialization.Codec
|
||||
import net.minecraft.core.Registry
|
||||
import net.minecraft.core.registries.Registries
|
||||
import net.minecraft.resources.ResourceKey
|
||||
import net.minecraft.tags.TagKey
|
||||
|
||||
val ITEM_REGISTRY_LIKE_CODEC = makeCodecForRegistryLikeCondition("item", Registries.ITEM)
|
||||
|
||||
fun <T : Any> makeCodecForRegistryLikeCondition(name: String, registryKey: ResourceKey<Registry<T>>): Codec<RegistryLikeCondition<T>> {
|
||||
return CodecUtils.createByStringCodec(
|
||||
from = { str ->
|
||||
if (str.startsWith("#")) {
|
||||
return@createByStringCodec RegistryLikeTagCondition<T>(TagKey.create(registryKey, str.substring(1).asIdentifierDefaultingNamespace()))
|
||||
} else {
|
||||
return@createByStringCodec RegistryLikeIdentifierCondition<T>(str.asIdentifierDefaultingNamespace())
|
||||
}
|
||||
},
|
||||
to = { condition ->
|
||||
if (condition is RegistryLikeTagCondition) {
|
||||
"#${condition.tag.location}"
|
||||
} else {
|
||||
(condition as RegistryLikeIdentifierCondition).identifier.toString()
|
||||
}
|
||||
},
|
||||
errorSupplier = { "Unknown $name condition: $it. Should be # followed by a tag, or $name resource location e.g. #minecraft:ladders or minecraft:grass_block." }
|
||||
)
|
||||
}
|
||||
+2
-2
@@ -26,13 +26,13 @@ open class RegistryLikeTagCondition<T : Any>(val tag: TagKey<T>) : RegistryLikeC
|
||||
companion object {
|
||||
const val PREFIX = "#"
|
||||
fun <T : Any> resolver(
|
||||
resourceKey: ResourceKey<Registry<T>>,
|
||||
ResourceKey: ResourceKey<Registry<T>>,
|
||||
constructor: (TagKey<T>) -> RegistryLikeTagCondition<T>
|
||||
): (JsonElement) -> RegistryLikeTagCondition<T>? = {
|
||||
val firstSymbol = it.asString.substring(0, 1)
|
||||
if (firstSymbol == PREFIX) {
|
||||
val identifier = ResourceLocation.parse(it.asString.substring(1))
|
||||
constructor(TagKey.create(resourceKey, identifier))
|
||||
constructor(TagKey.create(ResourceKey, identifier))
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
@@ -11,8 +11,6 @@ package com.cobblemon.mod.common.api.entity
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import net.minecraft.world.damagesource.DamageSource
|
||||
import net.minecraft.world.entity.Entity
|
||||
import net.minecraft.world.entity.Entity.MoveFunction
|
||||
import net.minecraft.world.entity.player.Player
|
||||
|
||||
interface PokemonSideDelegate : EntitySideDelegate<PokemonEntity> {
|
||||
|
||||
@@ -8,10 +8,6 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.events
|
||||
|
||||
import com.bedrockk.molang.runtime.MoParams
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.bedrockk.molang.runtime.value.MoValue
|
||||
|
||||
/**
|
||||
* Something that can be canceled. This is a highly complex class and should only be read by professional engineers.
|
||||
*
|
||||
@@ -25,9 +21,4 @@ abstract class Cancelable {
|
||||
fun cancel() {
|
||||
isCanceled = true
|
||||
}
|
||||
|
||||
val cancelFunc: Pair<String, (MoParams) -> MoValue> = "cancel" to {
|
||||
cancel()
|
||||
DoubleValue.ONE
|
||||
}
|
||||
}
|
||||
@@ -52,7 +52,6 @@ import com.cobblemon.mod.common.api.reactive.EventObservable
|
||||
import com.cobblemon.mod.common.api.reactive.Observable.Companion.filter
|
||||
import com.cobblemon.mod.common.api.reactive.Observable.Companion.map
|
||||
import com.cobblemon.mod.common.api.reactive.SimpleObservable
|
||||
import com.cobblemon.mod.common.api.riding.events.SelectDriverEvent
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
|
||||
@@ -212,10 +211,6 @@ object CobblemonEvents {
|
||||
val HELD_ITEM_PRE = CancelableObservable<HeldItemEvent.Pre>()
|
||||
@JvmField
|
||||
val HELD_ITEM_POST = EventObservable<HeldItemEvent.Post>()
|
||||
@JvmField
|
||||
val COSMETIC_ITEM_PRE = CancelableObservable<HeldItemEvent.Pre>()
|
||||
@JvmField
|
||||
val COSMETIC_ITEM_POST = EventObservable<HeldItemEvent.Post>()
|
||||
|
||||
@JvmField
|
||||
val POKEMON_GAINED = EventObservable<PokemonGainedEvent>()
|
||||
@@ -258,12 +253,4 @@ object CobblemonEvents {
|
||||
val HATCH_EGG_PRE = CancelableObservable<HatchEggEvent.Pre>()
|
||||
@JvmField
|
||||
val HATCH_EGG_POST = EventObservable<HatchEggEvent.Post>()
|
||||
|
||||
// -------------------------------------------------------------------------------------
|
||||
//
|
||||
// Riding
|
||||
//
|
||||
// -------------------------------------------------------------------------------------
|
||||
@JvmField
|
||||
val SELECT_DRIVER = EventObservable<SelectDriverEvent>()
|
||||
}
|
||||
|
||||
+12
-1
@@ -8,12 +8,16 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.events.battles
|
||||
|
||||
import com.bedrockk.molang.runtime.struct.QueryStruct
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.bedrockk.molang.runtime.value.MoValue
|
||||
import com.bedrockk.molang.runtime.value.StringValue
|
||||
import com.cobblemon.mod.common.api.battles.interpreter.BattleContext
|
||||
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
|
||||
import com.cobblemon.mod.common.api.battles.model.actor.ActorType
|
||||
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
|
||||
import com.cobblemon.mod.common.util.asArrayValue
|
||||
import java.util.function.Function
|
||||
|
||||
/**
|
||||
* Event fired when a [BattlePokemon] faints. Exposes the [BattlePokemon] that fainted and the [BattleContext]
|
||||
@@ -33,6 +37,13 @@ data class BattleFaintedEvent(
|
||||
"npcs" to battle.actors.filter { it.type == ActorType.NPC }.asArrayValue { it.struct },
|
||||
"wild_pokemon" to battle.actors.filter { it.type == ActorType.WILD }.asArrayValue { it.struct },
|
||||
"pokemon" to killed.struct,
|
||||
"context" to context.getStruct()
|
||||
"context" to QueryStruct(
|
||||
hashMapOf(
|
||||
"type" to Function { StringValue(context.type.name) },
|
||||
"origin" to Function { context.origin?.struct ?: DoubleValue(0.0) },
|
||||
"id" to Function { StringValue(context.id) },
|
||||
"turn_created" to Function { DoubleValue(context.turn.toDouble()) },
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
-3
@@ -11,7 +11,6 @@ package com.cobblemon.mod.common.api.events.battles
|
||||
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
|
||||
import com.cobblemon.mod.common.api.battles.model.actor.ActorType
|
||||
import com.cobblemon.mod.common.api.events.Cancelable
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.moLangFunctionMap
|
||||
import com.cobblemon.mod.common.util.asArrayValue
|
||||
import net.minecraft.network.chat.MutableComponent
|
||||
|
||||
@@ -31,8 +30,6 @@ data class BattleStartedPreEvent (override val battle: PokemonBattle, var reason
|
||||
"npcs" to battle.actors.filter { it.type == ActorType.NPC }.asArrayValue { it.struct },
|
||||
"wild_pokemon" to battle.actors.filter { it.type == ActorType.WILD }.asArrayValue { it.struct }
|
||||
)
|
||||
|
||||
val functions = moLangFunctionMap(cancelFunc)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+1
-1
@@ -26,7 +26,7 @@ data class TerastallizationEvent(
|
||||
val battle: PokemonBattle,
|
||||
val pokemon: BattlePokemon,
|
||||
val teraType: TeraType
|
||||
) {
|
||||
) {
|
||||
val context = mutableMapOf<String, MoValue>(
|
||||
"battle" to battle.struct,
|
||||
"players" to battle.actors.filter { it.type == ActorType.PLAYER }.asArrayValue { it.struct },
|
||||
|
||||
-36
@@ -8,15 +8,9 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.events.pokeball
|
||||
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.bedrockk.molang.runtime.value.MoValue
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.moLangFunctionMap
|
||||
import com.cobblemon.mod.common.api.pokeball.catching.CaptureContext
|
||||
import com.cobblemon.mod.common.entity.pokeball.EmptyPokeBallEntity
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.util.getBooleanOrNull
|
||||
import com.cobblemon.mod.common.util.getIntOrNull
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
|
||||
@@ -38,34 +32,4 @@ class PokeBallCaptureCalculatedEvent(
|
||||
action(this, thrower)
|
||||
}
|
||||
}
|
||||
|
||||
val context = mutableMapOf<String, MoValue>(
|
||||
"thrower" to thrower.asMostSpecificMoLangValue(),
|
||||
"pokemon" to pokemonEntity.struct,
|
||||
"poke_ball" to pokeBallEntity.struct,
|
||||
"is_successful_capture" to DoubleValue(captureResult.isSuccessfulCapture),
|
||||
"is_critical_capture" to DoubleValue(captureResult.isCriticalCapture),
|
||||
)
|
||||
|
||||
val functions = moLangFunctionMap(
|
||||
"set_shakes" to { params ->
|
||||
val numShakes = params.getInt(0)
|
||||
val successful = params.getBooleanOrNull(1) ?: (numShakes == 4)
|
||||
captureResult = CaptureContext(
|
||||
numberOfShakes = numShakes,
|
||||
isSuccessfulCapture = successful,
|
||||
isCriticalCapture = false
|
||||
)
|
||||
DoubleValue.ONE
|
||||
},
|
||||
"set_critical_capture" to { params ->
|
||||
val numShakes = params.getIntOrNull(0) ?: 1
|
||||
captureResult = CaptureContext(
|
||||
numberOfShakes = numShakes,
|
||||
isSuccessfulCapture = true,
|
||||
isCriticalCapture = true
|
||||
)
|
||||
DoubleValue.ONE
|
||||
}
|
||||
)
|
||||
}
|
||||
+2
-1
@@ -20,7 +20,8 @@ import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
data class FriendshipUpdatedEvent(
|
||||
val pokemon: Pokemon,
|
||||
val newFriendshipInitial: Int
|
||||
) {
|
||||
)
|
||||
{
|
||||
var newFriendship: Int = newFriendshipInitial
|
||||
set(value) {
|
||||
field = value.coerceIn(0, Cobblemon.config.maxPokemonFriendship)
|
||||
|
||||
@@ -9,11 +9,13 @@
|
||||
package com.cobblemon.mod.common.api.events.pokemon
|
||||
|
||||
import com.cobblemon.mod.common.api.events.Cancelable
|
||||
import com.cobblemon.mod.common.api.events.pokemon.HeldItemEvent.Post
|
||||
import com.cobblemon.mod.common.api.events.pokemon.HeldItemEvent.Pre
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import net.minecraft.world.item.ItemStack
|
||||
|
||||
/**
|
||||
* The base for all the events related to held items and cosmetic items.
|
||||
* The base for all the events related to held items.
|
||||
*
|
||||
* @see [Pre]
|
||||
* @see [Post]
|
||||
@@ -26,7 +28,7 @@ interface HeldItemEvent {
|
||||
val pokemon: Pokemon
|
||||
|
||||
/**
|
||||
* Fired at the start of [Pokemon.swapHeldItem] and [Pokemon.swapCosmeticItem].
|
||||
* Fired at the start of [Pokemon.swapHeldItem].
|
||||
*
|
||||
* This event should be used to mutate the results of this transaction.
|
||||
*
|
||||
@@ -42,7 +44,7 @@ interface HeldItemEvent {
|
||||
data class Pre(override val pokemon: Pokemon, var receiving: ItemStack, var returning: ItemStack, var decrement: Boolean) : HeldItemEvent, Cancelable()
|
||||
|
||||
/**
|
||||
* Fired at the end of [Pokemon.swapHeldItem] and [Pokemon.swapCosmeticItem].
|
||||
* Fired at the end of [Pokemon.swapHeldItem].
|
||||
*
|
||||
* @property pokemon The [Pokemon] triggering this event.
|
||||
* @property received The [ItemStack] considered as received and set to the [pokemon]. This is a copy and mutation will not be taken into account.
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
package com.cobblemon.mod.common.api.events.pokemon
|
||||
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.moLangFunctionMap
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
|
||||
/**
|
||||
@@ -24,11 +23,4 @@ class LevelUpEvent(val pokemon: Pokemon, val oldLevel: Int, var newLevel: Int) {
|
||||
"old_level" to DoubleValue(oldLevel.toDouble()),
|
||||
"new_level" to DoubleValue(newLevel.toDouble())
|
||||
)
|
||||
|
||||
val functions = moLangFunctionMap(
|
||||
"set_new_level" to {
|
||||
newLevel = it.getInt(0)
|
||||
DoubleValue.ONE
|
||||
}
|
||||
)
|
||||
}
|
||||
+1
-4
@@ -13,7 +13,6 @@ import com.bedrockk.molang.runtime.value.MoValue
|
||||
import com.bedrockk.molang.runtime.value.StringValue
|
||||
import com.cobblemon.mod.common.api.events.Cancelable
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.moLangFunctionMap
|
||||
import com.cobblemon.mod.common.api.pokedex.AbstractPokedexManager
|
||||
import com.cobblemon.mod.common.api.pokedex.FormDexRecord
|
||||
import com.cobblemon.mod.common.api.pokedex.PokedexEntryProgress
|
||||
@@ -48,9 +47,7 @@ sealed interface PokedexDataChangedEvent {
|
||||
override val knowledge: PokedexEntryProgress,
|
||||
override val playerUUID: UUID,
|
||||
override val record: FormDexRecord
|
||||
) : PokedexDataChangedEvent, Cancelable() {
|
||||
val functions = moLangFunctionMap(cancelFunc)
|
||||
}
|
||||
) : PokedexDataChangedEvent, Cancelable()
|
||||
|
||||
class Post(
|
||||
override val dataSource: PokedexEntityData,
|
||||
|
||||
-8
@@ -8,12 +8,8 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.events.pokemon
|
||||
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.bedrockk.molang.runtime.value.StringValue
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.moLangFunctionMap
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.util.server
|
||||
import java.util.UUID
|
||||
|
||||
data class PokemonGainedEvent(
|
||||
@@ -24,8 +20,4 @@ data class PokemonGainedEvent(
|
||||
"player_id" to StringValue(playerId.toString()),
|
||||
"pokemon" to pokemon.struct
|
||||
)
|
||||
|
||||
val functions = moLangFunctionMap(
|
||||
"player" to { server()?.playerList?.getPlayer(playerId)?.asMoLangValue() ?: DoubleValue.ZERO },
|
||||
)
|
||||
}
|
||||
+1
-11
@@ -8,10 +8,7 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.events.pokemon.evolution
|
||||
|
||||
import com.bedrockk.molang.runtime.value.MoValue
|
||||
import com.cobblemon.mod.common.api.events.Cancelable
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.moLangFunctionMap
|
||||
import com.cobblemon.mod.common.api.pokemon.evolution.Evolution
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
|
||||
@@ -28,11 +25,4 @@ import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
data class EvolutionAcceptedEvent(
|
||||
override val pokemon: Pokemon,
|
||||
override val evolution: Evolution
|
||||
) : Cancelable(), EvolutionEvent {
|
||||
val context = mutableMapOf<String, MoValue>(
|
||||
"pokemon" to pokemon.struct,
|
||||
"evolution" to evolution.asMoLangValue()
|
||||
)
|
||||
|
||||
val functions = moLangFunctionMap(cancelFunc)
|
||||
}
|
||||
) : Cancelable(), EvolutionEvent
|
||||
+1
-8
@@ -8,8 +8,6 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.events.pokemon.evolution
|
||||
|
||||
import com.bedrockk.molang.runtime.value.MoValue
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue
|
||||
import com.cobblemon.mod.common.api.pokemon.evolution.Evolution
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
|
||||
@@ -25,9 +23,4 @@ import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
data class EvolutionCompleteEvent(
|
||||
override val pokemon: Pokemon,
|
||||
override val evolution: Evolution
|
||||
) : EvolutionEvent {
|
||||
val context = mutableMapOf<String, MoValue>(
|
||||
"pokemon" to pokemon.struct,
|
||||
"evolution" to evolution.asMoLangValue()
|
||||
)
|
||||
}
|
||||
) : EvolutionEvent
|
||||
+1
-20
@@ -8,13 +8,8 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.events.pokemon.evolution
|
||||
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.bedrockk.molang.runtime.value.MoValue
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.moLangFunctionMap
|
||||
import com.cobblemon.mod.common.api.pokemon.evolution.Evolution
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.util.getBoolean
|
||||
|
||||
/**
|
||||
* An event fired when [Evolution.test] has been performed.
|
||||
@@ -30,18 +25,4 @@ data class EvolutionTestedEvent(
|
||||
override val evolution: Evolution,
|
||||
val originalResult: Boolean,
|
||||
var result: Boolean
|
||||
) : EvolutionEvent {
|
||||
val context = mutableMapOf<String, MoValue>(
|
||||
"pokemon" to pokemon.struct,
|
||||
"evolution" to evolution.asMoLangValue(),
|
||||
"original_result" to DoubleValue(originalResult),
|
||||
)
|
||||
|
||||
val functions = moLangFunctionMap(
|
||||
"result" to { DoubleValue(result) },
|
||||
"set_result" to {
|
||||
result = it.getBoolean(0)
|
||||
DoubleValue.ONE
|
||||
}
|
||||
)
|
||||
}
|
||||
) : EvolutionEvent
|
||||
|
||||
-3
@@ -16,9 +16,6 @@ import java.util.UUID
|
||||
data class PokemonInteractionGUICreationEvent(
|
||||
val pokemonID: UUID,
|
||||
val mountShoulder: Boolean,
|
||||
val giveHeld: Boolean,
|
||||
val giveCosmetic: Boolean,
|
||||
val canRide: Boolean,
|
||||
val options: Multimap<Orientation, InteractWheelOption>
|
||||
) {
|
||||
fun addFillingOption(option: InteractWheelOption) {
|
||||
|
||||
@@ -36,8 +36,6 @@ import com.cobblemon.mod.common.api.pokedex.PokedexEntryProgress
|
||||
import com.cobblemon.mod.common.api.pokedex.PokedexManager
|
||||
import com.cobblemon.mod.common.api.pokedex.SeenCount
|
||||
import com.cobblemon.mod.common.api.pokedex.SeenPercent
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
|
||||
import com.cobblemon.mod.common.api.pokemon.evolution.Evolution
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.Stats
|
||||
import com.cobblemon.mod.common.api.scripting.CobblemonScripts
|
||||
import com.cobblemon.mod.common.api.spawning.context.SpawningContext
|
||||
@@ -62,12 +60,8 @@ import com.cobblemon.mod.common.net.messages.client.animation.PlayPosableAnimati
|
||||
import com.cobblemon.mod.common.net.messages.client.effect.RunPosableMoLangPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.effect.SpawnSnowstormEntityParticlePacket
|
||||
import com.cobblemon.mod.common.net.messages.client.effect.SpawnSnowstormParticlePacket
|
||||
import com.cobblemon.mod.common.pokemon.Gender
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.pokemon.Species
|
||||
import com.cobblemon.mod.common.pokemon.evolution.variants.ItemInteractionEvolution
|
||||
import com.cobblemon.mod.common.pokemon.evolution.variants.LevelUpEvolution
|
||||
import com.cobblemon.mod.common.pokemon.evolution.variants.TradeEvolution
|
||||
import com.cobblemon.mod.common.util.*
|
||||
import com.mojang.datafixers.util.Either
|
||||
import java.util.UUID
|
||||
@@ -1008,82 +1002,6 @@ object MoLangFunctions {
|
||||
}
|
||||
)
|
||||
|
||||
val pokemonPropertiesFunctions: MutableList<(PokemonProperties) -> HashMap<String, java.util.function.Function<MoParams, Any>>> = mutableListOf(
|
||||
{ props ->
|
||||
val map = hashMapOf<String, java.util.function.Function<MoParams, Any>>()
|
||||
|
||||
map.put("level") { DoubleValue(props.level?.toDouble() ?: 0) }
|
||||
map.put("set_level") { params ->
|
||||
props.level = params.getIntOrNull(0)
|
||||
return@put DoubleValue.ONE
|
||||
}
|
||||
map.put("shiny") { DoubleValue(props.shiny) }
|
||||
map.put("set_shiny") { params ->
|
||||
props.shiny = params.getBooleanOrNull(0)
|
||||
return@put DoubleValue.ONE
|
||||
}
|
||||
map.put("species") { props.species?.let { StringValue(it) } ?: DoubleValue.ZERO }
|
||||
map.put("set_species") { params ->
|
||||
props.species = params.getStringOrNull(0)
|
||||
return@put DoubleValue.ONE
|
||||
}
|
||||
map.put("gender") { props.gender?.let { StringValue(it.name) } ?: DoubleValue.ZERO }
|
||||
map.put("set_gender") { params ->
|
||||
props.gender = params.getStringOrNull(0)?.let { Gender.valueOf(it) }
|
||||
return@put DoubleValue.ONE
|
||||
}
|
||||
map.put("form") { props.form?.let { StringValue(it) } ?: DoubleValue.ZERO }
|
||||
map.put("ivs") {
|
||||
val ivs = props.ivs
|
||||
if (ivs == null) {
|
||||
return@put DoubleValue.ZERO
|
||||
} else {
|
||||
return@put ivs.struct
|
||||
}
|
||||
}
|
||||
map.put("evs") {
|
||||
val evs = props.evs
|
||||
if (evs == null) {
|
||||
return@put DoubleValue.ZERO
|
||||
} else {
|
||||
return@put evs.struct
|
||||
}
|
||||
}
|
||||
map.put("friendship") { DoubleValue(props.friendship?.toDouble() ?: DoubleValue.ZERO) }
|
||||
map.put("set_friendship") { params ->
|
||||
props.friendship = params.getIntOrNull(0)
|
||||
return@put DoubleValue.ONE
|
||||
}
|
||||
map.put("create") { params ->
|
||||
val pokemon = props.create()
|
||||
return@put pokemon.struct
|
||||
}
|
||||
|
||||
map
|
||||
}
|
||||
)
|
||||
|
||||
val evolutionFunctions: MutableList<(Evolution) -> HashMap<String, java.util.function.Function<MoParams, Any>>> = mutableListOf(
|
||||
{ evolution ->
|
||||
val map = hashMapOf<String, java.util.function.Function<MoParams, Any>>()
|
||||
|
||||
map.put("result") { evolution.result.asMoLangValue() }
|
||||
|
||||
if (evolution is LevelUpEvolution) {
|
||||
map.put("is_level_up") { DoubleValue.ONE }
|
||||
} else if (evolution is TradeEvolution) {
|
||||
map.put("is_trade") { DoubleValue.ONE }
|
||||
} else if (evolution is ItemInteractionEvolution) {
|
||||
map.put("is_item") { DoubleValue.ONE }
|
||||
}
|
||||
|
||||
map.put("is_optional") { DoubleValue(evolution.optional) }
|
||||
map.put("consumes_held_item") { DoubleValue(evolution.consumeHeldItem) }
|
||||
|
||||
map
|
||||
}
|
||||
)
|
||||
|
||||
fun Holder<Biome>.asBiomeMoLangValue() = asMoLangValue(Registries.BIOME).addFunctions(biomeFunctions.flatMap { it(this).entries.map { it.key to it.value } }.toMap())
|
||||
fun Holder<Level>.asWorldMoLangValue() = asMoLangValue(Registries.DIMENSION).addFunctions(worldFunctions.flatMap { it(this).entries.map { it.key to it.value } }.toMap())
|
||||
fun Holder<Block>.asBlockMoLangValue() = asMoLangValue(Registries.BLOCK).addFunctions(blockFunctions.flatMap { it(this).entries.map { it.key to it.value } }.toMap())
|
||||
@@ -1116,24 +1034,6 @@ object MoLangFunctions {
|
||||
return value
|
||||
}
|
||||
|
||||
fun PokemonProperties.asMoLangValue(): ObjectValue<PokemonProperties> {
|
||||
val value = ObjectValue(
|
||||
obj = this,
|
||||
stringify = { it.asString() }
|
||||
)
|
||||
value.addFunctions(pokemonPropertiesFunctions.flatMap { it(this).entries.map { it.key to it.value } }.toMap())
|
||||
return value
|
||||
}
|
||||
|
||||
fun Evolution.asMoLangValue(): ObjectValue<Evolution> {
|
||||
val value = ObjectValue(
|
||||
obj = this,
|
||||
stringify = { it.toString() }
|
||||
)
|
||||
value.addFunctions(evolutionFunctions.flatMap { it(this).entries.map { it.key to it.value } }.toMap())
|
||||
return value
|
||||
}
|
||||
|
||||
fun PCStore.asMoLangValue(): ObjectValue<PCStore> {
|
||||
val value = ObjectValue(
|
||||
obj = this,
|
||||
@@ -1270,24 +1170,6 @@ object MoLangFunctions {
|
||||
return this
|
||||
}
|
||||
|
||||
fun moLangFunctionMap(
|
||||
vararg functions: Pair<String, (MoParams) -> MoValue>
|
||||
): Map<String, (MoParams) -> MoValue> {
|
||||
return functions.toMap()
|
||||
}
|
||||
|
||||
fun queryStructOf(
|
||||
vararg functions: Pair<String, (MoParams) -> MoValue>
|
||||
): QueryStruct {
|
||||
return QueryStruct(
|
||||
hashMapOf<String, java.util.function.Function<MoParams, Any>>(
|
||||
*functions.map { (name, func) ->
|
||||
name to java.util.function.Function<MoParams, Any> { params -> func(params) }
|
||||
}.toTypedArray()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
fun MoLangRuntime.setup(): MoLangRuntime {
|
||||
environment.query.addStandardFunctions()
|
||||
return this
|
||||
|
||||
@@ -320,7 +320,7 @@ a single battle challenge and this is a dynamic party, there will also be a `q.p
|
||||
"pokemon": "weedle",
|
||||
"weight": "10",
|
||||
"selectableTimes": "2",
|
||||
"levelVariation": "2",
|
||||
"levelVariation": "2"
|
||||
"npcLevels": "1-8"
|
||||
},
|
||||
{
|
||||
|
||||
@@ -8,6 +8,9 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.pokemon
|
||||
|
||||
import com.bedrockk.molang.runtime.struct.VariableStruct
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.bedrockk.molang.runtime.value.StringValue
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.abilities.Abilities
|
||||
import com.cobblemon.mod.common.api.abilities.Ability
|
||||
@@ -772,6 +775,17 @@ open class PokemonProperties {
|
||||
return pieces.joinToString(separator)
|
||||
}
|
||||
|
||||
fun asStruct(): VariableStruct {
|
||||
val struct = VariableStruct()
|
||||
species?.let { struct.setDirectly("species", StringValue(it)) }
|
||||
level?.let { struct.setDirectly("level", DoubleValue(it)) }
|
||||
shiny?.let { struct.setDirectly("shiny", DoubleValue(it)) }
|
||||
// add more of the optional properties to the struct as doubles or strings
|
||||
gender?.let { struct.setDirectly("gender", StringValue(it.name)) }
|
||||
friendship?.let { struct.setDirectly("friendship", DoubleValue(it)) }
|
||||
return struct
|
||||
}
|
||||
|
||||
fun updateAspects() {
|
||||
val aspects = mutableSetOf<String>()
|
||||
AspectProvider.providers.forEach { aspects.addAll(it.provide(this)) }
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.pokemon
|
||||
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.abilities.AbilityPool
|
||||
import com.cobblemon.mod.common.api.abilities.AbilityTemplate
|
||||
@@ -33,8 +32,6 @@ import com.cobblemon.mod.common.api.pokemon.moves.Learnset
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.Stat
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.Stats
|
||||
import com.cobblemon.mod.common.api.reactive.SimpleObservable
|
||||
import com.cobblemon.mod.common.api.riding.controller.RideController
|
||||
import com.cobblemon.mod.common.api.riding.stats.RidingStatDefinition
|
||||
import com.cobblemon.mod.common.api.spawning.TimeRange
|
||||
import com.cobblemon.mod.common.api.types.ElementalType
|
||||
import com.cobblemon.mod.common.api.types.adapters.ElementalTypeAdapter
|
||||
@@ -48,7 +45,6 @@ import com.cobblemon.mod.common.pokemon.evolution.adapters.CobblemonRequirementA
|
||||
import com.cobblemon.mod.common.pokemon.evolution.adapters.LegacyItemConditionWrapperAdapter
|
||||
import com.cobblemon.mod.common.pokemon.helditem.CobblemonHeldItemManager
|
||||
import com.cobblemon.mod.common.util.adapters.*
|
||||
import com.cobblemon.mod.common.util.adapters.RideControllerAdapter
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.google.common.collect.HashBasedTable
|
||||
import com.google.gson.Gson
|
||||
@@ -57,7 +53,6 @@ import com.google.gson.reflect.TypeToken
|
||||
import net.minecraft.advancements.critereon.ItemPredicate
|
||||
import net.minecraft.core.registries.BuiltInRegistries
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.server.packs.PackType
|
||||
@@ -98,7 +93,6 @@ object PokemonSpecies : JsonDataRegistry<Species> {
|
||||
.registerTypeAdapter(DropEntry::class.java, DropEntryAdapter)
|
||||
.registerTypeAdapter(CompoundTag::class.java, NbtCompoundAdapter)
|
||||
.registerTypeAdapter(ExpressionLike::class.java, ExpressionLikeAdapter)
|
||||
.registerTypeAdapter(Component::class.java, TextAdapter)
|
||||
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Biome::class.java).type, BiomeLikeConditionAdapter)
|
||||
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Block::class.java).type, BlockLikeConditionAdapter)
|
||||
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Item::class.java).type, ItemLikeConditionAdapter)
|
||||
@@ -106,9 +100,6 @@ object PokemonSpecies : JsonDataRegistry<Species> {
|
||||
.registerTypeAdapter(EggGroup::class.java, EggGroupAdapter)
|
||||
.registerTypeAdapter(MobEffect::class.java, RegistryElementAdapter<MobEffect>(BuiltInRegistries::MOB_EFFECT))
|
||||
.registerTypeAdapter(ItemPredicate::class.java, LegacyItemConditionWrapperAdapter)
|
||||
.registerTypeAdapter(RideController::class.java, RideControllerAdapter)
|
||||
.registerTypeAdapter(RidingStatDefinition::class.java, RidingStatDefinitionAdapter)
|
||||
.registerTypeAdapter(Expression::class.java, ExpressionAdapter)
|
||||
.disableHtmlEscaping()
|
||||
.enableComplexMapKeySerialization()
|
||||
.create()
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.riding
|
||||
|
||||
import net.minecraft.world.entity.PlayerRideableJumping
|
||||
|
||||
/**
|
||||
* Represents an entity that supports riding.
|
||||
*
|
||||
* @since 1.7.0
|
||||
*/
|
||||
interface Rideable : PlayerRideableJumping {
|
||||
|
||||
/**
|
||||
* Denotes the manager responsible for handling any instance of riding taking place on an entity
|
||||
*/
|
||||
val riding: RidingManager
|
||||
|
||||
}
|
||||
@@ -1,128 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.riding
|
||||
|
||||
import com.bedrockk.molang.runtime.MoLangRuntime
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.setup
|
||||
import com.cobblemon.mod.common.api.riding.controller.RideController
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.phys.Vec2
|
||||
import net.minecraft.world.phys.Vec3
|
||||
|
||||
data class RidingManager(val entity: PokemonEntity) {
|
||||
var lastSpeed = 0F
|
||||
var states: MutableMap<ResourceLocation, RidingState> = mutableMapOf()
|
||||
var deltaRotation = Vec2.ZERO
|
||||
|
||||
val runtime: MoLangRuntime by lazy {
|
||||
MoLangRuntime()
|
||||
.setup()
|
||||
.withQueryValue("entity", entity.struct)
|
||||
.also {
|
||||
it.environment.query.addFunction("passenger_count") { DoubleValue(entity.passengers.size.toDouble()) }
|
||||
}
|
||||
}
|
||||
|
||||
fun <T : RidingState> getState(id: ResourceLocation, constructor: (PokemonEntity) -> T): T {
|
||||
val storedState = states[id]
|
||||
if (storedState == null) {
|
||||
val newState = constructor(entity)
|
||||
states[id] = newState
|
||||
return newState
|
||||
}
|
||||
|
||||
return storedState as T
|
||||
}
|
||||
|
||||
fun getController(entity: PokemonEntity): RideController? {
|
||||
return entity.pokemon.riding.controller?.takeIf { it.condition.invoke(entity) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Responsible for handling riding conditions and transitions amongst controllers. This will tick
|
||||
* whenever the entity receives a tickControlled interaction.
|
||||
*/
|
||||
fun tick(entity: PokemonEntity, driver: Player, input: Vec3) {
|
||||
val controller = getController(entity) ?: return
|
||||
|
||||
val pose = controller.pose(entity)
|
||||
entity.entityData.set(PokemonEntity.POSE_TYPE, pose)
|
||||
|
||||
// driver.displayClientMessage(Component.literal("Speed: ").withStyle { it.withColor(ChatFormatting.GREEN) }.append(Component.literal("$lastSpeed b/t")), true)
|
||||
}
|
||||
|
||||
fun speed(entity: PokemonEntity, driver: Player): Float {
|
||||
val controller = getController(entity) ?: return 0.05F
|
||||
this.lastSpeed = controller.speed(entity, driver)
|
||||
return this.lastSpeed
|
||||
}
|
||||
|
||||
fun controlledRotation(entity: PokemonEntity, driver: Player): Vec2 {
|
||||
val controller = getController(entity) ?: return entity.rotationVector
|
||||
val previousRotation = entity.rotationVector
|
||||
val rotation = controller.rotation(entity, driver)
|
||||
this.deltaRotation = Vec2(rotation.x - previousRotation.x, rotation.y - previousRotation.y)
|
||||
return rotation
|
||||
}
|
||||
|
||||
fun clampPassengerRotation(entity: PokemonEntity, driver: LivingEntity) {
|
||||
val controller = getController(entity) ?: return
|
||||
return controller.clampPassengerRotation(entity, driver)
|
||||
}
|
||||
|
||||
fun updatePassengerRotation(entity: PokemonEntity, driver: LivingEntity) {
|
||||
val controller = getController(entity) ?: return
|
||||
return controller.updatePassengerRotation(entity, driver)
|
||||
}
|
||||
|
||||
fun velocity(entity: PokemonEntity, driver: Player, input: Vec3): Vec3 {
|
||||
val controller = getController(entity) ?: return Vec3.ZERO
|
||||
return controller.velocity(entity, driver, input)
|
||||
}
|
||||
|
||||
fun canJump(entity: PokemonEntity, driver: Player): Boolean {
|
||||
val controller = getController(entity) ?: return false
|
||||
return controller.canJump(entity, driver)
|
||||
}
|
||||
|
||||
fun jumpVelocity(entity: PokemonEntity, driver: Player, jumpStrength: Int): Vec3 {
|
||||
val controller = getController(entity) ?: return Vec3.ZERO
|
||||
return controller.jumpForce(entity, driver, jumpStrength)
|
||||
}
|
||||
|
||||
fun gravity(entity: PokemonEntity, regularGravity: Double): Double? {
|
||||
val controller = getController(entity) ?: return null
|
||||
return controller.gravity(entity, regularGravity)
|
||||
}
|
||||
|
||||
fun shouldRoll(entity: PokemonEntity): Boolean {
|
||||
val controller = getController(entity) ?: return false
|
||||
return controller.shouldRoll(entity)
|
||||
}
|
||||
|
||||
fun shouldRotatePlayerHead(entity: PokemonEntity): Boolean {
|
||||
val controller = getController(entity) ?: return false
|
||||
return controller.shouldRotatePlayerHead()
|
||||
}
|
||||
|
||||
fun shouldRotatePokemonHead(entity: PokemonEntity): Boolean {
|
||||
val controller = getController(entity) ?: return false
|
||||
return controller.shouldRotatePokemonHead()
|
||||
}
|
||||
|
||||
//FIXME: Make this not just be false for all controllers lol
|
||||
fun dismountOnShift(): Boolean {
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.riding
|
||||
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.cobblemon.mod.common.api.riding.controller.RideController
|
||||
import com.cobblemon.mod.common.api.riding.stats.RidingStat
|
||||
import com.cobblemon.mod.common.api.riding.stats.RidingStatDefinition
|
||||
import com.cobblemon.mod.common.util.adapters.RideControllerAdapter
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.cobblemon.mod.common.util.getString
|
||||
import com.cobblemon.mod.common.util.readIdentifier
|
||||
import com.cobblemon.mod.common.util.readString
|
||||
import com.cobblemon.mod.common.util.writeString
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
|
||||
class RidingProperties(
|
||||
val stats: Map<RidingStat, RidingStatDefinition> = mapOf(),
|
||||
val seats: List<Seat> = listOf(),
|
||||
val conditions: List<Expression> = listOf(),
|
||||
val controller: RideController? = null
|
||||
) {
|
||||
companion object {
|
||||
fun decode(buffer: RegistryFriendlyByteBuf): RidingProperties {
|
||||
val stats: Map<RidingStat, RidingStatDefinition> = buffer.readMap(
|
||||
{ buffer.readEnum<RidingStat>(RidingStat::class.java) },
|
||||
{ RidingStatDefinition.decode(buffer) }
|
||||
)
|
||||
val seats: List<Seat> = buffer.readList { _ -> Seat.decode(buffer) }
|
||||
val conditions = buffer.readList { buffer.readString().asExpression() }
|
||||
val controller = buffer.readNullable { _ ->
|
||||
val key = buffer.readIdentifier()
|
||||
val controller = RideControllerAdapter.types[key]?.getConstructor()?.newInstance() ?: error("Unknown controller key: $key")
|
||||
controller.decode(buffer)
|
||||
return@readNullable controller
|
||||
}
|
||||
|
||||
return RidingProperties(stats = stats, seats = seats, conditions = conditions, controller = controller)
|
||||
}
|
||||
}
|
||||
|
||||
val canRide: Boolean
|
||||
get() = seats.isNotEmpty() && controller != null
|
||||
|
||||
fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeMap(
|
||||
stats,
|
||||
{ _, stat -> buffer.writeEnum(stat) },
|
||||
{ _, stat -> stat.encode(buffer) }
|
||||
)
|
||||
buffer.writeCollection(seats) { _, seat -> seat.encode(buffer) }
|
||||
buffer.writeCollection(conditions) { _, condition -> buffer.writeString(condition.getString()) }
|
||||
buffer.writeNullable(controller) { _, controller -> controller.encode(buffer) }
|
||||
}
|
||||
|
||||
fun calculate(stat: RidingStat, style: RidingStyle, boosts: Int): Float {
|
||||
val definitions = stats[stat] ?: return 0F
|
||||
return definitions.calculate(style, boosts)
|
||||
}
|
||||
|
||||
fun hasStat(stat: RidingStat, style: RidingStyle): Boolean {
|
||||
return stats[stat]?.ranges?.containsKey(style) == true
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.riding
|
||||
|
||||
/**
|
||||
* Honestly having a base interface is probably unnecessary I'm just considering whether there's going to be some
|
||||
* kind of shared state later.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since October 6th, 2024
|
||||
*/
|
||||
interface RidingState
|
||||
@@ -1,22 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.riding
|
||||
|
||||
/**
|
||||
* A general medium for riding. Mainly used for categorizing which stats to pull from and for
|
||||
* presenting a simplified view of riding to users.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since February 17th, 2025
|
||||
*/
|
||||
enum class RidingStyle {
|
||||
LAND,
|
||||
LIQUID,
|
||||
AIR
|
||||
}
|
||||
@@ -1,91 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.riding
|
||||
|
||||
import com.cobblemon.mod.common.api.net.Encodable
|
||||
import com.cobblemon.mod.common.api.riding.controller.RidingAnimation
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.util.readString
|
||||
import com.cobblemon.mod.common.util.writeString
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.world.phys.Vec3
|
||||
|
||||
/**
|
||||
* Seat Properties are responsible for the base information that would then be used to construct a Seat on an entity.
|
||||
*/
|
||||
data class Seat(
|
||||
val locator: String = "seat_1",
|
||||
val offset: Vec3 = Vec3.ZERO,
|
||||
val poseOffsets: MutableList<SeatPoseOffset> = mutableListOf(),
|
||||
val poseAnimations: MutableList<SeatPoseAnimations> = mutableListOf()
|
||||
) : Encodable {
|
||||
fun getOffset(poseType: PoseType) : Vec3 {
|
||||
return poseOffsets.firstOrNull { poseType in it.poseTypes }?.offset ?: offset
|
||||
}
|
||||
|
||||
override fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeString(locator)
|
||||
buffer.writeDouble(offset.x)
|
||||
buffer.writeDouble(offset.y)
|
||||
buffer.writeDouble(offset.z)
|
||||
buffer.writeCollection(poseOffsets) { _, offset -> offset.encode(buffer) }
|
||||
buffer.writeCollection(poseAnimations) { _, animations -> animations.encode(buffer) }
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun decode(buffer: RegistryFriendlyByteBuf) : Seat {
|
||||
return Seat(
|
||||
buffer.readString(),
|
||||
Vec3(buffer.readDouble(), buffer.readDouble(), buffer.readDouble()),
|
||||
buffer.readList { SeatPoseOffset.decode(buffer) },
|
||||
buffer.readList { SeatPoseAnimations.decode(buffer) }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class SeatPoseOffset {
|
||||
val poseTypes = mutableSetOf<PoseType>()
|
||||
var offset = Vec3.ZERO
|
||||
|
||||
fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeCollection(poseTypes) { _, poseType -> buffer.writeString(poseType.name) }
|
||||
buffer.writeDouble(offset.x)
|
||||
buffer.writeDouble(offset.y)
|
||||
buffer.writeDouble(offset.z)
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun decode(buffer: RegistryFriendlyByteBuf) : SeatPoseOffset {
|
||||
val offset = SeatPoseOffset()
|
||||
offset.poseTypes.addAll(buffer.readList { buffer.readString().let { PoseType.valueOf(it) } })
|
||||
offset.offset = Vec3(buffer.readDouble(), buffer.readDouble(), buffer.readDouble())
|
||||
return offset
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class SeatPoseAnimations {
|
||||
val poseTypes = mutableSetOf<PoseType>()
|
||||
var animations = mutableListOf<RidingAnimation>()
|
||||
|
||||
fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeCollection(poseTypes) { _, poseType -> buffer.writeString(poseType.name) }
|
||||
buffer.writeCollection(animations) { _, animation -> animation.encode(buffer) }
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun decode(buffer: RegistryFriendlyByteBuf) : SeatPoseAnimations {
|
||||
val animations = SeatPoseAnimations()
|
||||
animations.poseTypes.addAll(buffer.readList { buffer.readString().let { PoseType.valueOf(it) } })
|
||||
animations.animations = buffer.readList { RidingAnimation.decode(buffer) }
|
||||
return animations
|
||||
}
|
||||
}
|
||||
}
|
||||
-106
@@ -1,106 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.riding.controller
|
||||
|
||||
import com.cobblemon.mod.common.api.net.Decodable
|
||||
import com.cobblemon.mod.common.api.net.Encodable
|
||||
import com.cobblemon.mod.common.api.riding.RidingState
|
||||
import com.cobblemon.mod.common.api.riding.controller.posing.PoseProvider
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.util.writeIdentifier
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.phys.Vec2
|
||||
import net.minecraft.world.phys.Vec3
|
||||
|
||||
/**
|
||||
* A riding controller is the internal control mechanism for determining how a pokemon
|
||||
* handles during riding. Controllers come into play once the pokemon being ridden has
|
||||
* established the path it's capable of. For instance, a land based controller could have
|
||||
* the pokemon experience drifting after movement, or generic movement. It's up to the
|
||||
* controller to decide how the pokemon behaves.
|
||||
*
|
||||
* @since 1.7.0
|
||||
*/
|
||||
interface RideController : Encodable, Decodable {
|
||||
|
||||
/** A reference key used to denote the individual controller */
|
||||
val key: ResourceLocation
|
||||
|
||||
/**
|
||||
* Specifies the provider of poses which helps control updating the current pose on the pokemon
|
||||
* being ridden. Controllers are expected to define the pose types responsible for posing the entity
|
||||
* through all expected conditions. It should define a default pose, that will be used in all cases
|
||||
* where a pose does not meet the current conditions for the current mount. Typically, this will be
|
||||
* an idle pose.
|
||||
*/
|
||||
val poseProvider: PoseProvider
|
||||
|
||||
/**
|
||||
* Represents a condition that must be met for this controller to be active. For instance, this can be used
|
||||
* to evaluate things such as current velocity or block state of the entity.
|
||||
*/
|
||||
val condition: (PokemonEntity) -> Boolean
|
||||
|
||||
/**
|
||||
* Specifies the pose the ridden mount should be positioned in. This queries the pose provider using
|
||||
* the entity as a means of determining the conditions the entity is currently under. This allows for
|
||||
* dynamic pose updates.
|
||||
*/
|
||||
fun pose(entity: PokemonEntity) : PoseType {
|
||||
return this.poseProvider.select(entity)
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the current speed of the mount.
|
||||
*/
|
||||
fun speed(entity: PokemonEntity, driver: Player) : Float
|
||||
|
||||
/**
|
||||
* Sets the rotation of the mount. This is typically based on the controlling driver and is manipulated as
|
||||
* necessary.
|
||||
*/
|
||||
fun rotation(entity: PokemonEntity, driver: LivingEntity) : Vec2
|
||||
|
||||
fun clampPassengerRotation(entity: PokemonEntity, driver: LivingEntity) {}
|
||||
|
||||
fun updatePassengerRotation(entity: PokemonEntity, driver: LivingEntity) {
|
||||
driver.yRot = entity.yRot
|
||||
}
|
||||
|
||||
/**
|
||||
* Manipulates the movement input as necessary by the controller. This is primarily used to apply limits
|
||||
* to the types of movements. For instance, we can apply limits to any sort of sideways movement input, so that
|
||||
* it would otherwise be slower than normal forward movement.
|
||||
*/
|
||||
fun velocity(entity: PokemonEntity, driver: Player, input: Vec3) : Vec3
|
||||
|
||||
fun canJump(entity: PokemonEntity, driver: Player) : Boolean
|
||||
fun jumpForce(entity: PokemonEntity, driver: Player, jumpStrength: Int) : Vec3
|
||||
|
||||
fun gravity(entity: PokemonEntity, regularGravity: Double) : Double? = null
|
||||
|
||||
fun shouldRoll(entity: PokemonEntity): Boolean = false
|
||||
|
||||
fun getRuntime(entity: PokemonEntity) = entity.riding.runtime
|
||||
|
||||
fun shouldRotatePokemonHead(): Boolean = false
|
||||
fun shouldRotatePlayerHead(): Boolean = false
|
||||
|
||||
fun <T : RidingState> getState(entity: PokemonEntity, constructor: (PokemonEntity) -> T): T {
|
||||
return entity.riding.getState(key, constructor)
|
||||
}
|
||||
|
||||
override fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeIdentifier(this.key)
|
||||
}
|
||||
}
|
||||
-32
@@ -1,32 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.riding.controller
|
||||
|
||||
import com.cobblemon.mod.common.util.readString
|
||||
import com.cobblemon.mod.common.util.writeString
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
|
||||
class RidingAnimation(
|
||||
val fileName: String,
|
||||
val animationName: String
|
||||
) {
|
||||
fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeString(fileName)
|
||||
buffer.writeString(animationName)
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun decode(buffer: RegistryFriendlyByteBuf) : RidingAnimation {
|
||||
return RidingAnimation(
|
||||
buffer.readString(),
|
||||
buffer.readString()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
-15
@@ -1,15 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.riding.controller.posing
|
||||
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import java.util.function.Predicate
|
||||
|
||||
data class PoseOption(val pose: PoseType, val condition: Predicate<PokemonEntity>)
|
||||
-31
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.riding.controller.posing
|
||||
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
|
||||
class PoseProvider(private val fallback: PoseType) {
|
||||
|
||||
private val options = mutableListOf<PoseOption>()
|
||||
|
||||
fun select(entity: PokemonEntity) : PoseType {
|
||||
return this.options.stream()
|
||||
.filter { it.condition.test(entity) }
|
||||
.map { it.pose }
|
||||
.findFirst()
|
||||
.orElse(this.fallback)
|
||||
}
|
||||
|
||||
fun with(option: PoseOption) : PoseProvider {
|
||||
this.options.add(option)
|
||||
return this
|
||||
}
|
||||
|
||||
}
|
||||
-33
@@ -1,33 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.riding.events
|
||||
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
|
||||
data class SelectDriverEvent(val options: Set<LivingEntity>) {
|
||||
|
||||
private var result: DriverSuggestion? = null
|
||||
|
||||
fun result(): LivingEntity? {
|
||||
return this.result?.entity
|
||||
}
|
||||
|
||||
/**
|
||||
* Suggests a particular living entity as a potential driver. Only non-negative
|
||||
* values are permitted by this function. All priority values with lesser priorities
|
||||
* will be outright ignored.
|
||||
*/
|
||||
fun suggest(target: LivingEntity, priority: Int) {
|
||||
if (priority >= 0 && priority > (this.result?.priority ?: -1)) {
|
||||
this.result = DriverSuggestion(target, priority)
|
||||
}
|
||||
}
|
||||
|
||||
data class DriverSuggestion(val entity: LivingEntity, val priority: Int)
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.riding.stats
|
||||
|
||||
import com.cobblemon.mod.common.api.berry.Flavor
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
import net.minecraft.network.chat.Component
|
||||
|
||||
/**
|
||||
* A stat that is used for riding Pokémon. The exact implementation of each of these depends on the [com.cobblemon.mod.common.api.riding.controller.RideController].
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since February 17th, 2025
|
||||
*/
|
||||
enum class RidingStat(
|
||||
val flavour: Flavor
|
||||
) {
|
||||
SPEED(Flavor.SWEET),
|
||||
ACCELERATION(Flavor.SPICY),
|
||||
SKILL(Flavor.DRY),
|
||||
JUMP(Flavor.BITTER),
|
||||
STAMINA(Flavor.SOUR);
|
||||
|
||||
companion object {
|
||||
fun getByName(name: String) = RidingStat.entries.firstOrNull { it.name.equals(name, ignoreCase = true) }
|
||||
}
|
||||
|
||||
val displayName: Component
|
||||
get() = lang("riding.stat.${name.lowercase()}.name")
|
||||
val description: Component
|
||||
get() = lang("riding.stat.${name.lowercase()}.desc")
|
||||
}
|
||||
-70
@@ -1,70 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.riding.stats
|
||||
|
||||
import com.cobblemon.mod.common.api.riding.RidingStyle
|
||||
import com.cobblemon.mod.common.net.IntSize
|
||||
import com.cobblemon.mod.common.util.readSizedInt
|
||||
import com.cobblemon.mod.common.util.readText
|
||||
import com.cobblemon.mod.common.util.writeSizedInt
|
||||
import com.cobblemon.mod.common.util.writeText
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.network.chat.Component
|
||||
|
||||
/**
|
||||
* The definition of all the different information related to a specific [RidingStat] on a Pokémon species.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since February 17th, 2025
|
||||
*/
|
||||
class RidingStatDefinition {
|
||||
// This object gets read from a JSON adapter manually (field-by-field) so don't add fields without updating the adapter.
|
||||
|
||||
/** A map from [RidingStyle] to a minimum and maximum value for this stat. */
|
||||
val ranges = mutableMapOf<RidingStyle, IntRange>()
|
||||
/** Display name for the stat, if null falls back to [RidingStat.displayName]. */
|
||||
var displayName: Component? = null
|
||||
/** Description for the stat, if null falls back to [RidingStat.description]. */
|
||||
var description: Component? = null
|
||||
|
||||
fun calculate(style: RidingStyle, aprijuiceBoost: Int): Float {
|
||||
val range = ranges[style] ?: ranges[RidingStyle.LAND] ?: return 0F
|
||||
val boostQuotient = aprijuiceBoost / 255F
|
||||
return range.first + (range.last - range.first) * boostQuotient
|
||||
}
|
||||
|
||||
fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeNullable(displayName) { _, it -> buffer.writeText(it) }
|
||||
buffer.writeNullable(description) { _, it -> buffer.writeText(it) }
|
||||
buffer.writeMap(
|
||||
ranges,
|
||||
{ _, it -> buffer.writeEnum(it) },
|
||||
{ _, it ->
|
||||
buffer.writeSizedInt(IntSize.U_BYTE, it.first)
|
||||
buffer.writeSizedInt(IntSize.U_BYTE, it.last)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun decode(buffer: RegistryFriendlyByteBuf): RidingStatDefinition {
|
||||
val displayName = buffer.readNullable { buffer.readText() }
|
||||
val description = buffer.readNullable { buffer.readText() }
|
||||
val ranges = buffer.readMap<RidingStyle, IntRange>(
|
||||
{ buffer.readEnum<RidingStyle>(RidingStyle::class.java) },
|
||||
{ IntRange(buffer.readSizedInt(IntSize.U_BYTE), buffer.readSizedInt(IntSize.U_BYTE)) }
|
||||
)
|
||||
return RidingStatDefinition().apply {
|
||||
this.displayName = displayName
|
||||
this.description = description
|
||||
this.ranges.putAll(ranges)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
-6
@@ -8,11 +8,9 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.spawning.detail
|
||||
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.cobblemon.mod.common.Cobblemon.LOGGER
|
||||
import com.cobblemon.mod.common.Cobblemon.config
|
||||
import com.cobblemon.mod.common.api.drop.DropTable
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonSpecies
|
||||
import com.cobblemon.mod.common.api.spawning.context.SpawningContext
|
||||
@@ -22,8 +20,8 @@ import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
|
||||
import com.cobblemon.mod.common.util.asTranslated
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import kotlin.math.ceil
|
||||
import net.minecraft.network.chat.MutableComponent
|
||||
import kotlin.math.ceil
|
||||
|
||||
/**
|
||||
* A [SpawnDetail] for spawning a [PokemonEntity].
|
||||
@@ -71,9 +69,7 @@ class PokemonSpawnDetail : SpawnDetail() {
|
||||
}
|
||||
|
||||
override fun autoLabel() {
|
||||
struct.addFunction("pokemon") { pokemon.asMoLangValue() }
|
||||
struct.addFunction("min_level") { DoubleValue(getDerivedLevelRange().start.toDouble()) }
|
||||
struct.addFunction("max_level") { DoubleValue(getDerivedLevelRange().endInclusive.toDouble()) }
|
||||
val pokemonStruct = pokemon.asStruct()
|
||||
if (pokemon.species != null) {
|
||||
val species = PokemonSpecies.getByIdentifier(pokemon.species!!.asIdentifierDefaultingNamespace())
|
||||
if (species != null) {
|
||||
@@ -92,6 +88,7 @@ class PokemonSpawnDetail : SpawnDetail() {
|
||||
}
|
||||
}
|
||||
|
||||
struct.setDirectly("pokemon", pokemonStruct)
|
||||
super.autoLabel()
|
||||
}
|
||||
|
||||
|
||||
+13
-14
@@ -8,12 +8,12 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.spawning.detail
|
||||
|
||||
import com.bedrockk.molang.runtime.struct.QueryStruct
|
||||
import com.bedrockk.molang.runtime.struct.ArrayStruct
|
||||
import com.bedrockk.molang.runtime.struct.VariableStruct
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.bedrockk.molang.runtime.value.StringValue
|
||||
import com.cobblemon.mod.common.Cobblemon.LOGGER
|
||||
import com.cobblemon.mod.common.api.ModDependant
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.queryStructOf
|
||||
import com.cobblemon.mod.common.api.spawning.SpawnBucket
|
||||
import com.cobblemon.mod.common.api.spawning.condition.CompositeSpawningCondition
|
||||
import com.cobblemon.mod.common.api.spawning.condition.SpawningCondition
|
||||
@@ -21,7 +21,6 @@ import com.cobblemon.mod.common.api.spawning.context.RegisteredSpawningContext
|
||||
import com.cobblemon.mod.common.api.spawning.context.SpawningContext
|
||||
import com.cobblemon.mod.common.api.spawning.multiplier.WeightMultiplier
|
||||
import com.cobblemon.mod.common.api.text.text
|
||||
import com.cobblemon.mod.common.util.asArrayValue
|
||||
import com.cobblemon.mod.common.util.asTranslated
|
||||
|
||||
/**
|
||||
@@ -56,21 +55,21 @@ abstract class SpawnDetail : ModDependant {
|
||||
|
||||
var labels = mutableListOf<String>()
|
||||
|
||||
val struct: QueryStruct = queryStructOf(
|
||||
"weight" to { DoubleValue(weight) },
|
||||
"percentage" to { DoubleValue(percentage) },
|
||||
"id" to { StringValue(id) },
|
||||
"bucket" to { StringValue(bucket.name) },
|
||||
"width" to { DoubleValue(width.toDouble()) },
|
||||
"height" to { DoubleValue(height.toDouble()) },
|
||||
"context" to { StringValue(context.name) },
|
||||
"labels" to { labels.asArrayValue { StringValue(it) } }
|
||||
)
|
||||
val struct: VariableStruct = VariableStruct()
|
||||
|
||||
override var neededInstalledMods = listOf<String>()
|
||||
override var neededUninstalledMods = listOf<String>()
|
||||
|
||||
open fun autoLabel() {}
|
||||
open fun autoLabel() {
|
||||
struct.setDirectly("weight", DoubleValue(weight.toDouble()))
|
||||
struct.setDirectly("percentage", DoubleValue(percentage.toDouble()))
|
||||
struct.setDirectly("id", StringValue(id))
|
||||
struct.setDirectly("bucket", StringValue(bucket.name))
|
||||
struct.setDirectly("width", DoubleValue(width.toDouble()))
|
||||
struct.setDirectly("height", DoubleValue(height.toDouble()))
|
||||
struct.setDirectly("context", StringValue(context.name))
|
||||
struct.setDirectly("labels", ArrayStruct(labels.mapIndexed { index, s -> "$index" to StringValue(s) }.toMap()))
|
||||
}
|
||||
|
||||
open fun getName() = displayName?.asTranslated() ?: id.text()
|
||||
|
||||
|
||||
@@ -124,10 +124,7 @@ object CobblemonItemTags {
|
||||
@JvmField val POWER_LENS = create("held/power_lens")
|
||||
@JvmField val POWER_WEIGHT = create("held/power_weight")
|
||||
@JvmField val TERRAIN_SEEDS = create("held/terrain_seeds")
|
||||
//Held Item Visibility Tags
|
||||
@JvmField val WEARABLE_FACE_ITEMS = create("held/visibility/face")
|
||||
@JvmField val WEARABLE_HAT_ITEMS = create("held/visibility/hat")
|
||||
@JvmField val HIDDEN_ITEMS = create("held/visibility/hidden")
|
||||
|
||||
|
||||
|
||||
private fun create(path: String) = TagKey.create(Registries.ITEM, cobblemonResource(path))
|
||||
|
||||
@@ -109,7 +109,7 @@ class BerryBlock(private val berryIdentifier: ResourceLocation, settings: Proper
|
||||
determineMutation(world, random, pos, newState)
|
||||
}
|
||||
|
||||
world.setBlock(pos, newState, UPDATE_CLIENTS)
|
||||
world.setBlock(pos, newState, Block.UPDATE_CLIENTS)
|
||||
convertMulchToEntity(world, newState, pos)
|
||||
treeEntity.goToNextStageTimer(FRUIT_AGE - curAge)
|
||||
treeEntity.setChanged()
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* 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.text.red
|
||||
import com.cobblemon.mod.common.api.text.text
|
||||
import com.cobblemon.mod.common.block.entity.StadiumBlockEntity
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.core.Direction
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.world.InteractionResult
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.item.context.BlockPlaceContext
|
||||
import net.minecraft.world.level.Level
|
||||
import net.minecraft.world.level.block.BaseEntityBlock
|
||||
import net.minecraft.world.level.block.Block
|
||||
import net.minecraft.world.level.block.HorizontalDirectionalBlock
|
||||
import net.minecraft.world.level.block.Mirror
|
||||
import net.minecraft.world.level.block.RenderShape
|
||||
import net.minecraft.world.level.block.Rotation
|
||||
import net.minecraft.world.level.block.entity.BlockEntity
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import net.minecraft.world.level.block.state.StateDefinition
|
||||
import net.minecraft.world.phys.BlockHitResult
|
||||
|
||||
class StadiumBlock(properties: Properties): BaseEntityBlock(properties) {
|
||||
companion object {
|
||||
val CODEC = simpleCodec(::StadiumBlock)
|
||||
}
|
||||
|
||||
init {
|
||||
registerDefaultState(stateDefinition.any().setValue(HorizontalDirectionalBlock.FACING, Direction.NORTH))
|
||||
}
|
||||
|
||||
override fun codec() = CODEC
|
||||
|
||||
override fun newBlockEntity(pos: BlockPos, state: BlockState): BlockEntity {
|
||||
return StadiumBlockEntity(pos, state)
|
||||
}
|
||||
|
||||
override fun getStateForPlacement(blockPlaceContext: BlockPlaceContext): BlockState {
|
||||
return this.defaultBlockState().setValue(HorizontalDirectionalBlock.FACING, blockPlaceContext.horizontalDirection)
|
||||
}
|
||||
|
||||
override fun createBlockStateDefinition(builder: StateDefinition.Builder<Block, BlockState>) {
|
||||
builder.add(HorizontalDirectionalBlock.FACING)
|
||||
}
|
||||
|
||||
override fun rotate(blockState: BlockState, rotation: Rotation): BlockState {
|
||||
return blockState.setValue(
|
||||
HorizontalDirectionalBlock.FACING, rotation.rotate(blockState.getValue(
|
||||
HorizontalDirectionalBlock.FACING)))
|
||||
}
|
||||
|
||||
override fun mirror(blockState: BlockState, mirror: Mirror): BlockState {
|
||||
return blockState.rotate(mirror.getRotation(blockState.getValue(HorizontalDirectionalBlock.FACING)))
|
||||
}
|
||||
|
||||
override fun onRemove(state: BlockState, world: Level, pos: BlockPos, newState: BlockState, moved: Boolean) {
|
||||
if (!state.`is`(newState.block)) super.onRemove(state, world, pos, newState, moved)
|
||||
}
|
||||
|
||||
//TODO: override getTicker
|
||||
|
||||
override fun getRenderShape(state: BlockState) = RenderShape.MODEL
|
||||
|
||||
override fun useWithoutItem(
|
||||
blockState: BlockState,
|
||||
world: Level,
|
||||
blockPos: BlockPos,
|
||||
player: Player,
|
||||
blockHitResult: BlockHitResult
|
||||
): InteractionResult {
|
||||
if (player !is ServerPlayer) return InteractionResult.SUCCESS
|
||||
|
||||
val blockEntity = world.getBlockEntity(blockPos)
|
||||
if (blockEntity !is StadiumBlockEntity) return InteractionResult.SUCCESS
|
||||
|
||||
// Toggle isInUse state
|
||||
blockEntity.isInUse = !blockEntity.isInUse
|
||||
|
||||
// debug
|
||||
val activateMessage = if (blockEntity.isInUse) "Stadium Activated!" else "Stadium Deactivated!"
|
||||
player.sendSystemMessage(text(activateMessage).red())
|
||||
|
||||
if (blockEntity.isInUse) {
|
||||
// Generate flight path when activated
|
||||
blockEntity.generateFlightPath(world, radiusX = 5.0, radiusZ = 3.0, height = 10.0, steps = 20)
|
||||
|
||||
} else {
|
||||
// Clear path when deactivated
|
||||
blockEntity.pathPoints.clear()
|
||||
}
|
||||
|
||||
val message = "Stadium Pos: " + blockEntity.blockPos +
|
||||
"\nPlayer 1 Pos: " + blockEntity.getPlayer1Pos() +
|
||||
"\nPoke 1 Pos: " + blockEntity.getPoke1Pos() +
|
||||
"\nPlayer 2 Pos: " + blockEntity.getPlayer2Pos() +
|
||||
"\nPoke 2 Pos: " + blockEntity.getPoke2Pos()
|
||||
player.sendSystemMessage(text(message).red())
|
||||
|
||||
blockEntity.setChanged()
|
||||
world.sendBlockUpdated(blockPos, blockState, blockState, Block.UPDATE_CLIENTS)
|
||||
|
||||
return InteractionResult.SUCCESS
|
||||
}
|
||||
}
|
||||
@@ -102,7 +102,7 @@ class BerryBlockEntity(pos: BlockPos, state: BlockState) : BlockEntity(Cobblemon
|
||||
mulchDuration = if (newDuration <= 0) {
|
||||
mulchVariant = MulchVariant.NONE
|
||||
this.setChanged()
|
||||
world.sendBlockUpdated(pos, state, state, UPDATE_CLIENTS)
|
||||
world.sendBlockUpdated(pos, state, state, Block.UPDATE_CLIENTS)
|
||||
0
|
||||
} else {
|
||||
newDuration
|
||||
@@ -313,10 +313,6 @@ class BerryBlockEntity(pos: BlockPos, state: BlockState) : BlockEntity(Cobblemon
|
||||
val berryPoints = arrayListOf<Pair<Berry, GrowthPoint>>()
|
||||
val sequenceIndices = growthPointSequence.toCharArray().filter { it.digitToInt(16) < baseBerry.growthPoints.size }
|
||||
for ((index, identifier) in this.growthPoints.withIndex()) {
|
||||
// Don't brick old broken worlds that had too many
|
||||
if (index >= sequenceIndices.size) {
|
||||
break
|
||||
}
|
||||
val berry = Berries.getByIdentifier(identifier) ?: continue
|
||||
val sequenceIndexHex = sequenceIndices[index].digitToInt(16)
|
||||
berryPoints.add(berry to baseBerry.growthPoints[sequenceIndexHex])
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
package com.cobblemon.mod.common.block.entity
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonBlockEntities
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.drone.DroneState
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.core.HolderLookup
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.nbt.ListTag
|
||||
import net.minecraft.network.protocol.Packet
|
||||
import net.minecraft.network.protocol.game.ClientGamePacketListener
|
||||
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket
|
||||
import net.minecraft.network.protocol.game.ClientboundPlayerLookAtPacket
|
||||
import net.minecraft.network.protocol.game.ClientboundSetCarriedItemPacket
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.world.level.Level
|
||||
import net.minecraft.world.level.block.entity.BlockEntity
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import net.minecraft.world.phys.Vec3
|
||||
|
||||
class StadiumBlockEntity(
|
||||
pos: BlockPos,
|
||||
blockState: BlockState
|
||||
): BlockEntity(
|
||||
CobblemonBlockEntities.STADIUM,
|
||||
pos,
|
||||
blockState
|
||||
) {
|
||||
var isInUse = false
|
||||
|
||||
val droneState = DroneState()
|
||||
|
||||
val pathPoints: MutableList<Vec3> = mutableListOf()
|
||||
|
||||
fun generateFlightPath(world: Level, radiusX: Double, radiusZ: Double, height: Double, steps: Int) {
|
||||
pathPoints.clear()
|
||||
|
||||
for (i in 0 until steps) {
|
||||
val angle = (i.toDouble() / steps) * Math.PI * 2
|
||||
val xOffset = radiusX * Math.cos(angle)
|
||||
val zOffset = radiusZ * Math.sin(angle)
|
||||
|
||||
val basePos = Vec3(blockPos.x + xOffset, blockPos.y + height, blockPos.z + zOffset)
|
||||
val adjustedPos = getValidPoint(world, basePos)
|
||||
|
||||
pathPoints.add(adjustedPos)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getValidPoint(world: Level, start: Vec3): Vec3 {
|
||||
val maxHeight = 40 // Max height for drone path
|
||||
val stepHeight = 1.0 // Step size for raycast
|
||||
|
||||
var adjustedHeight = start.y
|
||||
for (h in 0..maxHeight step stepHeight.toInt()) {
|
||||
val checkPos = BlockPos(start.x.toInt(), start.y.toInt() - h, start.z.toInt()) // Convert to BlockPos
|
||||
if (!world.getBlockState(checkPos).isAir) { // Check if block is solid
|
||||
return Vec3(start.x, start.y - h - 1, start.z) // Adjust position
|
||||
}
|
||||
}
|
||||
return start // No obstruction found
|
||||
}
|
||||
|
||||
|
||||
fun getPlayer1Pos(): BlockPos {
|
||||
return blockPos.north(10)
|
||||
}
|
||||
fun getPlayer2Pos(): BlockPos {
|
||||
return blockPos.south(10)
|
||||
}
|
||||
fun getPoke1Pos(): BlockPos {
|
||||
return blockPos.north(5)
|
||||
}
|
||||
fun getPoke2Pos(): BlockPos {
|
||||
return blockPos.south(5)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Saves data to NBT.
|
||||
*/
|
||||
override fun saveAdditional(tag: CompoundTag, registries: HolderLookup.Provider) {
|
||||
super.saveAdditional(tag, registries)
|
||||
|
||||
// Save the isInUse state
|
||||
tag.putBoolean("IsInUse", isInUse)
|
||||
|
||||
// Save path points
|
||||
val pathTag = ListTag()
|
||||
for (point in pathPoints) {
|
||||
val pointTag = CompoundTag()
|
||||
pointTag.putDouble("x", point.x)
|
||||
pointTag.putDouble("y", point.y)
|
||||
pointTag.putDouble("z", point.z)
|
||||
pathTag.add(pointTag)
|
||||
}
|
||||
tag.put("PathPoints", pathTag)
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads data from NBT.
|
||||
*/
|
||||
override fun loadAdditional(tag: CompoundTag, registries: HolderLookup.Provider) {
|
||||
super.loadAdditional(tag, registries)
|
||||
|
||||
// Load the isInUse state
|
||||
isInUse = tag.getBoolean("IsInUse")
|
||||
|
||||
// Load path points
|
||||
pathPoints.clear()
|
||||
val pathTag = tag.getList("PathPoints", 10) // 10 is the ID for CompoundTag
|
||||
for (i in 0 until pathTag.size) {
|
||||
val pointTag = pathTag.getCompound(i)
|
||||
val point = Vec3(pointTag.getDouble("x"), pointTag.getDouble("y"), pointTag.getDouble("z"))
|
||||
pathPoints.add(point)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getUpdatePacket(): Packet<ClientGamePacketListener>? {
|
||||
//println("getUpdatePacket called for NestBlockEntity at $blockPos with egg: $eggComponent")
|
||||
return ClientboundBlockEntityDataPacket.create(this)
|
||||
}
|
||||
|
||||
override fun getUpdateTag(registryLookup: HolderLookup.Provider): CompoundTag {
|
||||
val tag = saveWithoutMetadata(registryLookup)
|
||||
//println("getUpdateTag called for NestBlockEntity at $blockPos with tag: $tag")
|
||||
return tag
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -25,13 +25,7 @@ import com.cobblemon.mod.common.client.gui.battle.BattleOverlay
|
||||
import com.cobblemon.mod.common.client.particle.BedrockParticleOptionsRepository
|
||||
import com.cobblemon.mod.common.client.render.ClientPlayerIcon
|
||||
import com.cobblemon.mod.common.client.render.DeferredRenderer
|
||||
import com.cobblemon.mod.common.client.render.block.BerryBlockRenderer
|
||||
import com.cobblemon.mod.common.client.render.block.DisplayCaseRenderer
|
||||
import com.cobblemon.mod.common.client.render.block.FossilAnalyzerRenderer
|
||||
import com.cobblemon.mod.common.client.render.block.GildedChestBlockRenderer
|
||||
import com.cobblemon.mod.common.client.render.block.HealingMachineRenderer
|
||||
import com.cobblemon.mod.common.client.render.block.LecternBlockEntityRenderer
|
||||
import com.cobblemon.mod.common.client.render.block.RestorationTankRenderer
|
||||
import com.cobblemon.mod.common.client.render.block.*
|
||||
import com.cobblemon.mod.common.client.render.boat.CobblemonBoatRenderer
|
||||
import com.cobblemon.mod.common.client.render.entity.PokeBobberEntityRenderer
|
||||
import com.cobblemon.mod.common.client.render.generic.GenericBedrockRenderer
|
||||
@@ -256,7 +250,8 @@ object CobblemonClient {
|
||||
CobblemonBlocks.SKY_TUMBLESTONE_CLUSTER,
|
||||
CobblemonBlocks.GIMMIGHOUL_CHEST,
|
||||
CobblemonBlocks.DISPLAY_CASE,
|
||||
CobblemonBlocks.LECTERN
|
||||
CobblemonBlocks.LECTERN,
|
||||
CobblemonBlocks.STADIUM
|
||||
)
|
||||
|
||||
this.createBoatModelLayers()
|
||||
@@ -290,6 +285,7 @@ object CobblemonClient {
|
||||
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.GILDED_CHEST, ::GildedChestBlockRenderer)
|
||||
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.DISPLAY_CASE, ::DisplayCaseRenderer)
|
||||
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.LECTERN, ::LecternBlockEntityRenderer)
|
||||
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.STADIUM, ::StadiumBlockRenderer)
|
||||
}
|
||||
|
||||
private fun registerEntityRenderers() {
|
||||
|
||||
+1
-4
@@ -13,8 +13,8 @@ import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.bedrockk.molang.runtime.value.StringValue
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.Rollable
|
||||
import com.cobblemon.mod.common.api.entity.PokemonSideDelegate
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.addEntityFunctions
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.addFunctions
|
||||
import com.cobblemon.mod.common.api.pokeball.PokeBalls
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonSpecies
|
||||
@@ -42,11 +42,8 @@ import net.minecraft.sounds.SoundEvent
|
||||
import net.minecraft.sounds.SoundSource
|
||||
import net.minecraft.world.InteractionHand
|
||||
import net.minecraft.world.entity.Entity
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import org.joml.Matrix3f
|
||||
import org.joml.Vector3f
|
||||
|
||||
class PokemonClientDelegate : PosableState(), PokemonSideDelegate {
|
||||
companion object {
|
||||
|
||||
@@ -8,25 +8,22 @@
|
||||
|
||||
package com.cobblemon.mod.common.client.gui
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.CobblemonItems
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.api.gui.drawPosablePortrait
|
||||
import com.cobblemon.mod.common.api.text.darkGray
|
||||
import com.cobblemon.mod.common.api.text.red
|
||||
import com.cobblemon.mod.common.api.text.text
|
||||
import com.cobblemon.mod.common.client.CobblemonClient
|
||||
import com.cobblemon.mod.common.client.CobblemonResources
|
||||
import com.cobblemon.mod.common.client.gui.battle.BattleGUI
|
||||
import com.cobblemon.mod.common.client.gui.portrait.FullyAnimatedPortraitDrawer
|
||||
import com.cobblemon.mod.common.client.gui.portrait.SelectedAnimatedPortraitDrawer
|
||||
import com.cobblemon.mod.common.client.gui.portrait.InanimatePortraitDrawer
|
||||
import com.cobblemon.mod.common.client.gui.portrait.PortraitStyle
|
||||
import com.cobblemon.mod.common.client.gui.toast.CobblemonToast
|
||||
import com.cobblemon.mod.common.client.keybind.boundKey
|
||||
import com.cobblemon.mod.common.client.keybind.keybinds.HidePartyBinding
|
||||
import com.cobblemon.mod.common.client.keybind.keybinds.SummaryBinding
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.client.render.getDepletableRedGreen
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.FloatingState
|
||||
import com.cobblemon.mod.common.client.render.renderScaledGuiItemIcon
|
||||
import com.cobblemon.mod.common.pokemon.Gender
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
@@ -58,10 +55,7 @@ class PartyOverlay : Gui(Minecraft.getInstance()) {
|
||||
private val genderIconMale = cobblemonResource("textures/gui/party/party_gender_male.png")
|
||||
private val genderIconFemale = cobblemonResource("textures/gui/party/party_gender_female.png")
|
||||
private val portraitBackground = cobblemonResource("textures/gui/party/party_slot_portrait_background.png")
|
||||
|
||||
private val inanimatePortraitDrawer = InanimatePortraitDrawer()
|
||||
private val selectedAnimatedPortraitDrawer = SelectedAnimatedPortraitDrawer()
|
||||
private val fullyAnimatedPortraitDrawer = FullyAnimatedPortraitDrawer()
|
||||
val state = FloatingState()
|
||||
}
|
||||
|
||||
private val screenExemptions: List<Class<out Screen>> = listOf(
|
||||
@@ -90,7 +84,6 @@ class PartyOverlay : Gui(Minecraft.getInstance()) {
|
||||
|
||||
override fun render(context: GuiGraphics, tickCounter: DeltaTracker) {
|
||||
val partialDeltaTicks = tickCounter.realtimeDeltaTicks
|
||||
|
||||
val minecraft = Minecraft.getInstance()
|
||||
|
||||
// Hiding if a Screen is open and not exempt
|
||||
@@ -160,14 +153,15 @@ class PartyOverlay : Gui(Minecraft.getInstance()) {
|
||||
0.0
|
||||
)
|
||||
|
||||
val portraitDrawer = when (Cobblemon.config.partyPortraitAnimations) {
|
||||
PortraitStyle.NEVER_ANIMATE -> inanimatePortraitDrawer
|
||||
PortraitStyle.ANIMATE_SELECTED -> selectedAnimatedPortraitDrawer
|
||||
PortraitStyle.ALWAYS_ANIMATE -> fullyAnimatedPortraitDrawer
|
||||
}
|
||||
|
||||
portraitDrawer.draw(pokemon, matrices, partialDeltaTicks, selectedSlot == index, index)
|
||||
state.currentAspects = pokemon.aspects
|
||||
|
||||
drawPosablePortrait(
|
||||
identifier = pokemon.species.resourceIdentifier,
|
||||
matrixStack = matrices,
|
||||
partialTicks = 0F, // partialDeltaTicks, //Before you get any funny ideas about party animated pokemon, make sure they each get their own state instead of sharing.
|
||||
contextScale = pokemon.form.baseScale,
|
||||
state = state
|
||||
)
|
||||
matrices.popPose()
|
||||
context.disableScissor()
|
||||
}
|
||||
|
||||
-16
@@ -1,16 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.gui.interact.wheel
|
||||
|
||||
enum class InteractTypePokemon {
|
||||
SHOULDER,
|
||||
HELD_ITEM,
|
||||
COSMETIC_ITEM,
|
||||
RIDE;
|
||||
}
|
||||
+5
-5
@@ -36,7 +36,7 @@ class InteractWheelButton(
|
||||
const val BUTTON_SIZE = 69
|
||||
const val TEXTURE_HEIGHT = BUTTON_SIZE * 2
|
||||
const val ICON_SIZE = 32
|
||||
const val ICON_SCALE = 0.5F
|
||||
const val ICON_SCALE = 0.5f
|
||||
const val ICON_OFFSET = 26.5
|
||||
}
|
||||
|
||||
@@ -55,10 +55,10 @@ class InteractWheelButton(
|
||||
height = BUTTON_SIZE,
|
||||
vOffset = if (isHovered(mouseX.toFloat(), mouseY.toFloat()) && isEnabled) BUTTON_SIZE else 0,
|
||||
textureHeight = TEXTURE_HEIGHT,
|
||||
alpha = if (isEnabled) 1f else 0.4F
|
||||
alpha = if (isEnabled) 1f else 0.4f
|
||||
)
|
||||
|
||||
if(isEnabled && isHovered(mouseX.toFloat(), mouseY.toFloat())){
|
||||
if(isHovered(mouseX.toFloat(), mouseY.toFloat())){
|
||||
tooltipText?.let {
|
||||
context.renderTooltip(Minecraft.getInstance().font, Component.translatable(it), mouseX, mouseY)
|
||||
}
|
||||
@@ -74,7 +74,7 @@ class InteractWheelButton(
|
||||
y = iconY,
|
||||
width = ICON_SIZE,
|
||||
height = ICON_SIZE,
|
||||
alpha = if (isEnabled) 1F else 0.2F,
|
||||
alpha = if (isEnabled) 1f else 0.4f,
|
||||
red = colour.x,
|
||||
green = colour.y,
|
||||
blue = colour.z,
|
||||
@@ -93,7 +93,7 @@ class InteractWheelButton(
|
||||
y = (iconY.toFloat() - ICON_SIZE),
|
||||
width = ICON_SIZE,
|
||||
height = ICON_SIZE,
|
||||
alpha = if (isEnabled) 1F else 0.4F,
|
||||
alpha = if (isEnabled) 1f else 0.4f,
|
||||
red = colour.x,
|
||||
green = colour.y,
|
||||
blue = colour.z,
|
||||
|
||||
+1
-1
@@ -104,7 +104,7 @@ class InteractWheelGUI(private val options: Multimap<Orientation, InteractWheelO
|
||||
tooltipText = option?.tooltipText,
|
||||
x = x,
|
||||
y = y,
|
||||
isEnabled = option != null && option.enabled,
|
||||
isEnabled = option != null,
|
||||
colour = option?.colour ?: { null },
|
||||
onPress = { option?.onPress?.invoke() },
|
||||
canHover = { a: Double, b: Double -> !isMouseInCenter(a, b)}
|
||||
|
||||
+11
-45
@@ -21,70 +21,36 @@ import com.cobblemon.mod.common.net.messages.server.trade.OfferTradePacket
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.google.common.collect.ArrayListMultimap
|
||||
import com.google.common.collect.Multimap
|
||||
import java.util.UUID
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.network.chat.Component
|
||||
import java.util.*
|
||||
import org.joml.Vector3f
|
||||
|
||||
fun createPokemonInteractGui(pokemonID: UUID, canMountShoulder: Boolean, canGiveHeld: Boolean, canGiveCosmetic: Boolean, canRide: Boolean): InteractWheelGUI {
|
||||
fun createPokemonInteractGui(pokemonID: UUID, canMountShoulder: Boolean): InteractWheelGUI {
|
||||
val mountShoulder = InteractWheelOption(
|
||||
iconResource = cobblemonResource("textures/gui/interact/icon_shoulder.png"),
|
||||
tooltipText = "cobblemon.ui.interact.mount.shoulder",
|
||||
enabled = canMountShoulder,
|
||||
onPress = {
|
||||
if (canMountShoulder) {
|
||||
InteractPokemonPacket(pokemonID, InteractTypePokemon.SHOULDER).sendToServer()
|
||||
InteractPokemonPacket(pokemonID, true).sendToServer()
|
||||
closeGUI()
|
||||
}
|
||||
}
|
||||
)
|
||||
val giveHeldItem = InteractWheelOption(
|
||||
val giveItem = InteractWheelOption(
|
||||
iconResource = cobblemonResource("textures/gui/interact/icon_held_item.png"),
|
||||
tooltipText = "cobblemon.ui.interact.give.item",
|
||||
enabled = canGiveHeld,
|
||||
onPress = {
|
||||
if (canGiveHeld) {
|
||||
InteractPokemonPacket(pokemonID, InteractTypePokemon.HELD_ITEM).sendToServer()
|
||||
closeGUI()
|
||||
}
|
||||
InteractPokemonPacket(pokemonID, false).sendToServer()
|
||||
closeGUI()
|
||||
}
|
||||
)
|
||||
val giveCosmeticItem = InteractWheelOption(
|
||||
iconResource = cobblemonResource("textures/gui/interact/icon_cosmetic_item.png"),
|
||||
tooltipText = "cobblemon.ui.interact.give.cosmetic_item",
|
||||
enabled = canGiveCosmetic,
|
||||
onPress = {
|
||||
if (canGiveCosmetic) {
|
||||
InteractPokemonPacket(pokemonID, InteractTypePokemon.COSMETIC_ITEM).sendToServer()
|
||||
closeGUI()
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
val ride = InteractWheelOption(
|
||||
iconResource = cobblemonResource("textures/gui/interact/icon_ride.png"),
|
||||
tooltipText = "cobblemon.ui.interact.ride",
|
||||
onPress = {
|
||||
if (canRide) {
|
||||
InteractPokemonPacket(pokemonID, InteractTypePokemon.RIDE).sendToServer()
|
||||
closeGUI()
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
val options: Multimap<Orientation, InteractWheelOption> = ArrayListMultimap.create()
|
||||
options.put(Orientation.TOP_RIGHT, giveHeldItem)
|
||||
options.put(Orientation.BOTTOM_RIGHT, giveCosmeticItem)
|
||||
options.put(Orientation.BOTTOM_LEFT, ride)
|
||||
options.put(Orientation.TOP_LEFT, mountShoulder)
|
||||
CobblemonEvents.POKEMON_INTERACTION_GUI_CREATION.post(PokemonInteractionGUICreationEvent(
|
||||
pokemonID = pokemonID,
|
||||
mountShoulder = canMountShoulder,
|
||||
giveHeld = canGiveHeld,
|
||||
giveCosmetic = canGiveCosmetic,
|
||||
canRide = canRide,
|
||||
options = options
|
||||
))
|
||||
options.put(Orientation.TOP_RIGHT, giveItem)
|
||||
if (canMountShoulder) {
|
||||
options.put(Orientation.TOP_LEFT, mountShoulder)
|
||||
}
|
||||
CobblemonEvents.POKEMON_INTERACTION_GUI_CREATION.post(PokemonInteractionGUICreationEvent(pokemonID, canMountShoulder, options))
|
||||
return InteractWheelGUI(options, Component.translatable("cobblemon.ui.interact.pokemon"))
|
||||
}
|
||||
|
||||
|
||||
-1
@@ -14,7 +14,6 @@ import org.joml.Vector3f
|
||||
data class InteractWheelOption(
|
||||
val iconResource: ResourceLocation,
|
||||
val secondaryIconResource: ResourceLocation? = null,
|
||||
val enabled: Boolean = true,
|
||||
val tooltipText: String?,
|
||||
val colour: () -> Vector3f? = { null },
|
||||
val onPress: () -> Unit
|
||||
|
||||
-63
@@ -1,63 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.gui.portrait
|
||||
|
||||
import com.cobblemon.mod.common.api.gui.drawPosablePortrait
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.FloatingState
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.mojang.blaze3d.vertex.PoseStack
|
||||
import java.util.UUID
|
||||
|
||||
/**
|
||||
* Base logic for a [PortraitDrawer] that animates a portrait based on conditions.
|
||||
*/
|
||||
abstract class AnimatedPortraitDrawer : PortraitDrawer {
|
||||
|
||||
private val state = FloatingState()
|
||||
|
||||
private val stateAtIndex = hashMapOf<Int, Pair<UUID, FloatingState>>()
|
||||
|
||||
override fun draw(pokemon: Pokemon, poseStack: PoseStack, partialTicks: Float, isSelected: Boolean, index: Int) {
|
||||
drawPosablePortrait(
|
||||
identifier = pokemon.species.resourceIdentifier,
|
||||
matrixStack = poseStack,
|
||||
partialTicks = this.ticksFor(pokemon, isSelected, partialTicks),
|
||||
contextScale = pokemon.form.baseScale,
|
||||
state = this.stateFor(pokemon, isSelected, index)
|
||||
)
|
||||
}
|
||||
|
||||
protected abstract fun shouldAnimate(pokemon: Pokemon, isSelected: Boolean): Boolean
|
||||
|
||||
protected open fun ticksFor(pokemon: Pokemon, isSelected: Boolean, partialTicks: Float): Float {
|
||||
return if (this.shouldAnimate(pokemon, isSelected)) partialTicks else 0F
|
||||
}
|
||||
|
||||
protected open fun stateFor(pokemon: Pokemon, isSelected: Boolean, index: Int): FloatingState {
|
||||
if (!this.shouldAnimate(pokemon, isSelected)) {
|
||||
return this.state
|
||||
}
|
||||
val state = this.stateAtIndex.getOrPut(index) { pokemon.uuid to this.createState(pokemon) }
|
||||
if (state.first != pokemon.uuid) {
|
||||
val newState = this.createState(pokemon)
|
||||
this.stateAtIndex[index] = pokemon.uuid to newState
|
||||
return newState
|
||||
}
|
||||
return state.second
|
||||
}
|
||||
|
||||
protected open fun createState(pokemon: Pokemon): FloatingState {
|
||||
val state = FloatingState()
|
||||
state.currentAspects = pokemon.aspects
|
||||
return state
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
-25
@@ -1,25 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.gui.portrait
|
||||
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import net.minecraft.client.GraphicsStatus
|
||||
|
||||
/**
|
||||
* Draws portraits if the Pokemon is not fainted.
|
||||
*
|
||||
* Meant for client with [GraphicsStatus.FABULOUS].
|
||||
*/
|
||||
class FullyAnimatedPortraitDrawer : AnimatedPortraitDrawer() {
|
||||
|
||||
override fun shouldAnimate(pokemon: Pokemon, isSelected: Boolean): Boolean {
|
||||
return !pokemon.isFainted()
|
||||
}
|
||||
|
||||
}
|
||||
-37
@@ -1,37 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.gui.portrait
|
||||
|
||||
import com.cobblemon.mod.common.api.gui.drawPosablePortrait
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.FloatingState
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.mojang.blaze3d.vertex.PoseStack
|
||||
import net.minecraft.client.GraphicsStatus
|
||||
|
||||
/**
|
||||
* The simplest implementation, the Pokemon is drawn staying still.
|
||||
*
|
||||
* Meant for client with [GraphicsStatus.FAST].
|
||||
*/
|
||||
class InanimatePortraitDrawer : PortraitDrawer {
|
||||
|
||||
private val state = FloatingState()
|
||||
|
||||
override fun draw(pokemon: Pokemon, poseStack: PoseStack, partialTicks: Float, isSelected: Boolean, index: Int) {
|
||||
state.currentAspects = pokemon.aspects
|
||||
drawPosablePortrait(
|
||||
identifier = pokemon.species.resourceIdentifier,
|
||||
matrixStack = poseStack,
|
||||
partialTicks = 0F,
|
||||
contextScale = pokemon.form.baseScale,
|
||||
state = this.state
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.gui.portrait
|
||||
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.mojang.blaze3d.vertex.PoseStack
|
||||
|
||||
/**
|
||||
* Responsible for drawing a Pokemon portrait.
|
||||
*
|
||||
* Keep in mind any scaling and handling of the [PoseStack] must be done on the implementations using this system.
|
||||
*/
|
||||
fun interface PortraitDrawer {
|
||||
|
||||
/**
|
||||
* Draws the portrait.
|
||||
*
|
||||
* @param pokemon The [Pokemon] being drawn.
|
||||
* @param poseStack The [PoseStack] being used.
|
||||
* @param partialTicks The partial ticks of the screen using this.
|
||||
* @param isSelected If the [pokemon] is considered in a selected state for example hovered or the current party member.
|
||||
* @param index The index of the [pokemon] in the screen using this.
|
||||
*/
|
||||
fun draw(
|
||||
pokemon: Pokemon,
|
||||
poseStack: PoseStack,
|
||||
partialTicks: Float,
|
||||
isSelected: Boolean,
|
||||
index: Int
|
||||
)
|
||||
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.gui.portrait
|
||||
|
||||
import com.mojang.serialization.Codec
|
||||
import net.minecraft.util.StringRepresentable
|
||||
|
||||
enum class PortraitStyle : StringRepresentable {
|
||||
|
||||
NEVER_ANIMATE,
|
||||
ANIMATE_SELECTED,
|
||||
ALWAYS_ANIMATE;
|
||||
|
||||
override fun getSerializedName(): String = this.name
|
||||
|
||||
companion object {
|
||||
|
||||
@JvmStatic
|
||||
val CODEC: Codec<PortraitStyle> = StringRepresentable.fromEnum(PortraitStyle::values)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
-25
@@ -1,25 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.gui.portrait
|
||||
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import net.minecraft.client.GraphicsStatus
|
||||
|
||||
/**
|
||||
* Draws portraits if the Pokemon is not fainted and selected.
|
||||
*
|
||||
* Meant for client with [GraphicsStatus.FANCY].
|
||||
*/
|
||||
class SelectedAnimatedPortraitDrawer : AnimatedPortraitDrawer() {
|
||||
|
||||
override fun shouldAnimate(pokemon: Pokemon, isSelected: Boolean): Boolean {
|
||||
return !pokemon.isFainted() && isSelected
|
||||
}
|
||||
|
||||
}
|
||||
@@ -9,7 +9,6 @@
|
||||
package com.cobblemon.mod.common.client.gui.summary
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.CobblemonNetwork.sendToServer
|
||||
import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.api.moves.Move
|
||||
@@ -37,7 +36,6 @@ import com.cobblemon.mod.common.client.gui.summary.widgets.screens.moves.MovesWi
|
||||
import com.cobblemon.mod.common.client.gui.summary.widgets.screens.stats.StatWidget
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.VaryingModelRepository
|
||||
import com.cobblemon.mod.common.net.messages.server.pokemon.update.SetItemHiddenPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.party.MovePartyPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.party.SwapPartyPokemonPacket
|
||||
import com.cobblemon.mod.common.pokemon.Gender
|
||||
@@ -91,14 +89,10 @@ class Summary private constructor(party: Collection<Pokemon?>, private val edita
|
||||
private val typeSpacerDoubleResource = cobblemonResource("textures/gui/summary/type_spacer_double.png")
|
||||
private val sideSpacerResource = cobblemonResource("textures/gui/summary/summary_side_spacer.png")
|
||||
private val evolveButtonResource = cobblemonResource("textures/gui/summary/summary_evolve_button.png")
|
||||
private val itemVisibleResource = cobblemonResource("textures/gui/summary/item_visible.png")
|
||||
private val itemHiddenResource = cobblemonResource("textures/gui/summary/item_hidden.png")
|
||||
private val tabIconInfo = cobblemonResource("textures/gui/summary/summary_tab_icon_info.png")
|
||||
private val tabIconMoves = cobblemonResource("textures/gui/summary/summary_tab_icon_moves.png")
|
||||
private val tabIconStats = cobblemonResource("textures/gui/summary/summary_tab_icon_stats.png")
|
||||
val iconShinyResource = cobblemonResource("textures/gui/summary/icon_shiny.png")
|
||||
val iconHeldItemResource = cobblemonResource("textures/gui/summary/icon_item_held.png")
|
||||
val iconCosmeticItemResource = cobblemonResource("textures/gui/summary/icon_item_cosmetic.png")
|
||||
|
||||
/**
|
||||
* Attempts to open this screen for a client.
|
||||
@@ -126,7 +120,6 @@ class Summary private constructor(party: Collection<Pokemon?>, private val edita
|
||||
private lateinit var modelWidget: ModelWidget
|
||||
private lateinit var nicknameEntryWidget: NicknameEntryWidget
|
||||
private val summaryTabs = mutableListOf<SummaryTab>()
|
||||
private var showCosmeticItem = false
|
||||
private var mainScreenIndex = INFO
|
||||
var sideScreenIndex = PARTY
|
||||
private val party = ArrayList(party)
|
||||
@@ -175,45 +168,6 @@ class Summary private constructor(party: Collection<Pokemon?>, private val edita
|
||||
)
|
||||
)
|
||||
|
||||
//Item Visibility Button
|
||||
val HeldItemVisibilityButton = SummaryButton(
|
||||
buttonX = x + 3F,
|
||||
buttonY = y + 104F,
|
||||
buttonWidth = 32,
|
||||
buttonHeight = 32,
|
||||
scale = 0.5F,
|
||||
resource = itemVisibleResource,
|
||||
activeResource = itemHiddenResource,
|
||||
clickAction = {
|
||||
selectedPokemon.heldItemVisible = !selectedPokemon.heldItemVisible
|
||||
(it as SummaryButton).buttonActive = !selectedPokemon.heldItemVisible
|
||||
modelWidget.heldItem = if (selectedPokemon.heldItemVisible) selectedPokemon.heldItem else null
|
||||
// Send item visibility update to server
|
||||
sendToServer(SetItemHiddenPacket(selectedPokemon.uuid, selectedPokemon.heldItemVisible))
|
||||
},
|
||||
renderRequirement = { !selectedPokemon.heldItemNoCopy().isEmpty && !showCosmeticItem },
|
||||
clickRequirement = { !selectedPokemon.heldItemNoCopy().isEmpty && !showCosmeticItem }
|
||||
)
|
||||
|
||||
addRenderableWidget(HeldItemVisibilityButton)
|
||||
|
||||
// Held/Cosmetic Item Button
|
||||
addRenderableWidget(
|
||||
SummaryButton(
|
||||
buttonX = x + 67F,
|
||||
buttonY = y + 113F,
|
||||
buttonWidth = 12,
|
||||
buttonHeight = 12,
|
||||
scale = 0.5F,
|
||||
resource = iconCosmeticItemResource,
|
||||
activeResource = iconHeldItemResource,
|
||||
clickAction = {
|
||||
showCosmeticItem = !showCosmeticItem
|
||||
(it as SummaryButton).buttonActive = showCosmeticItem
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
// Init Tabs
|
||||
summaryTabs.clear()
|
||||
summaryTabs.add(
|
||||
@@ -283,7 +237,6 @@ class Summary private constructor(party: Collection<Pokemon?>, private val edita
|
||||
rotationY = 325F,
|
||||
offsetY = -10.0,
|
||||
shouldFollowCursor = true,
|
||||
heldItem = if (selectedPokemon.heldItemVisible) selectedPokemon.heldItem else null
|
||||
)
|
||||
addRenderableOnly(this.modelWidget)
|
||||
}
|
||||
@@ -325,7 +278,6 @@ class Summary private constructor(party: Collection<Pokemon?>, private val edita
|
||||
|
||||
if (::modelWidget.isInitialized) {
|
||||
modelWidget.pokemon = selectedPokemon.asRenderablePokemon()
|
||||
modelWidget.heldItem = if (selectedPokemon.heldItemVisible) selectedPokemon.heldItem else null
|
||||
}
|
||||
|
||||
if (this::nicknameEntryWidget.isInitialized) {
|
||||
@@ -589,19 +541,19 @@ class Summary private constructor(party: Collection<Pokemon?>, private val edita
|
||||
scale = SCALE
|
||||
)
|
||||
|
||||
// Held/Cosmetic Item
|
||||
val displayedItem = if (showCosmeticItem) selectedPokemon.cosmeticItem else selectedPokemon.heldItemNoCopy()
|
||||
// Held Item
|
||||
val heldItem = selectedPokemon.heldItemNoCopy()
|
||||
val itemX = x + 3
|
||||
val itemY = y + 104
|
||||
if (!displayedItem.isEmpty) {
|
||||
context.renderItem(displayedItem, itemX, itemY)
|
||||
context.renderItemDecorations(Minecraft.getInstance().font, displayedItem, itemX, itemY)
|
||||
if (!heldItem.isEmpty) {
|
||||
context.renderItem(heldItem, itemX, itemY)
|
||||
context.renderItemDecorations(Minecraft.getInstance().font, heldItem, itemX, itemY)
|
||||
}
|
||||
|
||||
drawScaledText(
|
||||
context = context,
|
||||
text = lang("${if (showCosmeticItem) "cosmetic" else "held"}_item"),
|
||||
x = x + 24,
|
||||
text = lang("held_item"),
|
||||
x = x + 27,
|
||||
y = y + 114.5,
|
||||
scale = SCALE
|
||||
)
|
||||
@@ -624,19 +576,14 @@ class Summary private constructor(party: Collection<Pokemon?>, private val edita
|
||||
scale = SCALE
|
||||
)
|
||||
|
||||
matrices.pushPose()
|
||||
// Prevent widgets from being overlapped by other components
|
||||
matrices.translate(0.0, 0.0, 1000.0)
|
||||
|
||||
// Render all added Widgets
|
||||
super.render(context, mouseX, mouseY, delta)
|
||||
|
||||
// Render Item Tooltip
|
||||
if (!displayedItem.isEmpty) {
|
||||
if (!heldItem.isEmpty) {
|
||||
val itemHovered = mouseX.toFloat() in (itemX.toFloat()..(itemX.toFloat() + 16)) && mouseY.toFloat() in (itemY.toFloat()..(itemY.toFloat() + 16))
|
||||
if (itemHovered) context.renderTooltip(Minecraft.getInstance().font, displayedItem, mouseX, mouseY)
|
||||
if (itemHovered) context.renderTooltip(Minecraft.getInstance().font, heldItem, mouseX, mouseY)
|
||||
}
|
||||
matrices.popPose()
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+5
-12
@@ -38,8 +38,7 @@ class SummaryButton(
|
||||
private val silent: Boolean = false,
|
||||
private val boldText: Boolean = true,
|
||||
private val largeText: Boolean = true,
|
||||
private val textScale: Float = 1F,
|
||||
private val scale: Float = 1F
|
||||
private val textScale: Float = 1F
|
||||
): Button(buttonX.toInt(), buttonY.toInt(), buttonWidth.toInt(), buttonHeight.toInt(), text, clickAction, DEFAULT_NARRATION), CobblemonRenderable {
|
||||
|
||||
companion object {
|
||||
@@ -63,13 +62,12 @@ class SummaryButton(
|
||||
blitk(
|
||||
matrixStack = matrices,
|
||||
texture = if (buttonActive && activeResource != null) activeResource else resource,
|
||||
x = buttonX / scale,
|
||||
y = buttonY / scale,
|
||||
x = buttonX,
|
||||
y = buttonY,
|
||||
width = buttonWidth,
|
||||
height = buttonHeight,
|
||||
vOffset = if (hoverTexture && isButtonHovered(pMouseX, pMouseY)) buttonHeight else 0,
|
||||
vOffset = if (hoverTexture && isHovered) buttonHeight else 0,
|
||||
textureHeight = if (hoverTexture) (buttonHeight.toFloat() * 2) else buttonHeight,
|
||||
scale = scale
|
||||
)
|
||||
|
||||
// Render Text
|
||||
@@ -86,7 +84,7 @@ class SummaryButton(
|
||||
}
|
||||
|
||||
override fun mouseClicked(mouseX: Double, mouseY: Double, button: Int): Boolean {
|
||||
if (this.clickRequirement.invoke(this) && isButtonHovered(mouseX, mouseY)) {
|
||||
if (this.clickRequirement.invoke(this)) {
|
||||
super.mouseClicked(mouseX, mouseY, button)
|
||||
}
|
||||
return false
|
||||
@@ -104,9 +102,4 @@ class SummaryButton(
|
||||
this.buttonX = x
|
||||
this.buttonY = y
|
||||
}
|
||||
|
||||
fun isButtonHovered(mouseX: Number, mouseY: Number): Boolean {
|
||||
return mouseX.toFloat() in (buttonX..(buttonX + (buttonWidth.toFloat() * scale)))
|
||||
&& mouseY.toFloat() in (buttonY..(buttonY + (buttonHeight.toFloat() * scale)))
|
||||
}
|
||||
}
|
||||
-13
@@ -12,12 +12,10 @@ import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.client.gui.drawProfilePokemon
|
||||
import com.cobblemon.mod.common.client.gui.calculateHeadYawAndPitch
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.FloatingState
|
||||
import com.cobblemon.mod.common.client.render.item.HeldItemRenderer
|
||||
import com.cobblemon.mod.common.pokemon.RenderablePokemon
|
||||
import com.cobblemon.mod.common.util.math.fromEulerXYZDegrees
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import org.joml.Quaternionf
|
||||
import org.joml.Vector3f
|
||||
|
||||
@@ -30,7 +28,6 @@ class ModelWidget(
|
||||
var offsetY: Double = 0.0,
|
||||
val playCryOnClick: Boolean = false,
|
||||
val shouldFollowCursor: Boolean = false,
|
||||
var heldItem: ItemStack? = null
|
||||
): SoundlessWidget(pX, pY, pWidth, pHeight, Component.literal("Summary - ModelWidget")) {
|
||||
|
||||
companion object {
|
||||
@@ -42,11 +39,8 @@ class ModelWidget(
|
||||
set (value) {
|
||||
field = value
|
||||
currentYawAndPitch = Pair(0f, 0f)
|
||||
state = FloatingState()
|
||||
}
|
||||
|
||||
private val heldItemRenderer = HeldItemRenderer()
|
||||
|
||||
var state = FloatingState()
|
||||
var lookStartTime: Long? = null
|
||||
var currentYawAndPitch: Pair<Float, Float> = Pair(0f, 0f)
|
||||
@@ -112,13 +106,6 @@ class ModelWidget(
|
||||
headPitch = currentYawAndPitch.second,
|
||||
)
|
||||
|
||||
heldItemRenderer.renderOnModel(
|
||||
heldItem?: ItemStack.EMPTY,
|
||||
state.locatorStates,
|
||||
matrices,
|
||||
context.bufferSource()
|
||||
)
|
||||
|
||||
matrices.popPose()
|
||||
context.disableScissor()
|
||||
|
||||
|
||||
+1
-7
@@ -15,12 +15,6 @@ import net.minecraft.client.Minecraft
|
||||
|
||||
object InteractPokemonUIPacketHandler: ClientNetworkPacketHandler<InteractPokemonUIPacket> {
|
||||
override fun handle(packet: InteractPokemonUIPacket, client: Minecraft) {
|
||||
client.setScreen(createPokemonInteractGui(
|
||||
packet.pokemonID,
|
||||
packet.canMountShoulder,
|
||||
packet.canGiveHeld,
|
||||
packet.canGiveCosmetic,
|
||||
packet.canRide
|
||||
))
|
||||
client.setScreen(createPokemonInteractGui(packet.pokemonID, packet.canMountShoulder))
|
||||
}
|
||||
}
|
||||
+196
@@ -0,0 +1,196 @@
|
||||
/*
|
||||
* 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.block.entity.StadiumBlockEntity
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.drone.DroneModel
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.drone.DroneState
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.RenderContext
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.VaryingModelRepository
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.mojang.blaze3d.vertex.PoseStack
|
||||
import com.mojang.math.Axis
|
||||
import net.minecraft.client.renderer.MultiBufferSource
|
||||
import net.minecraft.client.renderer.RenderType
|
||||
import net.minecraft.client.renderer.blockentity.BlockEntityRenderer
|
||||
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider
|
||||
import net.minecraft.client.renderer.texture.OverlayTexture
|
||||
import net.minecraft.core.Direction
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.world.level.block.HorizontalDirectionalBlock
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
|
||||
class StadiumBlockRenderer(ctx: BlockEntityRendererProvider.Context) : BlockEntityRenderer<StadiumBlockEntity> {
|
||||
val context = RenderContext().also {
|
||||
it.put(RenderContext.DO_QUIRKS, false)
|
||||
it.put(RenderContext.RENDER_STATE, RenderContext.RenderState.BLOCK)
|
||||
}
|
||||
|
||||
private var pathIndex = 0
|
||||
private var animationTime = 0.0
|
||||
private val droneSpeed = 0.10
|
||||
|
||||
override fun render(
|
||||
blockEntity: StadiumBlockEntity,
|
||||
tickDelta: Float,
|
||||
poseStack: PoseStack,
|
||||
multiBufferSource: MultiBufferSource,
|
||||
light: Int,
|
||||
overlay: Int
|
||||
) {
|
||||
val blockState = blockEntity.blockState
|
||||
val yRot = blockState.getValue(HorizontalDirectionalBlock.FACING).toYRot()
|
||||
|
||||
val isClientSide = blockEntity.level?.isClientSide == true
|
||||
if (!isClientSide) return
|
||||
|
||||
val stadiumBlockState = blockEntity.level?.getBlockState(blockEntity.blockPos) ?: return
|
||||
if (stadiumBlockState.block != CobblemonBlocks.STADIUM) {
|
||||
return
|
||||
}
|
||||
|
||||
val droneState = blockEntity.droneState
|
||||
|
||||
|
||||
poseStack.pushPose()
|
||||
if (blockEntity.isInUse) {
|
||||
if (blockEntity.pathPoints.isEmpty()) {
|
||||
|
||||
poseStack.popPose()
|
||||
return
|
||||
}
|
||||
|
||||
spawnDebugParticles(blockEntity) // debug particles
|
||||
|
||||
// Center the drone at the block's center
|
||||
poseStack.translate(0.5, -3.0, 0.5)
|
||||
//poseStack.mulPose(Axis.XP.rotationDegrees(180F))
|
||||
//poseStack.mulPose(Axis.YP.rotationDegrees(180F))
|
||||
|
||||
val points = blockEntity.pathPoints
|
||||
val nextIndex = (pathIndex + 1) % points.size
|
||||
|
||||
val currentPoint = points[pathIndex]
|
||||
val nextPoint = points[nextIndex]
|
||||
|
||||
animationTime += tickDelta * droneSpeed
|
||||
if (animationTime >= 1.0) {
|
||||
animationTime = 0.0
|
||||
pathIndex = nextIndex
|
||||
}
|
||||
|
||||
val interpolatedPos = currentPoint.lerp(nextPoint, animationTime.toDouble())
|
||||
|
||||
println("DEBUG: Drone moving between points:")
|
||||
println(" - Current Point: ${currentPoint}")
|
||||
println(" - Next Point: ${nextPoint}")
|
||||
println(" - Interpolated Position: $interpolatedPos")
|
||||
|
||||
poseStack.translate(interpolatedPos.x - blockEntity.blockPos.x,
|
||||
interpolatedPos.y - blockEntity.blockPos.y,
|
||||
interpolatedPos.z - blockEntity.blockPos.z)
|
||||
|
||||
println("DEBUG: Drone position interpolated to: $interpolatedPos")
|
||||
|
||||
poseStack.mulPose(Axis.YP.rotationDegrees(-yRot))
|
||||
poseStack.mulPose(Axis.ZP.rotationDegrees(180F)) // flip the drone right side up
|
||||
|
||||
renderDrone(droneState, "sleep", tickDelta, poseStack, 1.0F, multiBufferSource, light)
|
||||
} else {
|
||||
val yRot = blockState.getValue(HorizontalDirectionalBlock.FACING).toYRot()
|
||||
|
||||
val poseEntry = poseStack.last()
|
||||
val matrix = poseEntry.pose()
|
||||
|
||||
poseStack.translate(0.5, 0.0, 0.5)
|
||||
poseStack.mulPose(Axis.YP.rotationDegrees(yRot))
|
||||
|
||||
val posX = matrix.m03()
|
||||
val posY = matrix.m13()
|
||||
val posZ = matrix.m23()
|
||||
|
||||
println("DEBUG: Drone is NOT in use. Rendering default position at: x=$posX, y=$posY, z=$posZ")
|
||||
|
||||
poseStack.mulPose(Axis.ZP.rotationDegrees(180F))
|
||||
renderDrone(droneState, "sleep", tickDelta, poseStack, 1.0F, multiBufferSource, light)
|
||||
}
|
||||
|
||||
poseStack.popPose()
|
||||
}
|
||||
|
||||
fun renderDrone(
|
||||
state: DroneState,
|
||||
pose: String,
|
||||
tickDelta: Float,
|
||||
poseStack: PoseStack,
|
||||
scale: Float = 1F,
|
||||
multiBufferSource: MultiBufferSource,
|
||||
light: Int,
|
||||
) {
|
||||
state.updatePartialTicks(tickDelta)
|
||||
|
||||
val droneResource: ResourceLocation = cobblemonResource("rotom_drone")
|
||||
|
||||
val model = VaryingModelRepository.getPoser(droneResource, state) as DroneModel
|
||||
val texture = VaryingModelRepository.getTexture(droneResource, state)
|
||||
|
||||
val buffer = multiBufferSource.getBuffer(RenderType.entityCutout(texture))
|
||||
model.bufferProvider = multiBufferSource
|
||||
|
||||
state.currentModel = model
|
||||
state.setPose(pose)
|
||||
|
||||
model.context = context
|
||||
context.put(RenderContext.TEXTURE, texture)
|
||||
context.put(RenderContext.RENDER_STATE, RenderContext.RenderState.BLOCK)
|
||||
context.put(RenderContext.POSABLE_STATE, state)
|
||||
|
||||
model.applyAnimations(
|
||||
entity = null,
|
||||
state = state,
|
||||
headYaw = 0F,
|
||||
headPitch = 0F,
|
||||
limbSwing = 0F,
|
||||
limbSwingAmount = 0F,
|
||||
ageInTicks = state.animationSeconds * 20
|
||||
)
|
||||
|
||||
poseStack.scale(scale, scale, scale)
|
||||
|
||||
// TODO: Make drone lighting dynamic (simply using the light arg makes the drone always appear dark)
|
||||
model.withLayerContext(multiBufferSource, state, VaryingModelRepository.getLayers(droneResource, state)) {
|
||||
model.render(context, poseStack, buffer, 200, OverlayTexture.NO_OVERLAY, -0x1)
|
||||
}
|
||||
model.setDefault()
|
||||
}
|
||||
|
||||
private fun spawnDebugParticles(blockEntity: StadiumBlockEntity) {
|
||||
val world = blockEntity.level ?: return
|
||||
if (!world.isClientSide) return // Only run on the client-side
|
||||
|
||||
for (point in blockEntity.pathPoints) {
|
||||
world.addParticle(
|
||||
net.minecraft.core.particles.ParticleTypes.FLAME, // Test particle (changeable)
|
||||
point.x, point.y, point.z, // Position of the particle
|
||||
0.0, 0.02, 0.0 // Slight upward motion
|
||||
)
|
||||
}
|
||||
|
||||
// Spawn a special particle at the next interpolation point
|
||||
if (blockEntity.pathPoints.isNotEmpty()) {
|
||||
val nextPoint = blockEntity.pathPoints[(pathIndex + 1) % blockEntity.pathPoints.size]
|
||||
world.addParticle(
|
||||
net.minecraft.core.particles.ParticleTypes.END_ROD, // Different effect for next point
|
||||
nextPoint.x, nextPoint.y, nextPoint.z,
|
||||
0.0, 0.05, 0.0
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
-122
@@ -1,122 +0,0 @@
|
||||
/*
|
||||
* 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.item
|
||||
|
||||
import com.cobblemon.mod.common.api.tags.CobblemonItemTags
|
||||
import com.cobblemon.mod.common.api.tags.CobblemonItemTags.WEARABLE_FACE_ITEMS
|
||||
import com.cobblemon.mod.common.api.tags.CobblemonItemTags.WEARABLE_HAT_ITEMS
|
||||
import com.cobblemon.mod.common.client.entity.PokemonClientDelegate
|
||||
import com.cobblemon.mod.common.client.render.MatrixWrapper
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.NullObjectParser
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.mojang.blaze3d.vertex.PoseStack
|
||||
import com.mojang.math.Axis
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.renderer.LightTexture
|
||||
import net.minecraft.client.renderer.MultiBufferSource
|
||||
import net.minecraft.client.renderer.texture.OverlayTexture
|
||||
import net.minecraft.world.item.ItemDisplayContext
|
||||
import net.minecraft.world.item.ItemStack
|
||||
|
||||
class HeldItemRenderer() {
|
||||
private val itemRenderer = Minecraft.getInstance().itemRenderer
|
||||
private var displayContext = ItemDisplayContext.FIXED
|
||||
private var scale = 1.0f
|
||||
|
||||
fun render(
|
||||
entity: PokemonEntity?,
|
||||
item: ItemStack,
|
||||
locators: Map<String, MatrixWrapper>,
|
||||
poseStack: PoseStack,
|
||||
buffer: MultiBufferSource,
|
||||
light: Int,
|
||||
seed: Int
|
||||
) {
|
||||
if (item.isEmpty) return
|
||||
displayContext = ItemDisplayContext.FIXED
|
||||
|
||||
poseStack.pushPose()
|
||||
when {
|
||||
(locators.containsKey("item_face") && item.`is`(WEARABLE_FACE_ITEMS)) -> {
|
||||
displayContext = ItemDisplayContext.HEAD
|
||||
poseStack.mulPose(locators["item_face"]!!.matrix)
|
||||
poseStack.translate(0f, 0f, .28f * scale)
|
||||
poseStack.scale(0.7f * scale, 0.7f * scale, 0.7f * scale)
|
||||
}
|
||||
(locators.containsKey("item_hat") && item.`is`(WEARABLE_HAT_ITEMS)) -> {
|
||||
displayContext = ItemDisplayContext.HEAD
|
||||
poseStack.mulPose(locators["item_hat"]!!.matrix)
|
||||
poseStack.translate(0f, -0.26f * scale, 0f)
|
||||
poseStack.scale(.68f * scale, .68f * scale, .68f * scale)
|
||||
}
|
||||
(locators.containsKey("item")) -> {
|
||||
updateModifiers("item",locators)
|
||||
poseStack.mulPose(locators["item"]!!.matrix)
|
||||
when(displayContext) {
|
||||
ItemDisplayContext.FIXED -> {
|
||||
poseStack.translate(0f, 0.01666f * scale, 0f)
|
||||
poseStack.scale(.5f * scale, .5f * scale, .5f * scale)
|
||||
poseStack.mulPose(Axis.XP.rotationDegrees(90f))
|
||||
}
|
||||
ItemDisplayContext.THIRD_PERSON_RIGHT_HAND -> {
|
||||
poseStack.translate(0.075f* scale, 0f * scale, -0.05f* scale)
|
||||
poseStack.scale(scale, scale, scale)
|
||||
poseStack.mulPose(Axis.XP.rotationDegrees(-90f))
|
||||
poseStack.mulPose(Axis.YP.rotationDegrees(-90f))
|
||||
}
|
||||
else -> {
|
||||
poseStack.scale(scale, scale, scale)
|
||||
}
|
||||
}
|
||||
}
|
||||
else -> { // Don't render any item
|
||||
poseStack.popPose()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
itemRenderer.renderStatic(entity, item, displayContext, false, poseStack, buffer, null, light, OverlayTexture.NO_OVERLAY, seed)
|
||||
poseStack.popPose()
|
||||
}
|
||||
|
||||
fun renderOnModel(
|
||||
item: ItemStack,
|
||||
locators: Map<String, MatrixWrapper>,
|
||||
poseStack: PoseStack,
|
||||
buffer: MultiBufferSource,
|
||||
light: Int = LightTexture.pack(11, 7)
|
||||
){
|
||||
if (!item.`is`(CobblemonItemTags.HIDDEN_ITEMS)) render(null, item, locators, poseStack, buffer, light, 0)
|
||||
}
|
||||
|
||||
fun renderOnEntity(
|
||||
entity: PokemonEntity,
|
||||
delegate: PokemonClientDelegate,
|
||||
poseStack: PoseStack,
|
||||
buffer: MultiBufferSource,
|
||||
light: Int
|
||||
) {
|
||||
val shownItem = entity.shownItem
|
||||
val locators: Map<String, MatrixWrapper> = delegate.locatorStates
|
||||
|
||||
render(entity, shownItem, locators, poseStack, buffer, light, 0)
|
||||
}
|
||||
|
||||
private fun updateModifiers(name: String, locators: Map<String, MatrixWrapper>) {
|
||||
locators.forEach { (locator: String, m: MatrixWrapper) ->
|
||||
val modifiers: Map<String, Float>
|
||||
if (locator.startsWith("_null_$name[")) {
|
||||
modifiers = NullObjectParser.parseNullObject(locator).modifiers
|
||||
if (modifiers.containsKey("scale")) scale = modifiers["scale"]!!
|
||||
if (modifiers.containsKey("mode")) displayContext = ItemDisplayContext.entries[((modifiers["mode"]!!).toInt()) % 9]
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
-19
@@ -9,7 +9,6 @@
|
||||
package com.cobblemon.mod.common.client.render.layer
|
||||
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonSpecies
|
||||
import com.cobblemon.mod.common.client.render.item.HeldItemRenderer
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.FloatingState
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.PosableModel
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.RenderContext
|
||||
@@ -36,7 +35,6 @@ import net.minecraft.nbt.NbtOps
|
||||
import net.minecraft.nbt.Tag
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.item.ItemStack
|
||||
|
||||
class PokemonOnShoulderRenderer<T : Player>(renderLayerParent: RenderLayerParent<T, PlayerModel<T>>) : RenderLayer<T, PlayerModel<T>>(renderLayerParent) {
|
||||
|
||||
@@ -44,8 +42,6 @@ class PokemonOnShoulderRenderer<T : Player>(renderLayerParent: RenderLayerParent
|
||||
it.put(RenderContext.RENDER_STATE, RenderContext.RenderState.WORLD)
|
||||
}
|
||||
|
||||
private val heldItemRenderer = HeldItemRenderer()
|
||||
|
||||
var leftState = FloatingState()
|
||||
var lastRenderedLeft: ShoulderData? = null
|
||||
var rightState = FloatingState()
|
||||
@@ -159,14 +155,6 @@ class PokemonOnShoulderRenderer<T : Player>(renderLayerParent: RenderLayerParent
|
||||
model.withLayerContext(buffer, state, VaryingModelRepository.getLayers(shoulderData.species.resourceIdentifier, state)) {
|
||||
model.render(context, matrixStack, vertexConsumer, packedLight, OverlayTexture.NO_OVERLAY, -0x1)
|
||||
}
|
||||
|
||||
heldItemRenderer.renderOnModel(
|
||||
shoulderData.shownItem,
|
||||
state.locatorStates,
|
||||
matrixStack,
|
||||
buffer
|
||||
)
|
||||
|
||||
model.setDefault()
|
||||
matrixStack.popPose()
|
||||
livingEntity.level().profiler.pop()
|
||||
@@ -189,7 +177,7 @@ class PokemonOnShoulderRenderer<T : Player>(renderLayerParent: RenderLayerParent
|
||||
if (!shoulderNbt.contains(DataKeys.SHOULDER_SPECIES)) {
|
||||
return Pokemon.CLIENT_CODEC.decode(NbtOps.INSTANCE, shoulderNbt.getCompound(DataKeys.POKEMON))
|
||||
.map { it.first }
|
||||
.mapOrElse({ ShoulderData(pokemonUUID, it.species, it.form, it.aspects, it.scaleModifier, it.heldItem) }, { null })
|
||||
.mapOrElse({ ShoulderData(pokemonUUID, it.species, it.form, it.aspects, it.scaleModifier) }, { null })
|
||||
}
|
||||
val species = PokemonSpecies.getByIdentifier(ResourceLocation.parse(shoulderNbt.getString(DataKeys.SHOULDER_SPECIES)))
|
||||
?: return null
|
||||
@@ -197,10 +185,7 @@ class PokemonOnShoulderRenderer<T : Player>(renderLayerParent: RenderLayerParent
|
||||
val form = species.forms.firstOrNull { it.name == formName } ?: species.standardForm
|
||||
val aspects = shoulderNbt.getList(DataKeys.SHOULDER_ASPECTS, Tag.TAG_STRING.toInt()).map { it.asString }.toSet()
|
||||
val scaleModifier = shoulderNbt.getFloat(DataKeys.SHOULDER_SCALE_MODIFIER)
|
||||
val shownItem = Minecraft.getInstance().level?.registryAccess()
|
||||
?.let { ItemStack.parseOptional(it, shoulderNbt.getCompound(DataKeys.SHOULDER_ITEM)) }
|
||||
?: ItemStack.EMPTY
|
||||
return ShoulderData(pokemonUUID, species, form, aspects, scaleModifier, shownItem)
|
||||
return ShoulderData(pokemonUUID, species, form, aspects, scaleModifier)
|
||||
}
|
||||
|
||||
private data class ShoulderCache(
|
||||
@@ -213,8 +198,7 @@ class PokemonOnShoulderRenderer<T : Player>(renderLayerParent: RenderLayerParent
|
||||
val species: Species,
|
||||
val form: FormData,
|
||||
val aspects: Set<String>,
|
||||
val scaleModifier: Float,
|
||||
val shownItem: ItemStack
|
||||
val scaleModifier: Float
|
||||
)
|
||||
|
||||
companion object {
|
||||
|
||||
+2
-2
@@ -69,11 +69,11 @@ class LocatorAccess(
|
||||
* Updates all of the locator states with the position at this current frame.
|
||||
* This is the same logic as ModelPart uses, that's why we reuse ModelPart#rotate.
|
||||
*/
|
||||
fun update(matrixStack: PoseStack, entity: Entity?, scale: Float, state: MutableMap<String, MatrixWrapper>, isRoot: Boolean = false) {
|
||||
fun update(matrixStack: PoseStack, entity: Entity, scale: Float, state: MutableMap<String, MatrixWrapper>, isRoot: Boolean = false) {
|
||||
matrixStack.pushPose()
|
||||
joint.transform(matrixStack)
|
||||
|
||||
if (isRoot && null!=entity) {
|
||||
if (isRoot) {
|
||||
matrixStack.pushPose()
|
||||
matrixStack.scale(-1F, -1F, 1F)
|
||||
state.getOrPut("root") { MatrixWrapper() }.updateMatrix(matrixStack.last().pose())
|
||||
|
||||
-50
@@ -1,50 +0,0 @@
|
||||
/*
|
||||
* 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.models.blockbench
|
||||
|
||||
/**
|
||||
* Uses the name of null objects in a model to get modifier values for a locator.
|
||||
* @author Josh
|
||||
*/
|
||||
object NullObjectParser {
|
||||
fun parseNullObject(input: String): NullObjectModifier {
|
||||
// Extract modifiedLocator
|
||||
val modifiedLocator = input.replaceFirst("^_null_".toRegex(), "").replace("\\[.*\\]$".toRegex(), "")
|
||||
|
||||
// Extract modifiers
|
||||
val modifiers: MutableMap<String, Float> = HashMap()
|
||||
val start = input.indexOf('[')
|
||||
val end = input.indexOf(']')
|
||||
|
||||
if (start != -1 && end != -1 && end > start) {
|
||||
val modifierPart = input.substring(start + 1, end)
|
||||
val modifierPairs = modifierPart.split(",".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
|
||||
|
||||
for (pair in modifierPairs) {
|
||||
val keyValue = pair.split("=".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
|
||||
if (keyValue.size == 2) {
|
||||
val key = keyValue[0].trim { it <= ' ' }
|
||||
try {
|
||||
val value = keyValue[1].trim { it <= ' ' }.toFloat()
|
||||
modifiers[key] = value
|
||||
} catch (e: NumberFormatException) {
|
||||
System.err.println("Invalid number format for: " + keyValue[1])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NullObjectModifier(modifiedLocator, modifiers)
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores modifiers for a particular locator.
|
||||
*/
|
||||
class NullObjectModifier(val locatorName: String, val modifiers: Map<String, Float>)
|
||||
}
|
||||
+10
-34
@@ -11,7 +11,6 @@ package com.cobblemon.mod.common.client.render.models.blockbench
|
||||
import com.bedrockk.molang.runtime.MoLangRuntime
|
||||
import com.bedrockk.molang.runtime.struct.QueryStruct
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.Rollable
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.addFunctions
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.setup
|
||||
@@ -51,11 +50,8 @@ import net.minecraft.client.renderer.MultiBufferSource
|
||||
import net.minecraft.client.renderer.RenderStateShard
|
||||
import net.minecraft.client.renderer.RenderType
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.util.Mth
|
||||
import net.minecraft.world.entity.Entity
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import org.joml.Matrix4f
|
||||
import org.joml.Vector3f
|
||||
|
||||
/**
|
||||
* A model that can be posed and animated using [PoseAnimation]s and [ActiveAnimation]s. This
|
||||
@@ -566,16 +562,14 @@ open class PosableModel(@Transient override val rootPart: Bone) : ModelFrame {
|
||||
applyPose(state, pose, 1F)
|
||||
|
||||
val primaryAnimation = state.primaryAnimation
|
||||
val shouldRotateHead = if(entity is PokemonEntity) entity.riding.shouldRotatePokemonHead(entity) else true
|
||||
|
||||
// Quirks will run if there is no primary animation running and quirks are enabled for this context.
|
||||
if (primaryAnimation == null && context.request(RenderContext.DO_QUIRKS) != false) {
|
||||
// Remove any quirk animations that don't exist in our current pose
|
||||
state.quirks.keys.filterNot(pose.quirks::contains).forEach(state.quirks::remove)
|
||||
|
||||
// Tick all the quirks
|
||||
pose.quirks.forEach {
|
||||
it.apply(context, this, state, limbSwing, limbSwingAmount, ageInTicks, if(shouldRotateHead) headYaw else 0f, if(shouldRotateHead) headPitch else 0f, 1F)
|
||||
it.apply(context, this, state, limbSwing, limbSwingAmount, ageInTicks, headYaw, headPitch, 1F)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -583,7 +577,6 @@ open class PosableModel(@Transient override val rootPart: Bone) : ModelFrame {
|
||||
// The pose intensity is the complement of the primary animation's curve. This is used to blend the primary.
|
||||
state.poseIntensity = 1 - primaryAnimation.curve((state.animationSeconds - primaryAnimation.started) / primaryAnimation.duration)
|
||||
// If the primary animation is done after running we're going to clean things up.
|
||||
//Set headYaw and headPitch to zero if Pokemon shouldn't move head during riding
|
||||
if (!primaryAnimation.run(
|
||||
context,
|
||||
this,
|
||||
@@ -591,8 +584,8 @@ open class PosableModel(@Transient override val rootPart: Bone) : ModelFrame {
|
||||
limbSwing,
|
||||
limbSwingAmount,
|
||||
ageInTicks,
|
||||
if(shouldRotateHead) headYaw else 0f,
|
||||
if(shouldRotateHead) headPitch else 0f,
|
||||
headYaw,
|
||||
headPitch,
|
||||
1 - state.poseIntensity
|
||||
)
|
||||
) {
|
||||
@@ -604,11 +597,11 @@ open class PosableModel(@Transient override val rootPart: Bone) : ModelFrame {
|
||||
|
||||
// Run active animations and return back any that are done and can be removed.
|
||||
val removedActiveAnimations = state.activeAnimations.toList()
|
||||
.filterNot { it.run(context, this, state, limbSwing, limbSwingAmount, ageInTicks, if(shouldRotateHead) headYaw else 0f, if(shouldRotateHead) headPitch else 0f, 1F) }
|
||||
.filterNot { it.run(context, this, state, limbSwing, limbSwingAmount, ageInTicks, headYaw, headPitch, 1F) }
|
||||
state.activeAnimations.removeAll(removedActiveAnimations)
|
||||
// Applies the pose's animations.
|
||||
state.currentPose?.let(poses::get)
|
||||
?.apply(context, this, state, limbSwing, limbSwingAmount, ageInTicks, if(shouldRotateHead) headYaw else 0f, if(shouldRotateHead) headPitch else 0f)
|
||||
?.apply(context, this, state, limbSwing, limbSwingAmount, ageInTicks, headYaw, headPitch)
|
||||
// Updates the locator positions now that all the animations are in effect. This is the last thing we do!
|
||||
updateLocators(entity, state)
|
||||
}
|
||||
@@ -676,46 +669,29 @@ open class PosableModel(@Transient override val rootPart: Bone) : ModelFrame {
|
||||
* found and used from other client-side systems.
|
||||
*/
|
||||
fun updateLocators(entity: Entity?, state: PosableState) {
|
||||
entity ?: return
|
||||
val matrixStack = PoseStack()
|
||||
var scale = 1F
|
||||
// We could improve this to be generalized for other entities. First we'd have to figure out wtf is going on, though.
|
||||
if (entity is PokemonEntity) {
|
||||
if(entity.passengers.isNotEmpty() && entity.controllingPassenger is Rollable && (entity.controllingPassenger as Rollable).orientation != null){
|
||||
val controllingPassenger = entity.controllingPassenger
|
||||
val transformationMatrix = Matrix4f()
|
||||
val center = Vector3f(0f, entity.bbHeight/2, 0f)
|
||||
transformationMatrix.translate(center)
|
||||
transformationMatrix.mul(Matrix4f((controllingPassenger as Rollable).orientation!!))
|
||||
transformationMatrix.translate(center.negate())
|
||||
matrixStack.mulPose(transformationMatrix)
|
||||
} else {
|
||||
var yRot = Mth.lerp(state.getPartialTicks(), entity.yBodyRotO, entity.yBodyRot)
|
||||
yRot = Mth.wrapDegrees(yRot)
|
||||
matrixStack.mulPose(Axis.YP.rotationDegrees(180 - yRot))
|
||||
}
|
||||
matrixStack.mulPose(Axis.YP.rotationDegrees(180 - entity.yBodyRot))
|
||||
matrixStack.pushPose()
|
||||
matrixStack.scale(-1F, -1F, 1F)
|
||||
scale = entity.pokemon.form.baseScale * entity.pokemon.scaleModifier * (entity.delegate as PokemonClientDelegate).entityScaleModifier
|
||||
matrixStack.scale(scale, scale, scale)
|
||||
} else if (entity is EmptyPokeBallEntity) {
|
||||
var yRot = Mth.lerp(state.getPartialTicks(), entity.yRot, entity.yRotO)
|
||||
yRot = Mth.wrapDegrees(yRot)
|
||||
matrixStack.mulPose(Axis.YP.rotationDegrees(yRot))
|
||||
matrixStack.mulPose(Axis.YP.rotationDegrees(entity.yRot))
|
||||
matrixStack.pushPose()
|
||||
matrixStack.scale(1F, -1F, -1F)
|
||||
scale = 0.7F
|
||||
matrixStack.scale(scale, scale, scale)
|
||||
} else if (entity is GenericBedrockEntity) {
|
||||
var yRot = Mth.lerp(state.getPartialTicks(), entity.yRot, entity.yRotO)
|
||||
yRot = Mth.wrapDegrees(yRot)
|
||||
matrixStack.mulPose(Axis.YP.rotationDegrees(yRot))
|
||||
matrixStack.mulPose(Axis.YP.rotationDegrees(entity.yRot))
|
||||
matrixStack.pushPose()
|
||||
// Not 100% convinced we need the -1 on Y but if we needed it for the Poke Ball then probably?
|
||||
matrixStack.scale(1F, -1F, 1F)
|
||||
} else if (entity is NPCEntity) {
|
||||
var yRot = Mth.lerp(state.getPartialTicks(), entity.yBodyRotO, entity.yBodyRot)
|
||||
yRot = Mth.wrapDegrees(yRot)
|
||||
matrixStack.mulPose(Axis.YP.rotationDegrees(180 - yRot))
|
||||
matrixStack.mulPose(Axis.YP.rotationDegrees(180 - entity.yBodyRot))
|
||||
matrixStack.pushPose()
|
||||
matrixStack.scale(-1F, -1F, 1F)
|
||||
}
|
||||
|
||||
+1
-1
@@ -51,7 +51,7 @@ open class BedrockActiveAnimation(
|
||||
headPitch: Float,
|
||||
intensity: Float
|
||||
): Boolean {
|
||||
return animation.run(model, state, state.animationSeconds - startedSeconds, limbSwing, limbSwingAmount, ageInTicks, intensity).also {
|
||||
return animation.run(context, model, state, state.animationSeconds - startedSeconds, limbSwing, limbSwingAmount, ageInTicks, intensity).also {
|
||||
if (!it) {
|
||||
afterAction(context, state)
|
||||
}
|
||||
|
||||
+6
-39
@@ -14,17 +14,15 @@ import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.api.snowstorm.BedrockParticleOptions
|
||||
import com.cobblemon.mod.common.client.particle.ParticleStorm
|
||||
import com.cobblemon.mod.common.client.render.MatrixWrapper
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.PosableModel
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.PosableState
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pose.Bone
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.RenderContext
|
||||
import com.cobblemon.mod.common.util.effectiveName
|
||||
import com.cobblemon.mod.common.util.genericRuntime
|
||||
import com.cobblemon.mod.common.util.getString
|
||||
import com.cobblemon.mod.common.util.math.geometry.toRadians
|
||||
import com.cobblemon.mod.common.util.resolveDouble
|
||||
import java.util.SortedMap
|
||||
import java.util.TreeMap
|
||||
import net.minecraft.CrashReport
|
||||
import net.minecraft.ReportedException
|
||||
import net.minecraft.client.Minecraft
|
||||
@@ -35,6 +33,8 @@ import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.sounds.SoundEvent
|
||||
import net.minecraft.world.entity.Entity
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import org.joml.Matrix4f
|
||||
import java.util.*
|
||||
|
||||
data class BedrockAnimationGroup(
|
||||
val formatVersion: String,
|
||||
@@ -149,40 +149,7 @@ data class BedrockAnimation(
|
||||
/** Useful to have, gets set after loading the animation. */
|
||||
var name: String = ""
|
||||
|
||||
|
||||
fun run(
|
||||
model: PosableModel,
|
||||
state: PosableState,
|
||||
animationSeconds: Float,
|
||||
limbSwing: Float,
|
||||
limbSwingAmount: Float,
|
||||
ageInTicks: Float,
|
||||
intensity: Float
|
||||
): Boolean {
|
||||
return run(
|
||||
model.context,
|
||||
model.relevantPartsByName,
|
||||
model.rootPart,
|
||||
state,
|
||||
animationSeconds,
|
||||
limbSwing,
|
||||
limbSwingAmount,
|
||||
ageInTicks,
|
||||
intensity
|
||||
)
|
||||
}
|
||||
|
||||
fun run(
|
||||
context: RenderContext?,
|
||||
relevantPartsByName: Map<String, ModelPart>,
|
||||
rootPart: Bone?,
|
||||
state: PosableState,
|
||||
animationSeconds: Float,
|
||||
limbSwing: Float,
|
||||
limbSwingAmount: Float,
|
||||
ageInTicks: Float,
|
||||
intensity: Float
|
||||
): Boolean {
|
||||
fun run(context: RenderContext, model: PosableModel, state: PosableState, animationSeconds: Float, limbSwing: Float, limbSwingAmount: Float, ageInTicks: Float, intensity: Float): Boolean {
|
||||
var animationSeconds = animationSeconds
|
||||
if (shouldLoop) {
|
||||
animationSeconds %= animationLength.toFloat()
|
||||
@@ -197,7 +164,7 @@ data class BedrockAnimation(
|
||||
runtime.environment.setSimpleVariable("age_in_ticks", DoubleValue(ageInTicks.toDouble()))
|
||||
|
||||
boneTimelines.forEach { (boneName, timeline) ->
|
||||
val part = relevantPartsByName[boneName] ?: if (boneName == "root_part") (rootPart as? ModelPart) else null
|
||||
val part = model.relevantPartsByName[boneName] ?: if (boneName == "root_part") (model.rootPart as ModelPart) else null
|
||||
if (part !== null) {
|
||||
if (!timeline.position.isEmpty()) {
|
||||
val position = timeline.position.resolve(animationSeconds.toDouble(), runtime).scale(intensity.toDouble())
|
||||
@@ -217,7 +184,7 @@ data class BedrockAnimation(
|
||||
zRot += rotation.z.toFloat().toRadians()
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
val exception = IllegalStateException("Bad animation for entity: ${(context?.request(RenderContext.ENTITY))?.effectiveName()?.string ?: "unknown entity (riding animation?)"}", e)
|
||||
val exception = IllegalStateException("Bad animation for entity: ${(model.context.request(RenderContext.ENTITY))!!.effectiveName().string}", e)
|
||||
val crash = CrashReport("Cobblemon encountered an unexpected crash", exception)
|
||||
val section = crash.addCategory("Animation Details")
|
||||
section.setDetail("Pose", state.currentPose!!)
|
||||
|
||||
+1
-1
@@ -34,7 +34,7 @@ class BedrockPoseAnimation(val animation: BedrockAnimation) : PoseAnimation() {
|
||||
}
|
||||
|
||||
override fun setupAnim(context: RenderContext, model: PosableModel, state: PosableState, limbSwing: Float, limbSwingAmount: Float, ageInTicks: Float, headYaw: Float, headPitch: Float, intensity: Float) {
|
||||
animation.run(model, state, state.animationSeconds, limbSwing, limbSwingAmount, ageInTicks, intensity)
|
||||
animation.run(context, model, state, state.animationSeconds, limbSwing, limbSwingAmount, ageInTicks, intensity)
|
||||
}
|
||||
|
||||
override fun applyEffects(entity: Entity?, state: PosableState, previousSeconds: Float, newSeconds: Float) {
|
||||
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (C) 2025 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.models.blockbench.drone
|
||||
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.PosableModel
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.animation.PoseAnimation
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pose.Bone
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.quirk.ModelQuirk
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import net.minecraft.client.model.geom.ModelPart
|
||||
|
||||
/**
|
||||
* A model for rendering the Rotom drone used by the stadium block.
|
||||
*
|
||||
* @author Flarkinater
|
||||
* @since February 14th, 2025
|
||||
*/
|
||||
class DroneModel(root: Bone) : PosableModel(root) {
|
||||
@Transient
|
||||
@SerializedName("So this name can be literally anything, huh?")
|
||||
override val rootPart = (root as ModelPart).registerChildWithAllChildren(root.children.entries.first().key)
|
||||
var droneAnimations: Array<PoseAnimation> = emptyArray()
|
||||
var droneQuirks: Array<ModelQuirk<*>> = emptyArray()
|
||||
|
||||
override fun registerPoses() {
|
||||
registerPose(
|
||||
poseType = PoseType.SLEEP,
|
||||
animations = droneAnimations,
|
||||
quirks = droneQuirks
|
||||
)
|
||||
}
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (C) 2025 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.models.blockbench.drone
|
||||
|
||||
import com.cobblemon.mod.common.api.scheduling.SchedulingTracker
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.PosableState
|
||||
|
||||
/**
|
||||
* State for a drone Rotom attached to a stadium block.
|
||||
*
|
||||
* @author Flarkinater
|
||||
* @since February 12th, 2025
|
||||
*/
|
||||
class DroneState() : PosableState() {
|
||||
init {
|
||||
setPose("sleep")
|
||||
age = 0
|
||||
currentPartialTicks = 0F
|
||||
}
|
||||
|
||||
override fun getEntity() = null
|
||||
|
||||
override fun updatePartialTicks(partialTicks: Float) {
|
||||
currentPartialTicks += partialTicks / 2
|
||||
}
|
||||
|
||||
override val schedulingTracker = SchedulingTracker()
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user