Beispiel #1
0
// LoadLocale loads the named locale if it exists.
func LoadLocale(name string) {
	lock.Lock()
	defer lock.Unlock()
	r, err := resource.Open("minecraft", fmt.Sprintf("lang/%s.lang", name))
	if err != nil {
		return
	}
	defer r.Close()
	b := bufio.NewScanner(r)
	for b.Scan() {
		line := b.Text()
		line = strings.TrimSpace(line)
		if len(line) == 0 {
			continue
		}
		parts := strings.SplitN(line, "=", 2)
		if len(parts) != 2 {
			continue
		}
		values[parts[0]] = parts[1]
	}
	if err := b.Err(); err != nil {
		panic(err)
	}
}
Beispiel #2
0
func loadJSON(plugin, name string, target interface{}) error {
	r, err := resource.Open(plugin, name)
	if err != nil {
		return err
	}
	defer r.Close()
	err = realjson.NewDecoder(r).Decode(target)
	if err != nil {
		// Take the slow path through our preprocessor.
		// Hopefully this can be removed in later minecraft versions.d, err := ioutil.ReadAll(r)
		r.Close()
		r, err = resource.Open(plugin, name)
		if err != nil {
			return err
		}

		d, err := ioutil.ReadAll(r)
		if err != nil {
			return err
		}
		return json.Unmarshal(d, target)
	}
	return err
}
Beispiel #3
0
func LoadSkinBuffer() {
	r, err := resource.Open("minecraft", "textures/entity/steve.png")
	if err != nil {
		skinBuffer = make([]byte, 64*64*4)
		return
	}
	defer r.Close()
	i, err := png.Decode(r)
	if err != nil {
		panic(err)
	}
	out := image.NewNRGBA(image.Rect(0, 0, 64, 64))
	draw.Draw(out, out.Bounds(), i, image.ZP, draw.Over)
	skinBuffer = out.Pix
}
Beispiel #4
0
func loadBiomeColors(name string) *image.NRGBA {
	f, err := resource.Open("minecraft", fmt.Sprintf("textures/colormap/%s.png", name))
	if err != nil {
		console.Text("loading biome colors: %s", err)
		return image.NewNRGBA(image.Rect(0, 0, 256, 256))
	}
	defer f.Close()
	img, err := png.Decode(f)
	if err != nil {
		panic(err)
	}
	i, ok := img.(*image.NRGBA)
	if !ok {
		i = convertImage(img)
	}
	return i
}
Beispiel #5
0
func loadFontInfo() {
	r, err := resource.Open("minecraft", "font/glyph_sizes.bin")
	if err != nil {
		console.Text("Error loading font info, %s", err)
		return
	}
	var data [0x10000]byte
	_, err = io.ReadFull(r, data[:])
	if err != nil {
		panic(err)
	}
	for i := range fontCharacterInfo {
		// Top nibble - start position
		// Bottom nibble - end position
		fontCharacterInfo[i].Start = int(data[i] >> 4)
		fontCharacterInfo[i].End = int(data[i]&0xF) + 1
	}
}
Beispiel #6
0
func loadFontPage(page int) {
	textureLock.Lock()
	defer textureLock.Unlock()
	isFontLoaded[page] = true
	var p string
	if page == 0 {
		// The ascii font is the minecraft style one
		// which is the default page 0 instead of the
		// unicode one for the english locales.
		p = "ascii"
	} else {
		p = fmt.Sprintf("unicode_page_%02x", page)
	}
	r, err := resource.Open("minecraft", "textures/font/"+p+".png")
	if err != nil {
		return
	}
	defer r.Close()
	img, err := png.Decode(r)
	if err != nil {
		panic(err)
	}
	width, height := img.Bounds().Dx(), img.Bounds().Dy()
	pix := imgToBytes(img)
	info := addTexture(pix, width, height)
	if fontPages[page] != nil {
		fontPages[page].atlas = info.atlas
		fontPages[page].rect = info.rect
	} else {
		fontPages[page] = info
	}
	if p == "ascii" {
		// The font map file included with minecraft has the
		// wide of the unicode page 0 instead of the ascii one
		// we need to work this out ourselves
		calculateFontSizes(img)
	}
}
Beispiel #7
0
func readStevenLogo() {
	r, _ := resource.Open("steven", "logo/logo.txt")
	defer r.Close()
	data, _ := ioutil.ReadAll(r)
	stevenLogo = string(data)
}
Beispiel #8
0
func loadAnimation(file string, max int) *animatedTexture {
	a := &animatedTexture{}
	defer func() {
		if a != nil {
			a.RemainingTime = float64(a.Frames[0].Time)
		}
	}()

	type animation struct {
		FrameTime   int
		Interpolate bool
		Frames      []json.RawMessage
	}
	type base struct {
		Animation animation
	}

	meta, err := resource.Open("minecraft", file+".mcmeta")
	if err != nil {
		fmt.Printf("%s: %s\n", file+".mcmeta", err)
		a = nil
		return nil
	}
	defer meta.Close()
	b := &base{}
	err = json.NewDecoder(meta).Decode(b)
	if err != nil {
		panic(err)
	}
	frameTime := b.Animation.FrameTime
	if frameTime == 0 {
		frameTime = 1
	}
	a.Interpolate = b.Animation.Interpolate

	if len(b.Animation.Frames) == 0 {
		a.Frames = make([]textureFrame, max)
		for i := range a.Frames {
			a.Frames[i] = textureFrame{
				Index: i,
				Time:  frameTime,
			}
		}
		return a
	}

	a.Frames = make([]textureFrame, len(b.Animation.Frames))
	for i := range a.Frames {
		a.Frames[i].Time = frameTime
		if b.Animation.Frames[i][0] == '{' {
			if err = json.Unmarshal(b.Animation.Frames[i], &a.Frames[i]); err != nil {
				panic(err)
			}
			a.Frames[i].Time *= frameTime
			continue
		}
		if err = json.Unmarshal(b.Animation.Frames[i], &a.Frames[i].Index); err != nil {
			panic(err)
		}
	}

	return a
}
Beispiel #9
0
// LoadTextures (re)loads all the block textures from the resource pack(s)
// TODO(Think) better error handling (if possible to recover?)
func LoadTextures() {
	textureLock.Lock()

	if texturesCreated {
		glTexture.Bind(gl.Texture2DArray)
		data := make([]byte, AtlasSize*AtlasSize*textureCount*4)
		glTexture.Image3D(0, AtlasSize, AtlasSize, textureCount, gl.RGBA, gl.UnsignedByte, data)
	} else {
		glTexture = gl.CreateTexture()
		glTexture.Bind(gl.Texture2DArray)
		textureDepth = len(textures)
		glTexture.Image3D(0, AtlasSize, AtlasSize, len(textures), gl.RGBA, gl.UnsignedByte, make([]byte, AtlasSize*AtlasSize*len(textures)*4))
		glTexture.Parameter(gl.TextureMagFilter, gl.Nearest)
		glTexture.Parameter(gl.TextureMinFilter, gl.Nearest)
		glTexture.Parameter(gl.TextureWrapS, gl.ClampToEdge)
		glTexture.Parameter(gl.TextureWrapT, gl.ClampToEdge)
		for i, tex := range textures {
			glTexture.SubImage3D(0, 0, 0, i, AtlasSize, AtlasSize, 1, gl.RGBA, gl.UnsignedByte, tex.Buffer)
			textures[i] = nil
		}
		texturesCreated = true
	}
	freeTextures = nil
	animatedTextures = nil
	textures = nil
	pix := []byte{
		0, 0, 0, 255,
		255, 0, 255, 255,
		255, 0, 255, 255,
		0, 0, 0, 255,
	}
	info := addTexture(pix, 2, 2)
	if t, ok := textureMap["missing_texture"]; ok {
		t.atlas = info.atlas
		t.rect = info.rect
	} else {
		textureMap["missing_texture"] = info
	}

	for _, t := range textureMap {
		t.atlas = info.atlas
		t.rect = info.rect
	}

	for _, s := range loadedTextures {
		func() {
			r, err := resource.Open(s.Plugin, s.File)
			if err == nil {
				defer r.Close()
				img, err := png.Decode(r)
				if err != nil {
					panic(fmt.Sprintf("(%s): %s", s.File, err))
				}
				s.Image = img
				loadTexFile(s)
			}
		}()
	}

	pix = []byte{255, 255, 255, 255}
	info = addTexture(pix, 1, 1)
	if t, ok := textureMap["solid"]; ok {
		t.atlas = info.atlas
		t.rect = info.rect
	} else {
		textureMap["solid"] = info
	}

	for _, skin := range skins {
		info := getFreeTexture(skin.info.W, skin.info.H)
		uploadTexture(info.info, skin.data)
		i := skin.info.info
		skin.info = info
		i.rect = info.info.rect
		i.atlas = info.info.atlas
		skin.info.info = i
	}

	textureLock.Unlock()

	loadFontInfo()
	loadFontPage(0)

	for i := range isFontLoaded {
		if i == 0 || !isFontLoaded[i] {
			continue
		}
		isFontLoaded[i] = false
		loadFontPage(i)
	}
}
Beispiel #10
0
// GetTexture returns the related TextureInfo for the requested texture.
// If the texture isn't found a placeholder is returned instead.
// The plugin prefix of 'minecraft:' is default
func GetTexture(name string) TextureInfo {
	textureLock.RLock()
	defer textureLock.RUnlock()
	t, ok := textureMap[name]
	if !ok {
		textureLock.RUnlock()
		ret := make(chan struct{}, 1)
		f := func() {
			textureLock.Lock()
			defer textureLock.Unlock()
			// Check to see if it was already loaded between
			// requesting it
			if _, ok = textureMap[name]; ok {
				t = textureMap[name]
				ret <- struct{}{}
				return
			}
			ns := name
			plugin := "minecraft"
			if pos := strings.IndexRune(name, ':'); pos != -1 {
				plugin = name[:pos]
				ns = name[pos+1:]
			}
			r, err := resource.Open(plugin, "textures/"+ns+".png")
			if err == nil {
				defer r.Close()
				img, err := png.Decode(r)
				if err != nil {
					panic(fmt.Sprintf("(%s): %s", name, err))
				}
				s := &loadedTexture{
					Plugin: plugin,
					File:   "textures/" + ns + ".png",
					Image:  img,
				}
				loadedTextures = append(loadedTextures, s)
				loadTexFile(s)
			}
			t, ok = textureMap[name]
			if !ok {
				ti := *textureMap["missing_texture"]
				t = &ti
				textureMap[name] = t
				s := &loadedTexture{
					Plugin: plugin,
					File:   "textures/" + ns + ".png",
					Image:  nil,
				}
				loadedTextures = append(loadedTextures, s)
			}
			ret <- struct{}{}
		}
		if w := glfw.GetCurrentContext(); w == nil {
			syncChan <- f
		} else {
			f()
		}
		<-ret
		textureLock.RLock()
	}
	return t
}
Beispiel #11
0
func genStaticModelFromItem(mdl *model, block Block, mode string) (out []*render.StaticVertex, mat mgl32.Mat4) {
	mat = mgl32.Rotate3DZ(math.Pi).Mat4().
		Mul4(mgl32.Rotate3DY(math.Pi / 2).Mat4()).
		Mul4(mgl32.Rotate3DZ(-math.Pi / 2).Mat4())

	if gui, ok := mdl.display[mode]; ok {
		if gui.Scale != nil {
			mat = mat.Mul4(mgl32.Scale3D(
				float32(gui.Scale[0]),
				float32(gui.Scale[1]),
				float32(gui.Scale[2]),
			))
		}
		if gui.Translation != nil {
			mat = mat.Mul4(mgl32.Translate3D(
				float32(gui.Translation[0]/32),
				float32(gui.Translation[1]/32),
				float32(gui.Translation[2]/32),
			))
		}
		if gui.Rotation != nil {
			mat = mat.Mul4(mgl32.Rotate3DX(math.Pi + float32(gui.Rotation[0]/180)*math.Pi).Mat4())
			mat = mat.Mul4(mgl32.Rotate3DZ(math.Pi + float32(gui.Rotation[2]/180)*math.Pi).Mat4())
			mat = mat.Mul4(mgl32.Rotate3DY(float32(gui.Rotation[1]/180) * math.Pi).Mat4())
		}
	}
	mat = mat.Mul4(mgl32.Rotate3DY(math.Pi / 2).Mat4())
	mat = mat.Mul4(mgl32.Translate3D(-1/16.0, 0, 0))

	tex := render.GetTexture("solid")
	rect := tex.Rect()

	tName, plugin := mdl.textureVars["layer0"], "minecraft"
	if pos := strings.IndexRune(tName, ':'); pos != -1 {
		plugin = tName[:pos]
		tName = tName[pos:]
	}
	f, err := resource.Open(plugin, "textures/"+tName+".png")
	if err != nil {
		return
	}
	defer f.Close()
	img, err := png.Decode(f)
	if err != nil {
		panic(err)
	}

	w, h := img.Bounds().Dx(), img.Bounds().Dy()
	sx := 1 / float32(w)
	sy := 1 / float32(h)

	isSolid := func(x, y int) bool {
		col := img.At(x, y)
		_, _, _, aa := col.RGBA()
		if aa == 0 {
			return false
		}
		return true
	}

	for x := 0; x < w; x++ {
		for y := 0; y < h; y++ {
			col := img.At(x, y)
			rr, gg, bb, aa := col.RGBA()
			if aa == 0 {
				continue
			}

			for i, f := range faceVertices {
				facing := direction.Type(i)
				if facing != direction.North && facing != direction.South {
					xx, yy, _ := facing.Offset()
					if isSolid(x+xx, y+yy) {
						continue
					}
				}

				var cr, cg, cb byte
				cr = byte(rr >> 8)
				cg = byte(gg >> 8)
				cb = byte(bb >> 8)
				if facing == direction.East || facing == direction.West {
					cr = byte(float64(cr) * 0.8)
					cg = byte(float64(cg) * 0.8)
					cb = byte(float64(cb) * 0.8)
				}
				if facing == direction.North || facing == direction.South {
					cr = byte(float64(cr) * 0.6)
					cg = byte(float64(cg) * 0.6)
					cb = byte(float64(cb) * 0.6)
				}

				for _, vert := range f.verts {
					vX, vY, vZ := float32(vert.X), float32(vert.Y), float32(vert.Z)
					vert := &render.StaticVertex{
						Y:        vY*sy - 0.5 + sy*float32(y),
						X:        vX*sx - 0.5 + sx*float32(x),
						Z:        (vZ - 0.5) * (1.0 / 16.0),
						Texture:  tex,
						TextureX: float64(vert.TOffsetX) / float64(16*rect.Width),
						TextureY: float64(vert.TOffsetY) / float64(16*rect.Height),
						R:        cr,
						G:        cg,
						B:        cb,
						A:        byte(aa >> 8),
					}
					out = append(out, vert)
				}
			}
		}
	}
	return
}
Beispiel #12
0
func playSoundInternal(cat soundCategory, snd sound, vol, pitch float64, rel bool, pos mgl32.Vec3, cb func()) {
	vol *= snd.Volume * 100
	baseVol := vol
	vol *= float64(muVolMaster.Value()) / 100
	if v, ok := volVars[cat]; ok {
		vol *= float64(v.Value()) / 100
	}
	if vol <= 0 {
		if cb != nil {
			go func() { syncChan <- cb }()
		}
		return
	}
	name := snd.Name
	key := pluginKey{"minecraft", name}
	sb, ok := loadedSounds[key]
	if !ok {
		f, err := resource.Open("minecraft", "sounds/"+name+".ogg")
		if err != nil {
			v, ok := assets.Objects[fmt.Sprintf("minecraft/sounds/%s.ogg", name)]
			if !ok {
				console.Text("Missing sound %s", key)
				if cb != nil {
					cb()
				}
				return
			}
			loc := fmt.Sprintf("./resources/%s", hashPath(v.Hash))
			f, err = os.Open(loc)
			if err != nil {
				console.Text("Missing sound %s", key)
				if cb != nil {
					cb()
				}
				return
			}
		}
		if snd.Stream {
			m := audio.NewMusic(f)
			m.SetVolume(vol)
			m.SetPitch(pitch)
			m.Play()
			currentMusic = append(currentMusic, music{Music: m, cb: cb, cat: cat, vol: baseVol})
			return
		}
		defer f.Close()
		data, err := ioutil.ReadAll(f)
		if err != nil {
			panic(err)
		}
		sb = audio.NewSoundBufferData(data)
		loadedSounds[key] = sb
	}
	var s audio.Sound
	n := true
	for _, sn := range soundList {
		if sn.Status() == audio.StatStopped {
			s = sn
			n = false
			break
		}
	}
	if n {
		if len(soundList) >= 100 {
			console.Component(
				format.Build("WARN: Skipping playing sound due to limit").
					Color(format.Yellow).Create(),
			)
			return
		}
		s = audio.NewSound()
		soundList = append(soundList, s)
	}
	s.SetBuffer(sb)
	s.SetVolume(vol)
	s.SetMinDistance(5)
	s.SetAttenuation(0.008)
	s.SetPitch(pitch)
	s.Play()
	if rel {
		s.SetRelative(true)
		s.SetPosition(pos.X(), pos.Y(), pos.Z())
	} else {
		s.SetRelative(false)
	}
}