星露谷物语mod制作
- 技术
- 2024-11-03
- 77热度
- 0评论
为什么要写星露谷物语的mod
由于某位沉迷于星露谷物语,而且不想使用效率类mod来提升游戏速度,对于我这种经营类苦手来说实在是太过于煎熬,于是决定自己写一点不是很影响游戏体验并且符合自己需求的mod来提升一下游戏体验。
星露谷物语mod的开发
在决定要写一点东西以后,就是上网寻找资料了,无奈简中网络没有搜索到什么合适的教程,找到比较好的教程还是19年在百度贴吧上的教程,而且图床都已经全部失效,没办法只能去全球最大的同性交友网站看看了。
这里先说一下,星露谷物语的社区开发其实非常完善,有一个很完善的社区支持。
星露谷wiki可以说是这么多年来看到最用心,最完善的游戏社区图鉴/教程集合。不仅拥有风格化界面,内容也事无巨细,相当丰富。
作者埃里克和社区也有相当紧密的合作,smapi是一个社区开发的星露谷mod管理器,smapi不仅可以很方便的管理星露谷mod,而且与游戏官方合作,保持版本更新并提供相当丰富的api接口给开发者,mod开发者可以在这个链接下载开发者版本的smapi获得更多的控制台输出。
怎么完成第一个mod
本教程旨在说明使用C#开发的功能类mod,使用json和自制资源可以方便的完成内容物mod,参见这个链接。
这里先贴上一些有用的网站:
星露谷wiki的smapi mod开发新手教程,从头开始讲述如何使用C#开发星露谷的mod。
这里简短的概括一下流程:
- 安装星露谷物语(废话),steam掏钱即可(喜,最简单的一步)
- 安装smapi,在上面的链接中下载开发者版本的smapi,解压后点击.bat文件并按照提示即可。
- 安装开发者工具,这里我使用的是windows,用微软的visual studio 2022,下载会先安装installer,在installer中安装visual studio 2022 community即可,勾选c#开发组建,并在单个组件中勾选.NET 6 SDK
- 创建一个类库项目,项目名称是你的mod名称,并选择.NET 6作为基准即可。
- 创建项目
- 在项目-管理Nuget程序包中安装Pathoschild.Stardew.ModBuildConfig包
在包管理中搜索下载安装即可 - 重启vs 2022
以上已经做好了编写一个mod的准备工作,接下来我们看看应该怎么完成第一个mod。
作为一个最最简单的mod,我们需要的只有两个文件:
- ModEntry.cs
- manifest.json
首先删除默认的class1.cs文件,新建上面两个文件

我们这里以一个简单的传送的mod作为示例来说一说里面的类结构
我们需要实现的功能是:在按下手柄左摇杆或着键盘的f1键,即可传送到另一个玩家身边。
在smapi启动时,会寻找ModEntry.cs的里面的ModEntry类的Entry方法作为入口,先来看入口定义
附上api文档
Modding:Modder Guide/APIs - Stardew Valley Wiki
using StardewModdingAPI;
using StardewModdingAPI.Events;
using StardewValley;
using System.Collections.Generic;
using System.Linq;
namespace Teleport
{
public class ModEntry : Mod
{
private List _farmers;
public override void Entry(IModHelper helper)//入口函数
{
//helper.Events.GameLoop.GameLaunched += this.OnGameLaunched;
helper.Events.GameLoop.SaveLoaded += this.OnSaveLoaded;
//helper.Events.GameLoop.ReturnedToTitle += this.OnReturnedToTitle;
}
private void OnSaveLoaded(object sender, SaveLoadedEventArgs e)
{
Helper.Events.Input.ButtonPressed += this.OnButtonPressed;
//Helper.Events.Input.ButtonReleased += this.OnButtonReleased;
}
private void OnButtonPressed(object sender, ButtonPressedEventArgs e)
{
}
}
}
这里我们先关注Entry方法,这个就是smapi调用的入口方法,这个方法的主要人物是将事件处理函数加到不同的事件池里面。
在这个例子里面添加了saveLoaded事件处理函数,这是一个在加载存档后会调用的方法池,你需要将加载存档时需要读取的数据/加载的内容放在这里,如农民数量等,需要在这里读取。
类似的,如果在OnGameLaunched事件池里添加方法,则可以在加载游戏的时候添加,比如增加一些设置功能等等。
private void OnSaveLoaded(object sender, SaveLoadedEventArgs e)
{
this._farmers = Game1.getAllFarmers().Where(f => !string.IsNullOrEmpty(f.Name)).ToList();
Monitor.Log("Game launched");
Helper.Events.Input.ButtonPressed += this.OnButtonPressed;
//Helper.Events.Input.ButtonReleased += this.OnButtonReleased;
}
相同的,我们再来看一下这个OnSaveLoaded函数里面干了些什么,我们在前面声明了一个变量数组_farmers作为一个类的私有变量,在这里我们调用smapi的项目接口Game1.getAllFarmers()来得到所有的农民类,并在monitor中打出log(这个log会打印在smapi的控制台里面),然后再加入一个成员方法OnButtonReleased到ButtonPressed事件池里面。
在接着定义ButtonPressed
private void OnButtonPressed(object sender, ButtonPressedEventArgs e)
{
if (e.Button == SButton.F1 || e.Button == SButton.LeftStick)
{
this.Monitor.Log($"Farmers: {this._farmers.Count}");
StardewValley.Farmer targetFramer;
if (this._farmers.Count > 1)
{
targetFramer = this._farmers[0] == Game1.player ? this._farmers[1] : this._farmers[0];
}
else
{
this.Monitor.Log("No other farmers found");
return;
}
this.WarpTo(targetFramer);
}
}
这个成员函数会在按键被按下的时候触发,并由e.Button传入,用if可以判断如果是F1和LeftStick就调用Warp函数,再用Warp函数处理即可。