feat: Enhance block appearance handling with detailed color and texture info, and improve block rendering performance

This commit is contained in:
MayaTheShy
2026-02-16 01:52:10 -05:00
parent cf0b66e2fe
commit 81e0dc4959

View File

@@ -18,7 +18,8 @@ function TurtleModel({ turtle, isSelected, onClick }) {
if (!position) return null; if (!position) return null;
// Calculate rotation based on facing (0=North(-Z), 1=East(+X), 2=South(+Z), 3=West(-X)) // Calculate rotation based on facing (0=North(-Z), 1=East(+X), 2=South(+Z), 3=West(-X))
const rotation = facing !== undefined ? [0, (facing * Math.PI / 2), 0] : [0, 0, 0]; // Add 180 degrees (Math.PI) to face the head forward initially, then apply facing rotation
const rotation = facing !== undefined ? [0, (facing * Math.PI / 2) + Math.PI, 0] : [0, Math.PI, 0];
const color = mode === 'mining' ? '#4ade80' : const color = mode === 'mining' ? '#4ade80' :
mode === 'exploring' ? '#60a5fa' : mode === 'exploring' ? '#60a5fa' :
@@ -134,69 +135,105 @@ function PathTrail({ turtle }) {
); );
} }
// Get color for block type // Get color and texture info for block type
function getBlockColor(blockName) { function getBlockAppearance(blockName) {
if (!blockName) return '#888'; if (!blockName) return { color: '#888', pattern: 'solid' };
const name = blockName.toLowerCase(); const name = blockName.toLowerCase();
// Ores // Ores - bright colors with sparkle
if (name.includes('diamond')) return '#00ffff'; if (name.includes('diamond')) return { color: '#00ffff', pattern: 'ore', emissive: '#00ffff', intensity: 0.3 };
if (name.includes('emerald')) return '#00ff00'; if (name.includes('emerald')) return { color: '#00ff00', pattern: 'ore', emissive: '#00ff00', intensity: 0.3 };
if (name.includes('gold')) return '#ffd700'; if (name.includes('gold')) return { color: '#ffd700', pattern: 'ore', emissive: '#ffd700', intensity: 0.2 };
if (name.includes('iron')) return '#d4d4d4'; if (name.includes('iron')) return { color: '#d4d4d4', pattern: 'ore' };
if (name.includes('coal')) return '#1a1a1a'; if (name.includes('coal')) return { color: '#1a1a1a', pattern: 'ore' };
if (name.includes('redstone')) return '#ff0000'; if (name.includes('redstone')) return { color: '#ff0000', pattern: 'ore', emissive: '#ff0000', intensity: 0.2 };
if (name.includes('lapis')) return '#0000ff'; if (name.includes('lapis')) return { color: '#1e40af', pattern: 'ore' };
if (name.includes('copper')) return '#ff8c00'; if (name.includes('copper')) return { color: '#ff8c00', pattern: 'ore' };
// Common blocks // Common blocks - textured
if (name.includes('stone')) return '#7f7f7f'; if (name.includes('stone') && !name.includes('cobble')) return { color: '#7f7f7f', pattern: 'stone' };
if (name.includes('dirt')) return '#8b4513'; if (name.includes('cobblestone')) return { color: '#808080', pattern: 'cobble' };
if (name.includes('grass')) return '#228b22'; if (name.includes('dirt')) return { color: '#8b4513', pattern: 'dirt' };
if (name.includes('sand')) return '#f4a460'; if (name.includes('grass')) return { color: '#228b22', pattern: 'grass' };
if (name.includes('gravel')) return '#808080'; if (name.includes('sand')) return { color: '#f4a460', pattern: 'sand' };
if (name.includes('bedrock')) return '#222'; if (name.includes('gravel')) return { color: '#808080', pattern: 'gravel' };
if (name.includes('obsidian')) return '#1a0033'; if (name.includes('bedrock')) return { color: '#222', pattern: 'solid' };
if (name.includes('netherrack')) return '#8b0000'; if (name.includes('obsidian')) return { color: '#1a0033', pattern: 'solid' };
if (name.includes('netherrack')) return { color: '#8b0000', pattern: 'netherrack' };
return '#666666'; // Default return { color: '#666666', pattern: 'solid' };
} }
// WorldBlocks component to render discovered blocks // WorldBlocks component to render discovered blocks
function WorldBlocks({ blocks }) { function WorldBlocks({ blocks }) {
const meshes = useMemo(() => { const [hoveredBlock, setHoveredBlock] = React.useState(null);
const instances = new Map();
// Group blocks by appearance for better performance
const blockGroups = useMemo(() => {
const groups = new Map();
blocks.forEach(block => { blocks.forEach(block => {
const color = getBlockColor(block.name); const appearance = getBlockAppearance(block.name);
if (!instances.has(color)) { const key = `${appearance.color}-${appearance.pattern}`;
instances.set(color, []);
if (!groups.has(key)) {
groups.set(key, { appearance, blocks: [] });
} }
instances.get(color).push(block); groups.get(key).blocks.push(block);
}); });
return instances; return Array.from(groups.values());
}, [blocks]); }, [blocks]);
return ( return (
<group> <group>
{Array.from(meshes.entries()).map(([color, blockList]) => ( {blockGroups.map((group, groupIdx) => (
<group key={color}> <group key={groupIdx}>
{blockList.map((block, idx) => ( {group.blocks.map((block) => {
<mesh const appearance = group.appearance;
key={`${block.x},${block.y},${block.z}`} const blockKey = `${block.x},${block.y},${block.z}`;
position={[block.x, block.y, block.z]} const isHovered = hoveredBlock === blockKey;
>
<boxGeometry args={[0.9, 0.9, 0.9]} /> return (
<meshStandardMaterial <group key={blockKey}>
color={color} <mesh
transparent position={[block.x, block.y, block.z]}
opacity={0.6} onPointerOver={(e) => {
roughness={0.8} e.stopPropagation();
/> setHoveredBlock(blockKey);
</mesh> }}
))} onPointerOut={() => setHoveredBlock(null)}
>
<boxGeometry args={[1.0, 1.0, 1.0]} />
<meshStandardMaterial
color={appearance.color}
emissive={appearance.emissive || appearance.color}
emissiveIntensity={isHovered ? (appearance.intensity || 0.05) + 0.3 : (appearance.intensity || 0.05)}
roughness={appearance.pattern === 'ore' ? 0.4 : 0.8}
metalness={appearance.pattern === 'ore' ? 0.3 : 0.0}
transparent
opacity={isHovered ? 0.95 : 0.85}
/>
</mesh>
{/* Block label on hover */}
{isHovered && (
<Text
position={[block.x, block.y + 0.8, block.z]}
fontSize={0.3}
color="white"
anchorX="center"
anchorY="middle"
outlineWidth={0.05}
outlineColor="#000000"
>
{block.name.replace('minecraft:', '').replace(/_/g, ' ').toUpperCase()}
</Text>
)}
</group>
);
})}
</group> </group>
))} ))}
</group> </group>