Загрузка данных


import pygame
import sys
import random
import math
import json
from dataclasses import dataclass

pygame.init()
pygame.font.init()

# =========================
# SETTINGS
# =========================
WIDTH, HEIGHT = 1280, 720
TILE = 32
FPS = 60

screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("2D Sandbox Dimensions")
clock = pygame.time.Clock()

FONT = pygame.font.SysFont("Arial", 20)
BIG = pygame.font.SysFont("Arial", 42)
SMALL = pygame.font.SysFont("Arial", 16)

# =========================
# COLORS
# =========================
C = {
    "sky": (135, 206, 235),
    "menu": (20, 20, 30),
    "panel": (35, 35, 50),
    "white": (255, 255, 255),
    "black": (0, 0, 0),
    "red": (220, 70, 70),
    "green": (80, 220, 120),
    "blue": (70, 120, 230),
    "yellow": (240, 220, 80),
    "grass": (80, 200, 120),
    "dirt": (139, 92, 52),
    "stone": (130, 130, 130),
    "wood": (120, 75, 35),
    "leaves": (40, 160, 70),
    "sand": (220, 210, 130),
    "netherrack": (140, 40, 40),
    "lava": (255, 90, 20),
    "endstone": (210, 210, 160),
    "portal": (120, 0, 255),
    "city": (180, 180, 220),
    "bedrock": (30, 30, 30),
    "village": (200, 170, 120),
    "spawner": (100, 0, 120),
    "trial": (70, 120, 180),
    "dragonegg": (50, 0, 60),
    "player": (50, 100, 220),
    "hair": (60, 40, 20),
    "skin": (240, 200, 170),
    "shirt": (50, 120, 220),
    "pants": (70, 70, 150),
}

BLOCK_COLORS = {
    "grass": C["grass"], "dirt": C["dirt"], "stone": C["stone"], "wood": C["wood"],
    "leaves": C["leaves"], "sand": C["sand"], "netherrack": C["netherrack"],
    "lava": C["lava"], "endstone": C["endstone"], "portal": C["portal"],
    "city": C["city"], "bedrock": C["bedrock"], "village": C["village"],
    "spawner": C["spawner"], "trial": C["trial"], "dragonegg": C["dragonegg"]
}

# =========================
# ITEM DATA
# =========================
TOOLS = ["pickaxe", "axe", "shovel", "hoe", "spear"]
TIER_ORDER = ["wood", "stone", "iron", "diamond", "netherite"]

TOOL_STATS = {
    "wood": {"power": 1, "dur": 50},
    "stone": {"power": 2, "dur": 90},
    "iron": {"power": 3, "dur": 140},
    "diamond": {"power": 4, "dur": 220},
    "netherite": {"power": 5, "dur": 320},
}
SWORD_POWER = {"wood": 2, "stone": 3, "iron": 4, "diamond": 5, "netherite": 7}
ARMOR_DEF = {"leather": 1, "iron": 3, "diamond": 4, "netherite": 5}
ARMOR_HP = {"leather": 10, "iron": 18, "diamond": 26, "netherite": 36}

ITEM_COLORS = {
    "wood": (120, 75, 35),
    "stone": (140, 140, 140),
    "iron": (200, 200, 210),
    "diamond": (70, 220, 220),
    "netherite": (80, 60, 90),
    "spear": (180, 180, 180),
    "mace": (150, 120, 90),
    "dragon_egg": C["dragonegg"],
    "netherite_ingot": (120, 90, 140),
    "diamond_gem": (80, 240, 240),
    "iron_ingot": (220, 220, 230),
}

def tool_name(tier, kind):
    return f"{tier}_{kind}"

def armor_name(tier, slot):
    return f"{tier}_{slot}"

# =========================
# GAME STATE
# =========================
class GameState:
    def __init__(self):
        self.mode = "menu"      # menu / play / skin / command / dead
        self.difficulty = "normal"  # easy / normal / hard / hardcore
        self.hardcore = False
        self.dead_forever = False
        self.selected_menu = 0
        self.command_text = ""

state = GameState()

# =========================
# INVENTORY
# =========================
class Inventory:
    def __init__(self):
        self.hotbar = [
            "wood_pickaxe", "wood_axe", "wood_shovel", "wood_hoe",
            "wood_spear", "wood_sword", "stone_pickaxe", "block_grass", "block_stone"
        ]
        self.selected = 0
        self.items = {
            "block_grass": 64,
            "block_dirt": 64,
            "block_stone": 64,
            "wood": 20,
            "iron_ingot": 10,
            "diamond_gem": 10,
            "netherite_ingot": 5,
            "dragon_egg": 1,
            "spawner_item": 2,
            "trial_key": 2,
            "mace": 1,
            "leather_helmet": 1, "leather_chest": 1, "leather_legs": 1, "leather_boots": 1,
            "iron_helmet": 1, "iron_chest": 1, "iron_legs": 1, "iron_boots": 1,
            "diamond_helmet": 1, "diamond_chest": 1, "diamond_legs": 1, "diamond_boots": 1,
            "netherite_helmet": 1, "netherite_chest": 1, "netherite_legs": 1, "netherite_boots": 1,
        }

    def add(self, item, n=1):
        self.items[item] = self.items.get(item, 0) + n

    def remove(self, item, n=1):
        if self.items.get(item, 0) >= n:
            self.items[item] -= n
            if self.items[item] <= 0:
                self.items.pop(item, None)
            return True
        return False

# =========================
# PLAYER
# =========================
class Player:
    def __init__(self, x, y):
        self.rect = pygame.Rect(x * TILE, y * TILE, 24, 30)
        self.vel_x = 0
        self.vel_y = 0
        self.speed = 4
        self.jump_power = -11
        self.on_ground = False
        self.max_hp = 20
        self.hp = 20
        self.hunger = 20
        self.armor = {"helmet": None, "chest": None, "legs": None, "boots": None}
        self.skin = {"hair": C["hair"], "skin": C["skin"], "shirt": C["shirt"], "pants": C["pants"]}
        self.dead = False
        self.invuln = 0

    def armor_points(self):
        pts = 0
        for item in self.armor.values():
            if item:
                tier = item.split("_")[0]
                if tier in ARMOR_DEF:
                    pts += ARMOR_DEF[tier]
        return pts

    def equip_armor(self, item):
        if item.endswith("_helmet"):
            self.armor["helmet"] = item
        elif item.endswith("_chest"):
            self