Skip to content

Commit 094d78c

Browse files
committed
Merge branch '1.18.x/dev' into '1.19.x/dev'
2 parents 2b2f6f1 + 20cb5fc commit 094d78c

17 files changed

+709
-2
lines changed

gradle.properties

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ yarn_mappings=1.19+build.1
88
loader_version=0.14.7
99

1010
# Mod Properties
11-
mod_version=4.1
11+
mod_version=4.2
1212
maven_group=dev.kir
1313
archives_base_name=sync
1414

src/main/java/dev/kir/sync/block/entity/TreadmillBlockEntity.java

+8-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import dev.kir.sync.api.event.EntityFitnessEvents;
55
import dev.kir.sync.config.SyncConfig;
66
import dev.kir.sync.Sync;
7+
import dev.kir.sync.easteregg.technoblade.TechnobladeManager;
78
import net.fabricmc.fabric.api.transfer.v1.transaction.TransactionContext;
89
import net.minecraft.block.BlockState;
910
import net.minecraft.block.DoubleBlockProperties;
@@ -69,7 +70,13 @@ private void setRunner(Entity entity) {
6970
EntityFitnessEvents.START_RUNNING.invoker().onStartRunning(this.runner, this);
7071
}
7172

72-
if (this.world != null && !this.world.isClient) {
73+
if (this.world == null) {
74+
return;
75+
}
76+
77+
if (this.world.isClient) {
78+
TechnobladeManager.refreshTechnobladeStatus(entity, this.pos);
79+
} else {
7380
this.markDirty();
7481
this.sync();
7582
}

src/main/java/dev/kir/sync/compat/cloth/SyncClothConfig.java

+70
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@
1212
import net.minecraft.util.registry.Registry;
1313

1414
import java.util.ArrayList;
15+
import java.util.HashSet;
1516
import java.util.List;
17+
import java.util.UUID;
1618
import java.util.stream.Collectors;
1719

1820
@Config(name = Sync.MOD_ID)
@@ -83,6 +85,9 @@ public static SyncConfig getInstance() {
8385
@ConfigEntry.Gui.Tooltip(count = 2)
8486
public boolean updateTranslationsAutomatically = SyncConfig.super.updateTranslationsAutomatically();
8587

88+
@ConfigEntry.Category(value = "easter_eggs")
89+
@ConfigEntry.Gui.TransitiveObject
90+
public EasterEggs easterEggs = new EasterEggs();
8691

8792
@Override
8893
public boolean enableInstantShellConstruction() {
@@ -156,6 +161,71 @@ public boolean updateTranslationsAutomatically() {
156161
return this.updateTranslationsAutomatically;
157162
}
158163

164+
@Override
165+
public boolean enableTechnobladeEasterEgg() {
166+
return this.easterEggs.technoblade.enable;
167+
}
168+
169+
@Override
170+
public boolean renderTechnobladeCape() {
171+
return this.easterEggs.technoblade.renderCape;
172+
}
173+
174+
@Override
175+
public boolean allowTechnobladeAnnouncements() {
176+
return this.easterEggs.technoblade.allowAnnouncements;
177+
}
178+
179+
@Override
180+
public boolean allowTechnobladeQuotes() {
181+
return this.easterEggs.technoblade.allowQuotes;
182+
}
183+
184+
@Override
185+
public int TechnobladeQuoteDelay() {
186+
return this.easterEggs.technoblade.quoteDelay;
187+
}
188+
189+
@Override
190+
public boolean isTechnoblade(UUID uuid) {
191+
return this.easterEggs.technoblade.cache.contains(uuid);
192+
}
193+
194+
@Override
195+
public void addTechnoblade(UUID uuid) {
196+
this.easterEggs.technoblade.cache.add(uuid);
197+
AutoConfig.getConfigHolder(SyncClothConfig.class).save();
198+
}
199+
200+
@Override
201+
public void removeTechnoblade(UUID uuid) {
202+
this.easterEggs.technoblade.cache.remove(uuid);
203+
AutoConfig.getConfigHolder(SyncClothConfig.class).save();
204+
}
205+
206+
@Override
207+
public void clearTechnobladeCache() {
208+
this.easterEggs.technoblade.cache.clear();
209+
AutoConfig.getConfigHolder(SyncClothConfig.class).save();
210+
}
211+
212+
public static class EasterEggs {
213+
@ConfigEntry.Gui.CollapsibleObject
214+
public TechnobladeEasterEgg technoblade = new TechnobladeEasterEgg();
215+
}
216+
217+
public static class TechnobladeEasterEgg {
218+
@ConfigEntry.Gui.RequiresRestart
219+
public boolean enable = true;
220+
public boolean renderCape = false;
221+
public boolean allowAnnouncements = true;
222+
public boolean allowQuotes = true;
223+
public int quoteDelay = 1800;
224+
225+
@ConfigEntry.Gui.Excluded
226+
public HashSet<UUID> cache = new HashSet<>();
227+
}
228+
159229
public static class EnergyMapEntry implements SyncConfig.EnergyMapEntry {
160230
@ConfigEntry.Gui.RequiresRestart
161231
public String entityId;

src/main/java/dev/kir/sync/config/SyncConfig.java

+38
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import net.minecraft.util.registry.Registry;
99

1010
import java.util.List;
11+
import java.util.UUID;
1112

1213
public interface SyncConfig {
1314
List<EnergyMapEntry> DEFAULT_ENERGY_MAP = List.of(
@@ -81,6 +82,43 @@ default boolean preserveOrigins() {
8182
return false;
8283
}
8384

85+
default boolean enableTechnobladeEasterEgg() {
86+
return true;
87+
}
88+
89+
default boolean renderTechnobladeCape() {
90+
// Techno hasn't worn a cape lately
91+
return false;
92+
}
93+
94+
default boolean allowTechnobladeAnnouncements() {
95+
return true;
96+
}
97+
98+
default boolean allowTechnobladeQuotes() {
99+
return true;
100+
}
101+
102+
default int TechnobladeQuoteDelay() {
103+
return 1800;
104+
}
105+
106+
default boolean isTechnoblade(UUID uuid) {
107+
return false;
108+
}
109+
110+
default void addTechnoblade(UUID uuid) {
111+
112+
}
113+
114+
default void removeTechnoblade(UUID uuid) {
115+
116+
}
117+
118+
default void clearTechnobladeCache() {
119+
120+
}
121+
84122
interface EnergyMapEntry {
85123
default String entityId() {
86124
return "minecraft:pig";
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
package dev.kir.sync.easteregg.mixin;
2+
3+
import com.google.gson.JsonObject;
4+
import com.google.gson.JsonParser;
5+
import com.google.gson.JsonPrimitive;
6+
import org.objectweb.asm.tree.ClassNode;
7+
import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin;
8+
import org.spongepowered.asm.mixin.extensibility.IMixinInfo;
9+
10+
import java.nio.file.Files;
11+
import java.nio.file.Path;
12+
import java.util.List;
13+
import java.util.Set;
14+
15+
public final class MixinEasterEggs implements IMixinConfigPlugin {
16+
@Override
17+
public boolean shouldApplyMixin(String targetClassName, String mixinClassName) {
18+
String name = getPackageName(mixinClassName);
19+
JsonObject config = this.getConfig();
20+
if (
21+
config.has(name) && config.get(name) instanceof JsonObject configEntry &&
22+
configEntry.has("enable") && configEntry.get("enable") instanceof JsonPrimitive enable && enable.isBoolean()
23+
) {
24+
return enable.getAsBoolean();
25+
}
26+
27+
return true;
28+
}
29+
30+
@Override
31+
public void onLoad(String mixinPackage) { }
32+
33+
@Override
34+
public String getRefMapperConfig() { return null; }
35+
36+
@Override
37+
public List<String> getMixins() { return null; }
38+
39+
@Override
40+
public void acceptTargets(Set<String> myTargets, Set<String> otherTargets) { }
41+
42+
@Override
43+
public void preApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) { }
44+
45+
@Override
46+
public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) { }
47+
48+
private static String getPackageName(String mixinClassName) {
49+
int mixinStartI = mixinClassName.lastIndexOf("mixin.");
50+
if (mixinStartI == -1)
51+
return mixinClassName;
52+
53+
int endI = mixinClassName.indexOf('.', mixinStartI + 6);
54+
return mixinClassName.substring(mixinStartI + 6, endI);
55+
}
56+
57+
private JsonObject config;
58+
private JsonObject getConfig() {
59+
if (this.config == null) {
60+
try {
61+
Path path = Path.of("./config/sync.json");
62+
if (Files.isReadable(path)) {
63+
String json = Files.readString(path);
64+
this.config = (JsonObject)JsonParser.parseString(json);
65+
}
66+
} catch (Throwable e) {
67+
this.config = null;
68+
}
69+
70+
if (this.config == null) {
71+
this.config = new JsonObject();
72+
}
73+
74+
if (this.config.has("easterEggs") && this.config.get("easterEggs") instanceof JsonObject easterEggs) {
75+
this.config = easterEggs;
76+
}
77+
}
78+
return this.config;
79+
}
80+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
package dev.kir.sync.easteregg.mixin.technoblade;
2+
3+
import dev.kir.sync.easteregg.technoblade.Technoblade;
4+
import dev.kir.sync.easteregg.technoblade.TechnobladeTransformable;
5+
import net.fabricmc.api.EnvType;
6+
import net.fabricmc.api.Environment;
7+
import net.minecraft.client.MinecraftClient;
8+
import net.minecraft.client.sound.EntityTrackingSoundInstance;
9+
import net.minecraft.client.sound.PositionedSoundInstance;
10+
import net.minecraft.client.world.ClientWorld;
11+
import net.minecraft.entity.Entity;
12+
import net.minecraft.entity.mob.MobEntity;
13+
import net.minecraft.entity.player.PlayerEntity;
14+
import net.minecraft.sound.SoundCategory;
15+
import net.minecraft.sound.SoundEvent;
16+
import net.minecraft.util.Identifier;
17+
import net.minecraft.util.math.Box;
18+
import net.minecraft.util.math.random.Random;
19+
import net.minecraft.util.profiler.Profiler;
20+
import net.minecraft.util.registry.Registry;
21+
import net.minecraft.util.registry.RegistryEntry;
22+
import net.minecraft.util.registry.RegistryKey;
23+
import net.minecraft.world.MutableWorldProperties;
24+
import net.minecraft.world.World;
25+
import net.minecraft.world.dimension.DimensionType;
26+
import org.jetbrains.annotations.Nullable;
27+
import org.spongepowered.asm.mixin.Final;
28+
import org.spongepowered.asm.mixin.Mixin;
29+
import org.spongepowered.asm.mixin.Shadow;
30+
import org.spongepowered.asm.mixin.injection.At;
31+
import org.spongepowered.asm.mixin.injection.Inject;
32+
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
33+
34+
import java.util.List;
35+
import java.util.function.Supplier;
36+
37+
@Environment(EnvType.CLIENT)
38+
@Mixin(ClientWorld.class)
39+
abstract class ClientWorldMixin extends World {
40+
@Shadow
41+
private @Final MinecraftClient client;
42+
43+
private ClientWorldMixin(MutableWorldProperties properties, RegistryKey<World> registryRef, RegistryEntry<DimensionType> dimension, Supplier<Profiler> profiler, boolean isClient, boolean debugWorld, long seed, int maxChainedNeighborUpdates) {
44+
super(properties, registryRef, dimension, profiler, isClient, debugWorld, seed, maxChainedNeighborUpdates);
45+
}
46+
47+
@Inject(method = "playSound(DDDLnet/minecraft/sound/SoundEvent;Lnet/minecraft/sound/SoundCategory;FFZJ)V", at = @At("HEAD"), cancellable = true)
48+
private void playSound(double x, double y, double z, SoundEvent sound, SoundCategory category, float volume, float pitch, boolean useDistance, long seed, CallbackInfo ci) {
49+
if (category != SoundCategory.NEUTRAL) {
50+
return;
51+
}
52+
53+
List<MobEntity> Technoblades = this.getEntitiesByClass(MobEntity.class, new Box(x - 0.1, y - 0.1, z - 0.1, x + 0.1, y + 0.1, z + 0.1), e -> e instanceof TechnobladeTransformable && ((TechnobladeTransformable)e).isTechnoblade());
54+
MobEntity entity = Technoblades.size() == 0 ? null : Technoblades.get(0);
55+
if (entity == null) {
56+
return;
57+
}
58+
59+
Technoblade Technoblade = ((TechnobladeTransformable)entity).asTechnoblade();
60+
sound = this.getTechnobladeSound(sound);
61+
if (sound == null) {
62+
ci.cancel();
63+
return;
64+
}
65+
66+
double distance = this.client.gameRenderer.getCamera().getPos().squaredDistanceTo(x, y, z);
67+
PositionedSoundInstance positionedSoundInstance = new PositionedSoundInstance(sound, Technoblade.getSoundCategory(), volume, pitch, Random.create(seed), x, y, z);
68+
if (useDistance && distance > 100) {
69+
this.client.getSoundManager().play(positionedSoundInstance, (int)(Math.sqrt(distance) * 0.5));
70+
} else {
71+
this.client.getSoundManager().play(positionedSoundInstance);
72+
}
73+
ci.cancel();
74+
}
75+
76+
@Inject(method = "playSoundFromEntity", at = @At("HEAD"), cancellable = true)
77+
private void playSoundFromEntity(PlayerEntity except, Entity entity, SoundEvent sound, SoundCategory category, float volume, float pitch, long seed, CallbackInfo ci) {
78+
if (except != this.client.player || !(entity instanceof TechnobladeTransformable) || !((TechnobladeTransformable)entity).isTechnoblade()) {
79+
return;
80+
}
81+
82+
Technoblade Technoblade = ((TechnobladeTransformable)entity).asTechnoblade();
83+
sound = this.getTechnobladeSound(sound);
84+
if (sound == null) {
85+
ci.cancel();
86+
return;
87+
}
88+
89+
this.client.getSoundManager().play(new EntityTrackingSoundInstance(sound, Technoblade.getSoundCategory(), volume, pitch, entity, seed));
90+
ci.cancel();
91+
}
92+
93+
private @Nullable SoundEvent getTechnobladeSound(SoundEvent sound) {
94+
Identifier originalSoundId = sound.getId();
95+
if (originalSoundId.getPath().endsWith(".ambient") || originalSoundId.getPath().endsWith(".death")) {
96+
return null;
97+
}
98+
99+
SoundEvent fixedSound = Registry.SOUND_EVENT.get(new Identifier(originalSoundId.getNamespace(), originalSoundId.getPath().replaceFirst("\\.[^.]+", ".player")));
100+
if (fixedSound == null) {
101+
fixedSound = sound;
102+
}
103+
return fixedSound;
104+
}
105+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package dev.kir.sync.easteregg.mixin.technoblade;
2+
3+
import dev.kir.sync.easteregg.technoblade.TechnobladeTransformable;
4+
import net.fabricmc.api.EnvType;
5+
import net.fabricmc.api.Environment;
6+
import net.minecraft.client.render.VertexConsumerProvider;
7+
import net.minecraft.client.render.entity.EntityRenderDispatcher;
8+
import net.minecraft.client.util.math.MatrixStack;
9+
import net.minecraft.entity.Entity;
10+
import org.spongepowered.asm.mixin.Mixin;
11+
import org.spongepowered.asm.mixin.injection.At;
12+
import org.spongepowered.asm.mixin.injection.ModifyArgs;
13+
import org.spongepowered.asm.mixin.injection.invoke.arg.Args;
14+
15+
@Environment(EnvType.CLIENT)
16+
@Mixin(EntityRenderDispatcher.class)
17+
abstract class EntityRenderDispatcherMixin {
18+
@ModifyArgs(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/entity/EntityRenderDispatcher;renderShadow(Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;Lnet/minecraft/entity/Entity;FFLnet/minecraft/world/WorldView;F)V"))
19+
private void getShadowOpacity(Args args, Entity entity, double x, double y, double z, float yaw, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light) {
20+
if (entity instanceof TechnobladeTransformable technobladeTransformable && technobladeTransformable.isTechnoblade()) {
21+
args.set(6, 0f);
22+
}
23+
}
24+
}

0 commit comments

Comments
 (0)