// 
// Decompiled by Procyon v0.6.0
// 

package com.hypixel.hytale.builtin.blocktick;

import com.hypixel.hytale.assetstore.map.BlockTypeAssetMap;
import com.hypixel.hytale.server.core.universe.world.chunk.BlockChunk;
import com.hypixel.hytale.server.core.universe.world.chunk.section.BlockSection;
import com.hypixel.hytale.server.core.universe.world.chunk.ChunkColumn;
import com.hypixel.hytale.server.core.universe.world.chunk.WorldChunk;
import com.hypixel.hytale.component.Holder;
import com.hypixel.hytale.server.core.asset.type.blocktype.config.BlockType;
import com.hypixel.hytale.server.core.asset.type.blocktick.BlockTickManager;
import com.hypixel.hytale.builtin.blocktick.system.MergeWaitingBlocksSystem;
import com.hypixel.hytale.component.system.ISystem;
import com.hypixel.hytale.builtin.blocktick.system.ChunkBlockTickSystem;
import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore;
import com.hypixel.hytale.server.core.universe.world.events.ChunkPreLoadProcessEvent;
import com.hypixel.hytale.event.EventPriority;
import com.hypixel.hytale.builtin.blocktick.procedure.SplitChanceBlockGrowthProcedure;
import com.hypixel.hytale.codec.Codec;
import com.hypixel.hytale.builtin.blocktick.procedure.BasicChanceBlockGrowthProcedure;
import com.hypixel.hytale.server.core.asset.type.blocktick.config.TickProcedure;
import javax.annotation.Nonnull;
import com.hypixel.hytale.server.core.plugin.JavaPluginInit;
import com.hypixel.hytale.server.core.asset.type.blocktick.IBlockTickProvider;
import com.hypixel.hytale.server.core.plugin.JavaPlugin;

public class BlockTickPlugin extends JavaPlugin implements IBlockTickProvider
{
    private static BlockTickPlugin instance;
    
    public static BlockTickPlugin get() {
        return BlockTickPlugin.instance;
    }
    
    public BlockTickPlugin(@Nonnull final JavaPluginInit init) {
        super(init);
        BlockTickPlugin.instance = this;
    }
    
    @Override
    protected void setup() {
        TickProcedure.CODEC.register("BasicChance", BasicChanceBlockGrowthProcedure.class, BasicChanceBlockGrowthProcedure.CODEC);
        TickProcedure.CODEC.register("SplitChance", SplitChanceBlockGrowthProcedure.class, SplitChanceBlockGrowthProcedure.CODEC);
        this.getEventRegistry().registerGlobal(EventPriority.EARLY, ChunkPreLoadProcessEvent.class, this::discoverTickingBlocks);
        ChunkStore.REGISTRY.registerSystem(new ChunkBlockTickSystem.PreTick());
        ChunkStore.REGISTRY.registerSystem(new ChunkBlockTickSystem.Ticking());
        ChunkStore.REGISTRY.registerSystem(new MergeWaitingBlocksSystem());
        BlockTickManager.setBlockTickProvider(this);
    }
    
    @Override
    public TickProcedure getTickProcedure(final int blockId) {
        return BlockType.getAssetMap().getAsset(blockId).getTickProcedure();
    }
    
    private void discoverTickingBlocks(@Nonnull final ChunkPreLoadProcessEvent event) {
        if (!event.isNewlyGenerated()) {
            return;
        }
        this.discoverTickingBlocks(event.getHolder(), event.getChunk());
    }
    
    public int discoverTickingBlocks(@Nonnull final Holder<ChunkStore> holder, @Nonnull final WorldChunk chunk) {
        if (!this.isEnabled()) {
            return 0;
        }
        final BlockChunk bc = chunk.getBlockChunk();
        if (!bc.consumeNeedsPhysics()) {
            return 0;
        }
        final ChunkColumn column = holder.getComponent(ChunkColumn.getComponentType());
        if (column == null) {
            return 0;
        }
        final Holder<ChunkStore>[] sections = column.getSectionHolders();
        if (sections == null) {
            return 0;
        }
        final BlockTypeAssetMap<String, BlockType> assetMap = BlockType.getAssetMap();
        int count = 0;
        for (int i = 0; i < sections.length; ++i) {
            final Holder<ChunkStore> sectionHolder = sections[i];
            final BlockSection section = sectionHolder.ensureAndGetComponent(BlockSection.getComponentType());
            if (!section.isSolidAir()) {
                for (int blockIdx = 0; blockIdx < 32768; ++blockIdx) {
                    final int blockId = section.get(blockIdx);
                    final BlockType blockType = assetMap.getAsset(blockId);
                    if (blockType != null) {
                        if (blockType.getTickProcedure() != null) {
                            section.setTicking(blockIdx, true);
                            bc.markNeedsSaving();
                            ++count;
                        }
                    }
                }
            }
        }
        return count;
    }
}
