throttle no explicit subchannel warning

This commit is contained in:
Glease committed 2022-09-02 15:45:13 +08:00
1 parent adc91bb1dd
commit 9b318f68fb
5 files changed
+131 -2

No files matched your search

@@ -24,6 +24,7 @@ import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.item.ItemStack;
import net.minecraft.profiler.Profiler;
import net.minecraft.util.ChatComponentText;
import net.minecraft.util.IChatComponent;
import net.minecraft.util.IIcon;
import net.minecraft.util.Vec3;
import net.minecraft.world.World;
@@ -69,6 +70,10 @@ public class ClientProxy extends CommonProxy {
* counter keeping track of how many renderThrough hint particle we have. enable optimization if no renderThrough
*/
private static int renderThrough;
/**
* A throttle map for local player. Integrated server will use the throttle map in super class instead.
*/
private static final Map<Object, Long> localThrottleMap = new HashMap<>();
@Override
public void hintParticleTinted(World w, int x, int y, int z, IIcon[] icons, short[] RGBa) {
@@ -152,6 +157,19 @@ public class ClientProxy extends CommonProxy {
return true;
}
@Override
public void addThrottledChat(
Object throttleKey,
EntityPlayer player,
IChatComponent text,
short intervalRequired,
boolean forceUpdateLastSend) {
if (player instanceof EntityPlayerMP)
super.addThrottledChat(throttleKey, player, text, intervalRequired, forceUpdateLastSend);
else if (player != null)
addThrottledChat(throttleKey, player, text, intervalRequired, forceUpdateLastSend, localThrottleMap);
}
static void removeGroup(HintGroup group) {
for (HintParticleInfo hintParticleInfo : group.getHints()) {
allHints.remove(hintParticleInfo);
@@ -423,10 +441,13 @@ public class ClientProxy extends CommonProxy {
@SubscribeEvent
public void onWorldLoad(WorldEvent.Load e) {
if (e.world.isRemote) {
// flush hints. we are in a different world now.
allHintsForRender.clear();
allGroups.clear();
lastPlayerPos.yCoord = -1e30;
renderThrough = 0;
// clear throttles. hopefully a world switch is enough long as a cool down.
localThrottleMap.clear();
}
}
@@ -3,11 +3,15 @@ package com.gtnewhorizon.structurelib;
import com.gtnewhorizon.structurelib.net.ErrorHintParticleMessage;
import com.gtnewhorizon.structurelib.net.UpdateHintParticleMessage;
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
import java.util.HashMap;
import java.util.Map;
import java.util.WeakHashMap;
import net.minecraft.block.Block;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.item.ItemStack;
import net.minecraft.server.MinecraftServer;
import net.minecraft.util.IChatComponent;
import net.minecraft.util.IIcon;
import net.minecraft.world.World;
@@ -61,4 +65,38 @@ public class CommonProxy {
return false;
}
}
private final Map<EntityPlayerMP, Map<Object, Long>> throttleMap = new WeakHashMap<>();
public void addThrottledChat(
Object throttleKey,
EntityPlayer player,
IChatComponent text,
short intervalRequired,
boolean forceUpdateLastSend) {
if (player instanceof EntityPlayerMP) {
Map<Object, Long> submap = throttleMap.computeIfAbsent((EntityPlayerMP) player, p -> new HashMap<>());
addThrottledChat(throttleKey, player, text, intervalRequired, forceUpdateLastSend, submap);
}
}
protected static void addThrottledChat(
Object throttleKey,
EntityPlayer player,
IChatComponent text,
short intervalRequired,
boolean forceUpdateLastSend,
Map<Object, Long> submap) {
long now = System.currentTimeMillis();
Long old;
if (forceUpdateLastSend) {
old = submap.put(throttleKey, now);
} else {
old = submap.get(throttleKey);
}
if (old == null || now - old >= intervalRequired) {
player.addChatComponentMessage(text);
if (!forceUpdateLastSend) submap.put(throttleKey, now);
}
}
}
@@ -13,6 +13,7 @@ import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.IChatComponent;
import net.minecraft.util.IIcon;
import net.minecraft.world.World;
@@ -225,4 +226,37 @@ public class StructureLibAPI {
Block block = w.getBlock(x, y, z);
return block.isAir(w, x, y, z) || block.isReplaceable(w, x, y, z);
}
/**
* Send chat to player, but throttled.
* @param throttleKey throttle key. Must properly implement {@link Object#hashCode()} and {@link Object#equals(Object)}
* to handle value equality.
* @param player player to send chat to
* @param text chat to send
* @param intervalRequired interval required before last recorded time to actually send the message. unit in millisecond.
* we purposefully chose to not use a bigger data type to limit how long this interval can be
*/
public static void addThrottledChat(
Object throttleKey, EntityPlayer player, IChatComponent text, short intervalRequired) {
addThrottledChat(throttleKey, player, text, intervalRequired, false);
}
/**
* Send chat to player, but throttled.
* @param throttleKey throttle key. Must properly implement {@link Object#hashCode()} and {@link Object#equals(Object)}
* to handle value equality.
* @param player player to send chat to
* @param text chat to send
* @param intervalRequired interval required before last recorded time to actually send the message. unit in millisecond.
* we purposefully chose to not use a bigger data type to limit how long this interval can be
* @param forceUpdateLastSend if true, always update the last send time, even if the message isn't actually sent.
*/
public static void addThrottledChat(
Object throttleKey,
EntityPlayer player,
IChatComponent text,
short intervalRequired,
boolean forceUpdateLastSend) {
proxy.addThrottledChat(throttleKey, player, text, intervalRequired, forceUpdateLastSend);
}
}
@@ -0,0 +1,30 @@
package com.gtnewhorizon.structurelib.structure;
class ChatThrottleKey {
static class NoExplicitChannel {
private static final int hashOffset = NoExplicitChannel.class.hashCode();
private final String subchannel;
public NoExplicitChannel(String subchannel) {
this.subchannel = subchannel;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof NoExplicitChannel)) return false;
NoExplicitChannel that = (NoExplicitChannel) o;
return subchannel.equals(that.subchannel);
}
@Override
public int hashCode() {
// as this one will be placed within a map along with instances of different classes, it'd be best to add
// an offset based off class type to avoid collision
return subchannel.hashCode() + hashOffset;
}
}
}
@@ -2706,12 +2706,18 @@ public class StructureUtility {
}
private void warnNoExplicitSubChannel(EntityPlayer currentPlayer) {
currentPlayer.addChatComponentMessage(
new ChatComponentTranslation("structurelib.autoplace.warning.no_explicit_channel", channel));
// throttle this warning a bit.
// I'm sure we can finish a check/autoplace round within 100 milliseconds.
StructureLibAPI.addThrottledChat(
new ChatThrottleKey.NoExplicitChannel(channel),
currentPlayer,
new ChatComponentTranslation("structurelib.autoplace.warning.no_explicit_channel", channel),
(short) 100);
}
public boolean placeBlock(T t, World world, int x, int y, int z, ItemStack trigger) {
// I hope a CREATIVE player know what he is doing...
// no warning for yah
return backing.placeBlock(t, world, x, y, z, ChannelDataAccessor.withChannel(trigger, channel));
}