Skip to content
Open
Show file tree
Hide file tree
Changes from 11 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: 6 additions & 0 deletions ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,9 @@ Configs of "Creative Invulnerable Crystal", Antispam, Packets, and Trackers, fro
## Modified Features

## Code Changes

## To-do List

1. Fix the bug that
`root.tick.level.blocks.getChunk.checkedPosition` causes huge lag(?) when elytra-flying over the nether.
2. Fix [MC-88179](https://bugs.mojang.com/browse/MC-88179): Armor bar disappears after changing dimension until GUI update.
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ modId=potato_tech_kit
modName=Potato Tech Kit
# lowercase, without hyphens
modPureName=potteckit
modVersion=0.2.2
modVersion=undefined-post-0.2.2

malilibVersion=0.54.0

Expand Down
21 changes: 21 additions & 0 deletions src/main/java/io/github/rainyaphthyl/potteckit/config/Configs.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,30 @@
import com.google.common.collect.ImmutableList;
import fi.dy.masa.malilib.config.JsonModConfig;
import fi.dy.masa.malilib.config.option.*;
import fi.dy.masa.malilib.config.option.list.BlackWhiteListConfig;
import fi.dy.masa.malilib.config.option.list.BlockListConfig;
import fi.dy.masa.malilib.config.option.list.EquipmentSlotListConfig;
import fi.dy.masa.malilib.config.option.list.ItemListConfig;
import fi.dy.masa.malilib.config.value.BlackWhiteList;
import fi.dy.masa.malilib.input.KeyBindSettings;
import fi.dy.masa.malilib.registry.Registry;
import fi.dy.masa.malilib.util.restriction.UsageRestriction;
import io.github.rainyaphthyl.potteckit.config.annotation.Config;
import io.github.rainyaphthyl.potteckit.config.annotation.Domain;
import io.github.rainyaphthyl.potteckit.config.annotation.Type;
import io.github.rainyaphthyl.potteckit.config.option.EntityListConfig;
import io.github.rainyaphthyl.potteckit.config.option.EnumRealmStatus;
import io.github.rainyaphthyl.potteckit.config.option.InvIntegerConfig;
import io.github.rainyaphthyl.potteckit.config.option.multipart.ChunkFilterListConfig;
import io.github.rainyaphthyl.potteckit.entities.Renderers;
import io.github.rainyaphthyl.potteckit.gui.ChunkFilterListConfigWidget;
import io.github.rainyaphthyl.potteckit.gui.EntityListConfigWidget;
import io.github.rainyaphthyl.potteckit.gui.GuiConfigScreen;
import io.github.rainyaphthyl.potteckit.gui.InvIntegerConfigWidget;
import io.github.rainyaphthyl.potteckit.input.PotteckitHotkeyProvider;
import io.github.rainyaphthyl.potteckit.util.Reference;
import net.minecraft.entity.Entity;
import net.minecraft.entity.passive.EntitySquid;
import net.minecraft.init.Blocks;
import net.minecraft.init.Items;
import net.minecraft.inventory.EntityEquipmentSlot;
Expand Down Expand Up @@ -100,6 +107,15 @@ public class Configs {
public static final BooleanAndDoubleConfig explosionPacketRange = new BooleanAndDoubleConfig("explosion_packet_range", false, 64.0, 0.0, 1024.0, "explosion_packet_range");
@Config(types = Type.NUMBER, domains = Domain.TWEAK, serverSide = true)
public static final BooleanAndIntConfig entityTrackerDistance = new BooleanAndIntConfig("entity_tracker_distance", false, 8, 0, 64, "entity_tracker_distance");
@Config(types = Type.LIST, domains = Domain.TWEAK, serverSide = true)
public static final BlackWhiteListConfig<Class<? extends Entity>> entityTrackerTweakList = new BlackWhiteListConfig<>(
"entity_tracker_tweak_list",
BlackWhiteList.of(
UsageRestriction.ListType.BLACKLIST,
new EntityListConfig("malilib.label.list_type.blacklist", ImmutableList.of(EntitySquid.class)),
new EntityListConfig("malilib.label.list_type.whitelist", ImmutableList.of())
), "entity_tracker_tweak_list", "entity_tracker_tweak_list"
);
@Config(types = Type.TOGGLE, domains = Domain.YEET, serverSide = true)
public static final HotkeyedBooleanConfig yeetItemAntiSpam = new HotkeyedBooleanConfig("yeet_item_anti_spam", false, "", "yeet_item_anti_spam", "yeet_item_anti_spam");
@Config(types = Type.TOGGLE, domains = Domain.YEET, serverSide = true)
Expand All @@ -110,6 +126,10 @@ public class Configs {
public static final EquipmentSlotListConfig protectCreativeSlotList = new EquipmentSlotListConfig("protect_creative_slot_list", ImmutableList.of(EntityEquipmentSlot.CHEST, EntityEquipmentSlot.FEET));
@Config(types = Type.TOGGLE, domains = Domain.YEET)
public static final BooleanAndIntConfig dynamicFPS = new BooleanAndIntConfig("dynamic_fps", false, 5, 1, 20, "dynamic_fps");
@Config(types = Type.TOGGLE, domains = Domain.YEET)
public static final HotkeyedBooleanConfig yeetTravelLightCheck = new HotkeyedBooleanConfig("yeet_travel_light_check", false, "", "yeet_travel_light_check", "yeet_travel_light_check");
@Config(types = Type.TOGGLE, domains = Domain.TWEAK)
public static final HotkeyedBooleanConfig autoSwapElytraChestplate = new HotkeyedBooleanConfig("swap_elytra_chestplate", false, "", "swap_elytra_chestplate", "swap_elytra_chestplate");

public static void registerOnInit() {
JsonModConfig jsonModConfig = new JsonModConfig(Reference.MOD_INFO, Reference.CONFIG_VERSION, ConfigHandler.optionCategoryList);
Expand All @@ -118,6 +138,7 @@ public static void registerOnInit() {
Registry.CONFIG_TAB.registerConfigTabProvider(Reference.MOD_INFO, GuiConfigScreen::getConfigTabs);
Registry.CONFIG_WIDGET.registerConfigWidgetFactory(InvIntegerConfig.class, InvIntegerConfigWidget::new);
Registry.CONFIG_WIDGET.registerConfigWidgetFactory(ChunkFilterListConfig.class, ChunkFilterListConfigWidget::new);
Registry.CONFIG_WIDGET.registerConfigWidgetFactory(EntityListConfig.class, EntityListConfigWidget::new);
Registry.HOTKEY_MANAGER.registerHotkeyProvider(new PotteckitHotkeyProvider());
Actions.init();
Callbacks.init();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package io.github.rainyaphthyl.potteckit.config.option;

import com.google.common.collect.ImmutableList;
import fi.dy.masa.malilib.config.option.list.ValueListConfig;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityList;
import net.minecraft.util.ResourceLocation;

import java.util.function.Function;

public class EntityListConfig extends ValueListConfig<Class<? extends Entity>> {
public static final Function<Class<? extends Entity>, String> TO_STRING_CONVERTER = eClass -> {
ResourceLocation key = EntityList.getKey(eClass);
return key == null ? null : key.toString();
};
public static final Function<String, Class<? extends Entity>> FROM_STRING_CONVERTER = EntityList::getClassFromName;

public EntityListConfig(String name, ImmutableList<Class<? extends Entity>> defaultValues) {
super(name, defaultValues, TO_STRING_CONVERTER, FROM_STRING_CONVERTER);
}

public EntityListConfig(String name, ImmutableList<Class<? extends Entity>> defaultValues, String commentTranslationKey, Object... commentArgs) {
super(name, defaultValues, TO_STRING_CONVERTER, FROM_STRING_CONVERTER, commentTranslationKey, commentArgs);
}

public EntityListConfig(String name, ImmutableList<Class<? extends Entity>> defaultValues, Function<Class<? extends Entity>, String> toStringConverter, Function<String, Class<? extends Entity>> fromStringConverter) {
super(name, defaultValues, toStringConverter, fromStringConverter);
}

@Override
public EntityListConfig copy() {
EntityListConfig config = new EntityListConfig(name, defaultValue, toStringConverter, fromStringConverter);
config.copyValuesFrom(this);
return config;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package io.github.rainyaphthyl.potteckit.gui;

import com.google.common.collect.ImmutableList;
import fi.dy.masa.malilib.gui.config.ConfigWidgetContext;
import fi.dy.masa.malilib.gui.widget.button.BaseValueListEditButton;
import fi.dy.masa.malilib.gui.widget.button.GenericButton;
import fi.dy.masa.malilib.gui.widget.list.entry.DataListEntryWidgetData;
import fi.dy.masa.malilib.gui.widget.list.entry.config.list.BaseValueListConfigWidget;
import fi.dy.masa.malilib.util.StringUtils;
import io.github.rainyaphthyl.potteckit.config.option.EntityListConfig;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityList;
import net.minecraft.entity.passive.EntityBat;

public class EntityListConfigWidget extends BaseValueListConfigWidget<Class<? extends Entity>, EntityListConfig> {
public EntityListConfigWidget(EntityListConfig config, DataListEntryWidgetData constructData, ConfigWidgetContext ctx) {
super(config, constructData, ctx);
}

@Override
protected GenericButton createButton(int width, int height, EntityListConfig config, ConfigWidgetContext ctx) {
String title = StringUtils.translate("potteckit.title.screen.item_list_edit", this.config.getDisplayName());
return new BaseValueListEditButton<>(width, height, config, this::updateWidgetState,
() -> EntityBat.class,
() -> {
ImmutableList.Builder<Class<? extends Entity>> builder = ImmutableList.builder();
for (Class<? extends Entity> eClass : EntityList.REGISTRY) {
builder.add(eClass);
}
return builder.build();
},
eClass -> String.valueOf(EntityList.getKey(eClass)),
null, title
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package io.github.rainyaphthyl.potteckit.gui;

import fi.dy.masa.malilib.gui.util.ScreenContext;
import fi.dy.masa.malilib.gui.widget.BaseModelWidget;
import net.minecraft.entity.Entity;

public class EntityWidget extends BaseModelWidget {
protected Class<? extends Entity> entityClass;

public EntityWidget(Class<? extends Entity> entityClass) {
this(16, entityClass);
}

public EntityWidget(int dimensions, Class<? extends Entity> entityClass) {
super(dimensions);
this.entityClass = entityClass;
}

@Override
protected void renderModel(int x, int y, float z, float scale, ScreenContext ctx) {
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
package io.github.rainyaphthyl.potteckit.mixin.inventory;

import com.mojang.authlib.GameProfile;
import fi.dy.masa.malilib.util.inventory.InventoryUtils;
import io.github.rainyaphthyl.potteckit.config.Configs;
import net.minecraft.client.entity.AbstractClientPlayer;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.init.Enchantments;
import net.minecraft.init.Items;
import net.minecraft.inventory.ClickType;
import net.minecraft.inventory.EntityEquipmentSlot;
import net.minecraft.inventory.Slot;
import net.minecraft.item.Item;
import net.minecraft.item.ItemArmor;
import net.minecraft.item.ItemStack;
import net.minecraft.network.datasync.DataParameter;
import net.minecraft.world.World;
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(EntityPlayerSP.class)
public abstract class MixinEntityPlayerSP extends AbstractClientPlayer {
@Shadow
private boolean wasFallFlying;
@Unique
private ItemStack potatoTechKit$cachedChestStack = ItemStack.EMPTY;

public MixinEntityPlayerSP(World worldIn, GameProfile playerProfile) {
super(worldIn, playerProfile);
}

@Inject(method = "onLivingUpdate", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/entity/EntityPlayerSP;getItemStackFromSlot(Lnet/minecraft/inventory/EntityEquipmentSlot;)Lnet/minecraft/item/ItemStack;"))
public void autoDeployElytra(CallbackInfo ci) {
if (Configs.enablePotteckit.getBooleanValue() && Configs.autoSwapElytraChestplate.getBooleanValue()) {
ItemStack chestStack = getItemStackFromSlot(EntityEquipmentSlot.CHEST);
if (chestStack.getItem() instanceof ItemArmor) {
ItemStack elytraStack = ItemStack.EMPTY;
Slot elytraSlot = null;
int prevDurability = 0;
boolean prevMending = false;
for (int i = -1; i < 36; ++i) {
int id = i == -1 ? 45 : (i < 9 ? i + 36 : i);
Slot currSlot = inventoryContainer.getSlot(id);
ItemStack currStack = currSlot.getStack();
if (!currStack.isEmpty() && currStack.getItem() == Items.ELYTRA) {
int level = EnchantmentHelper.getEnchantmentLevel(Enchantments.UNBREAKING, currStack);
int damage = currStack.getItemDamage();
boolean mending = EnchantmentHelper.getEnchantmentLevel(Enchantments.MENDING, currStack) > 0;
int durability = (currStack.getMaxDamage() - damage) * (level + 1);
// find the first of the best elytra(s):
// best remaining durability: (remaining durability) * (unbreaking grade)
// mending is better
if (elytraStack.isEmpty()
|| durability > prevDurability
|| durability == prevDurability && !prevMending && mending) {
elytraSlot = currSlot;
elytraStack = currStack;
prevDurability = durability;
prevMending = mending;
}
if (mending && level >= Enchantments.UNBREAKING.getMaxLevel() && damage == 0) {
// the perfect elytra
break;
}
}
}
if (elytraSlot != null && !elytraStack.isEmpty()) {
//swap Elytra & Chestplate
Slot chestSlot = inventoryContainer.getSlot(6);
int slotNumber = elytraSlot.slotNumber;
if (slotNumber >= 36 && slotNumber < 45) {
// hot-bar
InventoryUtils.clickSlot(inventoryContainer, chestSlot, slotNumber - 36, ClickType.SWAP);
} else {
int currentItem = inventory.currentItem;
InventoryUtils.clickSlot(inventoryContainer, elytraSlot, currentItem, ClickType.SWAP);
InventoryUtils.clickSlot(inventoryContainer, chestSlot, currentItem, ClickType.SWAP);
InventoryUtils.clickSlot(inventoryContainer, elytraSlot, currentItem, ClickType.SWAP);
}
potatoTechKit$cachedChestStack = chestStack;
}
}
}
}

@Inject(method = "notifyDataManagerChange", at = @At(value = "RETURN"))
public void autoDeployChestplate(DataParameter<?> key, CallbackInfo ci) {
if (Configs.enablePotteckit.getBooleanValue() && Configs.autoSwapElytraChestplate.getBooleanValue()) {
if (FLAGS.equals(key) && !isElytraFlying() && wasFallFlying) {
// the new data have been refreshed during EntityDataManager.setEntryValue()
ItemStack elytraStack = getItemStackFromSlot(EntityEquipmentSlot.CHEST);
Slot chestSlot = null;
ItemStack chestStack = ItemStack.EMPTY;
if (elytraStack.getItem() == Items.ELYTRA) {
for (int i = -1; i < 36; ++i) {
int id = i == -1 ? 45 : (i < 9 ? i + 36 : i);
Slot currSlot = inventoryContainer.getSlot(id);
ItemStack currStack = currSlot.getStack();
if (!currStack.isEmpty()) {
Item currItem = currStack.getItem();
if (currItem instanceof ItemArmor
&& ((ItemArmor) currItem).armorType == EntityEquipmentSlot.CHEST
&& InventoryUtils.areStacksEqualIgnoreDurability(potatoTechKit$cachedChestStack, currStack, false)) {
chestSlot = currSlot;
chestStack = currStack;
break;
}
}
}
}
if (chestSlot != null && !chestStack.isEmpty()) {
Slot elytraSlot = inventoryContainer.getSlot(6);
int slotNumber = chestSlot.slotNumber;
if (slotNumber >= 36 && slotNumber < 45) {
// hot-bar
InventoryUtils.clickSlot(inventoryContainer, elytraSlot, slotNumber - 36, ClickType.SWAP);
} else {
int currentItem = inventory.currentItem;
InventoryUtils.clickSlot(inventoryContainer, chestSlot, currentItem, ClickType.SWAP);
InventoryUtils.clickSlot(inventoryContainer, elytraSlot, currentItem, ClickType.SWAP);
InventoryUtils.clickSlot(inventoryContainer, chestSlot, currentItem, ClickType.SWAP);
}
potatoTechKit$cachedChestStack = ItemStack.EMPTY;
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package io.github.rainyaphthyl.potteckit.mixin.render;

import io.github.rainyaphthyl.potteckit.config.Configs;
import net.minecraft.client.Minecraft;
import net.minecraft.entity.Entity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.EnumSkyBlock;
import net.minecraft.world.World;
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.CallbackInfoReturnable;

@Mixin(World.class)
public abstract class MixinWorld {
@Shadow
@Final
public boolean isRemote;

@Unique
private static boolean potatoTechKit$needClientUpdate(Entity entity) {
boolean flag = false;
if (entity != null && entity.dimension == -1) {
if (entity.motionX * entity.motionX + entity.motionZ * entity.motionZ + entity.motionY * entity.motionY >= 0.3 * 0.3) {
flag = true;
} else {
Entity ridingEntity = entity.getRidingEntity();
if (ridingEntity != null) {
if (ridingEntity.motionX * ridingEntity.motionX + ridingEntity.motionZ * ridingEntity.motionZ + ridingEntity.motionY * ridingEntity.motionY >= 0.3 * 0.3) {
flag = true;
}
}
}
}
return flag;
}

@Inject(method = "checkLightFor", at = @At(value = "INVOKE_STRING", target = "Lnet/minecraft/profiler/Profiler;startSection(Ljava/lang/String;)V", args = "ldc=checkedPosition < toCheckCount"), cancellable = true)
public void yeetPositionsToCheck(EnumSkyBlock lightType, BlockPos pos, CallbackInfoReturnable<Boolean> cir) {
if (Configs.enablePotteckit.getBooleanValue() && this.isRemote && Configs.yeetTravelLightCheck.getBooleanValue()) {
Minecraft client = Minecraft.getMinecraft();
Entity viewEntity = client.getRenderViewEntity();
if (client.player == viewEntity) {
boolean flag = potatoTechKit$needClientUpdate(viewEntity);
if (flag && cir.isCancellable() && !cir.isCancelled()) {
cir.setReturnValue(true);
}
}
}
}
}
Loading