Skip to content

Commit

Permalink
Merge pull request #60 from KJP12/pr/datatracker-patches
Browse files Browse the repository at this point in the history
New Config: Allowed Health Tags
  • Loading branch information
samolego authored Jan 14, 2022
2 parents 9cd1cca + 9e94991 commit 61fe5f2
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,8 @@
import net.minecraft.entity.ItemEntity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.Saddleable;
import net.minecraft.entity.boss.WitherEntity;
import net.minecraft.entity.data.DataTracker;
import net.minecraft.entity.data.TrackedData;
import net.minecraft.entity.passive.IronGolemEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.network.packet.s2c.play.EntityTrackerUpdateS2CPacket;
import net.minecraft.util.math.MathHelper;
Expand Down Expand Up @@ -53,26 +51,28 @@ public class EntityTrackerUpdateS2CPacketMixin_DataPatch {

Entity entity = ((DataTrackerAccessor) tracker).getTrackedEntity();

if (golfConfig.packet.removeHealthTags && entity instanceof LivingEntity && entity.isAlive() && !(entity instanceof Saddleable)) {
if (golfConfig.packet.removeHealthTags && entity instanceof LivingEntity livingEntity && entity.isAlive() && !(entity instanceof Saddleable)) {
trackedValues.removeIf(trackedValue -> trackedValue.getData() == LIVING_ENTITY_HEALTH);
trackedValues.removeIf(trackedValue -> trackedValue.getData() == PLAYER_ENTITY_ABSORPTION);

if (entity instanceof IronGolemEntity || entity instanceof WitherEntity) {
// Reinjects the health data aligned to quarters.
LivingEntity livingEntity = (LivingEntity) entity;
// This allows for iron golems to be visually broken, withers to have their shields,
// and wolves to show their health, while still spoofing the health to a variable degree.
// This is editable in GolfConfig as allowHealthTags.
if (golfConfig.packet.allowedHealthTags.containsKey(entity.getType())) {
float percentage = golfConfig.packet.allowedHealthTags.getFloat(entity.getType());
float divider = livingEntity.getMaxHealth() * percentage;

// This takes away 1, divides by 25, floors, multiplies and add 1,
// spoofing health to be within 25 of the actual value.
// This allows for the iron golem to be visually broken, and for the wither to have its shield.
Float newHealth = MathHelper.floor((livingEntity.getHealth() - 1F) / 25F) * 25F + 1F;
// Shortcuts to livingEntity.getHealth on <= 1F.
Float newHealth = divider <= 1F ? livingEntity.getHealth() :
MathHelper.floor((livingEntity.getHealth() - 1F) / divider) * divider + 1F;

DataTracker.Entry<Float> fakeEntry = new DataTracker.Entry<>(LIVING_ENTITY_HEALTH, newHealth);
trackedValues.add(fakeEntry);
}
} else if (golfConfig.packet.removeDroppedItemInfo && entity instanceof ItemEntity) {
} else if (golfConfig.packet.removeDroppedItemInfo && entity instanceof ItemEntity itemEntity) {
boolean removed = trackedValues.removeIf(entry -> entry.getData() == ITEM_ENTITY_STACK); // Original item
if (removed) {
ItemStack original = ((ItemEntity) entity).getStack();
ItemStack original = itemEntity.getStack();

DataTracker.Entry<ItemStack> fakeEntry = new DataTracker.Entry<>(ITEM_ENTITY_STACK, fakeStack(original, false));
trackedValues.add(fakeEntry);
Expand Down
72 changes: 62 additions & 10 deletions src/main/java/org/samo_lego/golfiv/storage/GolfConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.TypeAdapter;
import com.google.gson.annotations.JsonAdapter;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
import it.unimi.dsi.fastutil.objects.Object2FloatMaps;
import it.unimi.dsi.fastutil.objects.Object2FloatOpenHashMap;
import net.minecraft.entity.EntityType;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
Expand Down Expand Up @@ -112,16 +112,33 @@ public static class Packet {
/**
* Removes entity health data from packets
* sent to client.
*
* <p>
* Status: working.
*/
public boolean removeHealthTags = true;

public final String _comment_allowedHealthTags_1 = "// Allows health tags for certain entities.";
public final String _comment_allowedHealthTags_2 = "// This maps entity ID to percentage as decimal.";

/**
* Entities that must have health sent to render correctly.
* <p>
* K -> Entities to allow health of.
* V -> Increments by percentage of health to allow.
* <p>
* Implied by default is 1F, or alive and dead.
*/
@JsonAdapter(UnnecessaryEntityTypeMapAdapter.class)
public Object2FloatOpenHashMap<EntityType<?>> allowedHealthTags = new Object2FloatOpenHashMap<>(
new EntityType<?>[]{EntityType.WOLF, EntityType.WITHER, EntityType.IRON_GOLEM},
new float[]{0F, 0.5F, 0.25F}
);

/**
* Removes entity equipment tags from
* packets. Players will still see if item is enchanted,
* but won't get the durability or stack size information.
*
* <p>
* Status: working.
*/
public boolean removeEquipmentTags = true;
Expand Down Expand Up @@ -250,4 +267,39 @@ public void saveConfig(File configFile) {
logError("Problem occurred when saving config: " + e.getMessage());
}
}

/**
* Adapts {@link EntityType} between it and the identifier.
* <p>
* Unnecessary, as map-level shouldn't be needed to begin with,
* yet arbitrary unforeseen restrictions require this anyways.
*
* @author KJP12
*/
private static final class UnnecessaryEntityTypeMapAdapter extends TypeAdapter<Object2FloatOpenHashMap<EntityType<?>>> {

@Override
public void write(JsonWriter out, Object2FloatOpenHashMap<EntityType<?>> value) throws IOException {
out.beginObject();
var itr = Object2FloatMaps.fastIterator(value);
while (itr.hasNext()) {
var entry = itr.next();
out.name(EntityType.getId(entry.getKey()).toString());
out.value(entry.getFloatValue());
}
out.endObject();
}

@Override
public Object2FloatOpenHashMap<EntityType<?>> read(JsonReader in) throws IOException {
in.beginObject();
var map = new Object2FloatOpenHashMap<EntityType<?>>();
while (in.hasNext()) {
map.put(EntityType.get(in.nextName()).orElseThrow(() -> new IOException("Invalid entity type.")),
(float) in.nextDouble());
}
in.endObject();
return map;
}
}
}

0 comments on commit 61fe5f2

Please sign in to comment.