Scan System

The scan system captures what a player observes with the Thaumometer, recording block, entity, and phenomena scans as ScanResult objects. Custom scan handlers can be registered to extend what the Thaumometer can detect.

ScanResult

Package: thaumcraft.api.research

Records the outcome of a single scan operation.

Fields

Field Type Description
type byte Scan type: 1 = blocks, 2 = entities, 3 = phenomena
id int Block ID (type 1) or 0
meta int Block metadata (type 1) or 0
entity Entity The scanned entity (type 2) or null
phenomena String Custom phenomena identifier (type 3)

Constructor

public ScanResult(byte type, int blockId, int blockMeta, Entity entity, String phenomena)
  • Type 1 (block): Pass blockId, blockMeta, null, null
  • Type 2 (entity): Pass 0, 0, entity, null
  • Type 3 (phenomena): Pass 0, 0, null, phenomena

Equality

Two ScanResult objects are equal when their type matches and:

  • Type 1: Same id and meta
  • Type 2: Same entity ID (entity.getEntityId())
  • Type 3: Same phenomena string
@Override
public boolean equals(Object obj) {
    if (obj instanceof ScanResult) {
        ScanResult sr = (ScanResult) obj;
        if (type != sr.type) return false;
        if (type == 1 && (id != sr.id || meta != sr.meta)) return false;
        if (type == 2 && entity.getEntityId() != sr.entity.getEntityId()) return false;
        if (type == 3 && !phenomena.equals(sr.phenomena)) return false;
    }
    return true;
}

IScanEventHandler

Package: thaumcraft.api.research

Interface for custom scan handlers. Implement this to extend Thaumometer functionality, for example to detect mod-specific phenomena that cannot be represented as plain blocks or entities.

public interface IScanEventHandler {
    ScanResult scanPhenomena(ItemStack stack, World world, EntityPlayer player);
}
Parameter Type Description
stack ItemStack The ItemStack held by the player (e.g., the Thaumometer)
world World The world in which the scan is performed
player EntityPlayer The player performing the scan

Returns a ScanResult if the handler recognizes something to record, or null if nothing applicable.

Registration

ThaumcraftApi.registerScanEventhandler(IScanEventHandler handler)

Add to your FMLPostInitializationEvent handler. Multiple handlers can be registered; they are called in registration order until one returns a non-null result.


Entity Scanning Tags

Thaumcraft also maintains a registry of aspects associated with entity types, used for both scanning and calculating vis drops.

EntityTags Inner Class

public static class EntityTags {
    public EntityTags(String entityName, AspectList aspects, EntityTagsNBT... nbts)

    public String entityName;       // e.g., "Skeleton"
    public EntityTagsNBT[] nbts;    // Optional NBT match conditions
    public AspectList aspects;      // Aspects associated with this entity
}

public static class EntityTagsNBT {
    public EntityTagsNBT(String name, Object value)
    public String name;  // NBT key
    public Object value; // Expected value
}

Registration

public static void registerEntityTag(String entityName, AspectList aspects, EntityTagsNBT... nbt)
Parameter Description
entityName Entity registry name (e.g., "Skeleton")
aspects AspectList of aspects for this entity
nbt Optional NBT-based conditions to distinguish variants

Examples

// All skeletons share these aspects
ThaumcraftApi.registerEntityTag("Skeleton",
    new AspectList().add(Aspect.DEATH, 5).add(Aspect.UNDEAD, 3));

// Wither skeleton has different aspects (NBT differentiates it)
ThaumcraftApi.registerEntityTag("Skeleton",
    new AspectList().add(Aspect.DEATH, 8).add(Aspect.UNDEAD, 5),
    new EntityTagsNBT("SkeletonType", (byte) 1));

Thaumometer Scan Process

  1. Player right-clicks with a Thaumometer equipped
  2. Ray-trace identifies target block, entity, or look-at point
  3. Type 1 (block): Thaumcraft looks up block ID + metadata
  4. Type 2 (entity): Thaumcraft records the entity
  5. Type 3 (phenomena): Custom IScanEventHandler instances are queried in order; first non-null result wins
  6. Result is compared against the player’s known scans; new unique scans grant research progress

Custom Phenomena Handler Example

public class MyModScanHandler implements IScanEventHandler {
    @Override
    public ScanResult scanPhenomena(ItemStack stack, World world, EntityPlayer player) {
        // Example: detect when player looks at a specific mod block
        MovingObjectPosition mop = ThaumcraftApiHelper.rayTraceIgnoringSource(
            world, player.posVec, player.getLook(1f), false, false, false);
        if (mop != null && mop.typeOfHit == MovingObjectPosition.MovingObjectType.BLOCK) {
            Block block = world.getBlock(mop.blockX, mop.blockY, mop.blockZ);
            if (block == MyModBlocks.mysteriousBlock) {
                return new ScanResult((byte) 3, 0, 0, null, "mymod.mystery");
            }
        }
        return null;
    }
}

// Registration
ThaumcraftApi.registerScanEventhandler(new MyModScanHandler());