Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update dev branch #80

Merged
merged 18 commits into from
Jun 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
[![Download on Modrinth](https://raw.githubusercontent.com/Prospector/badges/master/modrinth-badge-72h-padded.png)](https://modrinth.com/mod/wakes)
[![Modrinth Downloads](https://img.shields.io/modrinth/dt/wakes?logo=modrinth&color=00AF5C)](https://modrinth.com/mod/wakes) [![CurseForge Downloads](https://img.shields.io/curseforge/dt/884267?logo=curseforge&color=ff784d)](https://www.curseforge.com/minecraft/mc-mods/wakes)

## DISCLAIMER
My time developing the mod will be quite limited up until June 2024. Updates will not be as regular. I will try migrating the mod to newer versions of Minecraft but don't expect new features.

# Wakes
[![Download on Modrinth](https://raw.githubusercontent.com/Prospector/badges/master/modrinth-badge-72h-padded.png)](https://modrinth.com/mod/wakes)

# Wakes ![Modrinth Followers](https://img.shields.io/modrinth/followers/wakes)
### This mod aims to add simple wakes that fit the spirit of vanilla

![Splashes and wakes](https://github.com/Goby56/wakes/assets/60710855/c4a153ca-ec98-449a-a73d-68ec80934c56)
Expand Down
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
plugins {
id 'fabric-loom' version '1.2-SNAPSHOT'
id 'fabric-loom' version '1.6-SNAPSHOT'
id 'maven-publish'
id 'me.fallenbreath.yamlang' version '1.3.1'
}
Expand Down
17 changes: 8 additions & 9 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,21 @@ org.gradle.parallel=true

# Fabric Properties
# check these on https://fabricmc.net/develop
minecraft_version=1.20
yarn_mappings=1.20+build.1
loader_version=0.15.3
minecraft_version=1.20.1
yarn_mappings=1.20.1+build.10
loader_version=0.15.9

#Fabric api
fabric_version=0.83.0+1.20
fabric_version=0.92.1+1.20.1

# Mod Properties
mod_version=0.2.4
mod_version=0.2.4+1.20.1
maven_group=com.goby56.wakes
archives_base_name=wakes

# Dependencies
yacl_version=3.2.0+1.20
iris_version=1.6.4+1.20
modmenu_version=7.0.0
yacl_version=3.2.2+1.20
iris_version=1.6.17+1.20.1
modmenu_version=7.2.2
jankson_version=1.2.2
# TODO CHANGE SATIN TO 1.16.0 AND MC TO 1.20.4
satin_version=1.14.0
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
networkTimeout=10000
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
3 changes: 3 additions & 0 deletions src/main/java/com/goby56/wakes/WakesClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.goby56.wakes.command.DebugCommand;
import com.goby56.wakes.config.WakesConfig;
import com.goby56.wakes.event.PickBoat;
import com.goby56.wakes.event.WakeTicker;
import com.goby56.wakes.particle.ModParticles;
import com.goby56.wakes.render.SplashPlaneRenderer;
Expand All @@ -14,6 +15,7 @@
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents;
import net.fabricmc.fabric.api.event.client.player.ClientPickBlockGatherCallback;
import net.fabricmc.loader.api.FabricLoader;
import net.fabricmc.loader.api.metadata.ModMetadata;
import net.irisshaders.iris.api.v0.IrisApi;
Expand Down Expand Up @@ -49,6 +51,7 @@ public void onInitializeClient() {

// Game events
ClientTickEvents.END_WORLD_TICK.register(new WakeTicker());
ClientPickBlockGatherCallback.EVENT.register(new PickBoat());

// Rendering events
WorldRenderEvents.AFTER_TRANSLUCENT.register(new WakeTextureRenderer());
Expand Down
1 change: 1 addition & 0 deletions src/main/java/com/goby56/wakes/config/WakesConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ public class WakesConfig {
public int ticksBeforeFill = 2;
public boolean drawDebugBoxes = false;
public RenderType renderType = RenderType.AUTO;
public boolean useLODs = true;

// Appearance
public Resolution wakeResolution = Resolution.SIXTEEN;
Expand Down
3 changes: 3 additions & 0 deletions src/main/java/com/goby56/wakes/config/YACLIntegration.java
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,9 @@ public static Screen createScreen(Screen parent) {
.option(booleanOption("disable_mod", false)
.binding(false, () -> config.disableMod, val -> config.disableMod = val)
.build())
.option(booleanOption("use_lods", false)
.binding(false, () -> config.useLODs, val -> config.useLODs = val)
.build())
.group(intervalGroup(0, WakeColor.TRANSPARENT, -50, -45))
.group(intervalGroup(1, WakeColor.DARK_GRAY, -45, -35))
.group(intervalGroup(2, WakeColor.GRAY, -35, -30))
Expand Down
1 change: 1 addition & 0 deletions src/main/java/com/goby56/wakes/duck/ProducesWake.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
public interface ProducesWake {
boolean onWaterSurface();
float producingHeight();
void setProducingHeight(float h);
Vec3d getPrevPos();
void setPrevPos(Vec3d pos);
Vec3d getNumericalVelocity();
Expand Down
44 changes: 44 additions & 0 deletions src/main/java/com/goby56/wakes/event/PickBoat.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.goby56.wakes.event;

import net.fabricmc.fabric.api.event.client.player.ClientPickBlockGatherCallback;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.entity.vehicle.BoatEntity;
import net.minecraft.fluid.Fluids;
import net.minecraft.item.BoatItem;
import net.minecraft.item.ItemConvertible;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.registry.Registries;
import net.minecraft.util.Identifier;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.hit.HitResult;

import java.util.Random;

public class PickBoat implements ClientPickBlockGatherCallback {
@Override
public ItemStack pick(PlayerEntity player, HitResult result) {
if (player.raycast(5, 0, true) instanceof BlockHitResult fluidHit) {
if (player.getWorld().getFluidState(fluidHit.getBlockPos()).isOf(Fluids.WATER)) {
var boatTypes = BoatEntity.Type.values();
for (BoatEntity.Type boatType : boatTypes) {
ItemStack stack = getBoatFromType(boatType);
if (player.getInventory().contains(stack)) {
return stack;
}
}
if (player.isCreative()) {
int i = new Random().nextInt(boatTypes.length);
return getBoatFromType(boatTypes[i]);
}
}
}
return ItemStack.EMPTY;
}

private ItemStack getBoatFromType(BoatEntity.Type type) {
String waterCraft = type == BoatEntity.Type.BAMBOO ? "raft" : "boat";
return new ItemStack(Registries.ITEM.get(new Identifier(type.toString() + "_" + waterCraft)));
}
}
1 change: 1 addition & 0 deletions src/main/java/com/goby56/wakes/event/WakeTicker.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.goby56.wakes.event;

import com.goby56.wakes.render.SplashPlaneRenderer;
import com.goby56.wakes.render.WakeTextureRenderer;
import com.goby56.wakes.simulation.WakeHandler;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
import net.minecraft.client.world.ClientWorld;
Expand Down
1 change: 1 addition & 0 deletions src/main/java/com/goby56/wakes/mixin/DebugHudMixin.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ public class DebugHudMixin {
protected void getLeftText(CallbackInfoReturnable<List<String>> info) {
if (WakesClient.CONFIG_INSTANCE.drawDebugBoxes) {
info.getReturnValue().add(String.format("[Wakes] Rendering %d/%d wake nodes", WakeTextureRenderer.nodesRendered, WakeHandler.getInstance().getTotal()));
info.getReturnValue().add(String.format("[Wakes] Max tree depth: %d", WakeHandler.getInstance().getMaxDepth()));
}
}
}
36 changes: 36 additions & 0 deletions src/main/java/com/goby56/wakes/mixin/LilyPadFallMixin.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.goby56.wakes.mixin;

import com.goby56.wakes.WakesClient;
import com.goby56.wakes.config.enums.EffectSpawningRule;
import com.goby56.wakes.duck.ProducesWake;
import com.goby56.wakes.utils.WakesUtils;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.LilyPadBlock;
import net.minecraft.entity.Entity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraft.world.WorldAccess;
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(Block.class)
public class LilyPadFallMixin {

@Inject(at = @At("TAIL"), method = "onLandedUpon")
public void onLandedUpon(World world, BlockState state, BlockPos pos, Entity entity, float fallDistance, CallbackInfo ci) {
if (!world.getBlockState(pos.up()).isOf(Blocks.LILY_PAD)) return;
if (WakesClient.CONFIG_INSTANCE.disableMod) return;

EffectSpawningRule rule = WakesUtils.getEffectRuleFromSource(entity);
ProducesWake wakeProducer = (ProducesWake) entity;
if (rule.simulateWakes) {
wakeProducer.setProducingHeight(pos.getY() + world.getFluidState(pos).getHeight());
WakesUtils.placeFallSplash(entity);
}
}

}
7 changes: 6 additions & 1 deletion src/main/java/com/goby56/wakes/mixin/WakeSpawnerMixin.java
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,11 @@ public float producingHeight() {
return this.producingWaterLevel;
}

@Override
public void setProducingHeight(float h) {
this.producingWaterLevel = h;
}

@Override
public void setSplashPlane(SplashPlaneParticle particle) {
this.splashPlane = particle;
Expand Down Expand Up @@ -104,7 +109,7 @@ private void tick(CallbackInfo info) {
return;
}

if (this.onWaterSurface && this.horizontalNumericalVelocity > 1e-3 && !this.hasRecentlyTeleported) {
if (this.onWaterSurface && !this.hasRecentlyTeleported) {
if (this.producingWaterLevel == null)
this.producingWaterLevel = WakesUtils.getWaterLevel(this.world, thisEntity);

Expand Down
88 changes: 22 additions & 66 deletions src/main/java/com/goby56/wakes/render/DynamicWakeTexture.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,61 +19,41 @@

public class DynamicWakeTexture {

private static DynamicWakeTexture INSTANCE = null;
private final ArrayList<Texture> lods = new ArrayList<>();
private Texture currentTexture = null;
public int res;
public int glTexId;
public long imgPtr;

private DynamicWakeTexture() {
for (int i = 5; i >= 0; i--) {
lods.add(new Texture((int) Math.pow(2, i)));
}
}
public DynamicWakeTexture(int resolution) {
this.res = resolution;
this.glTexId = TextureUtil.generateTextureId();
this.imgPtr = MemoryUtil.nmemAlloc((long) resolution * resolution * 4);

public static DynamicWakeTexture getInstance() {
if (INSTANCE == null) {
INSTANCE = new DynamicWakeTexture();
}
return INSTANCE;
}
GlStateManager._bindTexture(this.glTexId);
GlStateManager._texParameter(GlConst.GL_TEXTURE_2D, GL12.GL_TEXTURE_MAX_LEVEL, 0);
GlStateManager._texParameter(GlConst.GL_TEXTURE_2D, GL12.GL_TEXTURE_MIN_LOD, 0);
GlStateManager._texParameter(GlConst.GL_TEXTURE_2D, GL12.GL_TEXTURE_MAX_LOD, 0);
GlStateManager._texParameter(GlConst.GL_TEXTURE_2D, GL14.GL_TEXTURE_LOD_BIAS, 0f);

private static int distToLOD(float distance) {
int pow = WakesClient.CONFIG_INSTANCE.wakeResolution.power;
return (int) Math.min(5, Math.floor(pow * (Math.exp(distance / (16 * pow)) - 2) + 5));
}
GlStateManager._texParameter(GlConst.GL_TEXTURE_2D, GL12.GL_TEXTURE_MIN_FILTER, GL12.GL_NEAREST);
GlStateManager._texParameter(GlConst.GL_TEXTURE_2D, GL12.GL_TEXTURE_MAG_FILTER, GL12.GL_NEAREST);

public void populatePixels(WakeNode node, float distance, int waterColor, float opacity) {
// TODO SAVE EACH NODE'S TEXTURE EACH TICK (HAVE THE TEXTURE READY FOR EACH FRAME)
// May decrease rendering time but will use up more memory
GlStateManager._texImage2D(GlConst.GL_TEXTURE_2D, 0, GlConst.GL_RGBA, resolution, resolution, 0, GlConst.GL_RGBA, GlConst.GL_UNSIGNED_BYTE, null);
}

// DISABLE LOD (DOESN'T LOOK GOOD YET)
// int lod = distToLOD(distance);
int lod = distToLOD(0);
Texture texture = lods.get(lod);
int samples = Math.max(1, WakeNode.res / texture.res);
for (int i = 0; i < texture.res; i++) {
for (int j = 0; j < texture.res; j++) {
float avg = 0;
for (int dy = 0; dy < samples; dy++) {
for (int dx = 0; dx < samples; dx++) {
avg = (node.u[0][i + dy + 1][j + dx + 1] + node.u[1][i + dy + 1][j + dx + 1] + node.u[2][i + dy + 1][j + dx + 1]) / 3;
}
}
int color = WakeColor.getColor(avg / (samples * samples), waterColor, opacity);
MemoryUtil.memPutInt(texture.imgPtr + (((i*(long) texture.res)+j)*4), color);
}
}
this.currentTexture = texture;
public static DynamicWakeTexture fromDist(float distance) {
int res = WakesClient.CONFIG_INSTANCE.wakeResolution.res;
return new DynamicWakeTexture((int) Math.ceil(res * Math.exp(-distance / res)));
}

public void render(Matrix4f matrix, float x, float y, float z, int light) {
GlStateManager._bindTexture(currentTexture.glTexId);
GlStateManager._bindTexture(this.glTexId);
GlStateManager._pixelStore(GlConst.GL_UNPACK_ROW_LENGTH, 0);
GlStateManager._pixelStore(GlConst.GL_UNPACK_SKIP_PIXELS, 0);
GlStateManager._pixelStore(GlConst.GL_UNPACK_SKIP_ROWS, 0);
GlStateManager._pixelStore(GlConst.GL_UNPACK_ALIGNMENT, 4);
GlStateManager._texSubImage2D(GlConst.GL_TEXTURE_2D, 0, 0, 0, currentTexture.res, currentTexture.res, GlConst.GL_RGBA, GlConst.GL_UNSIGNED_BYTE, currentTexture.imgPtr);
GlStateManager._texSubImage2D(GlConst.GL_TEXTURE_2D, 0, 0, 0, this.res, this.res, GlConst.GL_RGBA, GlConst.GL_UNSIGNED_BYTE, this.imgPtr);

RenderSystem.setShaderTexture(0, currentTexture.glTexId);
RenderSystem.setShaderTexture(0, this.glTexId);
RenderSystem.setShader(RenderType.getProgram());
RenderSystem.enableDepthTest(); // Is it THIS simple? https://github.com/Goby56/wakes/issues/46

Expand All @@ -92,28 +72,4 @@ public void render(Matrix4f matrix, float x, float y, float z, int light) {

Tessellator.getInstance().draw();
}

private static class Texture {
public int res;
public int glTexId;
public long imgPtr;

public Texture(int resolution) {
this.res = resolution;
this.glTexId = TextureUtil.generateTextureId();
this.imgPtr = MemoryUtil.nmemAlloc((long) resolution * resolution * 4);

GlStateManager._bindTexture(this.glTexId);
GlStateManager._texParameter(GlConst.GL_TEXTURE_2D, GL12.GL_TEXTURE_MAX_LEVEL, 0);
GlStateManager._texParameter(GlConst.GL_TEXTURE_2D, GL12.GL_TEXTURE_MIN_LOD, 0);
GlStateManager._texParameter(GlConst.GL_TEXTURE_2D, GL12.GL_TEXTURE_MAX_LOD, 0);
GlStateManager._texParameter(GlConst.GL_TEXTURE_2D, GL14.GL_TEXTURE_LOD_BIAS, 0f);

GlStateManager._texParameter(GlConst.GL_TEXTURE_2D, GL12.GL_TEXTURE_MIN_FILTER, GL12.GL_NEAREST);
GlStateManager._texParameter(GlConst.GL_TEXTURE_2D, GL12.GL_TEXTURE_MAG_FILTER, GL12.GL_NEAREST);

GlStateManager._texImage2D(GlConst.GL_TEXTURE_2D, 0, GlConst.GL_RGBA, resolution, resolution, 0, GlConst.GL_RGBA, GlConst.GL_UNSIGNED_BYTE, null);
}

}
}
11 changes: 7 additions & 4 deletions src/main/java/com/goby56/wakes/render/SplashPlaneRenderer.java
Original file line number Diff line number Diff line change
Expand Up @@ -91,22 +91,24 @@ public static <T extends Entity> void render(T entity, float yaw, float tickDelt

RenderSystem.setShaderTexture(0, tex.id);
tex.offsetPixels(animationFrame * tex.res, (int) (progress * (tex.outlineOffset - 1)) * tex.res);
renderSurface(matrix, color, light);
renderSurface(matrix, color, light, true);

color.set(1f, 1f, 1f);
tex.offsetPixels(animationFrame * tex.res, ((int) (progress * (tex.outlineOffset - 1)) + tex.outlineOffset) * tex.res);
renderSurface(matrix, color, light);
renderSurface(matrix, color, light, false);

matrices.pop();
}

private static void renderSurface(Matrix4f matrix, Vector3f color, int light) {
private static void renderSurface(Matrix4f matrix, Vector3f color, int light, boolean slightlyTransparent) {
BufferBuilder buffer = Tessellator.getInstance().getBuffer();
buffer.begin(VertexFormat.DrawMode.TRIANGLES, VertexFormats.POSITION_COLOR_TEXTURE_OVERLAY_LIGHT_NORMAL);
// TODO IMPROVE ANIMATION (WATER TRAVELS IN AN OUTWARDS DIRECTION)
// AND ADD A BOUNCY FEEL TO IT (BOBBING UP AND DOWN) WAIT IT IS JUST THE BOAT THAT IS DOING THAT
// MAYBE ADD TO BLAZINGLY FAST BOATS?
// https://streamable.com/tz0gp
float opacity = WakesClient.CONFIG_INSTANCE.wakeOpacity;
opacity *= slightlyTransparent ? 0.9f : 1f;
for (int s = -1; s < 2; s++) {
if (s == 0) continue;
for (int i = 0; i < vertices.size(); i++) {
Expand All @@ -116,7 +118,7 @@ private static void renderSurface(Matrix4f matrix, Vector3f color, int light) {
(float) (s * vertex.x * WakesClient.CONFIG_INSTANCE.splashPlaneWidth),
(float) (vertex.z * WakesClient.CONFIG_INSTANCE.splashPlaneHeight),
(float) (vertex.y * WakesClient.CONFIG_INSTANCE.splashPlaneDepth))
.color(color.x, color.y, color.z, WakesClient.CONFIG_INSTANCE.wakeOpacity)
.color(color.x, color.y, color.z, opacity)
.texture((float) (vertex.x / tex.width + tex.uvOffset.x), (float) (vertex.y / tex.height + tex.uvOffset.y))
.overlay(OverlayTexture.DEFAULT_UV)
.light(light)
Expand All @@ -126,6 +128,7 @@ private static void renderSurface(Matrix4f matrix, Vector3f color, int light) {
}

RenderSystem.disableCull();
RenderSystem.enableDepthTest();
Tessellator.getInstance().draw();
RenderSystem.enableCull();
}
Expand Down
Loading
Loading