aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/moe/nea/caelo/optifine/OptifineCustomItemCache.kt
blob: d0e8fc432d34e55d9de0564072fd30745a9e6aed (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
package moe.nea.caelo.optifine

import moe.nea.caelo.CaeloCommand
import moe.nea.caelo.config.CConfig
import moe.nea.caelo.event.NeaTickEvent
import moe.nea.caelo.util.Histogram
import moe.nea.caelo.util.MC
import net.minecraft.item.ItemStack
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
import net.optifine.CustomItemProperties
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable
import java.lang.ref.WeakReference

object OptifineCustomItemCache {

	init {
		CaeloCommand.subcommand("opticache") { args ->
			val cache = cacheSizeHistory.lastOrNull() ?: CacheStats()
			MC.display("OptiCache stats:")
			MC.display("- History: §3${cacheSizeHistory.size}")
			MC.display("- Misses: §c${cache.cacheMisses}")
			MC.display("- Hits: §a${cache.cacheHits}")
			MC.display("- Insertions: §b${cache.insertions}")
			MC.display("- Evictions: §b${cache.removals}")
			MC.display("- Cache Size: §b${cache.size}")
		}
	}

	class CacheKey(val itemStack: WeakReference<ItemStack>, val type: Int) {
		override fun equals(other: Any?): Boolean {
			if (other !is CacheKey) return false
			return itemStack.get() === other.itemStack.get() && type == other.type
		}

		override fun hashCode(): Int {
			return System.identityHashCode(itemStack.get()) * 31 + type
		}

		fun isPresent(): Boolean {
			return itemStack.get() != null
		}
	}

	data class CacheStats(
		var cacheHits: Int = 0,
		var cacheMisses: Int = 0,
		var insertions: Int = 0,
		var size: Int = 0,
		var removals: Int = 0,
	)

	private var map = mutableMapOf<CacheKey, CustomItemProperties?>()
	private val cacheSizeHistory = Histogram<CacheStats>(1000)
	private var cacheStats = CacheStats()

	@SubscribeEvent
	fun onTick(event: NeaTickEvent) {
		var removeCount = 0
		val nextMap = mutableMapOf<CacheKey, CustomItemProperties?>()
		for (entry in map) {
			if (entry.key.isPresent()) {
				nextMap[entry.key] = entry.value
			} else {
				removeCount++
			}
		}
		map = nextMap
		cacheStats.size = map.size
		cacheStats.removals = removeCount
		cacheSizeHistory.append(cacheStats)
		cacheStats = CacheStats()

	}

	@JvmStatic
	fun retrieveCacheHit(
		itemStack: ItemStack,
		type: Int,
		cir: CallbackInfoReturnable<CustomItemProperties?>
	) {
		if (!CConfig.config.optiCache.citCache)
			return
		val key = CacheKey(WeakReference(itemStack), type)
		if (!map.containsKey(key)) {
			cacheStats.cacheMisses++
			return
		}
		cacheStats.cacheHits++
		cir.returnValue = map[key]
	}

	@JvmStatic
	fun storeCustomItemProperties(itemStack: ItemStack, type: Int, cip: CustomItemProperties) {
		map[CacheKey(WeakReference(itemStack), type)] = cip
		cacheStats.insertions++
	}

	@JvmStatic
	fun storeNoCustomItemProperties(itemStack: ItemStack, type: Int) {
		map[CacheKey(WeakReference(itemStack), type)] = null
		cacheStats.insertions++
	}
}