diff --git a/src/main/java/ru/dbotthepony/mc/otm/OverdriveThatMatters.java b/src/main/java/ru/dbotthepony/mc/otm/OverdriveThatMatters.java index fdb845469..207dfb876 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/OverdriveThatMatters.java +++ b/src/main/java/ru/dbotthepony/mc/otm/OverdriveThatMatters.java @@ -171,6 +171,7 @@ public final class OverdriveThatMatters { EVENT_BUS.addListener(EventPriority.NORMAL, MatterManager.INSTANCE::reloadEvent); EVENT_BUS.addListener(EventPriority.NORMAL, MatterManager.INSTANCE::onServerStarted); + EVENT_BUS.addListener(EventPriority.NORMAL, MatterManager.INSTANCE::onDataPackSync); EVENT_BUS.addListener(EventPriority.NORMAL, MatterManager.INSTANCE::addCommands); EVENT_BUS.addListener(EventPriority.NORMAL, SynchronizedBlockEntity.Companion::onServerStopping); diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/item/CreativePatternItem.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/item/CreativePatternItem.kt index 7e4c62548..2f2c04c0d 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/item/CreativePatternItem.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/item/CreativePatternItem.kt @@ -31,16 +31,16 @@ class CreativePatternItem : Item(Properties().rarity(Rarity.EPIC).tab(OverdriveT private val resolver = LazyOptional.of { this } override val patterns: Stream - get() = MatterManager.valuesList.stream().map { PatternState(UUID(34783464838L, 4463458382L + ForgeRegistries.ITEMS.getID(it.first)), it.first, 1.0) } + get() = MatterManager.map.keys.stream().map { PatternState(UUID(34783464838L, 4463458382L + ForgeRegistries.ITEMS.getID(it)), it, 1.0) } override val patternCapacity: Int get() { - return MatterManager.valuesList.size + return MatterManager.map.size } override val storedPatterns: Int get() { - return MatterManager.valuesList.size + return MatterManager.map.size } override fun insertPattern( diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/matter/IMatterValue.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/matter/IMatterValue.kt index 4eed564c3..8a66a147e 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/matter/IMatterValue.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/matter/IMatterValue.kt @@ -1,6 +1,9 @@ package ru.dbotthepony.mc.otm.matter +import net.minecraft.network.FriendlyByteBuf import ru.dbotthepony.mc.otm.core.ImpreciseFraction +import ru.dbotthepony.mc.otm.core.readImpreciseFraction +import ru.dbotthepony.mc.otm.core.writeImpreciseFraction interface IMatterValue : Comparable { val matter: ImpreciseFraction @@ -37,6 +40,23 @@ interface IMatterValue : Comparable { } } + +fun FriendlyByteBuf.writeMatterValue(value: IMatterValue) { + writeImpreciseFraction(value.matter) + writeDouble(value.complexity) +} + +fun FriendlyByteBuf.readMatterValue(): IMatterValue { + val matter = readImpreciseFraction() + val complexity = readDouble() + + if (matter.isZero && complexity == 0.0) { + return IMatterValue.Companion + } else { + return MatterValue(matter, complexity) + } +} + data class MatterValue( override val matter: ImpreciseFraction, override val complexity: Double diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/matter/MatterManager.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/matter/MatterManager.kt index 8e9386747..1d534ffaf 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/matter/MatterManager.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/matter/MatterManager.kt @@ -18,6 +18,7 @@ import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet import net.minecraft.ChatFormatting import net.minecraft.commands.CommandSourceStack import net.minecraft.commands.Commands +import net.minecraft.network.FriendlyByteBuf import net.minecraft.network.chat.Component import net.minecraft.network.chat.MutableComponent import net.minecraft.resources.ResourceKey @@ -34,11 +35,14 @@ import net.minecraft.world.item.crafting.Recipe import net.minecraft.world.item.crafting.RecipeType import net.minecraft.world.level.ItemLike import net.minecraftforge.event.AddReloadListenerEvent +import net.minecraftforge.event.OnDatapackSyncEvent import net.minecraftforge.event.RegisterCommandsEvent import net.minecraftforge.event.entity.player.ItemTooltipEvent import net.minecraftforge.event.server.ServerStartedEvent import net.minecraftforge.eventbus.api.IEventBus import net.minecraftforge.fml.ModList +import net.minecraftforge.network.NetworkEvent +import net.minecraftforge.network.PacketDistributor import net.minecraftforge.registries.DeferredRegister import net.minecraftforge.registries.ForgeRegistries import net.minecraftforge.server.command.EnumArgument @@ -61,14 +65,18 @@ import ru.dbotthepony.mc.otm.core.formatSiComponent import ru.dbotthepony.mc.otm.core.isActuallyEmpty import ru.dbotthepony.mc.otm.core.isZero import ru.dbotthepony.mc.otm.core.orNull +import ru.dbotthepony.mc.otm.core.readItemType import ru.dbotthepony.mc.otm.core.registryName import ru.dbotthepony.mc.otm.core.stream -import ru.dbotthepony.mc.otm.isServerThread +import ru.dbotthepony.mc.otm.core.writeItemType +import ru.dbotthepony.mc.otm.network.MatteryPacket +import ru.dbotthepony.mc.otm.network.RegistryNetworkChannel import ru.dbotthepony.mc.otm.registry.RegistryDelegate import ru.dbotthepony.mc.otm.storage.ItemStackWrapper import java.io.File import java.math.BigInteger import java.util.* +import java.util.function.Supplier import java.util.stream.Stream import kotlin.ConcurrentModificationException import kotlin.collections.ArrayDeque @@ -1198,10 +1206,8 @@ object MatterManager { } private val matterValues = Reference2ObjectOpenHashMap() - private val validMatterValues = ArrayList>() - val valuesMap: Map = Collections.unmodifiableMap(matterValues) - val valuesList: List> = Collections.unmodifiableList(validMatterValues) + val map: Map = Collections.unmodifiableMap(matterValues) private var registryIsBuilt = false @@ -1214,21 +1220,29 @@ object MatterManager { registryIsBuilt = true - synchronized(matterValues) { - commentary.clear() - matterValues.clear() - validMatterValues.clear() + commentary.clear() + matterValues.clear() - Resolver.resolve(server) + Resolver.resolve(server) - for (item in ForgeRegistries.ITEMS) { - val value = compute(item).value ?: IMatterValue.Companion + for (item in ForgeRegistries.ITEMS) { + val value = compute(item).value + + if (value?.hasMatterValue == true) matterValues[item] = value + } - if (value.hasMatterValue) { - validMatterValues.add(item to value) - } - } + RegistryNetworkChannel.send(PacketDistributor.ALL.noArg(), SyncPacket(matterValues, commentary)) + } + + fun onDataPackSync(event: OnDatapackSyncEvent) { + if (!registryIsBuilt) + return + + if (event.player == null) { + RegistryNetworkChannel.send(PacketDistributor.ALL.noArg(), SyncPacket(matterValues, commentary)) + } else { + RegistryNetworkChannel.send(PacketDistributor.PLAYER.with { event.player ?: throw ConcurrentModificationException() }, SyncPacket(matterValues, commentary)) } } @@ -1239,12 +1253,37 @@ object MatterManager { } fun get(value: Item): IMatterValue { - if (SERVER_IS_LIVE && !isServerThread()) { - synchronized(matterValues) { // /reload - return matterValues[value] ?: throw ConcurrentModificationException("${value.registryName} has no matter value in registry, this should be impossible") + return matterValues[value] ?: IMatterValue.Companion + } + + fun readSyncPacket(buff: FriendlyByteBuf): SyncPacket { + return SyncPacket( + buff.readMap(FriendlyByteBuf::readItemType, FriendlyByteBuf::readMatterValue), + buff.readMap(FriendlyByteBuf::readItemType) { self -> self.readCollection(::ArrayList, FriendlyByteBuf::readComponent) } + ) + } + + class SyncPacket( + val values: Map, + val comments: Map> + ) : MatteryPacket { + override fun write(buff: FriendlyByteBuf) { + buff.writeMap(values, FriendlyByteBuf::writeItemType, FriendlyByteBuf::writeMatterValue) + buff.writeMap(comments, FriendlyByteBuf::writeItemType) { self, value -> self.writeCollection(value, FriendlyByteBuf::writeComponent) } + } + + override fun play(context: Supplier) { + if (SERVER_IS_LIVE) + return // singleplayer or LAN host + + matterValues.clear() + matterValues.putAll(values) + + commentary.clear() + + for ((k, v) in comments) { + commentary[k] = ArrayList(v.size).also { it.addAll(v) } } - } else { - return matterValues[value] ?: throw ConcurrentModificationException("${value.registryName} has no matter value in registry, this should be impossible") } } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/network/RegistryNetworkChannel.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/network/RegistryNetworkChannel.kt index 4d4dbd2f3..8106c4a41 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/network/RegistryNetworkChannel.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/network/RegistryNetworkChannel.kt @@ -2,12 +2,14 @@ package ru.dbotthepony.mc.otm.network import net.minecraftforge.network.NetworkDirection import ru.dbotthepony.mc.otm.android.AndroidResearchManager +import ru.dbotthepony.mc.otm.matter.MatterManager object RegistryNetworkChannel : MatteryNetworkChannel( - version = "1", + version = "2", name = "registry" ) { fun register() { add(AndroidResearchManager.SyncPacket::class.java, AndroidResearchManager::readSyncPacket, NetworkDirection.PLAY_TO_CLIENT) + add(MatterManager.SyncPacket::class.java, MatterManager::readSyncPacket, NetworkDirection.PLAY_TO_CLIENT) } }