From 0e1da10afb97c738fad987e29849f18d555b3dcf Mon Sep 17 00:00:00 2001 From: Falkreon Date: Tue, 13 Sep 2022 16:57:38 -0500 Subject: [PATCH] Double scarf gravity again, add trinket slot to stapler, add slot icons, improve API --- .../blue/endless/scarves/ScarvesApiImpl.java | 48 +++++++++++++++ .../java/blue/endless/scarves/ScarvesMod.java | 3 + .../blue/endless/scarves/api/ScarfLogic.java | 33 +++++++++++ .../blue/endless/scarves/api/ScarvesApi.java | 55 ++++++++++++++++++ .../scarves/api/ScarvesIntegration.java | 17 ++++-- .../scarves/api/WindVectorProvider.java | 10 ++++ .../endless/scarves/client/ScarfNode.java | 21 ++++++- .../endless/scarves/client/ScarvesClient.java | 13 +++-- .../gui/ScarfStaplerGuiDescription.java | 24 +++++++- .../scarves/textures/gui/slots/square.png | Bin 0 -> 1270 bytes 10 files changed, 212 insertions(+), 12 deletions(-) create mode 100644 src/main/java/blue/endless/scarves/ScarvesApiImpl.java create mode 100644 src/main/java/blue/endless/scarves/api/ScarvesApi.java create mode 100644 src/main/java/blue/endless/scarves/api/WindVectorProvider.java create mode 100644 src/main/resources/assets/scarves/textures/gui/slots/square.png diff --git a/src/main/java/blue/endless/scarves/ScarvesApiImpl.java b/src/main/java/blue/endless/scarves/ScarvesApiImpl.java new file mode 100644 index 0000000..d2fb35b --- /dev/null +++ b/src/main/java/blue/endless/scarves/ScarvesApiImpl.java @@ -0,0 +1,48 @@ +package blue.endless.scarves; + +import java.util.ArrayList; + +import blue.endless.scarves.api.FabricSquare; +import blue.endless.scarves.api.FabricSquareRegistry; +import blue.endless.scarves.api.ScarvesApi; +import blue.endless.scarves.api.WindVectorProvider; +import net.minecraft.block.Block; +import net.minecraft.item.ItemConvertible; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; + +public class ScarvesApiImpl implements ScarvesApi { + private static ScarvesApiImpl INSTANCE = new ScarvesApiImpl(); + + private ArrayList windProviders = new ArrayList<>(); + + public static ScarvesApiImpl getInstance() { + return INSTANCE; + } + + @Override + public void register(Block block, String textureId) { + FabricSquareRegistry.register(block, textureId); + } + + @Override + public void register(ItemConvertible item, FabricSquare square) { + FabricSquareRegistry.register(item, square); + } + + @Override + public void provideWind(WindVectorProvider wind) { + windProviders.add(wind); + } + + @Override + public Vec3d getWind(World world, Vec3d pos) { + Vec3d result = new Vec3d(0,0,0); + + for(WindVectorProvider provider : windProviders) { + result = result.add(provider.apply(world, pos)); + } + + return result; + } +} diff --git a/src/main/java/blue/endless/scarves/ScarvesMod.java b/src/main/java/blue/endless/scarves/ScarvesMod.java index 4f0f75f..fb7c4a0 100644 --- a/src/main/java/blue/endless/scarves/ScarvesMod.java +++ b/src/main/java/blue/endless/scarves/ScarvesMod.java @@ -3,6 +3,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import blue.endless.scarves.api.ScarvesApi; import blue.endless.scarves.api.ScarvesIntegration; import net.fabricmc.api.ModInitializer; import net.fabricmc.fabric.api.client.itemgroup.FabricItemGroupBuilder; @@ -18,6 +19,7 @@ public class ScarvesMod implements ModInitializer { public static ItemGroup ITEM_GROUP; + @SuppressWarnings("removal") @Override public void onInitialize() { ITEM_GROUP = FabricItemGroupBuilder @@ -32,6 +34,7 @@ public void onInitialize() { for (EntrypointContainer entrypoint : FabricLoader.getInstance().getEntrypointContainers(MODID, ScarvesIntegration.class)) { try { entrypoint.getEntrypoint().integrateWithScarves(); + entrypoint.getEntrypoint().integrateWithScarves(ScarvesApi.instance()); } catch (Throwable t) { LOGGER.error("Mod '"+entrypoint.getProvider().getMetadata().getId()+"' threw an exception trying to activate Scarves integration.", t); } diff --git a/src/main/java/blue/endless/scarves/api/ScarfLogic.java b/src/main/java/blue/endless/scarves/api/ScarfLogic.java index ecf4a97..f7e6a4a 100644 --- a/src/main/java/blue/endless/scarves/api/ScarfLogic.java +++ b/src/main/java/blue/endless/scarves/api/ScarfLogic.java @@ -2,6 +2,7 @@ import java.util.List; +import blue.endless.scarves.ScarvesApiImpl; import blue.endless.scarves.client.ScarfAttachment; import blue.endless.scarves.client.ScarfNode; import blue.endless.scarves.client.ScarvesClient; @@ -12,6 +13,7 @@ import net.minecraft.world.World; public class ScarfLogic { + public static double maxWindMagnitude = 0.5; /** * Updates the ScarfAttachment with new scarf data and applies gravity. Should be called each tick by an IScarfHaver. @@ -32,6 +34,7 @@ public static void updateScarfAttachment(ScarfAttachment attachment, World world } ScarfNode node = nodes.get(i); + node.setLastPosition(node.getPosition()); Vec3d prospectivePosition = node.getPosition().add(0, ScarvesClient.SCARF_GRAVITY, 0); BlockPos blockInThatPosition = new BlockPos(prospectivePosition.add(0,-ScarfNode.FABRIC_SQUARE_WIDTH,0)); if (world!=null) { @@ -39,6 +42,21 @@ public static void updateScarfAttachment(ScarfAttachment attachment, World world node.setPosition(prospectivePosition); } } + + Vec3d wind = ScarvesApiImpl.getInstance().getWind(world, node.getPosition()); + //cap wind + if (wind.lengthSquared()>maxWindMagnitude*maxWindMagnitude) { + wind = wind.normalize().multiply(maxWindMagnitude); + } + + //move it + prospectivePosition = node.getPosition().add(wind); + blockInThatPosition = new BlockPos(prospectivePosition); + if (world!=null) { + if (!world.isTopSolid(blockInThatPosition, entity)) { + node.setPosition(prospectivePosition); + } + } } } @@ -57,6 +75,21 @@ public static void updateGravityOnly(ScarfAttachment attachment, World world, En node.setPosition(prospectivePosition); } } + + Vec3d wind = ScarvesApiImpl.getInstance().getWind(world, node.getPosition()); + //cap wind + if (wind.lengthSquared()>maxWindMagnitude*maxWindMagnitude) { + wind = wind.normalize().multiply(maxWindMagnitude); + } + + //move it + prospectivePosition = node.getPosition().add(wind); + blockInThatPosition = new BlockPos(prospectivePosition); + if (world!=null) { + if (!world.isTopSolid(blockInThatPosition, entity)) { + node.setPosition(prospectivePosition); + } + } } } } diff --git a/src/main/java/blue/endless/scarves/api/ScarvesApi.java b/src/main/java/blue/endless/scarves/api/ScarvesApi.java new file mode 100644 index 0000000..f24c197 --- /dev/null +++ b/src/main/java/blue/endless/scarves/api/ScarvesApi.java @@ -0,0 +1,55 @@ +package blue.endless.scarves.api; + +import blue.endless.scarves.ScarvesApiImpl; +import net.minecraft.block.Block; +import net.minecraft.item.ItemConvertible; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; + +public interface ScarvesApi { + + public static ScarvesApi instance() { + return ScarvesApiImpl.getInstance(); + } + + //API + + /** + * Registers a block and allows it to be used in the left or right slots of the Scarf Stapler. The center of the + * texture will be used for the appearance of the square. + * + *

Notes: Animated textures, and textures that have been synthetically stitched into the texture atlas used for + * blocks and items, will all work seamlessly. Glowing blocks will automatically be rendered emissively. + * Substituting a different texture from the atlas, a vanilla texture, a texture from a namespace you do not own, + * these things are ALL ALLOWED. Cut out the middle of the diamond pickaxe texture and put it on a square, I'm not + * your dad. Basically, if you can figure out its name, it's fair game. Putting any invalid identifier, including + * "", will result in the pink checkers we all know and love. + * + * @param block The block to be accepted as a Fabric Square by the Scarf Stapler in its left or right slot. + * @param textureId The resulting fabric square's appearance. For example, if you use cube_all, the same identifier + * string that you use for the "all" texture parameter in the block's model will work here. + */ + void register(Block block, String textureId); + + /** + * Registers a block, item, or other item-like object and allows it to be used in the left or right slots of the + * Scarf Stapler. The appearance of the square will be governed completely by the FabricSquare provided. + * + *

See Also: {@link #register(Block, String)} + * + * @param item The item or item-like object to be accepted as a Fabric Square by the Scarf Stapler in its left or + * right slot. + * @param square The appearance this item should have when stitched to the end of a scarf. + */ + public void register(ItemConvertible item, FabricSquare square); + + /** + * Registers a wind provider. These providers let Scarves know about wind that may vary based on location in the + * world. This allows scarves to move in unison with other wind-affected objects, or serve as indicators of strong + * winds for mods which provide windmills. + * @param wind A function which yields a Vec3d of wind direction/strength at the provided world location. + */ + public void provideWind(WindVectorProvider wind); + + public Vec3d getWind(World world, Vec3d pos); +} diff --git a/src/main/java/blue/endless/scarves/api/ScarvesIntegration.java b/src/main/java/blue/endless/scarves/api/ScarvesIntegration.java index 9706ed1..7ca66fa 100644 --- a/src/main/java/blue/endless/scarves/api/ScarvesIntegration.java +++ b/src/main/java/blue/endless/scarves/api/ScarvesIntegration.java @@ -1,10 +1,19 @@ package blue.endless.scarves.api; +/** + * This interface can be registered as an entrypoint with the "scarves" id, in order to do mod interop things, such as + * making your blocks/items work in the Scarf Stapler, or letting Scarves know which way the wind + * is blowing. + */ public interface ScarvesIntegration { /** - * The main thing you can do here is safely call {@link FabricSquareRegistry#register(net.minecraft.block.Block, net.minecraft.util.Identifier)} - * - *

Set this class aside and don't touch it, and when this method is called register your blocks as fabric squares! + * Retained for ModFest compatibility. Please move to {@link #integrateWithScarves(ScarvesApi)} as soon as possible. */ - void integrateWithScarves(); + @Deprecated(forRemoval = true) + default void integrateWithScarves() {} + + /** + * Allows you to call methods on ScarvesApi without worrying about a hard dependency! + */ + default void integrateWithScarves(ScarvesApi api) {} } diff --git a/src/main/java/blue/endless/scarves/api/WindVectorProvider.java b/src/main/java/blue/endless/scarves/api/WindVectorProvider.java new file mode 100644 index 0000000..6db34a9 --- /dev/null +++ b/src/main/java/blue/endless/scarves/api/WindVectorProvider.java @@ -0,0 +1,10 @@ +package blue.endless.scarves.api; + +import java.util.function.BiFunction; + +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; + +@FunctionalInterface +public interface WindVectorProvider extends BiFunction { +} diff --git a/src/main/java/blue/endless/scarves/client/ScarfNode.java b/src/main/java/blue/endless/scarves/client/ScarfNode.java index a06b4c9..44a51d6 100644 --- a/src/main/java/blue/endless/scarves/client/ScarfNode.java +++ b/src/main/java/blue/endless/scarves/client/ScarfNode.java @@ -1,6 +1,7 @@ package blue.endless.scarves.client; import blue.endless.scarves.api.FabricSquare; +import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.Vec3d; public class ScarfNode { @@ -9,11 +10,13 @@ public class ScarfNode { /** Maximum d^2 allowed between fabric squares; the squared width of a square. */ public static final float SQUARED_WIDTH = FABRIC_SQUARE_WIDTH * FABRIC_SQUARE_WIDTH; protected Vec3d position; - protected Vec3d velocity; + protected Vec3d lastPosition; + //protected Vec3d velocity; protected FabricSquare square; public ScarfNode(Vec3d pos, FabricSquare square) { this.position = pos; + this.lastPosition = pos; this.square = square; }; @@ -29,10 +32,26 @@ public Vec3d getPosition() { return position; } + public Vec3d getLastPosition() { + return lastPosition; + } + public void setPosition(Vec3d pos) { position = pos; } + public void setLastPosition(Vec3d pos) { + lastPosition = pos; + } + + public Vec3d getLerpedPosition(double deltaTime) { + return new Vec3d( + MathHelper.lerp(deltaTime, lastPosition.x, position.x), + MathHelper.lerp(deltaTime, lastPosition.y, position.y), + MathHelper.lerp(deltaTime, lastPosition.z, position.z) + ); + } + public void setSquare(FabricSquare square) { this.square = square; } diff --git a/src/main/java/blue/endless/scarves/client/ScarvesClient.java b/src/main/java/blue/endless/scarves/client/ScarvesClient.java index 576c8c1..f5fd301 100644 --- a/src/main/java/blue/endless/scarves/client/ScarvesClient.java +++ b/src/main/java/blue/endless/scarves/client/ScarvesClient.java @@ -16,7 +16,7 @@ import net.minecraft.world.LightType; public class ScarvesClient implements ClientModInitializer { - public static final double SCARF_GRAVITY = -0.005; + public static final double SCARF_GRAVITY = -0.01; @Override public void onInitializeClient() { @@ -61,9 +61,10 @@ public static void beforeEntities(WorldRenderContext ctx) { Vec3d prevUp = new Vec3d(0,1,0).multiply(ScarfNode.FABRIC_SQUARE_WIDTH); for(int i=0; iit.isOf(ScarvesItems.SCARF)); + itemSlot.setIcon(new TextureIcon(SCARF_SLOT_ICON)); root.add(itemSlot, 4, 2); WItemSlot leftSlot = WItemSlot.of(blockInventory, ScarfStaplerBlockEntity.LEFT_SLOT); leftSlot.setFilter(FabricSquareRegistry::canBeStapled); + leftSlot.setIcon(new TextureIcon(SQUARE_SLOT_ICON)); root.add(leftSlot, 2, 2); WItemSlot rightSlot = WItemSlot.of(blockInventory, ScarfStaplerBlockEntity.RIGHT_SLOT); rightSlot.setFilter(FabricSquareRegistry::canBeStapled); + rightSlot.setIcon(new TextureIcon(SQUARE_SLOT_ICON)); root.add(rightSlot, 6, 2); WButton stapleButton = new WButton(Text.translatable("gui.scarves.staple")); @@ -52,6 +62,18 @@ public ScarfStaplerGuiDescription(int syncId, PlayerInventory playerInventory, S root.add(stapleButton, 2, 3, 5, 1); root.add(this.createPlayerInventoryPanel(), 0, 5); + + Map> inventoryMap = TrinketsApi.getTrinketComponent(playerInventory.player).get().getInventory(); + Map chestGroup = inventoryMap.get("chest"); + if (chestGroup!=null) { + TrinketInventory scarfInventory = chestGroup.get("scarf"); + if (scarfInventory!=null && scarfInventory.size()>0) { + WItemSlot playerScarfSlot = WItemSlot.of(scarfInventory, 0); + playerScarfSlot.setFilter(it->it.isOf(ScarvesItems.SCARF)); + playerScarfSlot.setIcon(new TextureIcon(SCARF_SLOT_ICON)); + root.add(playerScarfSlot, 0, 4); + } + } root.validate(this); } diff --git a/src/main/resources/assets/scarves/textures/gui/slots/square.png b/src/main/resources/assets/scarves/textures/gui/slots/square.png new file mode 100644 index 0000000000000000000000000000000000000000..bfdb357b08ecf9b434707169391a4b51c28b7f43 GIT binary patch literal 1270 zcmV zaB^>EX>4U6ba`-PAZ2)IW&i+q+U=HGa^)xthTmC5F9F? z;am~MJvn0*%;>mI(FAT~x(>*!a8@XIz_*F)6I%13$^3kpk&#BzrIY&(FIW28% zT2P;I+tj(0V+F+xg^|OoU^rgG+K*8&BDdTVX&$-f4Wm;fCdreO1~r& z%*>tTkcBu`?vjN>lc*?7cBwKXgr)N?0x4g)&=I#D;W`BZ4}vBWoDnRJkPZm@3AAlP`5O*h-h=38uaYaPd@Yqwsy_vp2^G>T#1=CUVEX>4Tx0C=2zkv&MmKpe$iQ;S+EqIM8*$WWauh>AFB6^c-y)C#RSm|Xe= zO&XFE7e~Rh;NZt%)xpJCR|i)?5c~jfbaGO3krMxx6k5c1aNLh~_a1le0HI!Hs@X9P zsG4P@;xRFkT@^cD(TyPb5kQ~BOnokyOu%z|-NVP%yC~1{KKJM7QF0~&d?N8I(+!Jw zgLrz=(mC%Fhgnflh|h_~47wokBiCh@-#8Z>7Ib`5kz)ZBsE`~#_#gc4*33^%xJjWH5O}fej}f4A7iiRM`}^3o8z+GO8Mx9~{z@H~ z`6Rv8(jrGd?>2C8-O}Ve;Bp5Te9|RDawI=ZA)g1{&*+=7z`!jKTyuMC?&I_UNK;pd z8{ps&7%foty2rb_+I#!=OtZfq0@8AN>k^r@0000{NklFN2;KmlN4pb)UY z7;SwM7#J8B7^;d2P!zz#VE|p81znPmhPJ*5C}J$=PD0m!O&-}0io;;kfWcq@3$FO3 gX-Y%}j02t<0cpu4-_Sp!%K!iX07*qoM6N<$g2TvDH~;_u literal 0 HcmV?d00001