org.blockartistry.DynSurround.client.footsteps.implem.BlockMap.java Source code

Java tutorial

Introduction

Here is the source code for org.blockartistry.DynSurround.client.footsteps.implem.BlockMap.java

Source

/*
 * This file is part of Dynamic Surroundings, licensed under the MIT License (MIT).
 *
 * Copyright (c) OreCruncher
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

package org.blockartistry.DynSurround.client.footsteps.implem;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;

import org.apache.commons.lang3.StringUtils;
import org.blockartistry.DynSurround.DSurround;
import org.blockartistry.DynSurround.client.footsteps.interfaces.IAcoustic;
import org.blockartistry.DynSurround.client.footsteps.system.Isolator;
import org.blockartistry.DynSurround.client.handlers.EnvironStateHandler.EnvironState;
import org.blockartistry.DynSurround.facade.FacadeHelper;
import org.blockartistry.DynSurround.registry.BlockInfo;
import org.blockartistry.lib.MCHelper;
import com.google.common.collect.ImmutableMap;

import gnu.trove.map.hash.THashMap;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import net.minecraft.init.Blocks;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;

@SideOnly(Side.CLIENT)
public class BlockMap {
    private static final Pattern pattern = Pattern.compile("([^:]+:[^^+]+)\\^?(\\d+)?\\+?(\\w+)?");

    private final Isolator isolator;
    private final BlockAcousticMap metaMap = new BlockAcousticMap();
    private Map<String, BlockAcousticMap> substrateMap = new HashMap<String, BlockAcousticMap>();

    private static class MacroEntry {
        public final int meta;
        public final String substrate;
        public final String value;

        public MacroEntry(@Nonnull final String substrate, final @Nonnull String value) {
            this(-1, substrate, value);
        }

        public MacroEntry(final int meta, @Nonnull final String substrate, @Nonnull final String value) {
            this.meta = meta;
            this.substrate = substrate;
            this.value = value;
        }
    }

    private static final THashMap<String, List<MacroEntry>> macros = new THashMap<String, List<MacroEntry>>();

    static {
        List<MacroEntry> entries = new ArrayList<MacroEntry>();
        entries.add(new MacroEntry(null, "NOT_EMITTER"));
        entries.add(new MacroEntry("messy", "MESSY_GROUND"));
        entries.add(new MacroEntry("foliage", "straw"));
        macros.put("#sapling", entries);
        macros.put("#reed", entries);

        entries = new ArrayList<MacroEntry>();
        entries.add(new MacroEntry(null, "NOT_EMITTER"));
        entries.add(new MacroEntry("messy", "MESSY_GROUND"));
        entries.add(new MacroEntry(0, "foliage", "NOT_EMITTER"));
        entries.add(new MacroEntry(1, "foliage", "NOT_EMITTER"));
        entries.add(new MacroEntry(2, "foliage", "brush"));
        entries.add(new MacroEntry(3, "foliage", "brush"));
        entries.add(new MacroEntry(4, "foliage", "brush_straw_transition"));
        entries.add(new MacroEntry(5, "foliage", "brush_straw_transition"));
        entries.add(new MacroEntry(6, "foliage", "straw"));
        entries.add(new MacroEntry(7, "foliage", "straw"));
        macros.put("#wheat", entries);

        entries = new ArrayList<MacroEntry>();
        entries.add(new MacroEntry(null, "NOT_EMITTER"));
        entries.add(new MacroEntry("messy", "MESSY_GROUND"));
        entries.add(new MacroEntry(0, "foliage", "NOT_EMITTER"));
        entries.add(new MacroEntry(1, "foliage", "NOT_EMITTER"));
        entries.add(new MacroEntry(2, "foliage", "NOT_EMITTER"));
        entries.add(new MacroEntry(3, "foliage", "NOT_EMITTER"));
        entries.add(new MacroEntry(4, "foliage", "brush"));
        entries.add(new MacroEntry(5, "foliage", "brush"));
        entries.add(new MacroEntry(6, "foliage", "brush"));
        entries.add(new MacroEntry(7, "foliage", "brush"));
        macros.put("#crop", entries);

        entries = new ArrayList<MacroEntry>();
        entries.add(new MacroEntry(null, "NOT_EMITTER"));
        entries.add(new MacroEntry("messy", "MESSY_GROUND"));
        entries.add(new MacroEntry(0, "foliage", "NOT_EMITTER"));
        entries.add(new MacroEntry(1, "foliage", "NOT_EMITTER"));
        entries.add(new MacroEntry(2, "foliage", "brush"));
        entries.add(new MacroEntry(3, "foliage", "brush"));
        macros.put("#beets", entries);

        entries = new ArrayList<MacroEntry>();
        entries.add(new MacroEntry("bigger", "bluntwood"));
        macros.put("#fence", entries);
    }

    public BlockMap(@Nonnull final Isolator isolator) {
        this.isolator = isolator;
        this.metaMap.put(new BlockInfo(Blocks.AIR), AcousticsManager.NOT_EMITTER);
    }

    @Nullable
    public IAcoustic[] getBlockAcoustics(@Nonnull final IBlockState state, @Nonnull final BlockPos pos) {
        final IBlockState trueState = FacadeHelper.resolveState(state, EnvironState.getWorld(), pos, EnumFacing.UP);
        return this.metaMap.getBlockAcoustics(trueState);
    }

    @Nullable
    public IAcoustic[] getBlockSubstrateAcoustics(@Nonnull final IBlockState state, @Nonnull final BlockPos pos,
            @Nonnull final String substrate) {
        final IBlockState trueState = FacadeHelper.resolveState(state, EnvironState.getWorld(), pos, EnumFacing.UP);
        final BlockAcousticMap sub = this.substrateMap.get(substrate);
        return sub != null ? sub.getBlockAcousticsWithSpecial(trueState) : null;
    }

    private void put(@Nonnull final Block block, final int meta, @Nonnull final String substrate,
            @Nonnull final String value) {

        final IAcoustic[] acoustics = this.isolator.getAcoustics().compileAcoustics(value);

        if (StringUtils.isEmpty(substrate)) {
            this.metaMap.put(new BlockInfo(block, meta), acoustics);
        } else {
            BlockAcousticMap sub = this.substrateMap.get(substrate);
            if (sub == null)
                this.substrateMap.put(substrate.intern(), sub = new BlockAcousticMap());
            sub.put(new BlockInfo(block, meta), acoustics);
        }
    }

    private void expand(@Nonnull final Block block, @Nonnull final String value) {
        final List<MacroEntry> macro = macros.get(value);
        if (macro != null) {
            for (final MacroEntry entry : macro) {
                final int trueMeta = MCHelper.hasVariants(block) ? entry.meta : BlockInfo.NO_SUBTYPE;
                put(block, trueMeta, entry.substrate, entry.value);
            }
        } else {
            DSurround.log().debug("Unknown macro '%s'", value);
        }
    }

    public void register(@Nonnull final String key, @Nonnull final String value) {
        final Matcher matcher = pattern.matcher(key);
        if (matcher.matches()) {
            final String blockName = matcher.group(1);
            final Block block = MCHelper.getBlockByName(blockName);
            if (block == null) {
                DSurround.log().debug("Unable to locate block for blockMap '%s'", blockName);
            } else if (block == Blocks.AIR) {
                DSurround.log().warn("Attempt to insert AIR into blockMap '%s'", blockName);
            } else if (value.startsWith("#")) {
                expand(block, value);
            } else {
                final int meta = matcher.group(2) == null
                        ? (MCHelper.hasVariants(block) ? BlockInfo.GENERIC : BlockInfo.NO_SUBTYPE)
                        : Integer.parseInt(matcher.group(2));
                final String substrate = matcher.group(3);
                put(block, meta, substrate, value);
            }
        } else {
            DSurround.log().warn("Malformed key in blockMap '%s'", key);
        }
    }

    @Nonnull
    private static String combine(@Nonnull final IAcoustic[] acoustics) {
        final StringBuilder builder = new StringBuilder();
        boolean addComma = false;
        for (final IAcoustic a : acoustics) {
            if (addComma)
                builder.append(",");
            else
                addComma = true;
            builder.append(a.getAcousticName());
        }
        return builder.toString();
    }

    public void collectData(@Nonnull final IBlockState state, @Nonnull final BlockPos pos,
            @Nonnull final List<String> data) {

        final IAcoustic[] temp = getBlockAcoustics(state, pos);
        if (temp != null)
            data.add(combine(temp));

        for (final Entry<String, BlockAcousticMap> e : this.substrateMap.entrySet()) {
            final IAcoustic[] acoustics = e.getValue().getBlockAcousticsWithSpecial(state);
            if (acoustics != null)
                data.add(e.getKey() + ":" + combine(acoustics));
        }
    }

    public void clear() {
        this.metaMap.clear();
        this.substrateMap = new HashMap<String, BlockAcousticMap>();
        this.metaMap.put(new BlockInfo(Blocks.AIR), AcousticsManager.NOT_EMITTER);
    }

    public void freeze() {
        this.metaMap.freeze();
        this.substrateMap = new ImmutableMap.Builder<String, BlockAcousticMap>().putAll(this.substrateMap).build();
    }
}